shortcode-tree
Advanced tools
Comparing version 1.2.0 to 1.2.1
{ | ||
"name": "shortcode-tree", | ||
"version": "1.2.0", | ||
"version": "1.2.1", | ||
"description": "Parser library for reading short codes (BB codes) into a tree structure", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -85,3 +85,5 @@ # shortcode-tree | ||
| `getProperty([string] key)` | value or null | Gets value of property with name `key`, or NULL if not set. | | ||
| `setProperty([string] key, value)` | void | Add or update property with given key and value. | | ||
| `setProperty([string] key, value)` | void | Add or update property with given key and value. | | ||
| `addChild([Shortcode] shortcode)` | void | Append a `shortcode` item to this shortcode's content using stringify. | | ||
| `appendContent([string] content)` | void | Append content to the existing content. | | ||
@@ -150,3 +152,4 @@ ### The `TextNode` object | ||
| `throwErrors` | boolean | `true` | If enabled: On shortcode parse error, an `Error` is thrown. If disabled: `false` is returned on parse error. | | ||
| `precise` | boolean | `false` | If things aren't working as expected, enable this for deep recursive parsing. Reduces performance exponentially. | | ||
| `precise` | boolean | `false` | If things aren't working as expected, enable this for deep recursive parsing. Reduces performance exponentially. | | ||
| `selfClosingTags` | array | `[]` | You can specify a list of tags that should always be treated as self-closing. Needed when they don't use the "[selfcloser/]" syntax. | | ||
@@ -153,0 +156,0 @@ The default options are defined in `ShortcodeParser.DEFAULT_OPTIONS`. |
@@ -285,2 +285,8 @@ let Shortcode = require('./shortcode'); | ||
shortcode.properties = properties; | ||
if (!shortcode.isSelfClosing && options.selfClosingTags.indexOf(shortcode.name) > -1) { | ||
// Explicitly listed in options as a naughty, misbehaving self-closing tag | ||
// This is one unfortunate scenario where we simply cannot parse blindly :-( | ||
shortcode.isSelfClosing = true; | ||
} | ||
} | ||
@@ -301,8 +307,43 @@ }; | ||
ShortcodeParser.DEFAULT_OPTIONS = { | ||
/** | ||
* Parser mode to operate under. | ||
* | ||
* @type string | ||
*/ | ||
mode: ShortcodeParser.MODE_NORMAL, | ||
/** | ||
* Offset to begin parsing from, relative to input string. | ||
* | ||
* @type int | ||
*/ | ||
offset: 0, | ||
/** | ||
* If true, throw errors if there is a syntax problem. | ||
* If false, return false and fail silently. | ||
* | ||
* @type boolean | ||
*/ | ||
throwErrors: true, | ||
precise: false | ||
/** | ||
* If true, perform recursive parsing for each tag. | ||
* This will ensure that the tag hierarchy is correctly understood, but more performance heavy. | ||
* | ||
* Precise mode is more accurate, but more performance heavy and breaks easier if shortcode syntax is unpredictable. | ||
* | ||
* @type boolean | ||
*/ | ||
precise: false, | ||
/** | ||
* A list of tag names that the parser always treats as self closing, without content or closing tag. | ||
* This needs to be supplied if self-closing tags do not include the "[selfcloser/]" style syntax. | ||
* | ||
* @type array | ||
*/ | ||
selfClosingTags: [] | ||
}; | ||
module.exports = ShortcodeParser; |
@@ -12,9 +12,10 @@ let ShortcodeExtractor = require('./shortcode-extractor'); | ||
* | ||
* @param {string} input | ||
* @param {string} input Text input to parse. | ||
* @param {object|null} options Parser options. | ||
* @return {ShortcodeNode} | ||
*/ | ||
parse(input) { | ||
parse(input, options) { | ||
let rootNode = new ShortcodeNode(input); | ||
this.traverseNode(rootNode); | ||
this.traverseNode(rootNode, options); | ||
@@ -28,6 +29,7 @@ return rootNode; | ||
* @param {ShortcodeNode} node | ||
* @param {object|null} options Parser options. | ||
*/ | ||
traverseNode(node) { | ||
traverseNode(node, options) { | ||
// Extract shortcodes from this node's raw text | ||
let shortcodesExtracted = ShortcodeExtractor.extractShortcodes(node.text); | ||
let shortcodesExtracted = ShortcodeExtractor.extractShortcodes(node.text, options); | ||
let lastEndIndex = 0; | ||
@@ -34,0 +36,0 @@ let anyChildNodes = false; |
let ShortcodeFormatter = require('./shortcode-formatter'); | ||
/** | ||
* Data structure that represents a single [shortcode]. | ||
*/ | ||
class Shortcode { | ||
constructor (name, content, properties, isSelfClosing, codeText, offset) { | ||
/** | ||
* The tag name. | ||
* | ||
* @type {null|string} | ||
*/ | ||
this.name = name || null; | ||
/** | ||
* Raw content contained within this shortcode. | ||
* Will be NULL for self-closing tags. | ||
* | ||
* @type {null|string} | ||
*/ | ||
this.content = (typeof content === "undefined" ? null : content); | ||
/** | ||
* Key/value object that holds all properties for this shortcode. | ||
* | ||
* @type {object} | ||
*/ | ||
this.properties = properties || {}; | ||
/** | ||
* Indicates whether this is a self-closing tag or not. | ||
* | ||
* @type {boolean} | ||
*/ | ||
this.isSelfClosing = !!isSelfClosing; | ||
/** | ||
* Raw text block that was parsed for this shortcode. | ||
* | ||
* @type {string|null} | ||
*/ | ||
this.codeText = codeText || null; | ||
/** | ||
* Offset, relative to the extractor input string. | ||
* | ||
* @type {number} | ||
*/ | ||
this.offset = offset || 0; | ||
} | ||
/** | ||
* Internal helper function: Get the end offset of this shortcode, relative to the extractor input string. | ||
* | ||
* @returns {*} | ||
*/ | ||
getEndOffset() { | ||
@@ -17,2 +61,8 @@ return this.offset + this.codeText.length; | ||
/** | ||
* Gets whether this shortcode has a set property with a given `key`. | ||
* | ||
* @param {string} key | ||
* @returns {boolean} | ||
*/ | ||
hasProperty(key) { | ||
@@ -22,2 +72,8 @@ return this.properties && (typeof this.properties[key] !== "undefined"); | ||
/** | ||
* Get the value of a property. | ||
* | ||
* @param key | ||
* @returns {string|null} | ||
*/ | ||
getProperty(key) { | ||
@@ -27,2 +83,8 @@ return this.hasProperty(key) ? this.properties[key] : null; | ||
/** | ||
* Add or update a property. | ||
* | ||
* @param {string} key | ||
* @param value | ||
*/ | ||
setProperty(key, value) { | ||
@@ -32,2 +94,25 @@ this.properties[key] = value; | ||
/** | ||
* Appends a given `shortcode` to this shortcode's content, by rendering the input as a string. | ||
* | ||
* @param {Shortcode} shortcode | ||
*/ | ||
addChild(shortcode) { | ||
this.appendContent(shortcode.stringify()); | ||
} | ||
/** | ||
* Appends given `content` to the end of this shortcode's content. | ||
* | ||
* @param {string} content | ||
*/ | ||
appendContent(content) { | ||
this.content += content; | ||
} | ||
/** | ||
* Renders this Shortcode as formatted code. | ||
* | ||
* @returns {string} | ||
*/ | ||
stringify() { | ||
@@ -37,2 +122,7 @@ return ShortcodeFormatter.stringify(this); | ||
/** | ||
* Converts this item to string. | ||
* | ||
* @returns {string} | ||
*/ | ||
toString() { | ||
@@ -39,0 +129,0 @@ return this.stringify(); |
@@ -176,2 +176,10 @@ let ShortcodeParser = require('../src').ShortcodeParser; | ||
}); | ||
it('supports parsing self-closing tags without valid syntax, with list supplement', function () { | ||
let testInput = `[img src="what.jpg" standards="no"]`; | ||
let expectedOutput = new Shortcode('img', null, {"src": "what.jpg", "standards": "no"}, true, `[img src="what.jpg" standards="no"]`, 0); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, { selfClosingTags: ["img"] }) || null; | ||
expect(actualOutput).to.deep.equal(expectedOutput); | ||
}); | ||
}); | ||
@@ -178,0 +186,0 @@ |
59309
1056
187