-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(index): support
posthtml.config.js
&& result.messages
- Loading branch information
1 parent
7bd5896
commit e05b44c
Showing
3 changed files
with
187 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class LoaderError extends Error { | ||
constructor(err) { | ||
super(err); | ||
|
||
this.name = 'PostHTML Loader'; | ||
this.message = `\n\n${err.message}\n`; | ||
|
||
// TODO(michael-ciniawsky) | ||
// add 'SyntaxError', 'PluginError', 'PluginWarning' | ||
|
||
Error.captureStackTrace(this, this.constructor); | ||
} | ||
} | ||
|
||
module.exports = LoaderError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,163 @@ | ||
'use strict' | ||
|
||
const path = require('path') | ||
|
||
const loaderUtils = require('loader-utils') | ||
const validateOptions = require('schema-utils') | ||
|
||
const schema = require('./options.json') | ||
|
||
const posthtml = require('posthtml') | ||
const posthtmlrc = require('posthtml-load-config') | ||
|
||
module.exports = function (source) { | ||
if (this.cacheable) this.cacheable() | ||
const parseOptions = require('./options') | ||
|
||
// configure options | ||
const qs = loaderUtils.parseQuery(this.query) | ||
const LoaderError = require('./Error') | ||
/** | ||
* PostHTML Loader | ||
* | ||
* @author Michael Ciniawsky <michael.ciniawsky@gmail.com> (@michael-ciniawsky) | ||
* @license MIT | ||
* | ||
* @version 1.0.0 | ||
* | ||
* @requires loader-utils | ||
* @requires schema-utils | ||
* | ||
* @requires posthtml | ||
* @requires posthtml-load-config | ||
* | ||
* @method posthtml-loader | ||
* | ||
* @param {String} html HTML | ||
* | ||
* @return {String} html HTML | ||
*/ | ||
module.exports = function loader (html, map, meta) { | ||
// Loader Options | ||
const options = loaderUtils.getOptions(this) || {} | ||
|
||
validateOptions(schema, options, 'PostHTML Loader') | ||
|
||
// Make the loader async | ||
const cb = this.async() | ||
let config | ||
try { | ||
config = parseOptions.call(this, this.options.posthtml, qs) | ||
} catch (err) { | ||
return cb(err) | ||
} | ||
|
||
// configure custom parser argument if necessary | ||
const processArgs = [source.toString()] | ||
if (config.parser) { processArgs.push({ parser: config.parser }) } | ||
|
||
// run posthtml | ||
const ph = posthtml(config.plugins) | ||
ph.process.apply(ph, processArgs) | ||
.then((result) => cb(null, result.html), cb) | ||
} | ||
const file = this.resourcePath | ||
|
||
function parseOptions (config = [], qs = {}) { | ||
const res = {} | ||
Promise.resolve().then(() => { | ||
const length = Object.keys(options) | ||
.filter((option) => { | ||
switch (option) { | ||
case 'ident': | ||
case 'config': | ||
return | ||
default: | ||
return option | ||
} | ||
}) | ||
.length | ||
|
||
// if we have a function, run it | ||
if (typeof config === 'function') { config = config.call(this, this) } | ||
if (length) { | ||
return parseOptions.call(this, options) | ||
} | ||
|
||
// if it's not an object at this point, error | ||
if (typeof config !== 'object') { | ||
throw new Error('Configuration must return an array or object') | ||
} | ||
const rc = { | ||
path: path.dirname(file), | ||
ctx: { | ||
file: { | ||
extname: path.extname(file), | ||
dirname: path.dirname(file), | ||
basename: path.basename(file) | ||
}, | ||
options: {} | ||
} | ||
} | ||
|
||
// if we now have an array, that represents the plugins directly | ||
if (Array.isArray(config)) { | ||
res.plugins = config | ||
// if not, it's an object. if a plugin pack is being used, use it. | ||
// otherwise, use default plugins | ||
} else { | ||
res.plugins = qs.pack ? config[qs.pack] : config.plugins | ||
} | ||
if (options.config) { | ||
if (options.config.path) { | ||
rc.path = path.resolve(options.config.path) | ||
} | ||
|
||
// load in the custom parser if there is one | ||
if (config.parser) { res.parser = config.parser } | ||
if (options.config.ctx) { | ||
rc.ctx.options = options.config.ctx | ||
} | ||
} | ||
|
||
// try loading custom parser from query | ||
if (qs.parser) { | ||
res.parser = require(qs.parser) | ||
} | ||
return posthtmlrc(rc.ctx, rc.path, { argv: false }) | ||
}) | ||
.then((config) => { | ||
if (!config) config = {} | ||
|
||
return res | ||
} | ||
if (config.file) this.addDependency(config.file) | ||
|
||
if (config.options) { | ||
// Disable overriding `options.to` (`posthtml.config.js`) | ||
if (config.options.to) delete config.options.to | ||
// Disable overriding `options.from` (`posthtml.config.js`) | ||
if (config.options.from) delete config.options.from | ||
} | ||
|
||
let plugins = config.plugins || [] | ||
let options = Object.assign( | ||
{ from: file, to: file }, | ||
config.options | ||
) | ||
|
||
if (typeof options.parser === 'string') { | ||
options.parser = require(options.parser)() | ||
} | ||
|
||
// TODO(michael-ciniawsky) enable if when custom renderer available | ||
// if (typeof options.render === 'string') { | ||
// options.render = require(options.render)() | ||
// } | ||
|
||
return posthtml(plugins) | ||
.process(html, options) | ||
.then((result) => { | ||
if (result.messages) { | ||
result.messages.forEach((msg) => { | ||
switch (msg.type) { | ||
case 'error': | ||
this.emitError(msg.message) | ||
|
||
module.exports.parseOptions = parseOptions | ||
break | ||
case 'warning': | ||
this.emitWarning(msg.message) | ||
|
||
break | ||
case 'dependency': | ||
this.addDependency(msg.file) | ||
|
||
break | ||
default: | ||
break | ||
} | ||
}) | ||
} | ||
|
||
html = result.html | ||
|
||
if (this.loaderIndex === 0) { | ||
html = `export default \`${html}\`` | ||
|
||
cb(null, html) | ||
|
||
return null | ||
} | ||
|
||
if (!meta) meta = {} | ||
|
||
meta.ast = { type: 'posthtml', root: result.tree } | ||
meta.messages = result.messages | ||
|
||
cb(null, html, map, meta) | ||
|
||
return null | ||
}) | ||
}) | ||
.catch((err) => { | ||
cb(new LoaderError(err)) | ||
|
||
return null | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
'use strict' | ||
|
||
module.exports = function parseOptions (params) { | ||
if (typeof params.plugins === 'function') { | ||
params.plugins = params.plugins.call(this, this) | ||
} | ||
|
||
let plugins | ||
|
||
if (typeof params.plugins === 'undefined') plugins = [] | ||
else if (Array.isArray(params.plugins)) plugins = params.plugins | ||
else plugins = [ params.plugins ] | ||
|
||
const options = {} | ||
|
||
if (typeof params !== 'undefined') { | ||
options.parser = params.parser | ||
// options.render = params.render | ||
} | ||
|
||
return Promise.resolve({ options: options, plugins: plugins }) | ||
} |