babelute-html-string-pragmatics
Version:
String output engine for babelute-html-lexicon
331 lines (249 loc) • 7.63 kB
JavaScript
import babelute from 'babelute';
import htmlLexicon from 'babelute-html-lexicon';
/**
* Export.
*/
var index$3 = toNoCase;
/**
* Test whether a string is camel-case.
*/
var hasSpace = /\s/;
var hasSeparator = /(_|-|\.|:)/;
var hasCamel = /([a-z][A-Z]|[A-Z][a-z])/;
/**
* Remove any starting case from a `string`, like camel or snake, but keep
* spaces and punctuation that may be important otherwise.
*
* @param {String} string
* @return {String}
*/
function toNoCase(string) {
if (hasSpace.test(string)) return string.toLowerCase();
if (hasSeparator.test(string)) return (unseparate(string) || string).toLowerCase();
if (hasCamel.test(string)) return uncamelize(string).toLowerCase();
return string.toLowerCase();
}
/**
* Separator splitter.
*/
var separatorSplitter = /[\W_]+(.|$)/g;
/**
* Un-separate a `string`.
*
* @param {String} string
* @return {String}
*/
function unseparate(string) {
return string.replace(separatorSplitter, function (m, next) {
return next ? ' ' + next : '';
});
}
/**
* Camelcase splitter.
*/
var camelSplitter = /(.)([A-Z]+)/g;
/**
* Un-camelcase a `string`.
*
* @param {String} string
* @return {String}
*/
function uncamelize(string) {
return string.replace(camelSplitter, function (m, previous, uppers) {
return previous + ' ' + uppers.toLowerCase().split('').join(' ');
});
}
/**
* Export.
*/
var index$1 = toSpaceCase;
/**
* Convert a `string` to space case.
*
* @param {String} string
* @return {String}
*/
function toSpaceCase(string) {
return index$3(string).replace(/[\W_]+(.|$)/g, function (matches, match) {
return match ? ' ' + match : '';
}).trim();
}
/**
* Export.
*/
var index = toSlugCase;
/**
* Convert a `string` to slug case.
*
* @param {String} string
* @return {String}
*/
function toSlugCase(string) {
return index$1(string).replace(/\s/g, '-');
}
/**
* Encode and decode html special chars : aka (&,<,>,\",') from/to (&,<,...)
*
* Useful for html string output.
*/
var mapEncode = {
"&": "&",
"<": "<",
">": ">",
"\"": """,
"'": "'" // ' -> ' for XML only
};
var mapDecode = {
"&": "&",
"<": "<",
">": ">",
""": "\"",
"'": "'"
};
var htmlSpecialChars = {
encode: function encode(str) {
return str.replace(/[&<>"']/g, function (m) {
return mapEncode[m];
});
},
decode: function decode(str) {
return str.replace(/(&|<|>|"|')/g, function (m) {
return mapDecode[m];
});
}
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
/**
************* HTML-to-String Actions ***********
*
* @author Gilles Coomans
* @licence MIT
* @copyright 2016-2017 Gilles Coomans
*/
var $baseOutput = babelute.FacadePragmatics.prototype.$output;
/**
* html-to-string pragmatics
* @type {FacadePragmatics}
* @public
* @example
* import stringPragmas from 'babelute-html/src/html-to-string.js';
* import htmlLexicon from 'babelute-html/src/html-lexicon.js';
*
* const h = htmlLexicon.initializer;
* const sentence = h.div(state.intro).section(h.class('my-section').h1(state.title));
*
* var stringOutput = stringPragmas.$output(null, sentence);
*/
var stringPragmas = babelute.createFacadePragmatics({
html: true
}, {
// we only need logical atoms definitions. (without user interactions. aka click etc.)
tag: function tag(_tag, args /* tagName, babelutes */, component) {
var child = new TagDescriptor(),
babelutes = args[1];
var templ = void 0;
if (babelutes) for (var i = 0, len = babelutes.length; i < len; ++i) {
templ = babelutes[i];
if (typeof templ === 'undefined') continue;
if (templ && templ.__babelute__) this.$output(child, templ, component);else if (typeof templ === 'string') child.children += htmlSpecialChars.encode(templ); //.replace(/</g, '<').replace(/>/g, '>');
else child.children += templ;
}
tagOutput(_tag, child, args[0]);
},
text: function text(tag, args /* value */) {
tag.children += htmlSpecialChars.encode(args[0]);
},
class: function _class(tag, args /* className */) {
if (args[0] && (args.length === 1 || args[1])) tag.classes += (tag.classes ? ' ' : '') + args[0];
},
classes: function classes(tag, args /* className */) {
tag.classes += (tag.classes ? ' ' : '') + args[0];
},
style: function style(tag, args /* name, value */) {
tag.style += args[0] + ':' + args[1] + ';';
},
prop: function prop(tag, args) {
if (args[1]) tag.attributes += ' ' + args[0];
},
data: function data(tag, args) {
var name = 'data-' + index(args[0]),
value = args[1],
hasValue = typeof value !== 'undefined';
tag.attributes += ' ' + name + (hasValue ? '="' + value + '"' : '');
},
attr: function attr(tag, args /* name, value */) {
var value = args[1];
// tag.attributes += ' ' + args[0] + '="' + (typeof value === 'string' ? encodeHtmlSpecialChars(value) : value) + '"';
tag.attributes += ' ' + args[0] + '="' + (typeof value === 'string' ? value.replace(/"/g, '\\"').replace(/</g, '<').replace(/>/g, '>') : value) + '"';
},
id: function id(tag, args /* value */) {
tag.attributes = ' id="' + args[0] + '"' + tag.attributes;
},
html: function html(tag, args) {
tag.children += args[0]; // TODO : should be sanitize
},
onString: function onString(tag, args /* render */, component) {
var onRender = args[0];
if (onRender) onRender(tag, component);
},
ref: function ref(tag, args, component) {
component[args[0]] = tag;
},
component: function component(descriptor, args, parent) {
var Class = args[0],
props = args[1],
instance = new Class(props, parent);
this.$output(descriptor, instance.render(false), instance);
},
postalComponent: function postalComponent() {
// nothing to do
},
container: function container(descriptor, args, parent) {
this.$output(descriptor, args[0]({
unmount: function unmount() {}
}), parent);
},
switchUse: function switchUse(descriptor, args, parent) {
var _ref;
var b = (_ref = new babelute.Babelute())._use.apply(_ref, [args[0]].concat(toConsumableArray(args[1])));
this.$output(descriptor, b, parent);
},
$output: function $output(tag, babelute$$1, component) {
return $baseOutput.call(this, tag || new TagDescriptor(), babelute$$1, component).children;
}
});
// for tags string construction
var TagDescriptor = function TagDescriptor() {
classCallCheck(this, TagDescriptor);
this.children = '';
this.classes = '';
this.style = '';
this.attributes = '';
};
var selfClosingTags = /area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr/;
// TagDescriptor-to-string output
function tagOutput(parent, tag, name) {
var out = '<' + name + tag.attributes;
if (tag.style) out += ' style="' + tag.style + '"';
if (tag.classes) out += ' class="' + tag.classes + '"';
if (tag.children) parent.children += out + '>' + tag.children + '</' + name + '>';else if (selfClosingTags.test(name)) parent.children += out + '/>';else parent.children += out + '></' + name + '>';
}
htmlLexicon.addAliases({
$toHTMLString: function $toHTMLString(domElement) {
return stringPragmas.$output(domElement, this);
}
});
export default stringPragmas;
//# sourceMappingURL=index.mjs.map