Skip to content

Instantly share code, notes, and snippets.

@moetelo
Last active August 26, 2019 14:35
Show Gist options
  • Save moetelo/383b3a79720aa8f98eeb0ebfb8e7405d to your computer and use it in GitHub Desktop.
Save moetelo/383b3a79720aa8f98eeb0ebfb8e7405d to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
const argv = require("yargs").argv;
const htmlPugConverter = require("html-pug-converter");
const cheerio = require("cheerio");
const fs = require("fs");
const path = require("path");
const { JSDOM } = require("jsdom");
const to = require('to-case');
const walk = (dir, filelist = []) => {
if (fs.statSync(dir).isDirectory()) {
const files = fs.readdirSync(dir);
for (file of files) {
if (file[0] === "." || file === "node_modules") {
continue;
}
const filepath = path.join(dir, file);
const stat = fs.statSync(filepath);
if (stat.isDirectory()) {
filelist = walk(filepath, filelist);
} else {
filelist.push(filepath);
}
}
} else {
if (!dir.match(/\.vue$/)) {
throw new Error("Error: Please specify a .vue file");
}
filelist.push(dir);
}
return filelist;
};
if (argv._.length !== 1) {
throw new Error("Error: Please specify a .vue file or a directory");
}
const fileList = walk(argv._[0]);
for (file of fileList) {
if (!file.match(/\.vue$/)) {
continue;
}
try {
let vueFileContent = fs.readFileSync(file, "utf8");
if (vueFileContent.split('\n')[0].includes("pug")) {
console.log(file + '...lang="pug" detected. skipping...');
continue;
}
const templateMatch = vueFileContent.match(/<template>((.|\n|\r\n)+)<\/template>/);
const scriptContentMatch = vueFileContent.match(/<script lang="ts">((.|\n|\r\n)+)<\/script>/gm);
let $ = cheerio.load(vueFileContent, {
decodeEntities: false,
// lowerCaseTags: false
xmlMode: true,
});
let stopSlugging = false;
$("*").each((i, el) => {
// не знаю нужно ли это проверять
// if (stopSlugging || ['script', 'style'].includes(el.tagName)) {
// stopSlugging = true;
// return;
// }
//el.tagName = to.slug(el.tagName);
});
let xml = $.xml();
let dom = new JSDOM(
'<html xmlns="http://www.w3.org/1999/xhtml">'
+ xml +
"</html>",
{ contentType: "text/html" }
);
const window = dom.window;
$ = cheerio.load(window.document.documentElement.outerHTML, {
decodeEntities: false,
});
const templateElement = $("template:first-child");
const templateHtml = templateElement.html();
if (!templateElement) {
console.log("no template");
continue;
}
let pugTemplateContent = htmlPugConverter(templateHtml, {
caseSensitive: true,
collapseInlineTagWhitespace: false,
//collapseWhitespace: false,
});
// правит отступы и лишние теги
pugTemplateContent = pugTemplateContent
.replace(`html\n head\n body`, '')
.replace(/^ {2}/gm, "");
templateElement.attr("lang", "pug");
templateElement.html('');
templateElement.text(pugTemplateContent + "\n");
let output = $.html();
// удалить рудименты cheerio
output = output.replace(/^<html xmlns="http:\/\/www.w3.org\/1999\/xhtml"><head>/, '');
output = output.replace(/<\/head><body><\/body><\/html>$/, "");
// вернуть на место нормальный скрипт
if (scriptContentMatch)
output = output.replace(/<script lang="ts">((.|\n)+)<\/script>/gm, scriptContentMatch[0]);
fs.writeFileSync(file, output, "utf8");
console.log(file + ' | done');
} catch (err) {
console.error("Error: Failed to process " + file);
throw err;
}
}
@moetelo
Copy link
Author

moetelo commented Aug 23, 2019

package.json

{
    "name": "vue-pug",
    "version": "4.0.0",
    "description": "Converts Vue template in HTML to Pug templating language (formerly Jade).",
    "main": "pugconv.js",
    "dependencies": {
        "cheerio": "^1.0.0-rc.2",
        "html-pug-converter": "^3.0.0",
        "jsdom": "^13.2.0",
        "to-case": "^2.0.0",
        "yargs": "^12.0.5"
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment