Skip to content

Commit

Permalink
fix(parser): don't eat not allowed tags with params (#58) fixes #54
Browse files Browse the repository at this point in the history
* feat(parser): write test for only allowed tags parsing

* chore(parser): rename only allowed test

* fix(parser): only allowed tag rendering

* fix(plugin-helper): add new TagNode toString tests
  • Loading branch information
JiLiZART authored Apr 12, 2020
1 parent f28f19e commit a16b9f7
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 27 deletions.
53 changes: 33 additions & 20 deletions packages/bbob-parser/src/parse.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import TagNode from '@bbob/plugin-helper/lib/TagNode';
import { isTagNode } from '@bbob/plugin-helper';
import { createLexer } from './lexer';
import { createList } from './utils';

Expand Down Expand Up @@ -57,8 +58,25 @@ const parse = (input, opts = {}) => {
return nestedTagsMap[token.getValue()];
};

/**
* @param tagName
* @returns {boolean}
*/
const isTagNested = (tagName) => !!nestedTagsMap[tagName];

/**
* @private
* @param {String} value
* @return {boolean}
*/
const isAllowedTag = (value) => {
if (options.onlyAllowTags && options.onlyAllowTags.length) {
return options.onlyAllowTags.indexOf(value) >= 0;
}

return true;
};

/**
* Flushes temp tag nodes and its attributes buffers
* @private
Expand Down Expand Up @@ -86,27 +104,22 @@ const parse = (input, opts = {}) => {

/**
* @private
* @param {TagNode} tag
* @param {string|TagNode} node
*/
const appendNodes = (tag) => {
const appendNodes = (node) => {
const items = getNodes();

if (Array.isArray(items)) {
items.push(tag);
}
};

/**
* @private
* @param {String} value
* @return {boolean}
*/
const isAllowedTag = (value) => {
if (options.onlyAllowTags && options.onlyAllowTags.length) {
return options.onlyAllowTags.indexOf(value) >= 0;
if (isTagNode(node)) {
if (isAllowedTag(node.tag)) {
items.push(node.toTagNode());
} else {
items.push(node.toString());
}
} else {
items.push(node);
}
}

return true;
};

/**
Expand All @@ -124,7 +137,7 @@ const parse = (input, opts = {}) => {
if (isNested) {
nestedNodes.push(tagNode);
} else {
appendNodes(tagNode);
appendNodes(tagNode, token);
}
};

Expand All @@ -138,8 +151,8 @@ const parse = (input, opts = {}) => {
const lastNestedNode = nestedNodes.flushLast();

if (lastNestedNode) {
appendNodes(lastNestedNode);
} else if (options.onError) {
appendNodes(lastNestedNode, token);
} else if (typeof options.onError === 'function') {
const tag = token.getValue();
const line = token.getLine();
const column = token.getColumn();
Expand Down Expand Up @@ -217,7 +230,7 @@ const parse = (input, opts = {}) => {
* @param {Token} token
*/
const onToken = (token) => {
if (token.isTag() && isAllowedTag(token.getName())) {
if (token.isTag()) {
handleTag(token);
} else {
handleNode(token);
Expand Down
26 changes: 26 additions & 0 deletions packages/bbob-parser/test/parse.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,32 @@ describe('Parser', () => {
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]',
])
});

describe('html', () => {
const parseHTML = input => parse(input, { openTag: '<', closeTag: '>' });

Expand Down
36 changes: 33 additions & 3 deletions packages/bbob-plugin-helper/src/TagNode.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
import { OPEN_BRAKET, CLOSE_BRAKET, SLASH } from './char';
import { getNodeLength, appendToNode } from './index';
import {
getNodeLength, appendToNode, attrsToString, attrValue, getUniqAttr,
} from './index';

const getTagAttrs = (tag, params) => {
const uniqAattr = getUniqAttr(params);

if (uniqAattr) {
const tagAttr = attrValue(tag, uniqAattr);
const attrs = { ...params };

delete attrs[uniqAattr];

const attrsStr = attrsToString(attrs);

return `${tagAttr}${attrsStr}`;
}

return `${tag}${attrsToString(params)}`;
};

class TagNode {
constructor(tag, attrs, content) {
this.tag = tag.toLowerCase();
this.tag = tag;
this.attrs = attrs;
this.content = [].concat(content);
}
Expand All @@ -24,11 +43,22 @@ class TagNode {
return getNodeLength(this);
}

toTagNode() {
return new TagNode(this.tag.toLowerCase(), this.attrs, this.content);
}

toString() {
const OB = OPEN_BRAKET;
const CB = CLOSE_BRAKET;
const isEmpty = this.content.length === 0;
const content = this.content.reduce((r, node) => r + node.toString(), '');
const tagAttrs = getTagAttrs(this.tag, this.attrs);

if (isEmpty) {
return `${OB}${tagAttrs}${CB}`;
}

return OB + this.tag + CB + this.content.reduce((r, node) => r + node.toString(), '') + OB + SLASH + this.tag + CB;
return `${OB}${tagAttrs}${CB}${content}${OB}${SLASH}${this.tag}${CB}`;
}
}

Expand Down
34 changes: 30 additions & 4 deletions packages/bbob-plugin-helper/test/TagNode.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,35 @@ describe('@bbob/plugin-helper/lib/TagNode', () => {
expect(TagNode.isOf(tagNode, 'test')).toBe(true);
});

test('toString', () => {
const tagNode = TagNode.create('test', {test: 1}, ['Hello']);
describe('toString', () => {
test('tag with content and params', () => {
const tagNode = TagNode.create('test', {test: 1}, ['Hello']);

expect(String(tagNode)).toBe('[test]Hello[/test]');
});
expect(String(tagNode)).toBe('[test test="1"]Hello[/test]');
});

test('tag with content and uniq attr', () => {
const tagNode = TagNode.create('test', {test: 'test'}, ['Hello']);

expect(String(tagNode)).toBe('[test="test"]Hello[/test]');
});

test('tag without content', () => {
const tagNode = TagNode.create('test');

expect(String(tagNode)).toBe('[test]');
});

test('tag without content', () => {
const tagNode = TagNode.create('test', {}, 'Content');

expect(String(tagNode)).toBe('[test]Content[/test]');
});

test('tag with snakeCase', () => {
const tagNode = TagNode.create('snakeCaseTag');

expect(String(tagNode)).toBe('[snakeCaseTag]');
});
})
});

0 comments on commit a16b9f7

Please sign in to comment.