const posthtml = require("posthtml");
const { imports, urls } = require("@posthtml/esm");
const {
HTMLURLDependency,
HTMLImportDependency,
HTMLExportDependency
} = require("./dependencies");
const SingleEntryPlugin = require("../SingleEntryPlugin");
const { OriginalSource } = require("webpack-sources");
const isDependency = msg => {
return (
msg.type.includes("import") ||
msg.type.includes("export") ||
msg.type.includes("entry")
);
};
// Move to @posthtml/esm
const entries = options => {
return function entries(tree) {
let idx = 0;
tree.match({ tag: "script" }, node => {
if (node.attrs) {
delete node.attrs.entry;
tree.messages.push({
type: "entry",
plugin: "@posthtml/esm",
url: node.attrs.src,
name: `HTML__ENTRY__${idx}`
});
node.attrs.src = "${" + `HTML__ENTRY__${idx}` + "}";
}
idx++;
return node;
});
return tree;
};
};
class HTMLParser {
constructor(options = {}) {
this.options = options;
}
parse(source, state, cb) {
const plugins = [
entries(),
urls({
url: /ENTRY/
}),
imports({
imports: true
})
];
const options = {
to: state.module.resource,
from: state.module.resource
};
posthtml(plugins)
.process(source, options)
.then(({ tree, html, messages }) => {
state.module._ast = tree;
state.module._source = new OriginalSource(html);
const dependencies = messages.filter(isDependency);
// HACK PostHTML Bug (#250)
messages.length = 0;
return dependencies.reduce(
(done, dep) =>
new Promise((resolve, reject) => {
if (dep.name.includes("HTML__ENTRY")) {
const dependency = SingleEntryPlugin.createDependency(
dep.url,
dep.name
);
state.compilation.addEntry(
state.module.context,
dependency,
dep.name,
err => {
if (err) reject(err);
resolve();
}
);
}
if (dep.name.includes("HTML__URL")) {
const dependency = new HTMLURLDependency(dep.url, dep.name);
state.module.addDependency(dependency, err => {
if (err) reject(err);
resolve();
});
}
if (dep.name.includes("HTML__IMPORT")) {
const dependency = new HTMLImportDependency(dep.url, dep.name);
state.module.addDependency(dependency, err => {
if (err) reject(err);
resolve();
});
}
if (dep.name.includes("HTML__EXPORT")) {
const dependency = new HTMLExportDependency(
dep.export(),
dep.name
);
state.module.addDependency(dependency, err => {
if (err) reject(err);
resolve();
});
}
resolve();
}),
Promise.resolve()
);
})
.then(() => cb(null, state))
.catch(err => cb(err));
}
}
module.exports = HTMLParser;