Move ts script check into embed print (#14559)
This commit is contained in:
1 parent
919670df68
commit
bae1eb4a14
5 files changed
+76
-59
No files matched your search
+42
-41
@@ -28,17 +28,18 @@ import {
|
||||
inferElementParser,
|
||||
htmlTrimPreserveIndentation,
|
||||
dedentString,
|
||||
unescapeQuoteEntities,
|
||||
isVueSlotAttribute,
|
||||
isVueSfcBindingsAttribute,
|
||||
getTextValueParts,
|
||||
getUnescapedAttributeValue,
|
||||
} from "./utils/index.js";
|
||||
import isVueSfcWithTypescriptScript from "./utils/is-vue-sfc-with-typescript-script.js";
|
||||
import getNodeContent from "./get-node-content.js";
|
||||
|
||||
async function printEmbeddedAttributeValue(node, htmlTextToDoc, options) {
|
||||
async function printEmbeddedAttributeValue(path, htmlTextToDoc, options) {
|
||||
const { node } = path;
|
||||
const isKeyMatched = (patterns) =>
|
||||
new RegExp(patterns.join("|")).test(node.fullName);
|
||||
const getValue = () => unescapeQuoteEntities(node.value);
|
||||
|
||||
let shouldHug = false;
|
||||
|
||||
@@ -77,40 +78,43 @@ async function printEmbeddedAttributeValue(node, htmlTextToDoc, options) {
|
||||
__embeddedInHtml: true,
|
||||
...opts,
|
||||
});
|
||||
const value = getUnescapedAttributeValue(node);
|
||||
|
||||
if (
|
||||
node.fullName === "srcset" &&
|
||||
(node.parent.fullName === "img" || node.parent.fullName === "source")
|
||||
) {
|
||||
return printExpand(printImgSrcset(getValue()));
|
||||
return printExpand(printImgSrcset(value));
|
||||
}
|
||||
|
||||
if (node.fullName === "class" && !options.parentParser) {
|
||||
const value = getValue();
|
||||
if (!value.includes("{{")) {
|
||||
return printClassNames(value);
|
||||
}
|
||||
if (
|
||||
node.fullName === "class" &&
|
||||
!options.parentParser &&
|
||||
!value.includes("{{")
|
||||
) {
|
||||
return printClassNames(value);
|
||||
}
|
||||
|
||||
if (node.fullName === "style" && !options.parentParser) {
|
||||
const value = getValue();
|
||||
if (!value.includes("{{")) {
|
||||
return printExpand(
|
||||
await attributeTextToDoc(value, {
|
||||
parser: "css",
|
||||
__isHTMLStyleAttribute: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
if (
|
||||
node.fullName === "style" &&
|
||||
!options.parentParser &&
|
||||
!value.includes("{{")
|
||||
) {
|
||||
return printExpand(
|
||||
await attributeTextToDoc(value, {
|
||||
parser: "css",
|
||||
__isHTMLStyleAttribute: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (options.parser === "vue") {
|
||||
if (node.fullName === "v-for") {
|
||||
return printVueFor(getValue(), attributeTextToDoc, options);
|
||||
return printVueFor(path, attributeTextToDoc, options);
|
||||
}
|
||||
|
||||
if (isVueSlotAttribute(node) || isVueSfcBindingsAttribute(node, options)) {
|
||||
return printVueBindings(getValue(), attributeTextToDoc, options);
|
||||
return printVueBindings(path, attributeTextToDoc, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,12 +135,11 @@ async function printEmbeddedAttributeValue(node, htmlTextToDoc, options) {
|
||||
const jsExpressionBindingPatterns = ["^v-"];
|
||||
|
||||
if (isKeyMatched(vueEventBindingPatterns)) {
|
||||
const value = getValue();
|
||||
const parser = isVueEventBindingExpression(value)
|
||||
? options.__should_parse_vue_template_with_ts
|
||||
? isVueSfcWithTypescriptScript(path, options)
|
||||
? "__ts_expression"
|
||||
: "__js_expression"
|
||||
: options.__should_parse_vue_template_with_ts
|
||||
: isVueSfcWithTypescriptScript(path, options)
|
||||
? "__vue_ts_event_binding"
|
||||
: "__vue_event_binding";
|
||||
return printMaybeHug(await attributeTextToDoc(value, { parser }));
|
||||
@@ -144,8 +147,8 @@ async function printEmbeddedAttributeValue(node, htmlTextToDoc, options) {
|
||||
|
||||
if (isKeyMatched(vueExpressionBindingPatterns)) {
|
||||
return printMaybeHug(
|
||||
await attributeTextToDoc(getValue(), {
|
||||
parser: options.__should_parse_vue_template_with_ts
|
||||
await attributeTextToDoc(value, {
|
||||
parser: isVueSfcWithTypescriptScript(path, options)
|
||||
? "__vue_ts_expression"
|
||||
: "__vue_expression",
|
||||
})
|
||||
@@ -154,8 +157,8 @@ async function printEmbeddedAttributeValue(node, htmlTextToDoc, options) {
|
||||
|
||||
if (isKeyMatched(jsExpressionBindingPatterns)) {
|
||||
return printMaybeHug(
|
||||
await attributeTextToDoc(getValue(), {
|
||||
parser: options.__should_parse_vue_template_with_ts
|
||||
await attributeTextToDoc(value, {
|
||||
parser: isVueSfcWithTypescriptScript(path, options)
|
||||
? "__ts_expression"
|
||||
: "__js_expression",
|
||||
})
|
||||
@@ -196,33 +199,29 @@ async function printEmbeddedAttributeValue(node, htmlTextToDoc, options) {
|
||||
const ngI18nPatterns = ["^i18n(-.+)?$"];
|
||||
|
||||
if (isKeyMatched(ngStatementBindingPatterns)) {
|
||||
return printMaybeHug(
|
||||
await ngTextToDoc(getValue(), { parser: "__ng_action" })
|
||||
);
|
||||
return printMaybeHug(await ngTextToDoc(value, { parser: "__ng_action" }));
|
||||
}
|
||||
|
||||
if (isKeyMatched(ngExpressionBindingPatterns)) {
|
||||
return printMaybeHug(
|
||||
await ngTextToDoc(getValue(), { parser: "__ng_binding" })
|
||||
await ngTextToDoc(value, { parser: "__ng_binding" })
|
||||
);
|
||||
}
|
||||
|
||||
if (isKeyMatched(ngI18nPatterns)) {
|
||||
const value = getValue().trim();
|
||||
return printExpand(
|
||||
fill(getTextValueParts(node, value)),
|
||||
fill(getTextValueParts(node, value.trim())),
|
||||
!value.includes("@@")
|
||||
);
|
||||
}
|
||||
|
||||
if (isKeyMatched(ngDirectiveBindingPatterns)) {
|
||||
return printMaybeHug(
|
||||
await ngTextToDoc(getValue(), { parser: "__ng_directive" })
|
||||
await ngTextToDoc(value, { parser: "__ng_directive" })
|
||||
);
|
||||
}
|
||||
|
||||
const interpolationRegex = /{{(.+?)}}/s;
|
||||
const value = getValue();
|
||||
if (interpolationRegex.test(value)) {
|
||||
const parts = [];
|
||||
for (const [index, part] of value.split(interpolationRegex).entries()) {
|
||||
@@ -341,10 +340,12 @@ function embed(path, options) {
|
||||
textToDocOptions.parser = "__ng_interpolation";
|
||||
textToDocOptions.trailingComma = "none";
|
||||
} else if (options.parser === "vue") {
|
||||
textToDocOptions.parser =
|
||||
options.__should_parse_vue_template_with_ts
|
||||
? "__vue_ts_expression"
|
||||
: "__vue_expression";
|
||||
textToDocOptions.parser = isVueSfcWithTypescriptScript(
|
||||
path,
|
||||
options
|
||||
)
|
||||
? "__vue_ts_expression"
|
||||
: "__vue_expression";
|
||||
} else {
|
||||
textToDocOptions.parser = "__js_expression";
|
||||
}
|
||||
@@ -394,7 +395,7 @@ function embed(path, options) {
|
||||
|
||||
return async (textToDoc) => {
|
||||
const embeddedAttributeValueDoc = await printEmbeddedAttributeValue(
|
||||
node,
|
||||
path,
|
||||
(code, opts) =>
|
||||
// strictly prefer single quote to avoid unnecessary html entity escape
|
||||
textToDoc(code, {
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
isLeadingSpaceSensitiveNode,
|
||||
isTrailingSpaceSensitiveNode,
|
||||
isWhitespaceSensitiveNode,
|
||||
isVueScriptTag,
|
||||
} from "./utils/index.js";
|
||||
|
||||
const PREPROCESS_PIPELINE = [
|
||||
@@ -23,7 +22,6 @@ const PREPROCESS_PIPELINE = [
|
||||
addHasHtmComponentClosingTag,
|
||||
addIsSpaceSensitive,
|
||||
mergeSimpleElementIntoText,
|
||||
markTsScript,
|
||||
];
|
||||
|
||||
function preprocess(ast, options) {
|
||||
@@ -403,14 +401,4 @@ function addIsSpaceSensitive(ast, options) {
|
||||
});
|
||||
}
|
||||
|
||||
function markTsScript(ast, options) {
|
||||
options.__should_parse_vue_template_with_ts =
|
||||
options.parser === "vue" &&
|
||||
ast.children.some(
|
||||
(child) =>
|
||||
isVueScriptTag(child, options) &&
|
||||
["ts", "typescript"].includes(child.attrMap.lang)
|
||||
);
|
||||
}
|
||||
|
||||
export default preprocess;
|
||||
@@ -1,4 +1,7 @@
|
||||
import { group } from "../document/builders.js";
|
||||
import { getUnescapedAttributeValue } from "./utils/index.js";
|
||||
import isVueSfcWithTypescriptScript from "./utils/is-vue-sfc-with-typescript-script.js";
|
||||
|
||||
/**
|
||||
* @typedef {import("../document/builders.js").Doc} Doc
|
||||
*/
|
||||
@@ -9,14 +12,14 @@ import { group } from "../document/builders.js";
|
||||
* v-for="(..., ...) in ..."
|
||||
* v-for="(..., ...) of ..."
|
||||
*
|
||||
* @param {*} value
|
||||
* @param {(code: string, opts: *) => Doc} attributeTextToDoc
|
||||
* @param {*} options
|
||||
* @returns {Promise<Doc>}
|
||||
*/
|
||||
async function printVueFor(value, attributeTextToDoc, options) {
|
||||
async function printVueFor(path, attributeTextToDoc, options) {
|
||||
const value = getUnescapedAttributeValue(path.node);
|
||||
const { left, operator, right } = parseVueFor(value);
|
||||
const parseWithTs = options.__should_parse_vue_template_with_ts;
|
||||
const parseWithTs = isVueSfcWithTypescriptScript(path, options);
|
||||
return [
|
||||
group(
|
||||
await attributeTextToDoc(`function _(${left}) {}`, {
|
||||
@@ -80,14 +83,14 @@ function parseVueFor(value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} value
|
||||
* @param {(code: string, opts: *) => Doc} attributeTextToDoc
|
||||
* @param {*} options
|
||||
* @returns {Doc}
|
||||
*/
|
||||
function printVueBindings(value, attributeTextToDoc, options) {
|
||||
function printVueBindings(path, attributeTextToDoc, options) {
|
||||
const value = getUnescapedAttributeValue(path.node);
|
||||
return attributeTextToDoc(`function _(${value}) {}`, {
|
||||
parser: options.__should_parse_vue_template_with_ts ? "babel-ts" : "babel",
|
||||
parser: isVueSfcWithTypescriptScript(path, options) ? "babel-ts" : "babel",
|
||||
__isVueBindings: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -551,6 +551,10 @@ function unescapeQuoteEntities(text) {
|
||||
return text.replaceAll("'", "'").replaceAll(""", '"');
|
||||
}
|
||||
|
||||
function getUnescapedAttributeValue(node) {
|
||||
return unescapeQuoteEntities(node.value);
|
||||
}
|
||||
|
||||
// top-level elements (excluding <template>, <style> and <script>) in Vue SFC are considered custom block
|
||||
// See https://vue-loader.vuejs.org/spec.html for detail
|
||||
const vueRootElementsSet = new Set(["template", "style", "script"]);
|
||||
@@ -650,4 +654,5 @@ export {
|
||||
unescapeQuoteEntities,
|
||||
getTextValueParts,
|
||||
htmlWhitespaceUtils,
|
||||
getUnescapedAttributeValue,
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import { isVueScriptTag } from "./index.js";
|
||||
|
||||
const cache = new WeakMap();
|
||||
function isVueSfcWithTypescriptScript(path, options) {
|
||||
const { root } = path;
|
||||
if (!cache.has(root)) {
|
||||
cache.set(
|
||||
root,
|
||||
root.children.some(
|
||||
(child) =>
|
||||
isVueScriptTag(child, options) &&
|
||||
["ts", "typescript"].includes(child.attrMap.lang)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return cache.get(root);
|
||||
}
|
||||
|
||||
export default isVueSfcWithTypescriptScript;
|
||||
Reference in new issue
Block a user