Add underline and overline styling [#54]

This commit is contained in:
David Evans 2018-05-06 00:07:26 +01:00
parent b23e278729
commit 5deec319df
14 changed files with 154 additions and 28 deletions

View File

@ -19,6 +19,9 @@
<FileRef
location = "container:.gitignore">
</FileRef>
<FileRef
location = "container:eslintrc.js">
</FileRef>
<FileRef
location = "container:index.html">
</FileRef>

View File

@ -10,6 +10,14 @@ module.exports = {
'plugin:jasmine/recommended',
],
'globals': {'SharedArrayBuffer': false},
'overrides': [
{
'files': ['**/*spec.*'],
'rules': {
'max-statements': ['off'],
},
},
],
'parserOptions': {
'sourceType': 'module',
},

View File

@ -4158,6 +4158,10 @@
const STYLES = [
{
attrs: {'font-style': 'italic'},
begin: {matcher: /<i>/g, skip: 0},
end: {matcher: /<\/i>/g, skip: 0},
}, {
attrs: {'font-style': 'italic'},
begin: {matcher: /[\s_~`>]\*(?=\S)/g, skip: 1},
end: {matcher: /\S\*(?=[\s_~`<])/g, skip: 1},
@ -4165,6 +4169,10 @@
attrs: {'font-style': 'italic'},
begin: {matcher: /[\s*~`>]_(?=\S)/g, skip: 1},
end: {matcher: /\S_(?=[\s*~`<])/g, skip: 1},
}, {
attrs: {'font-weight': 'bolder'},
begin: {matcher: /<b>/g, skip: 0},
end: {matcher: /<\/b>/g, skip: 0},
}, {
attrs: {'font-weight': 'bolder'},
begin: {matcher: /[\s_~`>]\*\*(?=\S)/g, skip: 1},
@ -4173,14 +4181,26 @@
attrs: {'font-weight': 'bolder'},
begin: {matcher: /[\s*~`>]__(?=\S)/g, skip: 1},
end: {matcher: /\S__(?=[\s*~`<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'line-through'},
begin: {matcher: /<s>/g, skip: 0},
end: {matcher: /<\/s>/g, skip: 0},
}, {
attrs: {'text-decoration': 'line-through'},
begin: {matcher: /[\s_*`>]~(?=\S)/g, skip: 1},
end: {matcher: /\S~(?=[\s_*`<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'overline'},
begin: {matcher: /<o>/g, skip: 0},
end: {matcher: /<\/o>/g, skip: 0},
}, {
attrs: {'font-family': 'Courier New,Liberation Mono,monospace'},
begin: {matcher: /[\s_*~.>]`(?=\S)/g, skip: 1},
end: {matcher: /\S`(?=[\s_*~.<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'underline'},
begin: {matcher: /<u>/g, skip: 0},
end: {matcher: /<\/u>/g, skip: 0},
}, {
attrs: {'fill': '#DD0000'},
begin: {matcher: /<red>/g, skip: 0},
@ -4221,11 +4241,21 @@
return null;
}
const attrs = {};
const decorations = [];
active.forEach((on, ind) => {
if(on) {
Object.assign(attrs, STYLES[ind].attrs);
if(!on) {
return;
}
const activeAttrs = STYLES[ind].attrs;
const decoration = activeAttrs['text-decoration'];
if(decoration && !decorations.includes(decoration)) {
decorations.push(decoration);
}
Object.assign(attrs, activeAttrs);
});
if(decorations.length > 1) {
attrs['text-decoration'] = decorations.join(' ');
}
return attrs;
}

File diff suppressed because one or more lines are too long

View File

@ -4158,6 +4158,10 @@
const STYLES = [
{
attrs: {'font-style': 'italic'},
begin: {matcher: /<i>/g, skip: 0},
end: {matcher: /<\/i>/g, skip: 0},
}, {
attrs: {'font-style': 'italic'},
begin: {matcher: /[\s_~`>]\*(?=\S)/g, skip: 1},
end: {matcher: /\S\*(?=[\s_~`<])/g, skip: 1},
@ -4165,6 +4169,10 @@
attrs: {'font-style': 'italic'},
begin: {matcher: /[\s*~`>]_(?=\S)/g, skip: 1},
end: {matcher: /\S_(?=[\s*~`<])/g, skip: 1},
}, {
attrs: {'font-weight': 'bolder'},
begin: {matcher: /<b>/g, skip: 0},
end: {matcher: /<\/b>/g, skip: 0},
}, {
attrs: {'font-weight': 'bolder'},
begin: {matcher: /[\s_~`>]\*\*(?=\S)/g, skip: 1},
@ -4173,14 +4181,26 @@
attrs: {'font-weight': 'bolder'},
begin: {matcher: /[\s*~`>]__(?=\S)/g, skip: 1},
end: {matcher: /\S__(?=[\s*~`<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'line-through'},
begin: {matcher: /<s>/g, skip: 0},
end: {matcher: /<\/s>/g, skip: 0},
}, {
attrs: {'text-decoration': 'line-through'},
begin: {matcher: /[\s_*`>]~(?=\S)/g, skip: 1},
end: {matcher: /\S~(?=[\s_*`<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'overline'},
begin: {matcher: /<o>/g, skip: 0},
end: {matcher: /<\/o>/g, skip: 0},
}, {
attrs: {'font-family': 'Courier New,Liberation Mono,monospace'},
begin: {matcher: /[\s_*~.>]`(?=\S)/g, skip: 1},
end: {matcher: /\S`(?=[\s_*~.<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'underline'},
begin: {matcher: /<u>/g, skip: 0},
end: {matcher: /<\/u>/g, skip: 0},
}, {
attrs: {'fill': '#DD0000'},
begin: {matcher: /<red>/g, skip: 0},
@ -4221,11 +4241,21 @@
return null;
}
const attrs = {};
const decorations = [];
active.forEach((on, ind) => {
if(on) {
Object.assign(attrs, STYLES[ind].attrs);
if(!on) {
return;
}
const activeAttrs = STYLES[ind].attrs;
const decoration = activeAttrs['text-decoration'];
if(decoration && !decorations.includes(decoration)) {
decorations.push(decoration);
}
Object.assign(attrs, activeAttrs);
});
if(decorations.length > 1) {
attrs['text-decoration'] = decorations.join(' ');
}
return attrs;
}

View File

@ -23,8 +23,9 @@
"bin": {
"sequence-diagram-svg": "./bin/sequence-diagram-svg.js"
},
"eslintIgnore": ["lib", "web/lib", "ephemeral", "*FontData.mjs"],
"scripts": {
"lint": "eslint . --config spec/support/eslintrc.js --ignore-path spec/support/eslintignore --ext .js --ext .mjs",
"lint": "eslint . --config eslintrc.js --ext .js --ext .mjs",
"generate-screenshots": "bin/generate-screenshots.js README.md",
"minify-lib": "rollup --config scripts/rollup.config.js && uglifyjs --compress --mangle --warn --output lib/sequence-diagram-web.min.js -- lib/sequence-diagram-web.js",
"minify-web": "rollup --config web/scripts/rollup.config.js && uglifyjs --compress --mangle --warn --output web/lib/editor.min.js -- web/lib/editor.js",

View File

@ -1,5 +1,3 @@
/* eslint-disable max-statements */
import SequenceDiagram from '../SequenceDiagram.mjs';
const CM = window.CodeMirror;

View File

@ -1,5 +1,4 @@
/* eslint-disable max-lines */
/* eslint-disable max-statements */
import Generator from './Generator.mjs';

View File

@ -1,5 +1,9 @@
const STYLES = [
{
attrs: {'font-style': 'italic'},
begin: {matcher: /<i>/g, skip: 0},
end: {matcher: /<\/i>/g, skip: 0},
}, {
attrs: {'font-style': 'italic'},
begin: {matcher: /[\s_~`>]\*(?=\S)/g, skip: 1},
end: {matcher: /\S\*(?=[\s_~`<])/g, skip: 1},
@ -7,6 +11,10 @@ const STYLES = [
attrs: {'font-style': 'italic'},
begin: {matcher: /[\s*~`>]_(?=\S)/g, skip: 1},
end: {matcher: /\S_(?=[\s*~`<])/g, skip: 1},
}, {
attrs: {'font-weight': 'bolder'},
begin: {matcher: /<b>/g, skip: 0},
end: {matcher: /<\/b>/g, skip: 0},
}, {
attrs: {'font-weight': 'bolder'},
begin: {matcher: /[\s_~`>]\*\*(?=\S)/g, skip: 1},
@ -15,14 +23,26 @@ const STYLES = [
attrs: {'font-weight': 'bolder'},
begin: {matcher: /[\s*~`>]__(?=\S)/g, skip: 1},
end: {matcher: /\S__(?=[\s*~`<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'line-through'},
begin: {matcher: /<s>/g, skip: 0},
end: {matcher: /<\/s>/g, skip: 0},
}, {
attrs: {'text-decoration': 'line-through'},
begin: {matcher: /[\s_*`>]~(?=\S)/g, skip: 1},
end: {matcher: /\S~(?=[\s_*`<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'overline'},
begin: {matcher: /<o>/g, skip: 0},
end: {matcher: /<\/o>/g, skip: 0},
}, {
attrs: {'font-family': 'Courier New,Liberation Mono,monospace'},
begin: {matcher: /[\s_*~.>]`(?=\S)/g, skip: 1},
end: {matcher: /\S`(?=[\s_*~.<])/g, skip: 1},
}, {
attrs: {'text-decoration': 'underline'},
begin: {matcher: /<u>/g, skip: 0},
end: {matcher: /<\/u>/g, skip: 0},
}, {
attrs: {'fill': '#DD0000'},
begin: {matcher: /<red>/g, skip: 0},
@ -63,11 +83,21 @@ function combineAttrs(activeCount, active) {
return null;
}
const attrs = {};
const decorations = [];
active.forEach((on, ind) => {
if(on) {
Object.assign(attrs, STYLES[ind].attrs);
if(!on) {
return;
}
const activeAttrs = STYLES[ind].attrs;
const decoration = activeAttrs['text-decoration'];
if(decoration && !decorations.includes(decoration)) {
decorations.push(decoration);
}
Object.assign(attrs, activeAttrs);
});
if(decorations.length > 1) {
attrs['text-decoration'] = decorations.join(' ');
}
return attrs;
}

View File

@ -54,14 +54,16 @@ describe('Markdown Parser', () => {
});
it('recognises bold styling', () => {
const formatted = parser('a **b** c __d__ e');
const formatted = parser('a **b** c __d__ e <b>f</b> g');
expect(formatted).toEqual([[
{attrs: null, text: 'a '},
{attrs: {'font-weight': 'bolder'}, text: 'b'},
{attrs: null, text: ' c '},
{attrs: {'font-weight': 'bolder'}, text: 'd'},
{attrs: null, text: ' e'},
{attrs: null, text: ' e '},
{attrs: {'font-weight': 'bolder'}, text: 'f'},
{attrs: null, text: ' g'},
]]);
});
@ -86,23 +88,47 @@ describe('Markdown Parser', () => {
});
it('recognises italic styling', () => {
const formatted = parser('a *b* c _d_ e');
const formatted = parser('a *b* c _d_ e <i>f</i> g');
expect(formatted).toEqual([[
{attrs: null, text: 'a '},
{attrs: {'font-style': 'italic'}, text: 'b'},
{attrs: null, text: ' c '},
{attrs: {'font-style': 'italic'}, text: 'd'},
{attrs: null, text: ' e'},
{attrs: null, text: ' e '},
{attrs: {'font-style': 'italic'}, text: 'f'},
{attrs: null, text: ' g'},
]]);
});
it('recognises strikethrough styling', () => {
const formatted = parser('a ~b~ c');
const formatted = parser('a ~b~ c <s>d</s> e');
expect(formatted).toEqual([[
{attrs: null, text: 'a '},
{attrs: {'text-decoration': 'line-through'}, text: 'b'},
{attrs: null, text: ' c '},
{attrs: {'text-decoration': 'line-through'}, text: 'd'},
{attrs: null, text: ' e'},
]]);
});
it('recognises underline styling', () => {
const formatted = parser('a <u>b</u> c');
expect(formatted).toEqual([[
{attrs: null, text: 'a '},
{attrs: {'text-decoration': 'underline'}, text: 'b'},
{attrs: null, text: ' c'},
]]);
});
it('recognises overline styling', () => {
const formatted = parser('a <o>b</o> c');
expect(formatted).toEqual([[
{attrs: null, text: 'a '},
{attrs: {'text-decoration': 'overline'}, text: 'b'},
{attrs: null, text: ' c'},
]]);
});
@ -172,6 +198,16 @@ describe('Markdown Parser', () => {
]]);
});
it('combines text decorations', () => {
const formatted = parser('a <s><u>b</u></s> c');
expect(formatted).toEqual([[
{attrs: null, text: 'a '},
{attrs: {'text-decoration': 'line-through underline'}, text: 'b'},
{attrs: null, text: ' c'},
]]);
});
it('allows complex interactions between styles', () => {
const formatted = parser('_a **b_ ~c~**');

View File

@ -1,5 +1,4 @@
/* eslint-disable max-lines */
/* eslint-disable max-statements */
import Parser from './Parser.mjs';

View File

@ -1,5 +1,3 @@
/* eslint-disable max-statements */
import Tokeniser from './Tokeniser.mjs';
describe('Sequence Tokeniser', () => {

View File

@ -1,5 +1,5 @@
<svg width="96.69921875" height="124" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-48.349609375 -119 96.69921875 124"><metadata>title "Foo **Bar**
<svg width="96.6966781616211" height="124" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-48.34833908081055 -119 96.6966781616211 124"><metadata>title "Foo **Bar**
_Baz_ `Zig`
**_`Zag`_**
**_`Zag`_** &lt;u&gt;&lt;o&gt;~Abc~&lt;/o&gt;&lt;/u&gt;
&lt;highlight&gt;Back&lt;/highlight&gt; &lt;red&gt;Text&lt;/red&gt;"
</metadata><defs><filter id="R0highlight"><feMorphology in="SourceAlpha" operator="dilate" radius="4"></feMorphology><feGaussianBlur edgeMode="none" stdDeviation="3, 1.5"></feGaussianBlur><feComponentTransfer><feFuncA intercept="-70" slope="100" type="linear"></feFuncA></feComponentTransfer><feComponentTransfer><feFuncR intercept="1" slope="0" type="linear"></feFuncR><feFuncG intercept="0.9375" slope="0" type="linear"></feFuncG><feFuncB intercept="0.09375" slope="0" type="linear"></feFuncB><feFuncA slope="0.7" type="linear"></feFuncA></feComponentTransfer><feMerge><feMergeNode></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge></filter></defs><defs><mask id="R0FullMask" maskUnits="userSpaceOnUse"><rect fill="#FFFFFF" height="124" width="96.69921875" x="-48.349609375" y="-119"></rect></mask><mask id="R0LineMask" maskUnits="userSpaceOnUse"><rect fill="#FFFFFF" height="124" width="96.69921875" x="-48.349609375" y="-119"></rect></mask></defs><g></g><g><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-94">Foo <tspan font-weight="bolder">Bar</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-68"><tspan font-style="italic">Baz</tspan> <tspan font-family="Courier New,Liberation Mono,monospace">Zig</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-42"><tspan font-style="italic" font-weight="bolder" font-family="Courier New,Liberation Mono,monospace">Zag</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-16"><tspan filter="url(#R0highlight)">Back</tspan> <tspan fill="#DD0000">Text</tspan></text></g><g></g><g mask="url(#R0FullMask)"><g mask="url(#R0LineMask)"></g><g></g><g></g></g></svg>
</metadata><defs><filter id="R0highlight"><feMorphology in="SourceAlpha" operator="dilate" radius="4"></feMorphology><feGaussianBlur edgeMode="none" stdDeviation="3, 1.5"></feGaussianBlur><feComponentTransfer><feFuncA intercept="-70" slope="100" type="linear"></feFuncA></feComponentTransfer><feComponentTransfer><feFuncR intercept="1" slope="0" type="linear"></feFuncR><feFuncG intercept="0.9375" slope="0" type="linear"></feFuncG><feFuncB intercept="0.09375" slope="0" type="linear"></feFuncB><feFuncA slope="0.7" type="linear"></feFuncA></feComponentTransfer><feMerge><feMergeNode></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge></filter></defs><defs><mask id="R0FullMask" maskUnits="userSpaceOnUse"><rect fill="#FFFFFF" height="124" width="96.6966781616211" x="-48.34833908081055" y="-119"></rect></mask><mask id="R0LineMask" maskUnits="userSpaceOnUse"><rect fill="#FFFFFF" height="124" width="96.6966781616211" x="-48.34833908081055" y="-119"></rect></mask></defs><g></g><g><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-94">Foo <tspan font-weight="bolder">Bar</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-68"><tspan font-style="italic">Baz</tspan> <tspan font-family="Courier New,Liberation Mono,monospace">Zig</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-42"><tspan font-style="italic" font-weight="bolder" font-family="Courier New,Liberation Mono,monospace">Zag</tspan> <tspan text-decoration="line-through overline underline">Abc</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-16"><tspan filter="url(#R0highlight)">Back</tspan> <tspan fill="#DD0000">Text</tspan></text></g><g></g><g mask="url(#R0FullMask)"><g mask="url(#R0LineMask)"></g><g></g><g></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,6 +0,0 @@
node_modules
lib
web/lib
ephemeral
*FontData.mjs