Skip to content

Instantly share code, notes, and snippets.

@signalwerk
Last active November 7, 2022 16:05
Show Gist options
  • Select an option

  • Save signalwerk/f005d854a18211f4c84319e850071ccd to your computer and use it in GitHub Desktop.

Select an option

Save signalwerk/f005d854a18211f4c84319e850071ccd to your computer and use it in GitHub Desktop.
It is a tool to split a folder with .vue files into three files (.split.js/.split.scss/.split.vue) and merge them back together. Ideal for refactoring code with external tools that don't know .vue files.
const doc = `
## Vue-Splitter
It is a tool to split a folder with .vue files into three files (.split.js/.split.scss/.split.vue)
and merge them back together. Ideal for refactoring code with external tools that don't know .vue files.
## ⚠️ CAUTION
⚠️⚠️⚠️ Make sure you have a proper copy (git) of your code before you run this tool.
## Install
mkdir splitter
cd splitter
curl https://gist.githubusercontent.com/signalwerk/f005d854a18211f4c84319e850071ccd/raw/vue-splitter.js -o 'index.js'
npm init -y
npm i vue-template-compiler
## Usage
### Default params
--directory=./src/components/
--filenameEndsWith=.vue
### Example for SCSS conversion
node splitter/index.js --mode=split --directory=./src/ --filenameEndsWith=index.vue
sass-migrator division --no-multiplication **/*.scss
node splitter/index.js --mode=merge --directory=./src/ --filenameEndsWith=index.vue
---
## Split
use to split all .vue-files in a folder-tree:
node index.js --mode=split --directory=../src/components/ --filenameEndsWith=.vue
## Merge
use to merge all .split.js/.split.scss/.split.vue in a folder-tree where a .vue-file is present:
node index.js --mode=merge --directory=./src/components/ --filenameEndsWith=.vue
## Licence
[MIT](https://opensource.org/licenses/MIT)
`;
const fs = require("fs");
const path = require("path");
const compiler = require("vue-template-compiler");
// Return a list of files of the specified file-ending in the provided dir
function getFilesFromDir(dir, fileEnding) {
try {
const filesToReturn = [];
const stats = fs.statSync(dir);
// it's a dir
if (stats.isDirectory()) {
function walkDir(currentPath) {
const files = fs.readdirSync(currentPath);
for (const i in files) {
const curFile = path.join(currentPath, files[i]);
if (fs.statSync(curFile).isFile() && curFile.endsWith(fileEnding)) {
filesToReturn.push(curFile);
} else if (fs.statSync(curFile).isDirectory()) {
walkDir(curFile);
}
}
}
walkDir(dir);
}
if (stats.isFile()) {
filesToReturn.push(dir);
}
return filesToReturn;
} catch (err) {
console.error(err);
console.error(`couldn't read ${dir}`);
}
}
// split one .vue into multiple files
function split(filePath) {
const source = fs.readFileSync(`${filePath}`, "utf8");
const sfcDescriptor = compiler.parseComponent(source);
let additionalInformations = null;
if (sfcDescriptor.template) {
fs.writeFileSync(`${filePath}.split.vue`, sfcDescriptor.template.content);
}
if (sfcDescriptor.script) {
fs.writeFileSync(`${filePath}.split.js`, sfcDescriptor.script.content);
}
if (sfcDescriptor.styles.length > 0) {
const lang = sfcDescriptor.styles[0].lang || "css";
if (sfcDescriptor.styles[0]?.attrs?.scoped) {
additionalInformations = additionalInformations || {};
additionalInformations.styles = additionalInformations.styles || {};
additionalInformations.styles = { scoped: true };
}
fs.writeFileSync(
`${filePath}.split.${lang}`,
sfcDescriptor.styles[0].content
);
}
if (additionalInformations) {
fs.writeFileSync(
`${filePath}.split.json`,
JSON.stringify(additionalInformations, null, 2)
);
}
}
// merge multiple files into one .vue
function merge(filePath) {
const file = [];
const additionalInformations = {};
// load additional informations
if (fs.existsSync(`${filePath}.split.json`)) {
Object.assign(
additionalInformations,
JSON.parse(fs.readFileSync(`${filePath}.split.json`, "utf8"))
);
fs.unlinkSync(`${filePath}.split.json`);
}
if (fs.existsSync(`${filePath}.split.vue`)) {
const source = fs.readFileSync(`${filePath}.split.vue`, "utf8");
file.push(
`<template>${source
.split("\n")
.map((line) => (line ? ` ${line}` : line))
.join("\n")}</template>`
);
fs.unlinkSync(`${filePath}.split.vue`);
}
if (fs.existsSync(`${filePath}.split.js`)) {
const source = fs.readFileSync(`${filePath}.split.js`, "utf8");
file.push(`<script>${source}</script>`);
fs.unlinkSync(`${filePath}.split.js`);
}
if (fs.existsSync(`${filePath}.split.scss`)) {
const source = fs.readFileSync(`${filePath}.split.scss`, "utf8");
const scoped = additionalInformations?.styles?.scoped ? " scoped" : "";
file.push(`<style lang="scss"${scoped}>${source}</style>`);
fs.unlinkSync(`${filePath}.split.scss`);
} else if (fs.existsSync(`${filePath}.split.css`)) {
const source = fs.readFileSync(`${filePath}.split.css`, "utf8");
const scoped = additionalInformations?.styles?.scoped ? " scoped" : "";
file.push(`<style${scoped}>${source}</style>`);
fs.unlinkSync(`${filePath}.split.css`);
}
fs.writeFileSync(`${filePath}`, `${file.join("\n\n")}\n`);
}
// thx to https://stackoverflow.com/a/54098693/1184829
function getArgs() {
const args = {};
process.argv.slice(2, process.argv.length).forEach((arg) => {
// long arg
if (arg.slice(0, 2) === "--") {
const longArg = arg.split("=");
const longArgFlag = longArg[0].slice(2, longArg[0].length);
const longArgValue = longArg.length > 1 ? longArg[1] : true;
args[longArgFlag] = longArgValue;
}
});
return args;
}
const args = {
directory: "./src/components/",
filenameEndsWith: ".vue",
mode: "",
...getArgs(),
};
console.log(
`parsed arguments: --mode=${args.mode} --directory=${args.directory} --filenameEndsWith=${args.filenameEndsWith}`
);
const files = getFilesFromDir(args.directory, args.filenameEndsWith);
if (files && files.length === 0) {
console.warning("no files found");
console.log(doc.split("---")[1]);
return;
}
if (args.mode === "split") {
files.forEach((file) => split(file));
} else if (args.mode === "merge") {
files
.filter((item) => !item.endsWith(".split.vue"))
.forEach((file) => merge(file));
} else {
console.error("please specify the mode of this tool. ");
console.log(doc.split("---")[1]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment