Open haoliangwu opened 6 months ago
Hmm. I'm not very familiar with pug but I'll think about how to support it better. One problem I can see is that the stringify code outputs html and not pug.
Ideally it would just see <template lang="pug">
and adjust the parse/stringify strategy automatically for that file.
Thanks for raising this issue. I'll work on it a bit later
hi @UnrefinedBrain ,
Finally, I resolve the migration for pug template before executing vue-metamorph
with some scripts by using magic-string
and pug
compiler. Just compile and tranform the content between <template>
tags into html syntax.
So if you are not familiar with pug and I thought there are workarounds here, maybe we could close it first and re-open it in the future once other users also request this feature.
By the way, I'd like to share the scripts I used here(sorry for inline content, because the repo is enterprise private repo):
import MagicString from 'magic-string'
import * as pug from 'pug'
import stripIndent from 'strip-indent'
const LANG_PUG = /\slang="pug"/
const TPL_START_TAG = /<template(.+?)>/
const TPL_END_TAG = '</template>'
export function pug2html(raw) {
const ms = new MagicString(raw)
const templateStartTagStartMatch = raw.match(TPL_START_TAG)
const templateStartTagStart = templateStartTagStartMatch?.index ?? -1
if (templateStartTagStart < 0) {
return
}
const templateStartTagEnd = templateStartTagStart + templateStartTagStartMatch[0].length
// it is safe to use indexOf here because we can only declare </template> once
const templateEndTagStart = raw.indexOf(TPL_END_TAG)
const templateEndTagEnd = templateEndTagStart + TPL_END_TAG.length
// update the template start tag
ms.update(templateStartTagStart, templateStartTagEnd, templateStartTagStartMatch[0].replace(LANG_PUG, ''))
// if the template content is empty, we remove template totally
if (ms.slice(templateStartTagEnd, templateEndTagStart).trim().length === 0) {
ms.remove(templateStartTagStart, templateEndTagEnd)
} else {
const rawTpl = ms.slice(templateStartTagEnd, templateEndTagStart)
const compileHtml = pug.compile(stripIndent(rawTpl), {
// https://github.com/yyx990803/pug-plain-loader/blob/master/index.js
doctype: 'html',
pretty: true,
})
// update the template
ms.update(
templateStartTagEnd,
templateEndTagStart,
compileHtml()
// revert the escaped symbol for html spec
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
// it should be " but we assume it is a js expression
// and we prefer to use ' here
.replace(/"/g, "'")
.replace(/'/g, "'") + '\n',
)
}
return ms.toString().trimStart()
}
#!/usr/bin/env node
import fs from 'fs'
import path from 'path'
import url from 'url'
import { globSync } from 'glob'
import args from 'args'
import * as utils from './utils.js'
const commander = args.option(['p', 'pattern'], 'the glob pattern to match Vue SFC files, eg: **/*.vue')
const flags = args.parse(process.argv)
if (flags.pattern) {
const failedList = []
const __filename = url.fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// todo: dynamically
const vueSFCs = await globSync(flags.pattern, {
ignore: 'node_modules/**',
absolute: true,
})
vueSFCs.forEach(filePath => {
const raw = fs.readFileSync(filePath, 'utf-8')
try {
const tranformed = utils.pug2html(raw)
if (!tranformed) return
fs.writeFileSync(filePath, tranformed, 'utf-8')
} catch (err) {
console.error(err)
failedList.push(filePath)
}
})
if (failedList.length > 0) {
console.error(`The following Vue SFC files failed to tranform:`)
console.log(failedList.join('\n'))
}
} else {
commander.showHelp()
}
the scripts here must contains some bugs but it is enough for my project.
first, thanks for your awesome works for this project, I am engaging in migration of large scale webapp from nuxt2 to nuxt3, this project really save me time for migration.
anyway, our project contains some
.vue
files which template is written withpug
lang, in this case, the cli throws error like:I found it could be solved by overriding the parseOptions to let
vue-eslint-parser
usevue-eslint-parser-template-tokenizer-pug
parser to parse pug templates, but I have to hack into the source code of node_modules(I usepatch-package
right now).so maybe it is better to expose a interface to override the parserOptions of
vue-eslint-parser
.