UNPKG

@dolphinweex/himalaya

Version:
355 lines (315 loc) 9.06 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.feedPosition = feedPosition; exports.jumpPosition = jumpPosition; exports.makeInitialPosition = makeInitialPosition; exports.copyPosition = copyPosition; exports.default = lexer; exports.lex = lex; exports.findTextEnd = findTextEnd; exports.lexText = lexText; exports.lexComment = lexComment; exports.lexTag = lexTag; exports.isWhitespaceChar = isWhitespaceChar; exports.lexTagName = lexTagName; exports.lexTagAttributes = lexTagAttributes; exports.lexSkipTag = lexSkipTag; var _compat = require('./compat'); function feedPosition(position, str, len) { var start = position.index; var end = position.index = start + len; for (var i = start; i < end; i++) { var char = str.charAt(i); if (char === '\n') { position.line++; position.column = 0; } else { position.column++; } } } function jumpPosition(position, str, end) { var len = end - position.index; return feedPosition(position, str, len); } function makeInitialPosition() { return { index: 0, column: 0, line: 0 }; } function copyPosition(position) { return { index: position.index, line: position.line, column: position.column }; } function lexer(str, options) { var state = { str: str, options: options, position: makeInitialPosition(), tokens: [] }; lex(state); return state.tokens; } function lex(state) { var str = state.str, childlessTags = state.options.childlessTags; var len = str.length; while (state.position.index < len) { var start = state.position.index; lexText(state); if (state.position.index === start) { var isComment = (0, _compat.startsWith)(str, '!--', start + 1); if (isComment) { lexComment(state); } else { var tagName = lexTag(state); var safeTag = tagName; if(safeTag.toLowerCase() == 'template'){ //只有第一个也就是最外层的template需要跳过 内部tempalte不需要 if(state.position.line == 1){ if ((0, _compat.arrayIncludes)(childlessTags, safeTag)) { lexSkipTag(tagName, state); } } } } } } } var alphanumeric = /[A-Za-z0-9]/; function findTextEnd(str, index) { while (true) { var textEnd = str.indexOf('<', index); if (textEnd === -1) { return textEnd; } // 如果包含 Vue 插值表达式,跳过 极端情况 使用{{` < 123 > `}} 套住 if (str.lastIndexOf('{{', textEnd) > str.lastIndexOf('}}', textEnd)) { index = str.indexOf('}}', textEnd) + 2; continue; } var char = str.charAt(textEnd + 1); if (char === '/' || char === '!' || alphanumeric.test(char)) { return textEnd; } index = textEnd + 1; } } function lexText(state) { var type = 'text'; var str = state.str, position = state.position; var textEnd = findTextEnd(str, position.index); if (textEnd === position.index) return; if (textEnd === -1) { textEnd = str.length; } var start = copyPosition(position); var content = str.slice(position.index, textEnd); jumpPosition(position, str, textEnd); var end = copyPosition(position); state.tokens.push({ type: type, content: content, position: { start: start, end: end } }); } function lexComment(state) { var str = state.str, position = state.position; var start = copyPosition(position); feedPosition(position, str, 4); // "<!--".length var contentEnd = str.indexOf('-->', position.index); var commentEnd = contentEnd + 3; // "-->".length if (contentEnd === -1) { contentEnd = commentEnd = str.length; } var content = str.slice(position.index, contentEnd); jumpPosition(position, str, commentEnd); state.tokens.push({ type: 'comment', content: content, position: { start: start, end: copyPosition(position) } }); } function lexTag(state) { var str = state.str, position = state.position; { var secondChar = str.charAt(position.index + 1); var close = secondChar === '/'; var start = copyPosition(position); feedPosition(position, str, close ? 2 : 1); state.tokens.push({ type: 'tag-start', close: close, position: { start: start } }); } var tagName = lexTagName(state); lexTagAttributes(state); { var firstChar = str.charAt(position.index); var _close = firstChar === '/'; feedPosition(position, str, _close ? 2 : 1); var end = copyPosition(position); state.tokens.push({ type: 'tag-end', close: _close, position: { end: end } }); } return tagName; } // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#special-white-space var whitespace = /\s/; function isWhitespaceChar(char) { return whitespace.test(char); } function lexTagName(state) { var str = state.str, position = state.position; var len = str.length; var start = position.index; while (start < len) { var char = str.charAt(start); var isTagChar = !(isWhitespaceChar(char) || char === '/' || char === '>'); if (isTagChar) break; start++; } var end = start + 1; while (end < len) { var _char = str.charAt(end); var _isTagChar = !(isWhitespaceChar(_char) || _char === '/' || _char === '>'); if (!_isTagChar) break; end++; } jumpPosition(position, str, end); var tagName = str.slice(start, end); state.tokens.push({ type: 'tag', content: tagName }); return tagName; } function lexTagAttributes(state) { var str = state.str, position = state.position, tokens = state.tokens; var cursor = position.index; var quote = null; // null, single-, or double-quote var wordBegin = cursor; // index of word start var words = []; // "key", "key=value", "key='value'", etc var len = str.length; while (cursor < len) { var char = str.charAt(cursor); if (quote) { var isQuoteEnd = char === quote; if (isQuoteEnd) { quote = null; } cursor++; continue; } var isTagEnd = char === '/' || char === '>'; if (isTagEnd) { if (cursor !== wordBegin) { words.push(str.slice(wordBegin, cursor)); } break; } var isWordEnd = isWhitespaceChar(char); if (isWordEnd) { if (cursor !== wordBegin) { words.push(str.slice(wordBegin, cursor)); } wordBegin = cursor + 1; cursor++; continue; } var isQuoteStart = char === '\'' || char === '"'; if (isQuoteStart) { quote = char; cursor++; continue; } cursor++; } jumpPosition(position, str, cursor); var wLen = words.length; var type = 'attribute'; for (var i = 0; i < wLen; i++) { var word = words[i]; var isNotPair = word.indexOf('=') === -1; if (isNotPair) { var secondWord = words[i + 1]; if (secondWord && (0, _compat.startsWith)(secondWord, '=')) { if (secondWord.length > 1) { var newWord = word + secondWord; tokens.push({ type: type, content: newWord }); i += 1; continue; } var thirdWord = words[i + 2]; i += 1; if (thirdWord) { var _newWord = word + '=' + thirdWord; tokens.push({ type: type, content: _newWord }); i += 1; continue; } } } if ((0, _compat.endsWith)(word, '=')) { var _secondWord = words[i + 1]; if (_secondWord && !(0, _compat.stringIncludes)(_secondWord, '=')) { var _newWord3 = word + _secondWord; tokens.push({ type: type, content: _newWord3 }); i += 1; continue; } var _newWord2 = word.slice(0, -1); tokens.push({ type: type, content: _newWord2 }); continue; } tokens.push({ type: type, content: word }); } } var push = [].push; function lexSkipTag(tagName, state) { var str = state.str, position = state.position, tokens = state.tokens; var safeTagName = tagName.toLowerCase(); var len = str.length; var index = position.index; while (index < len) { var nextTag = str.indexOf('</', index); if (nextTag === -1) { lexText(state); break; } var tagStartPosition = copyPosition(position); jumpPosition(tagStartPosition, str, nextTag); var tagState = { str: str, position: tagStartPosition, tokens: [] }; var name = lexTag(tagState); if (safeTagName !== name.toLowerCase()) { index = tagState.position.index; continue; } if (nextTag !== position.index) { var textStart = copyPosition(position); jumpPosition(position, str, nextTag); tokens.push({ type: 'text', content: str.slice(textStart.index, nextTag), position: { start: textStart, end: copyPosition(position) } }); } push.apply(tokens, tagState.tokens); jumpPosition(position, str, tagState.position.index); break; } } //# sourceMappingURL=lexer.js.map