shortcode-tree
Advanced tools
Comparing version 1.0.2 to 1.0.3
{ | ||
"name": "shortcode-tree", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"description": "Parser library for reading short codes (BB codes) into a tree structure", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -18,3 +18,3 @@ # shortcode-tree | ||
// Shortcode { | ||
// Shortcode { | ||
// name: 'image', | ||
@@ -24,3 +24,4 @@ // content: null, | ||
// isSelfClosing: true, | ||
// codeText: "[image id=123 src="bla.jpg" align="center"/]" } | ||
// codeText: '[image id=123 src="bla.jpg" align="center"/]', | ||
// offset: 0 } | ||
@@ -51,3 +52,3 @@ ## Features | ||
The `parseShortcode` method returns a `Shortcode` object, as documented below. | ||
The `parseShortcode` method returns a `Shortcode` object. | ||
@@ -63,2 +64,3 @@ ### The `Shortcode` object | ||
| `codeText` | string | The raw shortcode text, as it was parsed. | | ||
| `offset` | integer | Offset index, relative to the original input string. | | ||
@@ -71,18 +73,22 @@ ### Extracting multiple shortcodes from text | ||
var shortcodes = extractor.extractShortcodes("[b]bold[/b] and [i]beautiful[/i]"); | ||
var shortcodes = extractor.extractShortcodes("Hey, [b]bold[/b] and [i]beautiful[/i]."); | ||
console.log(shortcodes); | ||
// [ Shortcode { | ||
name: 'b', | ||
content: 'bold', | ||
properties: {}, | ||
isSelfClosing: false, | ||
codeText: '[b]bold[/b]' }, | ||
Shortcode { | ||
name: 'i', | ||
content: 'beautiful', | ||
properties: {}, | ||
isSelfClosing: false, | ||
codeText: '[i]beautiful[/i]' } ] | ||
// name: 'b', | ||
// content: 'bold', | ||
// properties: {}, | ||
// isSelfClosing: false, | ||
// codeText: '[b]bold[/b]', | ||
// offset: 5 }, | ||
// Shortcode { | ||
// name: 'i', | ||
// content: 'beautiful', | ||
// properties: {}, | ||
// isSelfClosing: false, | ||
// codeText: '[i]beautiful[/i]', | ||
// offset: 21 } ] | ||
This function will only extract shortcodes from one level, and does not process any child tags. | ||
This method will only extract shortcodes from one level, and does not process any child tags. | ||
The `extractShortcodes` method returns an array of `Shortcode` objects. |
@@ -19,19 +19,14 @@ let ShortcodeParser = require('./shortcode-parser'); | ||
let m; | ||
let match; | ||
let resultSet = []; | ||
let matches = []; | ||
while ((m = regex.exec(text)) !== null) { | ||
if (m.index === regex.lastIndex) { | ||
while ((match = regex.exec(text)) !== null) { | ||
if (match.index === regex.lastIndex) { | ||
regex.lastIndex++; | ||
} | ||
m.forEach((match, groupIndex) => { | ||
if (groupIndex === 0) { | ||
matches = matches.concat(this.reduceShortcodeMatch(match)); | ||
} | ||
}); | ||
resultSet = resultSet.concat(this.reduceShortcodeMatch(text, match.index)); | ||
} | ||
return matches; | ||
return resultSet; | ||
}, | ||
@@ -42,14 +37,20 @@ | ||
* | ||
* @param {string} matchText | ||
* @param {string} text | ||
* @param {int} offset | ||
* @returns {array} | ||
*/ | ||
reduceShortcodeMatch (matchText) { | ||
reduceShortcodeMatch(text, offset) { | ||
let results = []; | ||
let remainingText = matchText; | ||
while (remainingText.length > 0) { | ||
let parsed = ShortcodeParser.parseShortcode(remainingText); | ||
results.push(parsed); | ||
while (offset < text.length) { | ||
let parsedShortcode = ShortcodeParser.parseShortcode(text, {offset: offset, throwErrors: false}); | ||
remainingText = remainingText.substr(ShortcodeParser.lastOffset + parsed.codeText.length); | ||
if (!parsedShortcode) { | ||
// Parse error | ||
break; | ||
} | ||
results.push(parsedShortcode); | ||
offset = parsedShortcode.offset + parsedShortcode.codeText.length; | ||
} | ||
@@ -56,0 +57,0 @@ |
@@ -10,3 +10,3 @@ let fs = require('fs'); | ||
} else { | ||
options = Object.assign(ShortcodeParser.DEFAULT_OPTIONS, options); | ||
options = Object.assign({}, ShortcodeParser.DEFAULT_OPTIONS, options); | ||
} | ||
@@ -16,11 +16,17 @@ | ||
// Step 0: Detect the first open tag, and offset our input buffer to that position | ||
// Step 0: Apply offset from options, then increase offset as needed by looking for an opening tag | ||
input = input.substr(options.offset); | ||
let openingBlockMatch = /\[(.*?)\]/g.exec(input); | ||
if (!openingBlockMatch) { | ||
throw new Error("Could not parse shortcode: No opening tag detected."); | ||
if (options.throwErrors) { | ||
throw new Error(`Could not parse shortcode: No opening tag detected in ${input}.`); | ||
} else { | ||
return false; | ||
} | ||
} | ||
input = input.substr(openingBlockMatch.index); | ||
ShortcodeParser.lastOffset = openingBlockMatch.index; | ||
shortcode.offset = options.offset + openingBlockMatch.index; | ||
@@ -34,3 +40,7 @@ // Step 1: Read the opening block without enclosing []'s | ||
if (!openBlockText || !openBlockText.length) { | ||
throw new Error('Malformatted shortcode: Invalid or missing opening tag'); | ||
if (options.throwErrors) { | ||
throw new Error(`Malformatted shortcode: Invalid or missing opening tag in ${input}`); | ||
} else { | ||
return false; | ||
} | ||
} | ||
@@ -121,3 +131,7 @@ | ||
if (!readingPropValLiteral) { | ||
throw new Error('Unexpected T_TAG_PROPERTY_VALUE_WRAPPER (expected a prior start marker)'); | ||
if (options.throwErrors) { | ||
throw new Error('Unexpected T_TAG_PROPERTY_VALUE_WRAPPER (expected a prior start marker)'); | ||
} else { | ||
return false; | ||
} | ||
} else { | ||
@@ -155,3 +169,7 @@ literalClosed = true; | ||
if (buffer.length > 0) { | ||
throw new Error('Malformatted shortcode: Invalid opening tag'); | ||
if (options.throwErrors) { | ||
throw new Error('Malformatted shortcode: Invalid opening tag'); | ||
} else { | ||
return false; | ||
} | ||
} | ||
@@ -173,3 +191,7 @@ | ||
if (closingTagIdx === -1) { | ||
throw new Error(`Malformatted shortcode: Expected closing tag: ${closingTagExpected}`); | ||
if (options.throwErrors) { | ||
throw new Error(`Malformatted shortcode: Expected closing tag: ${closingTagExpected}`); | ||
} else { | ||
return false; | ||
} | ||
} | ||
@@ -190,4 +212,2 @@ | ||
ShortcodeParser.lastOffset = 0; | ||
ShortcodeParser.T_TAG_BLOCK_START = "["; | ||
@@ -205,5 +225,7 @@ ShortcodeParser.T_TAG_BLOCK_END = "]"; | ||
ShortcodeParser.DEFAULT_OPTIONS = { | ||
mode: ShortcodeParser.MODE_NORMAL | ||
mode: ShortcodeParser.MODE_NORMAL, | ||
offset: 0, | ||
throwErrors: true | ||
}; | ||
module.exports = ShortcodeParser; |
class Shortcode { | ||
constructor (name, content, properties, isSelfClosing, codeText) { | ||
constructor (name, content, properties, isSelfClosing, codeText, offset) { | ||
this.name = name || null; | ||
@@ -8,2 +8,3 @@ this.content = (typeof content === "undefined" ? null : content); | ||
this.codeText = codeText || null; | ||
this.offset = offset || 0; | ||
} | ||
@@ -10,0 +11,0 @@ } |
@@ -18,3 +18,3 @@ let ShortcodeExtractor = require('../src').ShortcodeExtractor; | ||
let testInput = "Check out [b]bold wrap text[/b], it's pretty cool."; | ||
let expectedOutput = [new Shortcode("b", "bold wrap text", {}, false, "[b]bold wrap text[/b]")]; | ||
let expectedOutput = [new Shortcode("b", "bold wrap text", {}, false, "[b]bold wrap text[/b]", 10)]; | ||
@@ -30,4 +30,4 @@ let actualOutput = ShortcodeExtractor.extractShortcodes(testInput) || null; | ||
let expectedOutput = [ | ||
new Shortcode("b", "boldest text", {}, false, "[b]boldest text[/b]"), | ||
new Shortcode("i", "bats", {}, false, "[i]bats[/i]") | ||
new Shortcode("b", "boldest text", {}, false, "[b]boldest text[/b]", 0), | ||
new Shortcode("i", "bats", {}, false, "[i]bats[/i]", 19) | ||
]; | ||
@@ -44,4 +44,4 @@ | ||
let expectedOutput = [ | ||
new Shortcode("b", "boldest text", {}, false, "[b]boldest text[/b]"), | ||
new Shortcode("i", "bats", {}, false, "[i]bats[/i]") | ||
new Shortcode("b", "boldest text", {}, false, "[b]boldest text[/b]", 13), | ||
new Shortcode("i", "bats", {}, false, "[i]bats[/i]", 52) | ||
]; | ||
@@ -48,0 +48,0 @@ |
@@ -7,6 +7,8 @@ let ShortcodeParser = require('../src').ShortcodeParser; | ||
describe('ShortcodeParser.parseShortcode() in normal mode', function () { | ||
let options = ShortcodeParser.DEFAULT_OPTIONS; | ||
it('parses a simple shortcode with content', function () { | ||
let testInput = "[b]bold text[/b]"; | ||
let expectedOutput = new Shortcode("b", "bold text", {}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -19,3 +21,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("b", "", {}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -28,3 +30,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("text", "test", {"color": "red"}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -37,3 +39,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("text", "test", {"color": "stupid red"}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -46,3 +48,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("text", "test", {"color": ""}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -55,3 +57,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("text", "test", {"color": 'the "super escape"'}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -64,3 +66,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("separator", null, {}, true, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -73,3 +75,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("separator", null, {}, true, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -82,3 +84,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("image", null, {"id": "123", "src": "bla.jpg", "align": "center"}, true, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -91,3 +93,3 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let expectedOutput = new Shortcode("b", "test", {}, false, "[b]test[/b]"); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
@@ -99,7 +101,39 @@ expect(actualOutput).to.deep.equal(expectedOutput); | ||
let testInput = `another offset [b]test[/b] not [i]italics[/i]`; | ||
let expectedOutput = new Shortcode("b", "test", {}, false, "[b]test[/b]"); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
let expectedOutput = new Shortcode("b", "test", {}, false, "[b]test[/b]", 15); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
expect(actualOutput).to.deep.equal(expectedOutput); | ||
}); | ||
it('throws an error for malformatted input: missing opening tag', function () { | ||
let testInput = `no opening tag`; | ||
expect(function () { | ||
ShortcodeParser.parseShortcode(testInput, options) | ||
}).to.throw("opening tag"); | ||
}); | ||
it('throws an error for malformatted input: invalid closing tag', function () { | ||
let testInput = `we [open] but no [/close]`; | ||
expect(function () { | ||
ShortcodeParser.parseShortcode(testInput, options) | ||
}).to.throw("closing tag"); | ||
}); | ||
it('throws an error for malformatted input: invalid opening tag', function () { | ||
let testInput = `we [ ] weirdly`; | ||
expect(function () { | ||
ShortcodeParser.parseShortcode(testInput, options) | ||
}).to.throw("opening tag"); | ||
}); | ||
it('throws an error for malformatted input: misplaced property quotes', function () { | ||
let testInput = `we [img bla=a"/] weirdly`; | ||
expect(function () { | ||
ShortcodeParser.parseShortcode(testInput, options) | ||
}).to.throw("T_TAG_PROPERTY_VALUE_WRAPPER"); | ||
}); | ||
}); | ||
@@ -127,2 +161,20 @@ | ||
}); | ||
}); | ||
describe('ShortcodeParser.parseShortcode() with modified options', function () { | ||
it('supports parsing with an offset', function () { | ||
let testInput = "[b]ignore[/b] but [i]parse[/i]"; | ||
let expectedOutput = new Shortcode('i', 'parse', {}, false, "[i]parse[/i]", 18); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, { offset: 13 }) || null; | ||
expect(actualOutput).to.deep.equal(expectedOutput); | ||
}); | ||
it('does not throw errors if "throwErrors" is set to false', function () { | ||
let testInput = "this might be [b]invalid"; | ||
let expectedOutput = false; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, { throwErrors: false }); | ||
expect(actualOutput).to.equal(expectedOutput); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27057
411
89