diff --git a/packages/bbob-preset-html5/lib/index.js b/packages/bbob-preset-html5/lib/index.js index 3c5effb..ed8d563 100644 --- a/packages/bbob-preset-html5/lib/index.js +++ b/packages/bbob-preset-html5/lib/index.js @@ -46,6 +46,61 @@ // [b]bolded text[/b] => bolded text +const getStyleFromAttrs = (attrs) => { + const styles = []; + + if (attrs.color) { + styles.push(`color:${attrs.color};`); + } + + if (attrs.size) { + styles.push(`font-size:${attrs.size};`); + } + + return styles.join(' '); +}; + +const asListItems = (content) => { + const listItems = []; + let listIdx = 0; + const createItemNode = () => ({ tag: 'li', attrs: {}, content: [] }); + const ensureListItem = (val) => { + listItems[listIdx] = listItems[listIdx] || val; + }; + const addItem = (val) => { + if (listItems[listIdx] && listItems[listIdx].content) { + listItems[listIdx].content = listItems[listIdx].content.concat(val); + } else { + listItems[listIdx] = listItems[listIdx].concat(val); + } + }; + content.forEach(el => { + if (typeof el === 'string' && el[0] === '*') { + if (listItems[listIdx]) { + listIdx++; + } + ensureListItem(createItemNode()); + addItem(el.substr(1)); + } else if (typeof el === 'object' && el.tag && el.tag === '*') { + if (listItems[listIdx]) { + listIdx++; + } + ensureListItem(createItemNode()); + } else { + if (listItems[listIdx] && !listItems[listIdx].tag) { + listIdx++; + ensureListItem(el); + } else if (listItems[listIdx]) { + addItem(el); + } else { + ensureListItem(el); + } + } + }); + + return [].concat(listItems); +}; + const processors = { b: node => ({ tag: 'span', @@ -61,16 +116,66 @@ const processors = { }, content: node.content, }), + u: node => ({ + tag: 'span', + attrs: { + style: 'text-decoration: underline;', + }, + content: node.content, + }), + s: node => ({ + tag: 'span', + attrs: { + style: 'text-decoration: line-through;', + }, + content: node.content, + }), + url: (node, { render }) => ({ + tag: 'a', + attrs: { + href: node.attrs.url ? node.attrs.url : render(node.content), + }, + content: node.content, + }), + img: (node, { render }) => ({ + tag: 'img', + attrs: { + src: render(node.content), + }, + content: null, + }), + quote: node => ({ + tag: 'blockquote', + attrs: {}, + content: [{ + tag: 'p', + attrs: {}, + content: node.content, + }], + }), + code: node => ({ + tag: 'pre', + attrs: {}, + content: node.content, + }), + style: node => ({ + tag: 'span', + attrs: { + style: getStyleFromAttrs(node.attrs), + }, + content: node.content, + }), + list: node => ({ + tag: 'ul', + attrs: {}, + content: asListItems(node.content), + }), }; module.exports = function html5Preset(opts = {}) { - return function process(tree) { - tree.forEach((node) => { - if (node.tag && processors[node.tag]) { - return processors[node.tag](node, opts); - } - - return node; - }); + return function process(tree, core) { + tree.walk(node => (node.tag && processors[node.tag] + ? processors[node.tag](node, core) + : node)); }; }; diff --git a/packages/bbob-preset-html5/test/index.test.js b/packages/bbob-preset-html5/test/index.test.js index ba659db..d6b2d3e 100644 --- a/packages/bbob-preset-html5/test/index.test.js +++ b/packages/bbob-preset-html5/test/index.test.js @@ -1,19 +1,108 @@ const preset = require('../lib/index'); -const bbob = require('@bbob/core'); +const core = require('@bbob/core'); -const processor = bbob([ - preset(), -]); +const parse = input => core([preset()]).process(input).html; -describe('bbob-preset-html5', () => { - test.skip('render [url]', () => { - const input = '[url=https://ru.wikipedia.org]Text[/url]'; - const result = 'Text'; - - expect(processor.process(input, { sync: true })).toBe(result); +describe('@bbob/preset-html5', () => { + test('[b]bolded text[/b]', () => { + const input = '[b]bolded text[/b]'; + const result = 'bolded text'; + expect(parse(input)).toBe(result); }); - test('dummy', () => { - expect(1).toBe(1); - }) + test('[i]italicized text[/i]', () => { + const input = '[i]italicized text[/i]'; + const result = 'italicized text'; + expect(parse(input)).toBe(result); + }); + + test('[u]underlined text[/u]', () => { + const input = '[u]underlined text[/u]'; + const result = 'underlined text'; + expect(parse(input)).toBe(result); + }); + + test('[s]strikethrough text[/s]', () => { + const input = '[s]strikethrough text[/s]'; + const result = 'strikethrough text'; + expect(parse(input)).toBe(result); + }); + + test('[url]https://en.wikipedia.org[/url]', () => { + const input = '[url]https://en.wikipedia.org[/url]'; + const result = 'https://en.wikipedia.org'; + + expect(parse(input)).toBe(result); + }); + + test('[url=http://step.pgc.edu/]ECAT[/url]', () => { + const input = '[url=http://step.pgc.edu/]ECAT[/url]'; + const result = 'ECAT'; + + expect(parse(input)).toBe(result); + }); + + test('[img]https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Go-home-2.svg/100px-Go-home-2.svg.png[/img]', () => { + const input = '[img]https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Go-home-2.svg/100px-Go-home-2.svg.png[/img]'; + const result = ''; + + expect(parse(input)).toBe(result); + }); + + test('[quote="author"]quoted text[/quote]', () => { + const input = '[quote="author"]quoted text[/quote]'; + const result = '

quoted text

'; + + expect(parse(input)).toBe(result); + }); + + test('[code]monospaced text[/code]', () => { + const input = '[code]monospaced text[/code]'; + const result = '
monospaced text
'; + + expect(parse(input)).toBe(result); + }); + + test('[style size="15px"]Large Text[/style]', () => { + const input = '[style size="15px"]Large Text[/style]'; + const result = 'Large Text'; + + expect(parse(input)).toBe(result); + }); + + test('[style color="red"]Red Text[/style]', () => { + const input = '[style color="red"]Red Text[/style]'; + const result = 'Red Text'; + + expect(parse(input)).toBe(result); + }); + + test(`[list][*]Entry 1[/list]`, () => { + const input = `[list][*]Entry 1[*]Entry 2[/list]`; + const result = ''; + + expect(parse(input)).toBe(result); + }); + + test(`[list]*Entry 1[/list]`, () => { + const input = ` + [list] + *Entry 1 + *Entry 2 + [/list]`; + const result = ` + `; + + expect(parse(input)).toBe(result); + }); + + test(`[table][/table]`, () => { + const input = `[table][tr][td]table 1[/td][td]table 2[/td][/tr][tr][td]table 3[/td][td]table 4[/td][/tr][/table]`; + const result = `
table 1table 2
table 3table 4
`; + + expect(parse(input)).toBe(result); + }); });