grunt-single-file-component
A small grunt task which lets you keep all the assets of your component in a (custom) single file
Inspired by VUE.
Getting Started
If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a Gruntfile as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
npm install grunt-single-file-component --save-dev
One the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
grunt;
Options
dstBase (optional)
Type: string
Default: undefined
The base folder of all the (relative) dst
paths.
exts (optional)
Type: object
Default:
template: '.html' script: '.js' style: '.css'
Defines the file extension for the output files if dst
is a directory. Notes:
- The object you passed will be merged with the defaults.
- Dot prefix can be omitted.
DEPRECATED use processor.ext
instead!
processors
Type: object
Requires or defines processors.
About processors in general
Basically processors are functions to do the transformation of the node content. During transpiling the content of each component node will be passed to the corresponding processor (identified by the lang
or processor
[deprecated] attribute).
Processors have only one parameter:
- content [
string
]: The content of the current node to be transpiled - retVal [
string | Promise<string>
]: The transpiled content to be written out
They may have the following properties:
id
: The unique id of the processor (e.g. "pug")ext
: The extension of the output file (e.g. ".html"). Notes:- If presents it overrides the corresponding
exts
option. - Dot prefix can be omitted.
- If presents it overrides the corresponding
onTranspileStart
: An optional hook to be executed before the transpiling process (see below)onTranspileEnd
: An optional hook to be executed after the transpiling process
Defining processors
You can define a processor by adding an entry to the processors
object in the form of id: processor
. In this case you can omit the id
property.
Example:
processors: pug: render
or
const renderPug = render;processors: pug: Object
Requiring processors
You can require a processor by adding an entry in the form of idOrPathOfFactory: optionsObject
. In this case the system tries to load and execute the processor factory with the given options. Processor factory must return a processor function.
Example:
pug-processor.js
:
const pug = ; module { return Object;};
gruntfile.js
:
processors: 'pug-processor': basedir: '...' scope: {}
onTranspileStart (optional)
Type: function | function[]
Default: []
Fired before transpiling with the following parameters:
- fileName: The current component file
- nodesToProcess: The nodes about to processing
onTranspileEnd (optional)
Type: function | function[]
Default: []
Fired after transpiling with the following parameters:
- fileName: The current component file
- nodesProcessed: The successfully processed nodes
quiet (optional)
Type: boolean
Default: false
Tells the system whether or not output messages to the console.
Processor context
Each processor has its own context (accessible via this
) during execution. This context has the following properties:
name
Type: string
The name of the current node (e.g. "template").
dst
Type: string
The destination file (of the output). Valid only if the dst
attribute is set on the current node.
attrs
Type: object
All the attributes (e.g. "dst") of the current node (including custom ones).
content
Type: string
The content of the current node.
processor
Type: function
The processor currently being executed.
startIndex
Type: int
The start index of the current node.
endIndex
Type: int
The end index of the current node.
nodeStart
Type: int
The start line of the current node.
nodeEnd
Type: int
The end line of the current node.
contentStart
Type: int
The start line of the content.
contentEnd
Type: int
The end line of the content.
Usage Example
In your project's Gruntfile, add a section named sfc
to the data object passed into grunt.initConfig()
:
grunt;
dummy.component
:
<!-- Notes: 0) Node names must be unique (per component) 1) If "lang" is omitted the raw node content will be used 2) If "dst" is omitted the output of the processor will be treated as void 3) The output file will be named "dummy.html" (because "dst" is a folder) 4) Without "dstBase" "dst" should be "<%= project.dirs.dist %>/views/"-->.foo .bar XxX <!-- Notes: 0) The output file will be named "logic.js" (because "dst" is a file)-->console.log('kerekesfacapa');...
Getting the correct line numbers (example)
In the following snippet we're using ESLint to validate .js
files. Since the linter knows nothing about our component we have to fix the report line numbers manually:
const eslint = ;grunt;{ const engine = outputFile: false quiet: false maxWarnings: -1 failOnError: true configFile: 'eslint.json' formatter = CLIEngine; this{ const errorCount results = engine; results; gruntlog; if errorCount throw 'aborted by ESLint'; };}
Referencing the template URL from your script (example)
Sometimes it can be useful not to hardcode the template path into your script. The following code does the trick:
const path = ;grunt;
Referencing the template content from your script (example)
For example in AngularJS the template can be included in the js file. To achieve this we compile the template first and then we interpolate it back into the script:
dummy.ng
:
<!-- Since the order is matter, we have to put the template on the first place so the compiled HTML will be accessible to the following processors.-->.foo .bar XxX console.log($$TEMPLATE$$);...
gruntfile.js
:
grunt;
Sample processors
In this section you can see a set of sample processors. They are not intended to have their own repository, I just aim them to be a good starting point.
pug-processor.js
:
{const pug = ; module { return Object;}; }module require;
sass-processor.js
:
{const sass = ; module { return Object;}; }module require;
js-processor.js
:
{const path = eslint = ; // check the implementation out before module { return Object; { const scp = Object result = src; eslint; return result; } { const template = ; if !template return; const script = ; if !script return; const dst attrs: dst: originalDst = template; scripttemplateUrl = ? originalDst // ".posix" is necessary for proper separating : pathposix; {return nodes;} {return !!pathext;} {return pathbase;} }}; }module require;
Release History
- 0.0.1: Initial release
- 0.0.2: Fixed file naming issue
- 0.0.3: Improved performance
- 0.0.4: Fixed node parsing issue
- 0.0.5: Small improvements
- 0.0.6: User defined file extensions (
exts
) are now merged with the defaults - 0.0.7:
- Fixed line ending issue
- Processor context
- 0.0.8: Added
dstBase
option - 0.0.9: Added
onTranspileStart
andonTranspileEnd
hooks - 0.0.10:
- Processors can return falsy
- More detailed readme
- 0.0.11:
dst
is back - 0.0.12: Fixed missing grunt.template.process() call
- 0.0.13: Added
quiet
option - 0.0.14:
onTranspileStart
andonTranspileEnd
can be func[] - 0.0.15:
- Sample processors
- Empty nodes are skipped
- 0.0.16:
- You can suppress
dstBase
by using absolute path - Treat empty
dst
as a valid path
- You can suppress
- 0.0.17: Processors can be queried
- 0.0.18: Small refactor
- 0.0.19:
processor
attribute is DEPRECATED uselang
insteadlang
andprocessor
attributes are not mandatory anymore- Async processor support
- 0.0.20: Fixed error on task loading
- 0.0.21:
- Nodes can contain empty attributes (e.g.
scoped
) processor.ext
does not have to be dot prefixed
- Nodes can contain empty attributes (e.g.