diff --git a/extensions/emmet/src/selectItemHTML.ts b/extensions/emmet/src/selectItemHTML.ts index f818f5783a3..6400913396c 100644 --- a/extensions/emmet/src/selectItemHTML.ts +++ b/extensions/emmet/src/selectItemHTML.ts @@ -19,7 +19,7 @@ export function nextItemHTML(document: vscode.TextDocument, selectionStart: vsco if (currentNode.type !== 'comment') { // If cursor is in the tag name, select tag if (currentNode.open && - selectionEndOffset < currentNode.open.start + currentNode.name.length) { + selectionEndOffset <= currentNode.open.start + currentNode.name.length) { return getSelectionFromNode(document, currentNode); } diff --git a/extensions/emmet/src/util.ts b/extensions/emmet/src/util.ts index 831414126cd..572037fd8fd 100644 --- a/extensions/emmet/src/util.ts +++ b/extensions/emmet/src/util.ts @@ -376,32 +376,36 @@ export const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-t * If position is inside a script tag of type template, then it will be parsed to find the inner HTML node as well */ export function getHtmlFlatNode(documentText: string, root: FlatNode | undefined, offset: number, includeNodeBoundary: boolean): HtmlFlatNode | undefined { - const currentNode: HtmlFlatNode | undefined = getFlatNode(root, offset, includeNodeBoundary); + let currentNode: HtmlFlatNode | undefined = getFlatNode(root, offset, includeNodeBoundary); if (!currentNode) { return; } - const isTemplateScript = currentNode.name === 'script' && - (currentNode.attributes && - currentNode.attributes.some(x => x.name.toString() === 'type' - && allowedMimeTypesInScriptTag.includes(x.value.toString()))); - if (isTemplateScript - && currentNode.open - && offset > currentNode.open.end - && (!currentNode.close || offset < currentNode.close.start)) { - // blank out the rest of the document and search for the node within - const beforePadding = ' '.repeat(currentNode.open.end); - const endToUse = currentNode.close ? currentNode.close.start : currentNode.end; - const scriptBodyText = beforePadding + documentText.substring(currentNode.open.end, endToUse); - const innerRoot: HtmlFlatNode = parse(scriptBodyText); - const scriptBodyNode = getHtmlFlatNode(scriptBodyText, innerRoot, offset, includeNodeBoundary); - if (scriptBodyNode) { - scriptBodyNode.parent = currentNode; - currentNode.children.push(scriptBodyNode); - return scriptBodyNode; - } + // If the currentNode is a script one, first set up its subtree and then find HTML node. + if (currentNode.name === 'script' && currentNode.children.length === 0) { + setUpScriptNodeSubtree(documentText, currentNode); + currentNode = getFlatNode(currentNode, offset, includeNodeBoundary) ?? currentNode; } return currentNode; } +export function setUpScriptNodeSubtree(documentText: string, scriptNode: HtmlFlatNode): void { + const isTemplateScript = scriptNode.name === 'script' && + (scriptNode.attributes && + scriptNode.attributes.some(x => x.name.toString() === 'type' + && allowedMimeTypesInScriptTag.includes(x.value.toString()))); + if (isTemplateScript + && scriptNode.open) { + // blank out the rest of the document and generate the subtree. + const beforePadding = ' '.repeat(scriptNode.open.end); + const endToUse = scriptNode.close ? scriptNode.close.start : scriptNode.end; + const scriptBodyText = beforePadding + documentText.substring(scriptNode.open.end, endToUse); + const innerRoot: HtmlFlatNode = parse(scriptBodyText); + innerRoot.children.forEach(child => { + scriptNode.children.push(child); + child.parent = scriptNode; + }); + } +} + export function isOffsetInsideOpenOrCloseTag(node: FlatNode, offset: number): boolean { const htmlNode = node as HtmlFlatNode; if ((htmlNode.open && offset > htmlNode.open.start && offset < htmlNode.open.end)