├── .gitignore ├── .travis.yml ├── README.md ├── index.js ├── lib └── svg-namespaces.js ├── package.json └── test └── index_test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # html2hscript 2 | 3 | Parse html to hyperscript library. 4 | 5 | [![Build Status](https://travis-ci.org/twilson63/html2hscript.svg?branch=master)](https://travis-ci.org/twilson63/html2hscript) 6 | 7 | ## Usage 8 | 9 | ``` js 10 | var parser = require('html2hscript'); 11 | parser('

Hello World

', function(err, hscript) { 12 | console.log(hscript); 13 | }); 14 | ``` 15 | 16 | ## Install 17 | 18 | ``` sh 19 | npm install html2hscript 20 | ``` 21 | 22 | ## Test 23 | 24 | ``` sh 25 | npm test 26 | ``` 27 | 28 | ## Support 29 | 30 | Submit Issue in Github 31 | 32 | ## Contributions 33 | 34 | Pull Requests are welcome 35 | 36 | ## License 37 | 38 | MIT 39 | 40 | ## Thanks 41 | 42 | [https://www.npmjs.com/~unframework](https://www.npmjs.com/~unframework) who wrote the parsing code. 43 | 44 | [https://www.npmjs.com/~dominictarr](https://www.npmjs.com/~dominictarr) who wrote hyperscript. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // code pulled from https://www.npmjs.com/package/html2hyperscript 2 | var Parser = require('htmlparser2').Parser; 3 | var camel = require('to-camel-case'); 4 | var ent = require('ent'); 5 | var isEmpty = require('is-empty'); 6 | var thisIsSVGTag = require('./lib/svg-namespaces').thisIsSVGTag, 7 | getSVGNamespace = require('./lib/svg-namespaces').getSVGNamespace, 8 | getSVGAttributeNamespace = require('./lib/svg-namespaces').getSVGAttributeNamespace; 9 | 10 | var elementStack = []; 11 | 12 | function ItemList(parent) { 13 | this.parent = parent; 14 | this.content = ''; 15 | this.spacer = ''; 16 | this.indent = parent ? parent.indent : ''; 17 | this.isFirstItem = true; 18 | } 19 | 20 | ItemList.prototype.addSpace = function (space) { 21 | this.spacer += space; 22 | 23 | if (space.indexOf("\n") !== -1) { 24 | // reset indent when there are new lines 25 | this.indent = /[^\n]*$/.exec(space)[0]; 26 | } else { 27 | // otherwise keep appending to current indent 28 | this.indent += space; 29 | } 30 | } 31 | 32 | ItemList.prototype.add = function (data, ignoreComma) { 33 | if (!ignoreComma) { 34 | if (!this.isFirstItem) { 35 | this.content += this.spacer.length ? ',' : ', '; 36 | } 37 | 38 | this.isFirstItem = false; 39 | } 40 | 41 | this.content += this.spacer; 42 | this.spacer = ''; 43 | 44 | this.content += data; 45 | } 46 | 47 | module.exports = function(html, cb) { 48 | var currentItemList = new ItemList(null); 49 | 50 | var parser = new Parser({ 51 | onopentag: function (name, attribs) { 52 | currentItemList = new ItemList(currentItemList); 53 | elementStack.unshift([ name, attribs ]); 54 | }, 55 | ontext: function (text) { 56 | currentItemList.add(JSON.stringify(ent.decode(text))); 57 | /*var lines = text.split("\n"); 58 | 59 | var isFirst = true; 60 | 61 | lines.forEach(function (line) { 62 | var lineMatch = /^(\s*)(.*?)(\s*)$/.exec(line); 63 | 64 | var preSpace = lineMatch[1], 65 | mainText = lineMatch[2], 66 | postSpace = lineMatch[3]; 67 | 68 | if (!isFirst) { 69 | currentItemList.addSpace("\n"); 70 | } 71 | 72 | currentItemList.addSpace(preSpace); 73 | 74 | if (mainText.length > 0) { 75 | currentItemList.add(JSON.stringify(mainText)); 76 | } 77 | 78 | isFirst = false; 79 | });*/ 80 | }, 81 | onclosetag: function (tagname) { 82 | var element = elementStack.shift(); 83 | var elementContent = currentItemList.content + currentItemList.spacer; 84 | 85 | currentItemList = currentItemList.parent; 86 | 87 | var indent = currentItemList.indent; 88 | 89 | var attribs = element[1]; 90 | 91 | var id = attribs['id']; 92 | 93 | var idSuffix = id !== undefined ? '#' + id : ''; 94 | delete attribs['id']; 95 | 96 | var classNames = attribs['class']; 97 | var classSuffix; 98 | if ( !thisIsSVGTag( element[ 0 ] ) ) { 99 | classSuffix = (classNames !== undefined ? classNames : '').split(/\s+/g).filter(function(v) { 100 | return v.length > 0; 101 | }).map(function(cls) { 102 | return '.' + cls; 103 | }).join(''); 104 | delete attribs['class']; 105 | } else { 106 | classSuffix = ''; 107 | } 108 | // Convert inline CSS style attribute to an object 109 | if(attribs['style']){ 110 | var rules = attribs["style"].split(";"); 111 | attribs["style"] = {}; 112 | rules.forEach(function(rule){ 113 | var split = rule.split(":"); 114 | if(split.length == 2){ 115 | attribs["style"][split[0].trim()] = split[1].trim(); 116 | } 117 | }); 118 | } 119 | 120 | var style = attribs['style'] 121 | delete attribs['style'] 122 | 123 | var dataset = {}; 124 | var datasetKey; 125 | Object.keys(attribs).forEach(function (k) { 126 | if (k.slice(0, 5) === 'data-') { 127 | datasetKey = camel(k.slice(5)); 128 | dataset[datasetKey] = attribs[k]; 129 | delete attribs[k]; 130 | } 131 | }); 132 | 133 | var attrPairs = Object.keys( attribs ).map( function ( k ) { 134 | return JSON.stringify( k ) + ': ' + JSON.stringify( attribs[ k ] ) 135 | } ); 136 | var datasetPairs = Object.keys( dataset ).map( function ( k ) { 137 | return JSON.stringify( k ) + ': ' + JSON.stringify( dataset[ k ] ) 138 | } ); 139 | 140 | var objects = {} 141 | if (attribs.value) { 142 | objects.value = attribs.value; 143 | delete attribs.value; 144 | } 145 | if ( !isEmpty( style ) ) objects.style = style 146 | if ( !isEmpty( attribs ) ) objects.attributes = attribs 147 | if ( !isEmpty( dataset ) ) objects.dataset = dataset 148 | if ( thisIsSVGTag( element[ 0 ] ) ) { 149 | objects.namespace = getSVGNamespace(); 150 | 151 | Object.keys(attribs).forEach(function (k) { 152 | var namespace = getSVGAttributeNamespace(k); 153 | 154 | if (namespace === void 0) { // not a svg attribute 155 | return; 156 | } 157 | 158 | var value = objects.attributes[ k ]; 159 | 160 | if (typeof value !== 'string' && 161 | typeof value !== 'number' && 162 | typeof value !== 'boolean' 163 | ) { 164 | return; 165 | } 166 | 167 | if (namespace !== null) { // namespaced attribute 168 | objects[ k ] = 'SVGAttributeHook(\'' + namespace + '\',\'' + value + '\')'; 169 | } 170 | }); 171 | } 172 | var objectStr = !isEmpty(objects) ? JSON.stringify(objects) : "" 173 | 174 | var item = 'h(' + JSON.stringify(element[0] + idSuffix + classSuffix) + ( 175 | (objectStr !== "") ? ", " + objectStr : "" 176 | ) 177 | // attrPairs.length || datasetPairs.length 178 | // ? ", { \"attributes\": { " 179 | // : '' 180 | // ) + ( 181 | // attrPairs.length 182 | // ? attrPairs.join(",\n" + indent + ' ') 183 | // : '' 184 | // ) + ( 185 | // datasetPairs.length && attrPairs.length 186 | // ? ",\n" + indent + ' ' 187 | // : '' 188 | // ) + ( 189 | // datasetPairs.length 190 | // ? "\"dataset\": { " + datasetPairs.join(",\n" + indent + ' ') + "}" 191 | // : '' 192 | // ) + ( 193 | // attrPairs.length || datasetPairs.length 194 | // ? "}}" 195 | // : '' 196 | // ) 197 | 198 | + ( 199 | elementContent.length 200 | ? ', [' + (elementContent[0] === "\n" ? '' : ' ') + elementContent + (elementContent.match(/\s$/) ? '' : ' ') + ']' 201 | : '' 202 | ) + ')'; 203 | 204 | currentItemList.add(item); 205 | }, 206 | oncomment: function (text) { 207 | currentItemList.add('/*' + text + '*/', false); // @todo comment-safety 208 | }, 209 | onend: function () { 210 | cb(null, currentItemList.content); 211 | } 212 | }, {decodeEntities: true, xmlMode: true}); 213 | 214 | parser.write(html); 215 | parser.end(); 216 | } 217 | -------------------------------------------------------------------------------- /lib/svg-namespaces.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* 4 | Adapted from https://github.com/Matt-Esch/virtual-dom/blob/master/virtual-hyperscript/svg-attribute-namespace.js 5 | */ 6 | 7 | var DEFAULT_NAMESPACE = null; 8 | var SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; 9 | var EV_NAMESPACE = 'http://www.w3.org/2001/xml-events'; 10 | var XLINK_NAMESPACE = 'http://www.w3.org/1999/xlink'; 11 | var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'; 12 | 13 | // http://www.w3.org/TR/SVGTiny12/elementTable.html 14 | // http://www.w3.org/TR/SVG/eltindex.html 15 | var SVG_ELEMENTS = { 16 | 'listener': SVG_NAMESPACE, 17 | // 'a': SVG_NAMESPACE, 18 | 'animate': SVG_NAMESPACE, 19 | 'altGlyph': SVG_NAMESPACE, 20 | 'altGlyphDef': SVG_NAMESPACE, 21 | 'altGlyphItem': SVG_NAMESPACE, 22 | 'animateColor': SVG_NAMESPACE, 23 | 'animateMotion': SVG_NAMESPACE, 24 | 'animateTransform': SVG_NAMESPACE, 25 | 'animation': SVG_NAMESPACE, 26 | // 'audio': SVG_NAMESPACE, 27 | 'circle': SVG_NAMESPACE, 28 | 'defs': SVG_NAMESPACE, 29 | 'desc': SVG_NAMESPACE, 30 | 'discard': SVG_NAMESPACE, 31 | 'ellipse': SVG_NAMESPACE, 32 | 'feBlend': SVG_NAMESPACE, 33 | 'feColorMatrix': SVG_NAMESPACE, 34 | 'feComponentTransfer': SVG_NAMESPACE, 35 | 'feComposite': SVG_NAMESPACE, 36 | 'feConvolveMatrix': SVG_NAMESPACE, 37 | 'feDiffuseLighting': SVG_NAMESPACE, 38 | 'feDisplacementMap': SVG_NAMESPACE, 39 | 'feDistantLight': SVG_NAMESPACE, 40 | 'feFlood': SVG_NAMESPACE, 41 | 'feFuncA': SVG_NAMESPACE, 42 | 'feFuncB': SVG_NAMESPACE, 43 | 'feFuncG': SVG_NAMESPACE, 44 | 'feFuncR': SVG_NAMESPACE, 45 | 'feGaussianBlur': SVG_NAMESPACE, 46 | 'feImage': SVG_NAMESPACE, 47 | 'feMerge': SVG_NAMESPACE, 48 | 'feMergeNode': SVG_NAMESPACE, 49 | 'feMorphology': SVG_NAMESPACE, 50 | 'feOffset': SVG_NAMESPACE, 51 | 'fePointLight': SVG_NAMESPACE, 52 | 'feSpecularLighting': SVG_NAMESPACE, 53 | 'feSpotLight': SVG_NAMESPACE, 54 | 'feTile': SVG_NAMESPACE, 55 | 'feTurbulence': SVG_NAMESPACE, 56 | 'filter': SVG_NAMESPACE, 57 | 'font': SVG_NAMESPACE, 58 | 'font-face': SVG_NAMESPACE, 59 | 'font-face-format': SVG_NAMESPACE, 60 | 'font-face-name': SVG_NAMESPACE, 61 | 'font-face-src': SVG_NAMESPACE, 62 | 'font-face-uri': SVG_NAMESPACE, 63 | 'foreignObject': SVG_NAMESPACE, 64 | 'g': SVG_NAMESPACE, 65 | 'glyph': SVG_NAMESPACE, 66 | 'glyphRef': SVG_NAMESPACE, 67 | 'handler': SVG_NAMESPACE, 68 | 'hkern': SVG_NAMESPACE, 69 | 'image': SVG_NAMESPACE, 70 | 'line': SVG_NAMESPACE, 71 | 'linearGradient': SVG_NAMESPACE, 72 | 'metadata': SVG_NAMESPACE, 73 | 'missing-glyph': SVG_NAMESPACE, 74 | 'mpath': SVG_NAMESPACE, 75 | 'path': SVG_NAMESPACE, 76 | 'polygon': SVG_NAMESPACE, 77 | 'polyline': SVG_NAMESPACE, 78 | 'prefetch': SVG_NAMESPACE, 79 | 'radialGradient': SVG_NAMESPACE, 80 | 'rect': SVG_NAMESPACE, 81 | // 'script': SVG_NAMESPACE, 82 | 'set': SVG_NAMESPACE, 83 | 'solidColor': SVG_NAMESPACE, 84 | 'stop': SVG_NAMESPACE, 85 | 'svg': SVG_NAMESPACE, 86 | 'switch': SVG_NAMESPACE, 87 | 'symbol': SVG_NAMESPACE, 88 | 'tbreak': SVG_NAMESPACE, 89 | 'text': SVG_NAMESPACE, 90 | // 'textArea': SVG_NAMESPACE, 91 | 'title': SVG_NAMESPACE, 92 | 'tspan': SVG_NAMESPACE, 93 | 'tref': SVG_NAMESPACE, 94 | 'use': SVG_NAMESPACE, 95 | 'vkern': SVG_NAMESPACE, 96 | // 'video': SVG_NAMESPACE, 97 | }; 98 | 99 | // http://www.w3.org/TR/SVGTiny12/attributeTable.html 100 | // http://www.w3.org/TR/SVG/attindex.html 101 | var SVG_PROPERTIES = { 102 | 'about': DEFAULT_NAMESPACE, 103 | 'accent-height': DEFAULT_NAMESPACE, 104 | 'accumulate': DEFAULT_NAMESPACE, 105 | 'additive': DEFAULT_NAMESPACE, 106 | 'alignment-baseline': DEFAULT_NAMESPACE, 107 | 'alphabetic': DEFAULT_NAMESPACE, 108 | 'amplitude': DEFAULT_NAMESPACE, 109 | 'arabic-form': DEFAULT_NAMESPACE, 110 | 'ascent': DEFAULT_NAMESPACE, 111 | 'attributeName': DEFAULT_NAMESPACE, 112 | 'attributeType': DEFAULT_NAMESPACE, 113 | 'azimuth': DEFAULT_NAMESPACE, 114 | 'bandwidth': DEFAULT_NAMESPACE, 115 | 'baseFrequency': DEFAULT_NAMESPACE, 116 | 'baseProfile': DEFAULT_NAMESPACE, 117 | 'baseline-shift': DEFAULT_NAMESPACE, 118 | 'bbox': DEFAULT_NAMESPACE, 119 | 'begin': DEFAULT_NAMESPACE, 120 | 'bias': DEFAULT_NAMESPACE, 121 | 'by': DEFAULT_NAMESPACE, 122 | 'calcMode': DEFAULT_NAMESPACE, 123 | 'cap-height': DEFAULT_NAMESPACE, 124 | 'class': DEFAULT_NAMESPACE, 125 | 'clip': DEFAULT_NAMESPACE, 126 | 'clip-path': DEFAULT_NAMESPACE, 127 | 'clip-rule': DEFAULT_NAMESPACE, 128 | 'clipPathUnits': DEFAULT_NAMESPACE, 129 | 'color': DEFAULT_NAMESPACE, 130 | 'color-interpolation': DEFAULT_NAMESPACE, 131 | 'color-interpolation-filters': DEFAULT_NAMESPACE, 132 | 'color-profile': DEFAULT_NAMESPACE, 133 | 'color-rendering': DEFAULT_NAMESPACE, 134 | 'content': DEFAULT_NAMESPACE, 135 | 'contentScriptType': DEFAULT_NAMESPACE, 136 | 'contentStyleType': DEFAULT_NAMESPACE, 137 | 'cursor': DEFAULT_NAMESPACE, 138 | 'cx': DEFAULT_NAMESPACE, 139 | 'cy': DEFAULT_NAMESPACE, 140 | 'd': DEFAULT_NAMESPACE, 141 | 'datatype': DEFAULT_NAMESPACE, 142 | 'defaultAction': DEFAULT_NAMESPACE, 143 | 'descent': DEFAULT_NAMESPACE, 144 | 'diffuseConstant': DEFAULT_NAMESPACE, 145 | 'direction': DEFAULT_NAMESPACE, 146 | 'display': DEFAULT_NAMESPACE, 147 | 'divisor': DEFAULT_NAMESPACE, 148 | 'dominant-baseline': DEFAULT_NAMESPACE, 149 | 'dur': DEFAULT_NAMESPACE, 150 | 'dx': DEFAULT_NAMESPACE, 151 | 'dy': DEFAULT_NAMESPACE, 152 | 'edgeMode': DEFAULT_NAMESPACE, 153 | 'editable': DEFAULT_NAMESPACE, 154 | 'elevation': DEFAULT_NAMESPACE, 155 | 'enable-background': DEFAULT_NAMESPACE, 156 | 'end': DEFAULT_NAMESPACE, 157 | 'ev:event': EV_NAMESPACE, 158 | 'event': DEFAULT_NAMESPACE, 159 | 'exponent': DEFAULT_NAMESPACE, 160 | 'externalResourcesRequired': DEFAULT_NAMESPACE, 161 | 'fill': DEFAULT_NAMESPACE, 162 | 'fill-opacity': DEFAULT_NAMESPACE, 163 | 'fill-rule': DEFAULT_NAMESPACE, 164 | 'filter': DEFAULT_NAMESPACE, 165 | 'filterRes': DEFAULT_NAMESPACE, 166 | 'filterUnits': DEFAULT_NAMESPACE, 167 | 'flood-color': DEFAULT_NAMESPACE, 168 | 'flood-opacity': DEFAULT_NAMESPACE, 169 | 'focusHighlight': DEFAULT_NAMESPACE, 170 | 'focusable': DEFAULT_NAMESPACE, 171 | 'font-family': DEFAULT_NAMESPACE, 172 | 'font-size': DEFAULT_NAMESPACE, 173 | 'font-size-adjust': DEFAULT_NAMESPACE, 174 | 'font-stretch': DEFAULT_NAMESPACE, 175 | 'font-style': DEFAULT_NAMESPACE, 176 | 'font-variant': DEFAULT_NAMESPACE, 177 | 'font-weight': DEFAULT_NAMESPACE, 178 | 'format': DEFAULT_NAMESPACE, 179 | 'from': DEFAULT_NAMESPACE, 180 | 'fx': DEFAULT_NAMESPACE, 181 | 'fy': DEFAULT_NAMESPACE, 182 | 'g1': DEFAULT_NAMESPACE, 183 | 'g2': DEFAULT_NAMESPACE, 184 | 'glyph-name': DEFAULT_NAMESPACE, 185 | 'glyph-orientation-horizontal': DEFAULT_NAMESPACE, 186 | 'glyph-orientation-vertical': DEFAULT_NAMESPACE, 187 | 'glyphRef': DEFAULT_NAMESPACE, 188 | 'gradientTransform': DEFAULT_NAMESPACE, 189 | 'gradientUnits': DEFAULT_NAMESPACE, 190 | 'handler': DEFAULT_NAMESPACE, 191 | 'hanging': DEFAULT_NAMESPACE, 192 | 'height': DEFAULT_NAMESPACE, 193 | 'horiz-adv-x': DEFAULT_NAMESPACE, 194 | 'horiz-origin-x': DEFAULT_NAMESPACE, 195 | 'horiz-origin-y': DEFAULT_NAMESPACE, 196 | 'id': DEFAULT_NAMESPACE, 197 | 'ideographic': DEFAULT_NAMESPACE, 198 | 'image-rendering': DEFAULT_NAMESPACE, 199 | 'in': DEFAULT_NAMESPACE, 200 | 'in2': DEFAULT_NAMESPACE, 201 | 'initialVisibility': DEFAULT_NAMESPACE, 202 | 'intercept': DEFAULT_NAMESPACE, 203 | 'k': DEFAULT_NAMESPACE, 204 | 'k1': DEFAULT_NAMESPACE, 205 | 'k2': DEFAULT_NAMESPACE, 206 | 'k3': DEFAULT_NAMESPACE, 207 | 'k4': DEFAULT_NAMESPACE, 208 | 'kernelMatrix': DEFAULT_NAMESPACE, 209 | 'kernelUnitLength': DEFAULT_NAMESPACE, 210 | 'kerning': DEFAULT_NAMESPACE, 211 | 'keyPoints': DEFAULT_NAMESPACE, 212 | 'keySplines': DEFAULT_NAMESPACE, 213 | 'keyTimes': DEFAULT_NAMESPACE, 214 | 'lang': DEFAULT_NAMESPACE, 215 | 'lengthAdjust': DEFAULT_NAMESPACE, 216 | 'letter-spacing': DEFAULT_NAMESPACE, 217 | 'lighting-color': DEFAULT_NAMESPACE, 218 | 'limitingConeAngle': DEFAULT_NAMESPACE, 219 | 'local': DEFAULT_NAMESPACE, 220 | 'marker-end': DEFAULT_NAMESPACE, 221 | 'marker-mid': DEFAULT_NAMESPACE, 222 | 'marker-start': DEFAULT_NAMESPACE, 223 | 'markerHeight': DEFAULT_NAMESPACE, 224 | 'markerUnits': DEFAULT_NAMESPACE, 225 | 'markerWidth': DEFAULT_NAMESPACE, 226 | 'mask': DEFAULT_NAMESPACE, 227 | 'maskContentUnits': DEFAULT_NAMESPACE, 228 | 'maskUnits': DEFAULT_NAMESPACE, 229 | 'mathematical': DEFAULT_NAMESPACE, 230 | 'max': DEFAULT_NAMESPACE, 231 | 'media': DEFAULT_NAMESPACE, 232 | 'mediaCharacterEncoding': DEFAULT_NAMESPACE, 233 | 'mediaContentEncodings': DEFAULT_NAMESPACE, 234 | 'mediaSize': DEFAULT_NAMESPACE, 235 | 'mediaTime': DEFAULT_NAMESPACE, 236 | 'method': DEFAULT_NAMESPACE, 237 | 'min': DEFAULT_NAMESPACE, 238 | 'mode': DEFAULT_NAMESPACE, 239 | 'name': DEFAULT_NAMESPACE, 240 | 'nav-down': DEFAULT_NAMESPACE, 241 | 'nav-down-left': DEFAULT_NAMESPACE, 242 | 'nav-down-right': DEFAULT_NAMESPACE, 243 | 'nav-left': DEFAULT_NAMESPACE, 244 | 'nav-next': DEFAULT_NAMESPACE, 245 | 'nav-prev': DEFAULT_NAMESPACE, 246 | 'nav-right': DEFAULT_NAMESPACE, 247 | 'nav-up': DEFAULT_NAMESPACE, 248 | 'nav-up-left': DEFAULT_NAMESPACE, 249 | 'nav-up-right': DEFAULT_NAMESPACE, 250 | 'numOctaves': DEFAULT_NAMESPACE, 251 | 'observer': DEFAULT_NAMESPACE, 252 | 'offset': DEFAULT_NAMESPACE, 253 | 'opacity': DEFAULT_NAMESPACE, 254 | 'operator': DEFAULT_NAMESPACE, 255 | 'order': DEFAULT_NAMESPACE, 256 | 'orient': DEFAULT_NAMESPACE, 257 | 'orientation': DEFAULT_NAMESPACE, 258 | 'origin': DEFAULT_NAMESPACE, 259 | 'overflow': DEFAULT_NAMESPACE, 260 | 'overlay': DEFAULT_NAMESPACE, 261 | 'overline-position': DEFAULT_NAMESPACE, 262 | 'overline-thickness': DEFAULT_NAMESPACE, 263 | 'panose-1': DEFAULT_NAMESPACE, 264 | 'path': DEFAULT_NAMESPACE, 265 | 'pathLength': DEFAULT_NAMESPACE, 266 | 'patternContentUnits': DEFAULT_NAMESPACE, 267 | 'patternTransform': DEFAULT_NAMESPACE, 268 | 'patternUnits': DEFAULT_NAMESPACE, 269 | 'phase': DEFAULT_NAMESPACE, 270 | 'playbackOrder': DEFAULT_NAMESPACE, 271 | 'pointer-events': DEFAULT_NAMESPACE, 272 | 'points': DEFAULT_NAMESPACE, 273 | 'pointsAtX': DEFAULT_NAMESPACE, 274 | 'pointsAtY': DEFAULT_NAMESPACE, 275 | 'pointsAtZ': DEFAULT_NAMESPACE, 276 | 'preserveAlpha': DEFAULT_NAMESPACE, 277 | 'preserveAspectRatio': DEFAULT_NAMESPACE, 278 | 'primitiveUnits': DEFAULT_NAMESPACE, 279 | 'propagate': DEFAULT_NAMESPACE, 280 | 'property': DEFAULT_NAMESPACE, 281 | 'r': DEFAULT_NAMESPACE, 282 | 'radius': DEFAULT_NAMESPACE, 283 | 'refX': DEFAULT_NAMESPACE, 284 | 'refY': DEFAULT_NAMESPACE, 285 | 'rel': DEFAULT_NAMESPACE, 286 | 'rendering-intent': DEFAULT_NAMESPACE, 287 | 'repeatCount': DEFAULT_NAMESPACE, 288 | 'repeatDur': DEFAULT_NAMESPACE, 289 | 'requiredExtensions': DEFAULT_NAMESPACE, 290 | 'requiredFeatures': DEFAULT_NAMESPACE, 291 | 'requiredFonts': DEFAULT_NAMESPACE, 292 | 'requiredFormats': DEFAULT_NAMESPACE, 293 | 'resource': DEFAULT_NAMESPACE, 294 | 'restart': DEFAULT_NAMESPACE, 295 | 'result': DEFAULT_NAMESPACE, 296 | 'rev': DEFAULT_NAMESPACE, 297 | 'role': DEFAULT_NAMESPACE, 298 | 'rotate': DEFAULT_NAMESPACE, 299 | 'rx': DEFAULT_NAMESPACE, 300 | 'ry': DEFAULT_NAMESPACE, 301 | 'scale': DEFAULT_NAMESPACE, 302 | 'seed': DEFAULT_NAMESPACE, 303 | 'shape-rendering': DEFAULT_NAMESPACE, 304 | 'slope': DEFAULT_NAMESPACE, 305 | 'snapshotTime': DEFAULT_NAMESPACE, 306 | 'spacing': DEFAULT_NAMESPACE, 307 | 'specularConstant': DEFAULT_NAMESPACE, 308 | 'specularExponent': DEFAULT_NAMESPACE, 309 | 'spreadMethod': DEFAULT_NAMESPACE, 310 | 'startOffset': DEFAULT_NAMESPACE, 311 | 'stdDeviation': DEFAULT_NAMESPACE, 312 | 'stemh': DEFAULT_NAMESPACE, 313 | 'stemv': DEFAULT_NAMESPACE, 314 | 'stitchTiles': DEFAULT_NAMESPACE, 315 | 'stop-color': DEFAULT_NAMESPACE, 316 | 'stop-opacity': DEFAULT_NAMESPACE, 317 | 'strikethrough-position': DEFAULT_NAMESPACE, 318 | 'strikethrough-thickness': DEFAULT_NAMESPACE, 319 | 'string': DEFAULT_NAMESPACE, 320 | 'stroke': DEFAULT_NAMESPACE, 321 | 'stroke-dasharray': DEFAULT_NAMESPACE, 322 | 'stroke-dashoffset': DEFAULT_NAMESPACE, 323 | 'stroke-linecap': DEFAULT_NAMESPACE, 324 | 'stroke-linejoin': DEFAULT_NAMESPACE, 325 | 'stroke-miterlimit': DEFAULT_NAMESPACE, 326 | 'stroke-opacity': DEFAULT_NAMESPACE, 327 | 'stroke-width': DEFAULT_NAMESPACE, 328 | 'surfaceScale': DEFAULT_NAMESPACE, 329 | 'syncBehavior': DEFAULT_NAMESPACE, 330 | 'syncBehaviorDefault': DEFAULT_NAMESPACE, 331 | 'syncMaster': DEFAULT_NAMESPACE, 332 | 'syncTolerance': DEFAULT_NAMESPACE, 333 | 'syncToleranceDefault': DEFAULT_NAMESPACE, 334 | 'systemLanguage': DEFAULT_NAMESPACE, 335 | 'tableValues': DEFAULT_NAMESPACE, 336 | 'target': DEFAULT_NAMESPACE, 337 | 'targetX': DEFAULT_NAMESPACE, 338 | 'targetY': DEFAULT_NAMESPACE, 339 | 'text-anchor': DEFAULT_NAMESPACE, 340 | 'text-decoration': DEFAULT_NAMESPACE, 341 | 'text-rendering': DEFAULT_NAMESPACE, 342 | 'textLength': DEFAULT_NAMESPACE, 343 | 'timelineBegin': DEFAULT_NAMESPACE, 344 | 'title': DEFAULT_NAMESPACE, 345 | 'to': DEFAULT_NAMESPACE, 346 | 'transform': DEFAULT_NAMESPACE, 347 | 'transformBehavior': DEFAULT_NAMESPACE, 348 | 'type': DEFAULT_NAMESPACE, 349 | 'typeof': DEFAULT_NAMESPACE, 350 | 'u1': DEFAULT_NAMESPACE, 351 | 'u2': DEFAULT_NAMESPACE, 352 | 'underline-position': DEFAULT_NAMESPACE, 353 | 'underline-thickness': DEFAULT_NAMESPACE, 354 | 'unicode': DEFAULT_NAMESPACE, 355 | 'unicode-bidi': DEFAULT_NAMESPACE, 356 | 'unicode-range': DEFAULT_NAMESPACE, 357 | 'units-per-em': DEFAULT_NAMESPACE, 358 | 'v-alphabetic': DEFAULT_NAMESPACE, 359 | 'v-hanging': DEFAULT_NAMESPACE, 360 | 'v-ideographic': DEFAULT_NAMESPACE, 361 | 'v-mathematical': DEFAULT_NAMESPACE, 362 | 'values': DEFAULT_NAMESPACE, 363 | 'version': DEFAULT_NAMESPACE, 364 | 'vert-adv-y': DEFAULT_NAMESPACE, 365 | 'vert-origin-x': DEFAULT_NAMESPACE, 366 | 'vert-origin-y': DEFAULT_NAMESPACE, 367 | 'viewBox': DEFAULT_NAMESPACE, 368 | 'viewTarget': DEFAULT_NAMESPACE, 369 | 'visibility': DEFAULT_NAMESPACE, 370 | 'width': DEFAULT_NAMESPACE, 371 | 'widths': DEFAULT_NAMESPACE, 372 | 'word-spacing': DEFAULT_NAMESPACE, 373 | 'writing-mode': DEFAULT_NAMESPACE, 374 | 'x': DEFAULT_NAMESPACE, 375 | 'x-height': DEFAULT_NAMESPACE, 376 | 'x1': DEFAULT_NAMESPACE, 377 | 'x2': DEFAULT_NAMESPACE, 378 | 'xChannelSelector': DEFAULT_NAMESPACE, 379 | 'xlink:actuate': XLINK_NAMESPACE, 380 | 'xlink:arcrole': XLINK_NAMESPACE, 381 | 'xlink:href': XLINK_NAMESPACE, 382 | 'xlink:role': XLINK_NAMESPACE, 383 | 'xlink:show': XLINK_NAMESPACE, 384 | 'xlink:title': XLINK_NAMESPACE, 385 | 'xlink:type': XLINK_NAMESPACE, 386 | 'xml:base': XML_NAMESPACE, 387 | 'xml:id': XML_NAMESPACE, 388 | 'xml:lang': XML_NAMESPACE, 389 | 'xml:space': XML_NAMESPACE, 390 | 'y': DEFAULT_NAMESPACE, 391 | 'y1': DEFAULT_NAMESPACE, 392 | 'y2': DEFAULT_NAMESPACE, 393 | 'yChannelSelector': DEFAULT_NAMESPACE, 394 | 'z': DEFAULT_NAMESPACE, 395 | 'zoomAndPan': DEFAULT_NAMESPACE 396 | }; 397 | 398 | function thisIsSVGTag(tag) { 399 | return SVG_ELEMENTS.hasOwnProperty(tag); 400 | } 401 | 402 | function getSVGNamespace() { 403 | return SVG_NAMESPACE; 404 | } 405 | 406 | function getSVGAttributeNamespace(value) { 407 | if (SVG_PROPERTIES.hasOwnProperty(value)) { 408 | return SVG_PROPERTIES[value]; 409 | } 410 | } 411 | 412 | module.exports.thisIsSVGTag = thisIsSVGTag; 413 | 414 | module.exports.getSVGNamespace = getSVGNamespace; 415 | 416 | module.exports.getSVGAttributeNamespace = getSVGAttributeNamespace; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "html2hscript", 3 | "version": "2.0.0", 4 | "description": "parse html into hyperscript", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "dependencies": { 10 | "ent": "^2.2.0", 11 | "htmlparser2": "^3.8.2", 12 | "is-empty": "0.0.1", 13 | "to-camel-case": "^0.2.1" 14 | }, 15 | "devDependencies": { 16 | "tap": "^1.3.1" 17 | }, 18 | "scripts": { 19 | "test": "tap test/*.js" 20 | }, 21 | "keywords": [ 22 | "html", 23 | "parser", 24 | "hyperscript" 25 | ], 26 | "author": "https://www.npmjs.com/~unframework", 27 | "license": "MIT", 28 | "repository": { 29 | "type": "git", 30 | "url": "https://github.com/twilson63/html2hscript.git" 31 | }, 32 | "bugs": { 33 | "url": "https://github.com/twilson63/html2hscript/issues" 34 | }, 35 | "homepage": "https://github.com/twilson63/html2hscript" 36 | } 37 | -------------------------------------------------------------------------------- /test/index_test.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | var parser = require('../'); 3 | 4 | test('should return attributes', function(t) { 5 | parser('

Hello World

', function(err, hscript) { 6 | t.equals(hscript, 'h("h1", {"attributes":{"foo":"beep"}}, [ "Hello World" ])', 'success') 7 | t.end() 8 | }) 9 | }) 10 | 11 | test('should return hyperscript', function(t) { 12 | parser('

Hello World

', function(err, hscript) { 13 | t.equals(hscript, 'h("div", [ h("div", [ h("h1", {"attributes":{"foo":"beep"}}, [ "Hello World" ]) ]) ])', 'success') 14 | t.end() 15 | }) 16 | }) 17 | 18 | test('should return children', function(t) { 19 | parser('

Hello\nWorld

', function(err, hscript) { 20 | t.equals(hscript, 'h("p", [ "Hello\\n", h("b", [ "World" ]) ])', 'success') 21 | t.end() 22 | }) 23 | }) 24 | 25 | test('should handle correctly pre', function(t) { 26 | parser('
Hello\nWorld
', function(err, hscript) { 27 | t.equals(hscript, 'h("pre", [ "Hello\\nWorld" ])', 'success') 28 | t.end() 29 | }) 30 | }) 31 | 32 | test('should output style attribute as an object', function(t) { 33 | parser('

Hello World

', function(err, hscript) { 34 | t.equals(hscript, 'h("h1", {"style":{"color":"red","font-size":"12px"}}, [ "Hello World" ])', 'success') 35 | t.end() 36 | }) 37 | }) 38 | --------------------------------------------------------------------------------