mirror of
https://github.com/tenrok/BBob.git
synced 2026-06-17 19:21:20 +03:00
fix(parser): dont process nested tags as string if parent is not allowed (#84)
* fix(parser): dont process nested tags as string if parent is not allowed * fix(plugin-helper): toString method with default params
This commit is contained in:
committed by
GitHub
parent
0d839fa947
commit
70ff2e6660
@@ -1,4 +1,5 @@
|
|||||||
import TagNode from '@bbob/plugin-helper/lib/TagNode';
|
import TagNode from '@bbob/plugin-helper/lib/TagNode';
|
||||||
|
import { CLOSE_BRAKET, OPEN_BRAKET } from '@bbob/plugin-helper/lib/char';
|
||||||
import { isTagNode } from '@bbob/plugin-helper/lib/index';
|
import { isTagNode } from '@bbob/plugin-helper/lib/index';
|
||||||
import { createLexer } from './lexer';
|
import { createLexer } from './lexer';
|
||||||
import { createList } from './utils';
|
import { createList } from './utils';
|
||||||
@@ -16,6 +17,8 @@ import { createList } from './utils';
|
|||||||
*/
|
*/
|
||||||
const parse = (input, opts = {}) => {
|
const parse = (input, opts = {}) => {
|
||||||
const options = opts;
|
const options = opts;
|
||||||
|
const openTag = options.openTag || OPEN_BRAKET;
|
||||||
|
const closeTag = options.closeTag || CLOSE_BRAKET;
|
||||||
|
|
||||||
let tokenizer = null;
|
let tokenizer = null;
|
||||||
|
|
||||||
@@ -114,7 +117,15 @@ const parse = (input, opts = {}) => {
|
|||||||
if (isAllowedTag(node.tag)) {
|
if (isAllowedTag(node.tag)) {
|
||||||
items.push(node.toTagNode());
|
items.push(node.toTagNode());
|
||||||
} else {
|
} else {
|
||||||
items.push(node.toString());
|
items.push(node.toTagStart({ openTag, closeTag }));
|
||||||
|
|
||||||
|
if (node.content.length) {
|
||||||
|
node.content.forEach((item) => {
|
||||||
|
items.push(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
items.push(node.toTagEnd({ openTag, closeTag }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
items.push(node);
|
items.push(node);
|
||||||
@@ -240,8 +251,8 @@ const parse = (input, opts = {}) => {
|
|||||||
tokenizer = (opts.createTokenizer ? opts.createTokenizer : createLexer)(input, {
|
tokenizer = (opts.createTokenizer ? opts.createTokenizer : createLexer)(input, {
|
||||||
onToken,
|
onToken,
|
||||||
onlyAllowTags: options.onlyAllowTags,
|
onlyAllowTags: options.onlyAllowTags,
|
||||||
openTag: options.openTag,
|
openTag,
|
||||||
closeTag: options.closeTag,
|
closeTag,
|
||||||
enableEscapeTags: options.enableEscapeTags,
|
enableEscapeTags: options.enableEscapeTags,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -25,27 +25,106 @@ describe('Parser', () => {
|
|||||||
expectOutput(ast, output);
|
expectOutput(ast, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('parse only allowed tags', () => {
|
describe('onlyAllowTags', () => {
|
||||||
const ast = parse('[h1 name=value]Foo [Bar] [/h1]', {
|
test('parse only allowed tags', () => {
|
||||||
onlyAllowTags: ['h1']
|
const ast = parse('[h1 name=value]Foo [Bar] [/h1]', {
|
||||||
});
|
onlyAllowTags: ['h1']
|
||||||
const output = [
|
});
|
||||||
{
|
const output = [
|
||||||
tag: 'h1',
|
{
|
||||||
attrs: {
|
tag: 'h1',
|
||||||
name: 'value',
|
attrs: {
|
||||||
|
name: 'value',
|
||||||
|
},
|
||||||
|
content: [
|
||||||
|
'Foo',
|
||||||
|
' ',
|
||||||
|
'[Bar]',
|
||||||
|
' '
|
||||||
|
],
|
||||||
},
|
},
|
||||||
content: [
|
];
|
||||||
'Foo',
|
|
||||||
' ',
|
|
||||||
'[Bar]',
|
|
||||||
' '
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
expectOutput(ast, output);
|
expectOutput(ast, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('parse only allowed tags with params', () => {
|
||||||
|
const options = {
|
||||||
|
onlyAllowTags: ['b', 'i', 'u']
|
||||||
|
};
|
||||||
|
const ast = parse('hello [blah foo="bar"]world[/blah]', options);
|
||||||
|
|
||||||
|
expectOutput(ast, [
|
||||||
|
'hello',
|
||||||
|
' ',
|
||||||
|
'[blah foo="bar"]',
|
||||||
|
'world',
|
||||||
|
'[/blah]'
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parse only allowed tags with named param', () => {
|
||||||
|
const options = {
|
||||||
|
onlyAllowTags: ['b', 'i', 'u']
|
||||||
|
};
|
||||||
|
const ast = parse('hello [blah="bar"]world[/blah]', options);
|
||||||
|
|
||||||
|
expectOutput(ast, [
|
||||||
|
'hello',
|
||||||
|
' ',
|
||||||
|
'[blah="bar"]',
|
||||||
|
'world',
|
||||||
|
'[/blah]'
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parse only allowed tags inside disabled tags', () => {
|
||||||
|
const ast = parse('[tab] [ch]E[/ch]\nA cripple walks amongst you[/tab]\n[tab] [ch]A[/ch]\nAll you tired human beings[/tab]', {
|
||||||
|
onlyAllowTags: ['ch']
|
||||||
|
});
|
||||||
|
const output = [
|
||||||
|
'[tab]',
|
||||||
|
' ',
|
||||||
|
{
|
||||||
|
tag: 'ch',
|
||||||
|
attrs: {},
|
||||||
|
content: ['E'],
|
||||||
|
},
|
||||||
|
'\n',
|
||||||
|
'A',
|
||||||
|
' ',
|
||||||
|
'cripple',
|
||||||
|
' ',
|
||||||
|
'walks',
|
||||||
|
' ',
|
||||||
|
'amongst',
|
||||||
|
' ',
|
||||||
|
'you',
|
||||||
|
'[/tab]',
|
||||||
|
'\n',
|
||||||
|
'[tab]',
|
||||||
|
' ',
|
||||||
|
{
|
||||||
|
tag: 'ch',
|
||||||
|
attrs: {},
|
||||||
|
content: ['A'],
|
||||||
|
},
|
||||||
|
'\n',
|
||||||
|
'All',
|
||||||
|
' ',
|
||||||
|
'you',
|
||||||
|
' ',
|
||||||
|
'tired',
|
||||||
|
' ',
|
||||||
|
'human',
|
||||||
|
' ',
|
||||||
|
'beings',
|
||||||
|
'[/tab]',
|
||||||
|
];
|
||||||
|
|
||||||
|
expectOutput(ast, output);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
test('parse inconsistent tags', () => {
|
test('parse inconsistent tags', () => {
|
||||||
const ast = parse('[h1 name=value]Foo [Bar] /h1]');
|
const ast = parse('[h1 name=value]Foo [Bar] /h1]');
|
||||||
@@ -126,32 +205,6 @@ describe('Parser', () => {
|
|||||||
expect(onError).toHaveBeenCalled();
|
expect(onError).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('parse only allowed tags with params', () => {
|
|
||||||
const options = {
|
|
||||||
onlyAllowTags: ['b', 'i', 'u']
|
|
||||||
};
|
|
||||||
const ast = parse('hello [blah foo="bar"]world[/blah]', options);
|
|
||||||
|
|
||||||
expectOutput(ast, [
|
|
||||||
'hello',
|
|
||||||
' ',
|
|
||||||
'[blah foo="bar"]world[/blah]',
|
|
||||||
])
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parse only allowed tags with named param', () => {
|
|
||||||
const options = {
|
|
||||||
onlyAllowTags: ['b', 'i', 'u']
|
|
||||||
};
|
|
||||||
const ast = parse('hello [blah="bar"]world[/blah]', options);
|
|
||||||
|
|
||||||
expectOutput(ast, [
|
|
||||||
'hello',
|
|
||||||
' ',
|
|
||||||
'[blah="bar"]world[/blah]',
|
|
||||||
])
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parse few tags without spaces', () => {
|
test('parse few tags without spaces', () => {
|
||||||
const ast = parse('[mytag1 size="15"]Tag1[/mytag1][mytag2 size="16"]Tag2[/mytag2][mytag3]Tag3[/mytag3]');
|
const ast = parse('[mytag1 size="15"]Tag1[/mytag1][mytag2 size="16"]Tag2[/mytag2][mytag3]Tag3[/mytag3]');
|
||||||
const output = [
|
const output = [
|
||||||
@@ -189,7 +242,7 @@ describe('Parser', () => {
|
|||||||
attrs: {},
|
attrs: {},
|
||||||
content: ['hello'],
|
content: ['hello'],
|
||||||
},
|
},
|
||||||
' ',
|
' ',
|
||||||
{
|
{
|
||||||
tag: 'textarea',
|
tag: 'textarea',
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|||||||
@@ -43,22 +43,30 @@ class TagNode {
|
|||||||
return getNodeLength(this);
|
return getNodeLength(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toTagStart({ openTag = OPEN_BRAKET, closeTag = CLOSE_BRAKET } = {}) {
|
||||||
|
const tagAttrs = getTagAttrs(this.tag, this.attrs);
|
||||||
|
|
||||||
|
return `${openTag}${tagAttrs}${closeTag}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
toTagEnd({ openTag = OPEN_BRAKET, closeTag = CLOSE_BRAKET } = {}) {
|
||||||
|
return `${openTag}${SLASH}${this.tag}${closeTag}`;
|
||||||
|
}
|
||||||
|
|
||||||
toTagNode() {
|
toTagNode() {
|
||||||
return new TagNode(this.tag.toLowerCase(), this.attrs, this.content);
|
return new TagNode(this.tag.toLowerCase(), this.attrs, this.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString({ openTag = OPEN_BRAKET, closeTag = CLOSE_BRAKET } = {}) {
|
||||||
const OB = OPEN_BRAKET;
|
|
||||||
const CB = CLOSE_BRAKET;
|
|
||||||
const isEmpty = this.content.length === 0;
|
const isEmpty = this.content.length === 0;
|
||||||
const content = this.content.reduce((r, node) => r + node.toString(), '');
|
const content = this.content.reduce((r, node) => r + node.toString({ openTag, closeTag }), '');
|
||||||
const tagAttrs = getTagAttrs(this.tag, this.attrs);
|
const tagStart = this.toTagStart({ openTag, closeTag });
|
||||||
|
|
||||||
if (isEmpty) {
|
if (isEmpty) {
|
||||||
return `${OB}${tagAttrs}${CB}`;
|
return tagStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${OB}${tagAttrs}${CB}${content}${OB}${SLASH}${this.tag}${CB}`;
|
return `${tagStart}${content}${this.toTagEnd({ openTag, closeTag })}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user