diff --git a/README.md b/README.md new file mode 100644 index 0000000..8798ca6 --- /dev/null +++ b/README.md @@ -0,0 +1,173 @@ +# vue-sfc-split + +Convert SFCs for use without build + +## What it does + +* Converts `.vue` files into `.js` and `.css` files +* Includes template into script +* Auto-attaches generated css file +* Preserves `scoped` styles +* Supports SCSS +* Maintains structure +* Rewrites imorts + +## Installation & Usage + +### Global +Install: +```bash +npm i -g vue-sfc-split +``` +Run from project root: +```bash +vue-sfc-split +``` + +### Local (npm scripts) +Install: +```bash +npm i vue-sfc-split +``` +Add npm script to `package.json`: +```json +"scripts": { + "split": "vue-sfc-split" +}, +``` +Run from project root: +```bash +npm run split +``` + +## Options +`--ignore` patterns to ignore directories +`--noscope` ignore scoped css, and treat it like usual css +`--dest` destination folder +`--tab` this will be used to indent template entry in script + +### --ignore +Comma separated list of glob patterns + +`node_modules` is always ignored +```bash +vue-sfc-split --ignore=directory/*,directory-recursive/** +``` + +### --noscope +If this is specified scoped css will have no effect, all styles will be treated as unscoped +```bash +vue-sfc-split --noscope +``` + +### --dest +Where the output files will go + +Default: `dest/` + +Set this to an empty string to create `.js` and `.css` files next to original `.vue` files +```bash +vue-sfc-split --dest="" +``` + +## Scope +Scoped styles are processed similarly to [how vue does it](https://v3.vuejs.org/api/sfc-style.html#style-scoped) + +Custom `data-scope-*` attribute will be added to scoped style selectors and template elements + +Scope name is created based on file name and its path, keeping generated scope names predictable and non-duplicating + +For example this in file `hello.vue` +```xml +
Hola
+ +``` +Will get converted to this +```xml +
Hola
+ +``` +This can be disabled by specifying `--noscope` + +## Imports +In the output files all `.vue` imports will automatically be rewritten to target newly created `.js` files instead + +## Style attachment +Generated `.css` files will be automatically attached from generated `.js` files in this manner: +```javascript +fetch('hello.css') + .then(res => res.text()) + .then(style => document.head.insertAdjacentHTML('beforeend', '')) +``` + +## I/O example +### Input +__hello.vue__: +```xml + + + + + +``` +### Output +__hello.js__: +```javascript +import Two from './two.js' + +export default { + template: ` +
+

{{text}}

+ +
`, + name: 'One', + components: { Two, DeeperTwo }, + data() { + return { + text: 'Hello from component One' + } + }, +} + +// attach styles +fetch('hello.css').then(res => res.text()).then(style => document.head.insertAdjacentHTML('beforeend', '')) +``` +__hello.css__ +```css +.container[data-scope-hello] { + background: silver; +} +``` + + + diff --git a/convert.js b/convert.js index d6ffaf9..8d4b893 100644 --- a/convert.js +++ b/convert.js @@ -14,26 +14,24 @@ const htmlparser = require('node-html-parser') const args = minimist(process.argv.slice(2)) const opts = { - tab: ' ', ignore: ['node_modules/**'], noscope: false, dest: 'dist/', } -opts.tab = args.tab != undefined ? args.tab : opts.tab opts.ignore = args.ignore ? opts.ignore.concat(args.ignore.split(',')) : opts.ignore -opts.dest = args.dest - ? args.dest.slice(-1) != '/' +opts.dest = args.dest != undefined + ? args.dest && args.dest.slice(-1) != '/' ? args.dest+'/' : args.dest : opts.dest opts.noscope = args.noscope ? true : false +const tab = ' ' const files = glob.sync('**/*.vue', { ignore: opts.ignore }) - files.forEach(file => { const pathParse = path.parse(file) @@ -182,7 +180,7 @@ files.forEach(file => { if (match) { // there is a default export, append template to it script = script.replace( - match[0], match[0] + '\n' + opts.tab + templateString + match[0], match[0] + '\n' + tab + templateString ) } else { warnings.push('can\'t find default export')