shortcode-tree
Advanced tools
Comparing version 1.0.1 to 1.0.2
{ | ||
"name": "shortcode-tree", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "Parser library for reading short codes (BB codes) into a tree structure", | ||
"main": "src/index.js", | ||
"scripts": { | ||
"test": "mocha --reporter spec || exit 0" | ||
"test": "mocha --reporter spec" | ||
}, | ||
@@ -16,4 +16,7 @@ "author": "Roy de Jong <roy@softwarepunt.nl>", | ||
"dependencies": { | ||
"meta-shortcodes": "^1.0.3" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/roydejong/shortcode-tree" | ||
} | ||
} |
@@ -1,7 +0,11 @@ | ||
# Shortcode parser library | ||
# shortcode-tree | ||
A node.js parser library for reading shortcodes. | ||
[![npm](https://img.shields.io/npm/v/github.svg)](https://www.npmjs.com/package/shortcode-tree) | ||
[![Build Status](https://travis-ci.org/roydejong/shortcode-tree.svg?branch=master)](https://travis-ci.org/roydejong/shortcode-tree) | ||
## Introduction | ||
**shortcode-tree** provides generic parsing functionality for text containing short codes (also known as bb codes). | ||
`shortcode-tree` offers generic parsing functionality for text containing short codes (also known as bb codes). | ||
This library does not convert short codes to HTML (like many others do), but **it converts generic shortcode/HTML input to pure JavaScript objects**. | ||
This library does not convert short codes to HTML (like many other libraries do), but **it converts generic shortcode/HTML input to pure JavaScript objects**. | ||
@@ -14,9 +18,8 @@ No set up is required, and you do not need to pre-define a list of shortcodes. | ||
Result: | ||
Shortcode { | ||
name: 'image', | ||
content: null, | ||
properties: { id: '123', src: 'bla.jpg', align: 'center' }, | ||
isSelfClosing: true } | ||
// Shortcode { | ||
// name: 'image', | ||
// content: null, | ||
// properties: { id: '123', src: 'bla.jpg', align: 'center' }, | ||
// isSelfClosing: true, | ||
// codeText: "[image id=123 src="bla.jpg" align="center"/]" } | ||
@@ -40,10 +43,13 @@ ## Features | ||
To parse an individual short code, use the `ShortcodeParser` class: | ||
To parse **one** individual short code, use the `ShortcodeParser`: | ||
let ShortcodeParser = require('shortcode-tree/shortcode-parser'); | ||
var parser = require('shortcode-tree').ShortcodeParser; | ||
let parsed = ShortcodeParser.parseShortcode("[b]example input[/b]"); | ||
var shortcode = parser.parseShortcode("[b]example content[/b]"); | ||
console.log(shortcode.content); // example content | ||
The `parseShortcode` method returns a `Shortcode` object with the following properties: | ||
The `parseShortcode` method returns a `Shortcode` object, as documented below. | ||
### The `Shortcode` object | ||
| Property | Type | Description | | ||
@@ -54,4 +60,27 @@ | --- | --- | --- | | ||
| `content` | string or null | The raw, unparsed content of the tag. May contain HTML and other short codes. `NULL` for self-closing tags. | | ||
| `isSelfClosing` | bool | Indicates whether this is a self-closing tag without any content. | | ||
| `isSelfClosing` | bool | Indicates whether this is a self-closing tag without any content. | | ||
| `codeText` | string | The raw shortcode text, as it was parsed. | | ||
### Extracting multiple shortcodes from text | ||
If there are multiple shortcodes within one piece of text, you can extract them using the `ShortcodeExtractor`: | ||
var extractor = require('shortcode-tree').ShortcodeExtractor; | ||
var shortcodes = extractor.extractShortcodes("[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]' } ] | ||
This function will only extract shortcodes from one level, and does not process any child tags. |
module.exports = { | ||
"ShortcodeTree": require('./shortcode-tree'), | ||
"ShortcodeParser": require('./shortcode-parser'), | ||
"ShortcodeExtractor": require('./shortcode-extractor'), | ||
"Shortcode": require('./shortcode') | ||
@@ -5,0 +6,0 @@ }; |
@@ -6,5 +6,7 @@ let fs = require('fs'); | ||
let ShortcodeParser = { | ||
parseShortcode(input) { | ||
if (!input.startsWith(ShortcodeParser.T_TAG_BLOCK_START) || !input.endsWith(ShortcodeParser.T_TAG_BLOCK_END)) { | ||
throw new Error('parseShortcode() expects a full shortcode, from opening tag to closing tag'); | ||
parseShortcode(input, options) { | ||
if (!options) { | ||
options = ShortcodeParser.DEFAULT_OPTIONS; | ||
} else { | ||
options = Object.assign(ShortcodeParser.DEFAULT_OPTIONS, options); | ||
} | ||
@@ -14,2 +16,12 @@ | ||
// Step 0: Detect the first open tag, and offset our input buffer to that position | ||
let openingBlockMatch = /\[(.*?)\]/g.exec(input); | ||
if (!openingBlockMatch) { | ||
throw new Error("Could not parse shortcode: No opening tag detected."); | ||
} | ||
input = input.substr(openingBlockMatch.index); | ||
ShortcodeParser.lastOffset = openingBlockMatch.index; | ||
// Step 1: Read the opening block without enclosing []'s | ||
@@ -62,2 +74,7 @@ let openBlockStartIdx = 0; | ||
readingPropName = true; | ||
if (options.mode === ShortcodeParser.MODE_GET_OPENING_TAG_NAME) { | ||
return shortcode.name; | ||
} | ||
continue; | ||
@@ -140,13 +157,22 @@ } | ||
if (options.mode === ShortcodeParser.MODE_GET_OPENING_TAG_NAME) { | ||
return shortcode.name; | ||
} | ||
shortcode.properties = properties; | ||
// Step 4: If this is not a self closing tag; verify end tag is here as expected, and read the content | ||
let offsetFromEnd = 0; | ||
if (!shortcode.isSelfClosing) { | ||
let closingTagExpected = `[/${shortcode.name}]`; | ||
let closingTagIdx = input.lastIndexOf(closingTagExpected); | ||
if (input.lastIndexOf(closingTagExpected) !== input.length - closingTagExpected.length) { | ||
if (closingTagIdx === -1) { | ||
throw new Error(`Malformatted shortcode: Expected closing tag: ${closingTagExpected}`); | ||
} | ||
shortcode.content = input.substr(openBlockTextFull.length, (input.length - openBlockTextFull.length - closingTagExpected.length)); | ||
offsetFromEnd = (input.length - closingTagExpected.length) - closingTagIdx; | ||
shortcode.content = input.substr(openBlockStartIdx + openBlockTextFull.length, (input.length - openBlockTextFull.length - closingTagExpected.length - offsetFromEnd)); | ||
} else { | ||
@@ -156,2 +182,4 @@ shortcode.content = null; | ||
shortcode.codeText = input.substr(openBlockStartIdx, input.length - offsetFromEnd); | ||
return shortcode; | ||
@@ -161,2 +189,4 @@ } | ||
ShortcodeParser.lastOffset = 0; | ||
ShortcodeParser.T_TAG_BLOCK_START = "["; | ||
@@ -170,2 +200,9 @@ ShortcodeParser.T_TAG_BLOCK_END = "]"; | ||
ShortcodeParser.MODE_NORMAL = 'normal'; | ||
ShortcodeParser.MODE_GET_OPENING_TAG_NAME = 'tag_name'; | ||
ShortcodeParser.DEFAULT_OPTIONS = { | ||
mode: ShortcodeParser.MODE_NORMAL | ||
}; | ||
module.exports = ShortcodeParser; |
class Shortcode { | ||
constructor (name, content, properties, isSelfClosing) { | ||
constructor (name, content, properties, isSelfClosing, codeText) { | ||
this.name = name || null; | ||
@@ -7,2 +7,3 @@ this.content = (typeof content === "undefined" ? null : content); | ||
this.isSelfClosing = !!isSelfClosing; | ||
this.codeText = codeText || null; | ||
} | ||
@@ -9,0 +10,0 @@ } |
@@ -6,6 +6,6 @@ let ShortcodeParser = require('../src').ShortcodeParser; | ||
describe('ShortcodeParser.parseShortcode()', function () { | ||
describe('ShortcodeParser.parseShortcode() in normal mode', function () { | ||
it('parses a simple shortcode with content', function () { | ||
let testInput = "[b]bold text[/b]"; | ||
let expectedOutput = new Shortcode("b", "bold text", {}); | ||
let expectedOutput = new Shortcode("b", "bold text", {}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -18,3 +18,3 @@ | ||
let testInput = "[b][/b]"; | ||
let expectedOutput = new Shortcode("b", "", {}); | ||
let expectedOutput = new Shortcode("b", "", {}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -27,3 +27,3 @@ | ||
let testInput = `[text color=red]test[/text]`; | ||
let expectedOutput = new Shortcode("text", "test", {"color": "red"}); | ||
let expectedOutput = new Shortcode("text", "test", {"color": "red"}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -36,3 +36,3 @@ | ||
let testInput = `[text color="stupid red"]test[/text]`; | ||
let expectedOutput = new Shortcode("text", "test", {"color": "stupid red"}); | ||
let expectedOutput = new Shortcode("text", "test", {"color": "stupid red"}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -45,3 +45,3 @@ | ||
let testInput = `[text color=""]test[/text]`; | ||
let expectedOutput = new Shortcode("text", "test", {"color": ""}); | ||
let expectedOutput = new Shortcode("text", "test", {"color": ""}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -54,3 +54,3 @@ | ||
let testInput = `[text color="the \\\"super escape\\\""]test[/text]`; | ||
let expectedOutput = new Shortcode("text", "test", {"color": 'the "super escape"'}); | ||
let expectedOutput = new Shortcode("text", "test", {"color": 'the "super escape"'}, false, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -63,3 +63,3 @@ | ||
let testInput = "[separator/]"; | ||
let expectedOutput = new Shortcode("separator", null, {}, true); | ||
let expectedOutput = new Shortcode("separator", null, {}, true, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -72,3 +72,3 @@ | ||
let testInput = "[separator /]"; | ||
let expectedOutput = new Shortcode("separator", null, {}, true); | ||
let expectedOutput = new Shortcode("separator", null, {}, true, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -81,3 +81,3 @@ | ||
let testInput = `[image id=123 src="bla.jpg" align="center"/]`; | ||
let expectedOutput = new Shortcode("image", null, {"id": "123", "src": "bla.jpg", "align": "center"}, true); | ||
let expectedOutput = new Shortcode("image", null, {"id": "123", "src": "bla.jpg", "align": "center"}, true, testInput); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
@@ -87,2 +87,40 @@ | ||
}); | ||
it('parses only the first shortcode from a set of sticky shortcodes', function () { | ||
let testInput = `[b]test[/b] not [i]italics[/i]`; | ||
let expectedOutput = new Shortcode("b", "test", {}, false, "[b]test[/b]"); | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput) || null; | ||
expect(actualOutput).to.deep.equal(expectedOutput); | ||
}); | ||
it('parses the first shortcode encountered by detecting the opening tag', function () { | ||
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; | ||
expect(actualOutput).to.deep.equal(expectedOutput); | ||
}); | ||
}); | ||
describe('ShortcodeParser.parseShortcode() in MODE_GET_OPENING_TAG_NAME', function () { | ||
let options = { | ||
mode: ShortcodeParser.MODE_GET_OPENING_TAG_NAME | ||
}; | ||
it('parses a simple shortcode and returns its opening name, regardless of closing tag mismatch', function () { | ||
let testInput = "[blah]bold text[/boop]"; | ||
let expectedOutput = "blah"; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
expect(actualOutput).to.equal(expectedOutput); | ||
}); | ||
it('parses a self-closing shortcode and returns its opening name', function () { | ||
let testInput = "[blahp/]"; | ||
let expectedOutput = "blahp"; | ||
let actualOutput = ShortcodeParser.parseShortcode(testInput, options) || null; | ||
expect(actualOutput).to.equal(expectedOutput); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
24012
0
21
349
84
1
- Removedmeta-shortcodes@^1.0.3
- Removedmeta-shortcodes@1.0.3(transitive)