Skip to content

Instantly share code, notes, and snippets.

@MKRhere
Last active November 26, 2018 12:52
Show Gist options
  • Save MKRhere/23611e824bde92d82e361585f71470d6 to your computer and use it in GitHub Desktop.
Save MKRhere/23611e824bde92d82e361585f71470d6 to your computer and use it in GitHub Desktop.
HTML to SXML
#!/usr/bin/env node
/* USAGE:
* html2sxml /path/to/index.html > output.sxml
* html2sxml < input.html > output.sxml
*/
'use strict';
const path = require("path");
const { PassThrough } = require("stream");
const htmlparser = require("htmlparser2");
const html2sxml = input => {
const output = new PassThrough();
output.write(";generated by html2sxml\n")
output.write(";https://github.com/aditi/util\n");
let indentLevel = 0;
const parser = new htmlparser.Parser({
onopentag (name, attr) {
output.write("\n" + "\t".repeat(indentLevel++) + `(${name}`);
let attrKeys = Object.keys(attr);
if (attrKeys.length) {
let selector = "";
if (attr.id) selector += "#" + attr.id.split(" ").join("#");
if (attr.class) selector += "." + attr.class.split(" ").join(".");
if (selector) output.write(selector);
attrKeys = attrKeys.filter(name => ![ "class", "id" ].includes(name));
if (attrKeys.length) {
output.write(" (@ ");
attrKeys.forEach(name => output.write(`(${name} "${attr[name]}") `));
output.write(")");
}
}
},
oncomment (comments) {
(comments = comments.trim())
&& comments.split("\n")
.forEach(comment =>
output.write(
"\n; " + "\t".repeat(indentLevel) + comment.trim()
// Strip whitespace and prepend ; to every line of comment
)
);
},
ontext (text) {
text.trim() && output.write(
` "${text.replace(/"/g, String.raw`\"`)}"`
);
},
onclosetag () {
output.write(")");
indentLevel--;
},
onend () {
output.write("\n");
}
}, { decodeEntities: true });
input.pipe(parser);
return output;
};
if (require.main === module) {
if (process.argv[2]) {
if (process.argv[2].match(/.*htm(|l)$/)) {
// mode = 'file'
let pathToFile = process.argv[2];
if (!path.isAbsolute(pathToFile)) {
pathToFile = path.resolve(`${process.cwd()}/${process.argv[2]}`);
}
html2sxml(require("fs").createReadStream(pathToFile, "utf8"))
.pipe(process.stdout);
} else {
console.error("Path not a HTML file");
process.exit(1);
}
} else {
// mode = 'stdin'
html2sxml(process.stdin).pipe(process.stdout);
}
}
module.exports = html2sxml;
@MKRhere
Copy link
Author

MKRhere commented Nov 26, 2018

Note: The SXML output produced by this module is not fully compliant with SXML spec[1][2]. It is in fact a variant of SXML used as a DSL in the aditi blog engine. I might name this variant ASX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment