prettier-plugin-marko
Advanced tools
+238
-277
@@ -774,56 +774,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| print(path, opts, print) { | ||
| const { node } = path; | ||
| switch (node.type) { | ||
| case NodeType.AttrArgs: | ||
| case NodeType.AttrMethod: | ||
| case NodeType.AttrNamed: | ||
| case NodeType.AttrSpread: | ||
| case NodeType.Class: | ||
| case NodeType.Export: | ||
| case NodeType.Import: | ||
| case NodeType.OpenTagName: | ||
| case NodeType.Placeholder: | ||
| case NodeType.Scriptlet: | ||
| case NodeType.ShorthandClassName: | ||
| case NodeType.ShorthandId: | ||
| case NodeType.Static: | ||
| case NodeType.Style: | ||
| case NodeType.TagArgs: | ||
| case NodeType.TagParams: | ||
| case NodeType.TagTypeArgs: | ||
| case NodeType.TagTypeParams: | ||
| case NodeType.TagVar: return printExact(path, opts, print); | ||
| case NodeType.CDATA: return printCDATA(path, opts, print); | ||
| case NodeType.Comment: return printComment(path, opts, print); | ||
| case NodeType.Doctype: return printDoctype(path, opts, print); | ||
| case NodeType.Declaration: return printDeclaration(path, opts, print); | ||
| case NodeType.Program: return printProgram(path, opts, print); | ||
| case NodeType.Tag: | ||
| case NodeType.AttrTag: return printTag(path, opts, print); | ||
| case NodeType.Text: return printText(path, opts, print); | ||
| default: throw new Error(`Unknown node type in Marko template: ${NodeType[node.type] || node.type}`); | ||
| } | ||
| const { type } = path.node; | ||
| const handler = printHandlers[type]; | ||
| if (handler) return handler(path, opts, print); | ||
| /* c8 ignore next */ | ||
| throw new Error(`Unknown node type in Marko template: ${NodeType[type] || type}`); | ||
| }, | ||
| embed(path, opts) { | ||
| switch (path.node?.type) { | ||
| case NodeType.AttrNamed: return embedAttrNamed; | ||
| case NodeType.AttrSpread: return embedAttrSpread; | ||
| case NodeType.Class: return embedClass; | ||
| case NodeType.Export: return embedExport; | ||
| case NodeType.Import: return embedImport; | ||
| case NodeType.OpenTagName: return embedOpenTagName; | ||
| case NodeType.Placeholder: return embedPlaceholder; | ||
| case NodeType.Scriptlet: return embedScriptlet; | ||
| case NodeType.ShorthandClassName: return embedShorthandClassName; | ||
| case NodeType.ShorthandId: return embedShorthandId; | ||
| case NodeType.Static: return embedStatic; | ||
| case NodeType.Style: return embedStyle; | ||
| case NodeType.Tag: return embedTag(path, opts); | ||
| case NodeType.TagArgs: return embedTagArgs; | ||
| case NodeType.TagParams: return embedTagParams; | ||
| case NodeType.TagTypeArgs: return embedTagTypeArgs; | ||
| case NodeType.TagTypeParams: return embedTagTypeParams; | ||
| case NodeType.TagVar: return embedTagVar; | ||
| } | ||
| return null; | ||
| embed(path) { | ||
| return embedHandlers[path.node.type] ?? null; | ||
| }, | ||
@@ -834,47 +788,208 @@ getVisitorKeys(node) { | ||
| } }; | ||
| const printProgram = (path, opts, print) => { | ||
| const body = printBody(path, opts, print); | ||
| const lastStatic = path.node.static.length - (body ? 0 : 1); | ||
| let programDoc = path.map((child, i) => i !== lastStatic && hasExplicitLine(child, opts) ? [child.call(print), b.hardline] : child.call(print), "static"); | ||
| if (body) if (body.inline) programDoc.push(wrapConciseText(body.content)); | ||
| else programDoc = [...programDoc, ...body.content]; | ||
| return [b.join(b.hardline, programDoc), b.hardline]; | ||
| const printHandlers = { | ||
| [NodeType.AttrArgs]: printExact, | ||
| [NodeType.AttrMethod]: printExact, | ||
| [NodeType.AttrNamed]: printExact, | ||
| [NodeType.AttrSpread]: printExact, | ||
| [NodeType.Class]: printExact, | ||
| [NodeType.Export]: printExact, | ||
| [NodeType.Import]: printExact, | ||
| [NodeType.OpenTagName]: printExact, | ||
| [NodeType.Placeholder]: printExact, | ||
| [NodeType.Scriptlet]: printExact, | ||
| [NodeType.ShorthandClassName]: printExact, | ||
| [NodeType.ShorthandId]: printExact, | ||
| [NodeType.Static]: printExact, | ||
| [NodeType.Style]: printExact, | ||
| [NodeType.TagArgs]: printExact, | ||
| [NodeType.TagParams]: printExact, | ||
| [NodeType.TagTypeArgs]: printExact, | ||
| [NodeType.TagTypeParams]: printExact, | ||
| [NodeType.TagVar]: printExact, | ||
| [NodeType.Tag]: printTag, | ||
| [NodeType.AttrTag]: printTag, | ||
| [NodeType.CDATA]: (path, opts) => `<![CDATA[${read(path.node.value, opts)}]]>`, | ||
| [NodeType.Comment]: (path, opts) => { | ||
| const { node } = path; | ||
| const code = read(node, opts); | ||
| if (node.block) { | ||
| if (code.includes("\n")) { | ||
| const lines = code.split("\n"); | ||
| const len = lines.length; | ||
| let indent = Infinity; | ||
| for (let i = 1; i < len; i++) { | ||
| const match = lines[i].match(/^(\s+)/); | ||
| if (match) indent = Math.min(indent, match[1].length); | ||
| else { | ||
| indent = 0; | ||
| break; | ||
| } | ||
| } | ||
| const parts = [lines[0]]; | ||
| for (let i = 1; i < len; i++) parts.push(b.hardline, indent ? lines[i].slice(indent) : lines[i]); | ||
| return parts; | ||
| } | ||
| return code; | ||
| } | ||
| return b.lineSuffix(code); | ||
| }, | ||
| [NodeType.Doctype]: (path, opts) => `<!${read(path.node.value, opts).replace(/\s+/g, " ").trim()}>`, | ||
| [NodeType.Declaration]: (path, opts) => `<?${read(path.node.value, opts).trim()}?>`, | ||
| [NodeType.Program]: (path, opts, print) => { | ||
| const body = printBody(path, opts, print); | ||
| const lastStatic = path.node.static.length - (body ? 0 : 1); | ||
| let programDoc = path.map((child, i) => i !== lastStatic && hasExplicitLine(child, opts) ? [child.call(print), b.hardline] : child.call(print), "static"); | ||
| if (body) if (body.inline) programDoc.push(wrapConciseText(body.content)); | ||
| else programDoc = [...programDoc, ...body.content]; | ||
| return [b.join(b.hardline, programDoc), b.hardline]; | ||
| }, | ||
| [NodeType.Text]: (path, opts) => { | ||
| const text = read(path.node, opts).replace(/\\/g, "\\\\"); | ||
| return /^\$!?{/.test(text) ? "\\" + text : text; | ||
| } | ||
| }; | ||
| const printDoctype = (path, opts) => { | ||
| return `<!${read(path.node.value, opts).replace(/\s+/g, " ").trim()}>`; | ||
| }; | ||
| const printDeclaration = (path, opts) => { | ||
| return `<?${read(path.node.value, opts).trim()}?>`; | ||
| }; | ||
| const printCDATA = (path, opts) => { | ||
| return `<![CDATA[${read(path.node.value, opts)}]]>`; | ||
| }; | ||
| const printComment = (path, opts) => { | ||
| const { node } = path; | ||
| const code = read(node, opts); | ||
| if (node.block) { | ||
| if (code.includes("\n")) { | ||
| const lines = code.split("\n"); | ||
| const len = lines.length; | ||
| let indent = Infinity; | ||
| for (let i = 1; i < len; i++) { | ||
| const match = lines[i].match(/^(\s+)/); | ||
| if (match) indent = Math.min(indent, match[1].length); | ||
| else { | ||
| indent = 0; | ||
| break; | ||
| const embedHandlers = { | ||
| [NodeType.Class]: (toDoc, _print, path, opts) => toDoc(read(path.node, opts), exprParse), | ||
| [NodeType.Import]: (toDoc, _print, path, opts) => toDoc(read(path.node, opts), stmtParse), | ||
| [NodeType.Export]: (toDoc, _print, path, opts) => toDoc(read(path.node, opts), stmtParse), | ||
| [NodeType.Style]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| const code = read(node.value, opts).trim(); | ||
| const parser = getParserFromExt(node.ext?.slice(node.ext.lastIndexOf(".")) || ".css"); | ||
| if (parser) return b.group([ | ||
| `style${node.ext || ""} {`, | ||
| b.indent([b.line, await toDoc(code, { parser })]), | ||
| b.line, | ||
| "}" | ||
| ]); | ||
| }, | ||
| [NodeType.Static]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| const code = opts._markoParsed.code.slice(node.start + node.target.length + 1, node.end).replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim(); | ||
| return code ? [`${node.target} `, withBlockIfNeeded(await toDoc(code, stmtParse))] : []; | ||
| }, | ||
| [NodeType.Scriptlet]: async (toDoc, _print, path, opts) => { | ||
| const code = read(path.node.value, opts).replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim(); | ||
| return code ? [ | ||
| b.breakParent, | ||
| "$ ", | ||
| withBlockIfNeeded(await toDoc(code, stmtParse)) | ||
| ] : []; | ||
| }, | ||
| [NodeType.OpenTagName]: (toDoc, _print, path, opts) => templateToDoc(toDoc, path, opts), | ||
| [NodeType.Placeholder]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| const code = read(node.value, opts); | ||
| if (code === "\" \"" || code === "' '") return getVisibleSpace(opts); | ||
| return b.group([ | ||
| node.escape ? "${" : "$!{", | ||
| b.indent([b.softline, await toDoc(code, exprParse)]), | ||
| b.softline, | ||
| "}" | ||
| ]); | ||
| }, | ||
| [NodeType.TagArgs]: (toDoc, _print, path, opts) => argsToDoc(path.node, opts, toDoc), | ||
| [NodeType.AttrNamed]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| const name = read(node.name, opts); | ||
| if (!(node.args || node.value)) return name; | ||
| const attrDoc = [name]; | ||
| if (node.args && !isEmpty(node.args.value, opts)) { | ||
| const argsDoc = await argsToDoc(node.args, opts, toDoc); | ||
| if (argsDoc) attrDoc.push(argsDoc); | ||
| else return unexpectedDoc(opts, node); | ||
| } | ||
| if (node.value) if (node.value.type === NodeType.AttrMethod) { | ||
| const attrMethodDoc = await toDoc(`function${read(node.value, opts)}`, exprParse); | ||
| if (Array.isArray(attrMethodDoc) && attrMethodDoc.length && typeof attrMethodDoc[0] === "string") { | ||
| attrMethodDoc[0] = attrMethodDoc[0].replace(/^function\s*/, ""); | ||
| attrDoc.push(attrMethodDoc); | ||
| } else return unexpectedDoc(opts, node); | ||
| } else attrDoc.push(node.value.bound ? ":=" : "=", withParensIfNeeded(await toDoc(read(node.value.value, opts), exprParse), isConcise(opts))); | ||
| return b.group(attrDoc); | ||
| }, | ||
| [NodeType.AttrSpread]: async (toDoc, _print, path, opts) => { | ||
| return b.group(["...", withParensIfNeeded(await toDoc(read(path.node.value, opts), exprParse), isConcise(opts))]); | ||
| }, | ||
| [NodeType.ShorthandId]: async (toDoc, _print, path, opts) => ["#", await templateToDoc(toDoc, path, opts)], | ||
| [NodeType.ShorthandClassName]: async (toDoc, _print, path, opts) => [".", await templateToDoc(toDoc, path, opts)], | ||
| [NodeType.Tag]: async (toDoc, print, path, opts) => { | ||
| const parser = getTagParser(path.node, opts); | ||
| if (parser === void 0) return void 0; | ||
| return printTag(path, opts, print, { | ||
| inline: true, | ||
| preserve: parser === false, | ||
| content: await getFormattedBody(path, parser, toDoc, print, opts) | ||
| }); | ||
| }, | ||
| [NodeType.TagVar]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| let doc = await toDoc(`var ${read(node.value, opts).trim()}=_`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length === 1) doc = doc[0]; | ||
| if (typeof doc === "object" && !Array.isArray(doc) && doc.type === "group") doc = doc.contents; | ||
| if (Array.isArray(doc) && doc.length > 1) { | ||
| const varPart = doc[1]; | ||
| if (typeof varPart === "object" && "type" in varPart && varPart.type === "group" && Array.isArray(varPart.contents)) { | ||
| const varContents = varPart.contents; | ||
| for (let i = varContents.length; i--;) { | ||
| const item = varContents[i]; | ||
| if (typeof item === "string") { | ||
| const match = /\s*=\s*$/.exec(item); | ||
| if (match) { | ||
| varContents[i] = item.slice(0, -match[0].length); | ||
| varContents.length = i + 1; | ||
| return ["/", varContents]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| const parts = [lines[0]]; | ||
| for (let i = 1; i < len; i++) parts.push(b.hardline, indent ? lines[i].slice(indent) : lines[i]); | ||
| return parts; | ||
| } | ||
| return code; | ||
| return unexpectedDoc(opts, node); | ||
| /* c8 ignore stop */ | ||
| }, | ||
| [NodeType.TagTypeArgs]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| if (isEmpty(node.value, opts)) return ""; | ||
| const doc = await toDoc(`_<${read(node.value, opts).trim()}>`, exprParse); | ||
| if (typeof doc === "string") return doc.replace(/^_/, ""); | ||
| if (Array.isArray(doc) && typeof doc[0] === "string") { | ||
| doc[0] = doc[0].replace(/^_/, ""); | ||
| return doc; | ||
| } | ||
| /* c8 ignore next */ | ||
| return unexpectedDoc(opts, node); | ||
| }, | ||
| [NodeType.TagParams]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| if (isEmpty(node.value, opts)) return ""; | ||
| const doc = await toDoc(`function _(${read(node.value, opts).trim()}){}`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length > 1) { | ||
| const paramsGroup = doc[1]; | ||
| if (paramsGroup && typeof paramsGroup === "object" && "type" in paramsGroup && paramsGroup.type === "group" && Array.isArray(paramsGroup.contents)) { | ||
| const paramsContents = [...paramsGroup.contents]; | ||
| const first = paramsContents[0]; | ||
| const last = paramsContents[paramsContents.length - 1]; | ||
| if (typeof first === "string" && typeof last === "string") { | ||
| paramsContents[0] = first.replace(/^\(/, "|"); | ||
| paramsContents[paramsContents.length - 1] = last.replace(/\)$/, "|"); | ||
| } | ||
| return b.group(paramsContents); | ||
| } | ||
| } | ||
| /* c8 ignore next */ | ||
| return unexpectedDoc(opts, node); | ||
| }, | ||
| [NodeType.TagTypeParams]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| if (isEmpty(node.parent.params?.value, opts) || isEmpty(node.value, opts)) return ""; | ||
| const doc = await toDoc(`function _<${read(node.value, opts).trim()}>(){}`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length > 1) return doc[1]; | ||
| /* c8 ignore next */ | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return b.lineSuffix(code); | ||
| }; | ||
| const printTag = ((path, opts, print, body = printBody(path, opts, print)) => { | ||
| function printTag(path, opts, print, body = printBody(path, opts, print)) { | ||
| return (isConcise(opts) ? printConciseTag : printHTMLTag)(path, opts, print, body); | ||
| }); | ||
| const printHTMLTag = ((path, opts, print, body) => { | ||
| } | ||
| function printHTMLTag(path, opts, print, body) { | ||
| const { node } = path; | ||
@@ -909,4 +1024,4 @@ const openTagDoc = ["<", printTagBeforeAttrs(path, opts, print)]; | ||
| return b.group(openTagDoc); | ||
| }); | ||
| const printConciseTag = ((path, opts, print, body) => { | ||
| } | ||
| function printConciseTag(path, opts, print, body) { | ||
| const { node } = path; | ||
@@ -930,14 +1045,14 @@ const tagDoc = [printTagBeforeAttrs(path, opts, print)]; | ||
| return b.group(tagDoc); | ||
| }); | ||
| const printTagBeforeAttrs = (path, _opts, print) => { | ||
| } | ||
| function printTagBeforeAttrs(path, opts, print) { | ||
| const { node } = path; | ||
| const name = path.call(print, "name"); | ||
| const doc = [name]; | ||
| if (pathHas(path, "typeArgs")) doc.push(path.call(print, "typeArgs")); | ||
| if (pathHas(path, "typeArgs") && !isEmpty(path.node.typeArgs.value, opts)) doc.push(path.call(print, "typeArgs")); | ||
| if (pathHas(path, "shorthandId")) doc.push(path.call(print, "shorthandId")); | ||
| if (pathHas(path, "shorthandClassNames")) doc.push(path.map(print, "shorthandClassNames")); | ||
| if (pathHas(path, "args")) doc.push(path.call(print, "args")); | ||
| if (pathHas(path, "args") && !isEmpty(path.node.args.value, opts)) doc.push(path.call(print, "args")); | ||
| if (pathHas(path, "var")) doc.push(path.call(print, "var")); | ||
| if (pathHas(path, "params")) { | ||
| if (pathHas(path, "typeParams")) { | ||
| if (pathHas(path, "params") && !isEmpty(path.node.params.value, opts)) { | ||
| if (pathHas(path, "typeParams") && !isEmpty(path.node.typeParams.value, opts)) { | ||
| if (!(node.typeArgs || node.args || node.var)) doc.push(" "); | ||
@@ -949,4 +1064,4 @@ doc.push(path.call(print, "typeParams")); | ||
| return doc.length === 1 ? name : doc; | ||
| }; | ||
| const printBody = (path, opts, print) => { | ||
| } | ||
| function printBody(path, opts, print) { | ||
| const { node } = path; | ||
@@ -963,3 +1078,2 @@ if (!node.body) return; | ||
| const childDoc = child.call(print); | ||
| if (!childDoc) return; | ||
| content ||= []; | ||
@@ -1031,7 +1145,3 @@ if (isInline(child.node)) { | ||
| if (typeof childDoc === "string" && isVisibleSpace(childDoc)) { | ||
| if (endsWithLine(inline)) { | ||
| const last = inline.length - 1; | ||
| if (inline[last] === b.softline) inline[last] = b.line; | ||
| return; | ||
| } | ||
| if (endsWithLine(inline)) return; | ||
| childDoc = b.line; | ||
@@ -1074,162 +1184,7 @@ } | ||
| } | ||
| }; | ||
| const printText = (path, opts) => { | ||
| const text = read(path.node, opts).replace(/\\/g, "\\\\"); | ||
| if (/^\$!?{/.test(text)) return "\\" + text; | ||
| return text; | ||
| }; | ||
| const printExact = (path, opts) => read(path.node, opts); | ||
| const embedClass = (toDoc, _print, path, opts) => toDoc(read(path.node, opts), exprParse); | ||
| const embedImport = (toDoc, _print, path, opts) => toDoc(read(path.node, opts), stmtParse); | ||
| const embedExport = (toDoc, _print, path, opts) => toDoc(read(path.node, opts), stmtParse); | ||
| const embedStyle = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| const parser = getParserFromExt(node.ext?.slice(node.ext.lastIndexOf(".")) || ".css"); | ||
| if (parser) return b.group([ | ||
| `style${node.ext || ""} {`, | ||
| b.indent([b.line, await toDoc(code, { parser })]), | ||
| b.line, | ||
| "}" | ||
| ]); | ||
| }; | ||
| const embedStatic = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = opts._markoParsed.code.slice(node.start + node.target.length + 1, node.end).replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim(); | ||
| return code ? [`${node.target} `, withBlockIfNeeded(await toDoc(code, stmtParse))] : []; | ||
| }; | ||
| const embedScriptlet = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim(); | ||
| return code ? [ | ||
| b.breakParent, | ||
| "$ ", | ||
| withBlockIfNeeded(await toDoc(code, stmtParse)) | ||
| ] : []; | ||
| }; | ||
| const embedOpenTagName = async (toDoc, _print, path, opts) => embedTemplate(toDoc, _print, path, opts); | ||
| const embedPlaceholder = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts); | ||
| if (code === "\" \"" || code === "' '") return getVisibleSpace(opts); | ||
| return b.group([ | ||
| node.escape ? "${" : "$!{", | ||
| b.indent([b.softline, await toDoc(code, exprParse)]), | ||
| b.softline, | ||
| "}" | ||
| ]); | ||
| }; | ||
| const embedTagArgs = (toDoc, _print, path, opts) => { | ||
| return argsToDoc(path.node, opts, toDoc); | ||
| }; | ||
| const embedAttrNamed = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const name = read(node.name, opts); | ||
| if (!(node.args || node.value)) return name; | ||
| const attrDoc = [name]; | ||
| if (node.args) { | ||
| const argsDoc = await argsToDoc(node.args, opts, toDoc); | ||
| if (argsDoc) attrDoc.push(argsDoc); | ||
| else return unexpectedDoc(opts, node); | ||
| } | ||
| if (node.value) if (node.value.type === NodeType.AttrMethod) { | ||
| const attrMethodDoc = await toDoc(`function${read(node.value, opts)}`, exprParse); | ||
| if (Array.isArray(attrMethodDoc) && attrMethodDoc.length && typeof attrMethodDoc[0] === "string") { | ||
| attrMethodDoc[0] = attrMethodDoc[0].replace(/^function\s*/, ""); | ||
| attrDoc.push(attrMethodDoc); | ||
| } else return unexpectedDoc(opts, node); | ||
| } else attrDoc.push(node.value.bound ? ":=" : "=", withParensIfNeeded(await toDoc(read(node.value.value, opts), exprParse), isConcise(opts))); | ||
| return b.group(attrDoc); | ||
| }; | ||
| const embedAttrSpread = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| return b.group(["...", withParensIfNeeded(await toDoc(read(node.value, opts), exprParse), isConcise(opts))]); | ||
| }; | ||
| const embedShorthandId = async (toDoc, print, path, opts) => ["#", await embedTemplate(toDoc, print, path, opts)]; | ||
| const embedShorthandClassName = async (toDoc, print, path, opts) => [".", await embedTemplate(toDoc, print, path, opts)]; | ||
| const embedTag = (path, opts) => { | ||
| const tag = path.node; | ||
| const parser = getTagParser(tag, opts); | ||
| if (parser === void 0) return null; | ||
| return async (toDoc, print, path, opts) => printTag(path, opts, print, { | ||
| inline: true, | ||
| preserve: parser === false, | ||
| content: await getFormattedBody(path, parser, toDoc, print, opts) | ||
| }); | ||
| }; | ||
| const embedTagVar = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| let doc = await toDoc(`var ${code}=_`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length === 1) doc = doc[0]; | ||
| if (typeof doc === "object" && !Array.isArray(doc) && doc.type === "group") doc = doc.contents; | ||
| if (Array.isArray(doc) && doc.length > 1) { | ||
| const varPart = doc[1]; | ||
| if (typeof varPart === "object" && "type" in varPart && varPart.type === "group" && Array.isArray(varPart.contents)) { | ||
| const varContents = varPart.contents; | ||
| for (let i = varContents.length; i--;) { | ||
| const item = varContents[i]; | ||
| if (typeof item === "string") { | ||
| const match = /\s*=\s*$/.exec(item); | ||
| if (match) { | ||
| varContents[i] = item.slice(0, -match[0].length); | ||
| varContents.length = i + 1; | ||
| return ["/", varContents]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return []; | ||
| }; | ||
| const embedTagTypeArgs = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| const doc = await toDoc(`_<${code}>`, exprParse); | ||
| if (typeof doc === "string") return doc.replace(/^_/, ""); | ||
| if (Array.isArray(doc) && typeof doc[0] === "string") { | ||
| doc[0] = doc[0].replace(/^_/, ""); | ||
| return doc; | ||
| } | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return []; | ||
| }; | ||
| const embedTagParams = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| const doc = await toDoc(`function _(${code}){}`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length > 1) { | ||
| const paramsGroup = doc[1]; | ||
| if (paramsGroup && typeof paramsGroup === "object" && "type" in paramsGroup && paramsGroup.type === "group" && Array.isArray(paramsGroup.contents)) { | ||
| const paramsContents = [...paramsGroup.contents]; | ||
| const first = paramsContents[0]; | ||
| const last = paramsContents[paramsContents.length - 1]; | ||
| if (typeof first === "string" && typeof last === "string") { | ||
| paramsContents[0] = first.replace(/^\(/, "|"); | ||
| paramsContents[paramsContents.length - 1] = last.replace(/\)$/, "|"); | ||
| } | ||
| return b.group(paramsContents); | ||
| } | ||
| } | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return []; | ||
| }; | ||
| const embedTagTypeParams = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| const doc = await toDoc(`function _<${code}>(){}`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length > 1) return doc[1]; | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return []; | ||
| }; | ||
| const embedTemplate = async (toDoc, _print, path, opts) => { | ||
| } | ||
| function printExact(path, opts) { | ||
| return read(path.node, opts); | ||
| } | ||
| async function templateToDoc(toDoc, path, opts) { | ||
| const { expressions, quasis } = path.node; | ||
@@ -1252,14 +1207,12 @@ const first = read(quasis[0], opts); | ||
| return shorthandDoc; | ||
| }; | ||
| } | ||
| async function argsToDoc(node, opts, toDoc) { | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| const doc = await toDoc(`_(${code})`, exprParse); | ||
| if (Array.isArray(doc) && doc.length && typeof doc[0] === "string") { | ||
| doc[0] = doc[0].replace(/^_/, ""); | ||
| return doc; | ||
| } | ||
| return unexpectedDoc(opts, node); | ||
| if (isEmpty(node.value, opts)) return ""; | ||
| const doc = await toDoc(`_(${read(node.value, opts).trim()})`, exprParse); | ||
| if (Array.isArray(doc) && doc.length && typeof doc[0] === "string") { | ||
| doc[0] = doc[0].replace(/^_/, ""); | ||
| return doc; | ||
| } | ||
| return []; | ||
| /* c8 ignore next */ | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
@@ -1361,5 +1314,12 @@ function wrapConciseText(doc) { | ||
| } | ||
| const nonWhitespaceReg = /\S/g; | ||
| function isEmpty(range, opts) { | ||
| if (!range || range.start === range.end) return true; | ||
| nonWhitespaceReg.lastIndex = range.start; | ||
| return !(nonWhitespaceReg.test(opts._markoParsed.code) && nonWhitespaceReg.lastIndex <= range.end); | ||
| } | ||
| function pathHas(path, key) { | ||
| return !!path.node[key]; | ||
| } | ||
| /* c8 ignore start */ | ||
| function unexpectedDoc(opts, node) { | ||
@@ -1370,2 +1330,3 @@ const parsed = opts._markoParsed; | ||
| } | ||
| /* c8 ignore stop */ | ||
| exports.languages = languages; | ||
@@ -1372,0 +1333,0 @@ exports.options = options; |
+238
-278
@@ -1,2 +0,1 @@ | ||
| import "node:module"; | ||
| import { doc } from "prettier"; | ||
@@ -774,56 +773,10 @@ import { TagType, TagType as TagType$1, Validity, createParser, isValidAttrValue, isValidStatement } from "htmljs-parser"; | ||
| print(path, opts, print) { | ||
| const { node } = path; | ||
| switch (node.type) { | ||
| case NodeType.AttrArgs: | ||
| case NodeType.AttrMethod: | ||
| case NodeType.AttrNamed: | ||
| case NodeType.AttrSpread: | ||
| case NodeType.Class: | ||
| case NodeType.Export: | ||
| case NodeType.Import: | ||
| case NodeType.OpenTagName: | ||
| case NodeType.Placeholder: | ||
| case NodeType.Scriptlet: | ||
| case NodeType.ShorthandClassName: | ||
| case NodeType.ShorthandId: | ||
| case NodeType.Static: | ||
| case NodeType.Style: | ||
| case NodeType.TagArgs: | ||
| case NodeType.TagParams: | ||
| case NodeType.TagTypeArgs: | ||
| case NodeType.TagTypeParams: | ||
| case NodeType.TagVar: return printExact(path, opts, print); | ||
| case NodeType.CDATA: return printCDATA(path, opts, print); | ||
| case NodeType.Comment: return printComment(path, opts, print); | ||
| case NodeType.Doctype: return printDoctype(path, opts, print); | ||
| case NodeType.Declaration: return printDeclaration(path, opts, print); | ||
| case NodeType.Program: return printProgram(path, opts, print); | ||
| case NodeType.Tag: | ||
| case NodeType.AttrTag: return printTag(path, opts, print); | ||
| case NodeType.Text: return printText(path, opts, print); | ||
| default: throw new Error(`Unknown node type in Marko template: ${NodeType[node.type] || node.type}`); | ||
| } | ||
| const { type } = path.node; | ||
| const handler = printHandlers[type]; | ||
| if (handler) return handler(path, opts, print); | ||
| /* c8 ignore next */ | ||
| throw new Error(`Unknown node type in Marko template: ${NodeType[type] || type}`); | ||
| }, | ||
| embed(path, opts) { | ||
| switch (path.node?.type) { | ||
| case NodeType.AttrNamed: return embedAttrNamed; | ||
| case NodeType.AttrSpread: return embedAttrSpread; | ||
| case NodeType.Class: return embedClass; | ||
| case NodeType.Export: return embedExport; | ||
| case NodeType.Import: return embedImport; | ||
| case NodeType.OpenTagName: return embedOpenTagName; | ||
| case NodeType.Placeholder: return embedPlaceholder; | ||
| case NodeType.Scriptlet: return embedScriptlet; | ||
| case NodeType.ShorthandClassName: return embedShorthandClassName; | ||
| case NodeType.ShorthandId: return embedShorthandId; | ||
| case NodeType.Static: return embedStatic; | ||
| case NodeType.Style: return embedStyle; | ||
| case NodeType.Tag: return embedTag(path, opts); | ||
| case NodeType.TagArgs: return embedTagArgs; | ||
| case NodeType.TagParams: return embedTagParams; | ||
| case NodeType.TagTypeArgs: return embedTagTypeArgs; | ||
| case NodeType.TagTypeParams: return embedTagTypeParams; | ||
| case NodeType.TagVar: return embedTagVar; | ||
| } | ||
| return null; | ||
| embed(path) { | ||
| return embedHandlers[path.node.type] ?? null; | ||
| }, | ||
@@ -834,47 +787,208 @@ getVisitorKeys(node) { | ||
| } }; | ||
| const printProgram = (path, opts, print) => { | ||
| const body = printBody(path, opts, print); | ||
| const lastStatic = path.node.static.length - (body ? 0 : 1); | ||
| let programDoc = path.map((child, i) => i !== lastStatic && hasExplicitLine(child, opts) ? [child.call(print), b.hardline] : child.call(print), "static"); | ||
| if (body) if (body.inline) programDoc.push(wrapConciseText(body.content)); | ||
| else programDoc = [...programDoc, ...body.content]; | ||
| return [b.join(b.hardline, programDoc), b.hardline]; | ||
| const printHandlers = { | ||
| [NodeType.AttrArgs]: printExact, | ||
| [NodeType.AttrMethod]: printExact, | ||
| [NodeType.AttrNamed]: printExact, | ||
| [NodeType.AttrSpread]: printExact, | ||
| [NodeType.Class]: printExact, | ||
| [NodeType.Export]: printExact, | ||
| [NodeType.Import]: printExact, | ||
| [NodeType.OpenTagName]: printExact, | ||
| [NodeType.Placeholder]: printExact, | ||
| [NodeType.Scriptlet]: printExact, | ||
| [NodeType.ShorthandClassName]: printExact, | ||
| [NodeType.ShorthandId]: printExact, | ||
| [NodeType.Static]: printExact, | ||
| [NodeType.Style]: printExact, | ||
| [NodeType.TagArgs]: printExact, | ||
| [NodeType.TagParams]: printExact, | ||
| [NodeType.TagTypeArgs]: printExact, | ||
| [NodeType.TagTypeParams]: printExact, | ||
| [NodeType.TagVar]: printExact, | ||
| [NodeType.Tag]: printTag, | ||
| [NodeType.AttrTag]: printTag, | ||
| [NodeType.CDATA]: (path, opts) => `<![CDATA[${read(path.node.value, opts)}]]>`, | ||
| [NodeType.Comment]: (path, opts) => { | ||
| const { node } = path; | ||
| const code = read(node, opts); | ||
| if (node.block) { | ||
| if (code.includes("\n")) { | ||
| const lines = code.split("\n"); | ||
| const len = lines.length; | ||
| let indent = Infinity; | ||
| for (let i = 1; i < len; i++) { | ||
| const match = lines[i].match(/^(\s+)/); | ||
| if (match) indent = Math.min(indent, match[1].length); | ||
| else { | ||
| indent = 0; | ||
| break; | ||
| } | ||
| } | ||
| const parts = [lines[0]]; | ||
| for (let i = 1; i < len; i++) parts.push(b.hardline, indent ? lines[i].slice(indent) : lines[i]); | ||
| return parts; | ||
| } | ||
| return code; | ||
| } | ||
| return b.lineSuffix(code); | ||
| }, | ||
| [NodeType.Doctype]: (path, opts) => `<!${read(path.node.value, opts).replace(/\s+/g, " ").trim()}>`, | ||
| [NodeType.Declaration]: (path, opts) => `<?${read(path.node.value, opts).trim()}?>`, | ||
| [NodeType.Program]: (path, opts, print) => { | ||
| const body = printBody(path, opts, print); | ||
| const lastStatic = path.node.static.length - (body ? 0 : 1); | ||
| let programDoc = path.map((child, i) => i !== lastStatic && hasExplicitLine(child, opts) ? [child.call(print), b.hardline] : child.call(print), "static"); | ||
| if (body) if (body.inline) programDoc.push(wrapConciseText(body.content)); | ||
| else programDoc = [...programDoc, ...body.content]; | ||
| return [b.join(b.hardline, programDoc), b.hardline]; | ||
| }, | ||
| [NodeType.Text]: (path, opts) => { | ||
| const text = read(path.node, opts).replace(/\\/g, "\\\\"); | ||
| return /^\$!?{/.test(text) ? "\\" + text : text; | ||
| } | ||
| }; | ||
| const printDoctype = (path, opts) => { | ||
| return `<!${read(path.node.value, opts).replace(/\s+/g, " ").trim()}>`; | ||
| }; | ||
| const printDeclaration = (path, opts) => { | ||
| return `<?${read(path.node.value, opts).trim()}?>`; | ||
| }; | ||
| const printCDATA = (path, opts) => { | ||
| return `<![CDATA[${read(path.node.value, opts)}]]>`; | ||
| }; | ||
| const printComment = (path, opts) => { | ||
| const { node } = path; | ||
| const code = read(node, opts); | ||
| if (node.block) { | ||
| if (code.includes("\n")) { | ||
| const lines = code.split("\n"); | ||
| const len = lines.length; | ||
| let indent = Infinity; | ||
| for (let i = 1; i < len; i++) { | ||
| const match = lines[i].match(/^(\s+)/); | ||
| if (match) indent = Math.min(indent, match[1].length); | ||
| else { | ||
| indent = 0; | ||
| break; | ||
| const embedHandlers = { | ||
| [NodeType.Class]: (toDoc, _print, path, opts) => toDoc(read(path.node, opts), exprParse), | ||
| [NodeType.Import]: (toDoc, _print, path, opts) => toDoc(read(path.node, opts), stmtParse), | ||
| [NodeType.Export]: (toDoc, _print, path, opts) => toDoc(read(path.node, opts), stmtParse), | ||
| [NodeType.Style]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| const code = read(node.value, opts).trim(); | ||
| const parser = getParserFromExt(node.ext?.slice(node.ext.lastIndexOf(".")) || ".css"); | ||
| if (parser) return b.group([ | ||
| `style${node.ext || ""} {`, | ||
| b.indent([b.line, await toDoc(code, { parser })]), | ||
| b.line, | ||
| "}" | ||
| ]); | ||
| }, | ||
| [NodeType.Static]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| const code = opts._markoParsed.code.slice(node.start + node.target.length + 1, node.end).replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim(); | ||
| return code ? [`${node.target} `, withBlockIfNeeded(await toDoc(code, stmtParse))] : []; | ||
| }, | ||
| [NodeType.Scriptlet]: async (toDoc, _print, path, opts) => { | ||
| const code = read(path.node.value, opts).replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim(); | ||
| return code ? [ | ||
| b.breakParent, | ||
| "$ ", | ||
| withBlockIfNeeded(await toDoc(code, stmtParse)) | ||
| ] : []; | ||
| }, | ||
| [NodeType.OpenTagName]: (toDoc, _print, path, opts) => templateToDoc(toDoc, path, opts), | ||
| [NodeType.Placeholder]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| const code = read(node.value, opts); | ||
| if (code === "\" \"" || code === "' '") return getVisibleSpace(opts); | ||
| return b.group([ | ||
| node.escape ? "${" : "$!{", | ||
| b.indent([b.softline, await toDoc(code, exprParse)]), | ||
| b.softline, | ||
| "}" | ||
| ]); | ||
| }, | ||
| [NodeType.TagArgs]: (toDoc, _print, path, opts) => argsToDoc(path.node, opts, toDoc), | ||
| [NodeType.AttrNamed]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| const name = read(node.name, opts); | ||
| if (!(node.args || node.value)) return name; | ||
| const attrDoc = [name]; | ||
| if (node.args && !isEmpty(node.args.value, opts)) { | ||
| const argsDoc = await argsToDoc(node.args, opts, toDoc); | ||
| if (argsDoc) attrDoc.push(argsDoc); | ||
| else return unexpectedDoc(opts, node); | ||
| } | ||
| if (node.value) if (node.value.type === NodeType.AttrMethod) { | ||
| const attrMethodDoc = await toDoc(`function${read(node.value, opts)}`, exprParse); | ||
| if (Array.isArray(attrMethodDoc) && attrMethodDoc.length && typeof attrMethodDoc[0] === "string") { | ||
| attrMethodDoc[0] = attrMethodDoc[0].replace(/^function\s*/, ""); | ||
| attrDoc.push(attrMethodDoc); | ||
| } else return unexpectedDoc(opts, node); | ||
| } else attrDoc.push(node.value.bound ? ":=" : "=", withParensIfNeeded(await toDoc(read(node.value.value, opts), exprParse), isConcise(opts))); | ||
| return b.group(attrDoc); | ||
| }, | ||
| [NodeType.AttrSpread]: async (toDoc, _print, path, opts) => { | ||
| return b.group(["...", withParensIfNeeded(await toDoc(read(path.node.value, opts), exprParse), isConcise(opts))]); | ||
| }, | ||
| [NodeType.ShorthandId]: async (toDoc, _print, path, opts) => ["#", await templateToDoc(toDoc, path, opts)], | ||
| [NodeType.ShorthandClassName]: async (toDoc, _print, path, opts) => [".", await templateToDoc(toDoc, path, opts)], | ||
| [NodeType.Tag]: async (toDoc, print, path, opts) => { | ||
| const parser = getTagParser(path.node, opts); | ||
| if (parser === void 0) return void 0; | ||
| return printTag(path, opts, print, { | ||
| inline: true, | ||
| preserve: parser === false, | ||
| content: await getFormattedBody(path, parser, toDoc, print, opts) | ||
| }); | ||
| }, | ||
| [NodeType.TagVar]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| let doc = await toDoc(`var ${read(node.value, opts).trim()}=_`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length === 1) doc = doc[0]; | ||
| if (typeof doc === "object" && !Array.isArray(doc) && doc.type === "group") doc = doc.contents; | ||
| if (Array.isArray(doc) && doc.length > 1) { | ||
| const varPart = doc[1]; | ||
| if (typeof varPart === "object" && "type" in varPart && varPart.type === "group" && Array.isArray(varPart.contents)) { | ||
| const varContents = varPart.contents; | ||
| for (let i = varContents.length; i--;) { | ||
| const item = varContents[i]; | ||
| if (typeof item === "string") { | ||
| const match = /\s*=\s*$/.exec(item); | ||
| if (match) { | ||
| varContents[i] = item.slice(0, -match[0].length); | ||
| varContents.length = i + 1; | ||
| return ["/", varContents]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| const parts = [lines[0]]; | ||
| for (let i = 1; i < len; i++) parts.push(b.hardline, indent ? lines[i].slice(indent) : lines[i]); | ||
| return parts; | ||
| } | ||
| return code; | ||
| return unexpectedDoc(opts, node); | ||
| /* c8 ignore stop */ | ||
| }, | ||
| [NodeType.TagTypeArgs]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| if (isEmpty(node.value, opts)) return ""; | ||
| const doc = await toDoc(`_<${read(node.value, opts).trim()}>`, exprParse); | ||
| if (typeof doc === "string") return doc.replace(/^_/, ""); | ||
| if (Array.isArray(doc) && typeof doc[0] === "string") { | ||
| doc[0] = doc[0].replace(/^_/, ""); | ||
| return doc; | ||
| } | ||
| /* c8 ignore next */ | ||
| return unexpectedDoc(opts, node); | ||
| }, | ||
| [NodeType.TagParams]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| if (isEmpty(node.value, opts)) return ""; | ||
| const doc = await toDoc(`function _(${read(node.value, opts).trim()}){}`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length > 1) { | ||
| const paramsGroup = doc[1]; | ||
| if (paramsGroup && typeof paramsGroup === "object" && "type" in paramsGroup && paramsGroup.type === "group" && Array.isArray(paramsGroup.contents)) { | ||
| const paramsContents = [...paramsGroup.contents]; | ||
| const first = paramsContents[0]; | ||
| const last = paramsContents[paramsContents.length - 1]; | ||
| if (typeof first === "string" && typeof last === "string") { | ||
| paramsContents[0] = first.replace(/^\(/, "|"); | ||
| paramsContents[paramsContents.length - 1] = last.replace(/\)$/, "|"); | ||
| } | ||
| return b.group(paramsContents); | ||
| } | ||
| } | ||
| /* c8 ignore next */ | ||
| return unexpectedDoc(opts, node); | ||
| }, | ||
| [NodeType.TagTypeParams]: async (toDoc, _print, path, opts) => { | ||
| const { node } = path; | ||
| if (isEmpty(node.parent.params?.value, opts) || isEmpty(node.value, opts)) return ""; | ||
| const doc = await toDoc(`function _<${read(node.value, opts).trim()}>(){}`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length > 1) return doc[1]; | ||
| /* c8 ignore next */ | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return b.lineSuffix(code); | ||
| }; | ||
| const printTag = ((path, opts, print, body = printBody(path, opts, print)) => { | ||
| function printTag(path, opts, print, body = printBody(path, opts, print)) { | ||
| return (isConcise(opts) ? printConciseTag : printHTMLTag)(path, opts, print, body); | ||
| }); | ||
| const printHTMLTag = ((path, opts, print, body) => { | ||
| } | ||
| function printHTMLTag(path, opts, print, body) { | ||
| const { node } = path; | ||
@@ -909,4 +1023,4 @@ const openTagDoc = ["<", printTagBeforeAttrs(path, opts, print)]; | ||
| return b.group(openTagDoc); | ||
| }); | ||
| const printConciseTag = ((path, opts, print, body) => { | ||
| } | ||
| function printConciseTag(path, opts, print, body) { | ||
| const { node } = path; | ||
@@ -930,14 +1044,14 @@ const tagDoc = [printTagBeforeAttrs(path, opts, print)]; | ||
| return b.group(tagDoc); | ||
| }); | ||
| const printTagBeforeAttrs = (path, _opts, print) => { | ||
| } | ||
| function printTagBeforeAttrs(path, opts, print) { | ||
| const { node } = path; | ||
| const name = path.call(print, "name"); | ||
| const doc = [name]; | ||
| if (pathHas(path, "typeArgs")) doc.push(path.call(print, "typeArgs")); | ||
| if (pathHas(path, "typeArgs") && !isEmpty(path.node.typeArgs.value, opts)) doc.push(path.call(print, "typeArgs")); | ||
| if (pathHas(path, "shorthandId")) doc.push(path.call(print, "shorthandId")); | ||
| if (pathHas(path, "shorthandClassNames")) doc.push(path.map(print, "shorthandClassNames")); | ||
| if (pathHas(path, "args")) doc.push(path.call(print, "args")); | ||
| if (pathHas(path, "args") && !isEmpty(path.node.args.value, opts)) doc.push(path.call(print, "args")); | ||
| if (pathHas(path, "var")) doc.push(path.call(print, "var")); | ||
| if (pathHas(path, "params")) { | ||
| if (pathHas(path, "typeParams")) { | ||
| if (pathHas(path, "params") && !isEmpty(path.node.params.value, opts)) { | ||
| if (pathHas(path, "typeParams") && !isEmpty(path.node.typeParams.value, opts)) { | ||
| if (!(node.typeArgs || node.args || node.var)) doc.push(" "); | ||
@@ -949,4 +1063,4 @@ doc.push(path.call(print, "typeParams")); | ||
| return doc.length === 1 ? name : doc; | ||
| }; | ||
| const printBody = (path, opts, print) => { | ||
| } | ||
| function printBody(path, opts, print) { | ||
| const { node } = path; | ||
@@ -963,3 +1077,2 @@ if (!node.body) return; | ||
| const childDoc = child.call(print); | ||
| if (!childDoc) return; | ||
| content ||= []; | ||
@@ -1031,7 +1144,3 @@ if (isInline(child.node)) { | ||
| if (typeof childDoc === "string" && isVisibleSpace(childDoc)) { | ||
| if (endsWithLine(inline)) { | ||
| const last = inline.length - 1; | ||
| if (inline[last] === b.softline) inline[last] = b.line; | ||
| return; | ||
| } | ||
| if (endsWithLine(inline)) return; | ||
| childDoc = b.line; | ||
@@ -1074,162 +1183,7 @@ } | ||
| } | ||
| }; | ||
| const printText = (path, opts) => { | ||
| const text = read(path.node, opts).replace(/\\/g, "\\\\"); | ||
| if (/^\$!?{/.test(text)) return "\\" + text; | ||
| return text; | ||
| }; | ||
| const printExact = (path, opts) => read(path.node, opts); | ||
| const embedClass = (toDoc, _print, path, opts) => toDoc(read(path.node, opts), exprParse); | ||
| const embedImport = (toDoc, _print, path, opts) => toDoc(read(path.node, opts), stmtParse); | ||
| const embedExport = (toDoc, _print, path, opts) => toDoc(read(path.node, opts), stmtParse); | ||
| const embedStyle = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| const parser = getParserFromExt(node.ext?.slice(node.ext.lastIndexOf(".")) || ".css"); | ||
| if (parser) return b.group([ | ||
| `style${node.ext || ""} {`, | ||
| b.indent([b.line, await toDoc(code, { parser })]), | ||
| b.line, | ||
| "}" | ||
| ]); | ||
| }; | ||
| const embedStatic = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = opts._markoParsed.code.slice(node.start + node.target.length + 1, node.end).replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim(); | ||
| return code ? [`${node.target} `, withBlockIfNeeded(await toDoc(code, stmtParse))] : []; | ||
| }; | ||
| const embedScriptlet = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).replace(/^\s*\{([\s\S]*)\}\s*$/, "$1").trim(); | ||
| return code ? [ | ||
| b.breakParent, | ||
| "$ ", | ||
| withBlockIfNeeded(await toDoc(code, stmtParse)) | ||
| ] : []; | ||
| }; | ||
| const embedOpenTagName = async (toDoc, _print, path, opts) => embedTemplate(toDoc, _print, path, opts); | ||
| const embedPlaceholder = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts); | ||
| if (code === "\" \"" || code === "' '") return getVisibleSpace(opts); | ||
| return b.group([ | ||
| node.escape ? "${" : "$!{", | ||
| b.indent([b.softline, await toDoc(code, exprParse)]), | ||
| b.softline, | ||
| "}" | ||
| ]); | ||
| }; | ||
| const embedTagArgs = (toDoc, _print, path, opts) => { | ||
| return argsToDoc(path.node, opts, toDoc); | ||
| }; | ||
| const embedAttrNamed = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const name = read(node.name, opts); | ||
| if (!(node.args || node.value)) return name; | ||
| const attrDoc = [name]; | ||
| if (node.args) { | ||
| const argsDoc = await argsToDoc(node.args, opts, toDoc); | ||
| if (argsDoc) attrDoc.push(argsDoc); | ||
| else return unexpectedDoc(opts, node); | ||
| } | ||
| if (node.value) if (node.value.type === NodeType.AttrMethod) { | ||
| const attrMethodDoc = await toDoc(`function${read(node.value, opts)}`, exprParse); | ||
| if (Array.isArray(attrMethodDoc) && attrMethodDoc.length && typeof attrMethodDoc[0] === "string") { | ||
| attrMethodDoc[0] = attrMethodDoc[0].replace(/^function\s*/, ""); | ||
| attrDoc.push(attrMethodDoc); | ||
| } else return unexpectedDoc(opts, node); | ||
| } else attrDoc.push(node.value.bound ? ":=" : "=", withParensIfNeeded(await toDoc(read(node.value.value, opts), exprParse), isConcise(opts))); | ||
| return b.group(attrDoc); | ||
| }; | ||
| const embedAttrSpread = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| return b.group(["...", withParensIfNeeded(await toDoc(read(node.value, opts), exprParse), isConcise(opts))]); | ||
| }; | ||
| const embedShorthandId = async (toDoc, print, path, opts) => ["#", await embedTemplate(toDoc, print, path, opts)]; | ||
| const embedShorthandClassName = async (toDoc, print, path, opts) => [".", await embedTemplate(toDoc, print, path, opts)]; | ||
| const embedTag = (path, opts) => { | ||
| const tag = path.node; | ||
| const parser = getTagParser(tag, opts); | ||
| if (parser === void 0) return null; | ||
| return async (toDoc, print, path, opts) => printTag(path, opts, print, { | ||
| inline: true, | ||
| preserve: parser === false, | ||
| content: await getFormattedBody(path, parser, toDoc, print, opts) | ||
| }); | ||
| }; | ||
| const embedTagVar = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| let doc = await toDoc(`var ${code}=_`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length === 1) doc = doc[0]; | ||
| if (typeof doc === "object" && !Array.isArray(doc) && doc.type === "group") doc = doc.contents; | ||
| if (Array.isArray(doc) && doc.length > 1) { | ||
| const varPart = doc[1]; | ||
| if (typeof varPart === "object" && "type" in varPart && varPart.type === "group" && Array.isArray(varPart.contents)) { | ||
| const varContents = varPart.contents; | ||
| for (let i = varContents.length; i--;) { | ||
| const item = varContents[i]; | ||
| if (typeof item === "string") { | ||
| const match = /\s*=\s*$/.exec(item); | ||
| if (match) { | ||
| varContents[i] = item.slice(0, -match[0].length); | ||
| varContents.length = i + 1; | ||
| return ["/", varContents]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return []; | ||
| }; | ||
| const embedTagTypeArgs = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| const doc = await toDoc(`_<${code}>`, exprParse); | ||
| if (typeof doc === "string") return doc.replace(/^_/, ""); | ||
| if (Array.isArray(doc) && typeof doc[0] === "string") { | ||
| doc[0] = doc[0].replace(/^_/, ""); | ||
| return doc; | ||
| } | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return []; | ||
| }; | ||
| const embedTagParams = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| const doc = await toDoc(`function _(${code}){}`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length > 1) { | ||
| const paramsGroup = doc[1]; | ||
| if (paramsGroup && typeof paramsGroup === "object" && "type" in paramsGroup && paramsGroup.type === "group" && Array.isArray(paramsGroup.contents)) { | ||
| const paramsContents = [...paramsGroup.contents]; | ||
| const first = paramsContents[0]; | ||
| const last = paramsContents[paramsContents.length - 1]; | ||
| if (typeof first === "string" && typeof last === "string") { | ||
| paramsContents[0] = first.replace(/^\(/, "|"); | ||
| paramsContents[paramsContents.length - 1] = last.replace(/\)$/, "|"); | ||
| } | ||
| return b.group(paramsContents); | ||
| } | ||
| } | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return []; | ||
| }; | ||
| const embedTagTypeParams = async (toDoc, _print, path, opts) => { | ||
| const node = path.node; | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| const doc = await toDoc(`function _<${code}>(){}`, stmtParse); | ||
| if (Array.isArray(doc) && doc.length > 1) return doc[1]; | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
| return []; | ||
| }; | ||
| const embedTemplate = async (toDoc, _print, path, opts) => { | ||
| } | ||
| function printExact(path, opts) { | ||
| return read(path.node, opts); | ||
| } | ||
| async function templateToDoc(toDoc, path, opts) { | ||
| const { expressions, quasis } = path.node; | ||
@@ -1252,14 +1206,12 @@ const first = read(quasis[0], opts); | ||
| return shorthandDoc; | ||
| }; | ||
| } | ||
| async function argsToDoc(node, opts, toDoc) { | ||
| const code = read(node.value, opts).trim(); | ||
| if (code) { | ||
| const doc = await toDoc(`_(${code})`, exprParse); | ||
| if (Array.isArray(doc) && doc.length && typeof doc[0] === "string") { | ||
| doc[0] = doc[0].replace(/^_/, ""); | ||
| return doc; | ||
| } | ||
| return unexpectedDoc(opts, node); | ||
| if (isEmpty(node.value, opts)) return ""; | ||
| const doc = await toDoc(`_(${read(node.value, opts).trim()})`, exprParse); | ||
| if (Array.isArray(doc) && doc.length && typeof doc[0] === "string") { | ||
| doc[0] = doc[0].replace(/^_/, ""); | ||
| return doc; | ||
| } | ||
| return []; | ||
| /* c8 ignore next */ | ||
| return unexpectedDoc(opts, node); | ||
| } | ||
@@ -1361,5 +1313,12 @@ function wrapConciseText(doc) { | ||
| } | ||
| const nonWhitespaceReg = /\S/g; | ||
| function isEmpty(range, opts) { | ||
| if (!range || range.start === range.end) return true; | ||
| nonWhitespaceReg.lastIndex = range.start; | ||
| return !(nonWhitespaceReg.test(opts._markoParsed.code) && nonWhitespaceReg.lastIndex <= range.end); | ||
| } | ||
| function pathHas(path, key) { | ||
| return !!path.node[key]; | ||
| } | ||
| /* c8 ignore start */ | ||
| function unexpectedDoc(opts, node) { | ||
@@ -1370,2 +1329,3 @@ const parsed = opts._markoParsed; | ||
| } | ||
| /* c8 ignore stop */ | ||
| export { languages, options, parsers, printers }; |
+1
-1
| { | ||
| "name": "prettier-plugin-marko", | ||
| "version": "4.0.5", | ||
| "version": "4.0.6", | ||
| "description": "A prettier plugin for parsing and printing Marko files", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
1
-50%95328
-1.62%2915
-2.64%