From 22c0d89425ae2547288222c04403918b085e8d3e Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 28 May 2019 09:49:54 +0200 Subject: [PATCH] Add support for passing unadjusted tag names See: * The HTML tokenizer consumes ASCII upper alpha as lower alpha * SVG in HTML is therefore first lowercased, and afterwards has to be adjusted * The hast spec already described the local name must be used on elements Closes GH-11. --- build.js | 12 +++++++++ factory.js | 23 +++++++++++++++- package.json | 7 +++-- svg-case-sensitive-tag-names.json | 41 ++++++++++++++++++++++++++++ svg.js | 3 ++- test.js | 44 +++++++++++++++++++++++++++++++ 6 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 build.js create mode 100644 svg-case-sensitive-tag-names.json diff --git a/build.js b/build.js new file mode 100644 index 0000000..5373b05 --- /dev/null +++ b/build.js @@ -0,0 +1,12 @@ +'use strict' + +var fs = require('fs') +var tagNames = require('svg-tag-names') + +var casing = tagNames.filter(function(d) { + return d !== d.toLowerCase() +}) + +var doc = JSON.stringify(casing, null, 2) + '\n' + +fs.writeFileSync('./svg-case-sensitive-tag-names.json', doc) diff --git a/factory.js b/factory.js index 84f6a64..d1eea8e 100644 --- a/factory.js +++ b/factory.js @@ -8,15 +8,22 @@ var commas = require('comma-separated-tokens').parse module.exports = factory -function factory(schema, defaultTagName) { +var own = {}.hasOwnProperty + +function factory(schema, defaultTagName, caseSensitive) { + var adjust = caseSensitive ? createAdjustMap(caseSensitive) : null + return h // Hyperscript compatible DSL for creating virtual hast trees. function h(selector, properties) { var node = parseSelector(selector, defaultTagName) var children = Array.prototype.slice.call(arguments, 2) + var name = node.tagName.toLowerCase() var property + node.tagName = adjust && own.call(adjust, name) ? adjust[name] : name + if (properties && isChildren(properties, node)) { children.unshift(properties) properties = null @@ -189,3 +196,17 @@ function style(value) { return result.join('; ') } + +function createAdjustMap(values) { + var length = values.length + var index = -1 + var result = {} + var value + + while (++index < length) { + value = values[index] + result[value.toLowerCase()] = value + } + + return result +} diff --git a/package.json b/package.json index 6d3a0e3..c174f27 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "index.js", "factory.js", "html.js", - "svg.js" + "svg.js", + "svg-case-sensitive-tag-names.json" ], "dependencies": { "comma-separated-tokens": "^1.0.0", @@ -37,18 +38,20 @@ "prettier": "^1.0.0", "remark-cli": "^6.0.0", "remark-preset-wooorm": "^5.0.0", + "svg-tag-names": "^2.0.0", "tape": "^4.0.0", "tinyify": "^2.0.0", "xo": "^0.24.0" }, "scripts": { + "generate": "node build", "format": "remark . -qfo && prettier --write \"**/*.js\" && xo --fix", "build-bundle": "browserify . -s hastscript > hastscript.js", "build-mangle": "browserify . -s hastscript -p tinyify > hastscript.min.js", "build": "npm run build-bundle && npm run build-mangle", "test-api": "node test", "test-coverage": "nyc --reporter lcov tape test.js", - "test": "npm run format && npm run build && npm run test-coverage" + "test": "npm run generate && npm run format && npm run build && npm run test-coverage" }, "nyc": { "check-coverage": true, diff --git a/svg-case-sensitive-tag-names.json b/svg-case-sensitive-tag-names.json new file mode 100644 index 0000000..19f0e61 --- /dev/null +++ b/svg-case-sensitive-tag-names.json @@ -0,0 +1,41 @@ +[ + "altGlyph", + "altGlyphDef", + "altGlyphItem", + "animateColor", + "animateMotion", + "animateTransform", + "clipPath", + "feBlend", + "feColorMatrix", + "feComponentTransfer", + "feComposite", + "feConvolveMatrix", + "feDiffuseLighting", + "feDisplacementMap", + "feDistantLight", + "feDropShadow", + "feFlood", + "feFuncA", + "feFuncB", + "feFuncG", + "feFuncR", + "feGaussianBlur", + "feImage", + "feMerge", + "feMergeNode", + "feMorphology", + "feOffset", + "fePointLight", + "feSpecularLighting", + "feSpotLight", + "feTile", + "feTurbulence", + "foreignObject", + "glyphRef", + "linearGradient", + "radialGradient", + "solidColor", + "textArea", + "textPath" +] diff --git a/svg.js b/svg.js index ef2d435..b933def 100644 --- a/svg.js +++ b/svg.js @@ -1,9 +1,10 @@ 'use strict' var schema = require('property-information/svg') +var caseSensitive = require('./svg-case-sensitive-tag-names.json') var factory = require('./factory') -var svg = factory(schema, 'g') +var svg = factory(schema, 'g', caseSensitive) svg.displayName = 'svg' module.exports = svg diff --git a/test.js b/test.js index 9a7390f..d8998a3 100644 --- a/test.js +++ b/test.js @@ -1121,5 +1121,49 @@ test('hastscript', function(t) { st.end() }) + t.test('tag names', function(st) { + st.deepEqual( + h(null, [h('DIV'), h('dIv'), h('div')]), + { + type: 'element', + tagName: 'div', + properties: {}, + children: [ + {type: 'element', tagName: 'div', properties: {}, children: []}, + {type: 'element', tagName: 'div', properties: {}, children: []}, + {type: 'element', tagName: 'div', properties: {}, children: []} + ] + }, + 'should create lowercase tag names' + ) + + st.deepEqual( + s(null, [ + s('RECT'), + s('rEcT'), + s('rect'), + s('feFuncA'), + s('FEFUNCA'), + s('fefunca') + ]), + { + type: 'element', + tagName: 'g', + properties: {}, + children: [ + {type: 'element', tagName: 'rect', properties: {}, children: []}, + {type: 'element', tagName: 'rect', properties: {}, children: []}, + {type: 'element', tagName: 'rect', properties: {}, children: []}, + {type: 'element', tagName: 'feFuncA', properties: {}, children: []}, + {type: 'element', tagName: 'feFuncA', properties: {}, children: []}, + {type: 'element', tagName: 'feFuncA', properties: {}, children: []} + ] + }, + 'should create lowercase SVG tag names, and fix certain cases' + ) + + st.end() + }) + t.end() })