Tidy up chunky theme, add theme name autocomplete [#17]
This commit is contained in:
parent
f6f557bcd7
commit
2cb34c273c
|
@ -14,7 +14,7 @@
|
||||||
form-action 'none';
|
form-action 'none';
|
||||||
">
|
">
|
||||||
|
|
||||||
<title>Sequence Diagram</title>
|
<title>Readme Image Generator</title>
|
||||||
<link rel="icon" href="favicon.png">
|
<link rel="icon" href="favicon.png">
|
||||||
|
|
||||||
<link rel="stylesheet" href="styles/readme_images.css">
|
<link rel="stylesheet" href="styles/readme_images.css">
|
||||||
|
|
|
@ -109,6 +109,9 @@ define([
|
||||||
const code = new CodeMirror(container, {
|
const code = new CodeMirror(container, {
|
||||||
value,
|
value,
|
||||||
mode: 'sequence',
|
mode: 'sequence',
|
||||||
|
globals: {
|
||||||
|
themes: this.renderer.getThemeNames(),
|
||||||
|
},
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
showTrailingSpace: true,
|
showTrailingSpace: true,
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
|
|
|
@ -24,7 +24,11 @@ defineDescribe('Interface', ['./Interface'], (Interface) => {
|
||||||
agents: [],
|
agents: [],
|
||||||
stages: [],
|
stages: [],
|
||||||
});
|
});
|
||||||
renderer = jasmine.createSpyObj('renderer', ['render', 'svg']);
|
renderer = jasmine.createSpyObj('renderer', [
|
||||||
|
'render',
|
||||||
|
'svg',
|
||||||
|
'getThemeNames',
|
||||||
|
]);
|
||||||
renderer.svg.and.returnValue(document.createElement('svg'));
|
renderer.svg.and.returnValue(document.createElement('svg'));
|
||||||
container = jasmine.createSpyObj('container', ['appendChild']);
|
container = jasmine.createSpyObj('container', ['appendChild']);
|
||||||
exporter = jasmine.createSpyObj('exporter', ['getSVGURL']);
|
exporter = jasmine.createSpyObj('exporter', ['getSVGURL']);
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PNG_RESOLUTION = 4;
|
||||||
|
|
||||||
const FAVICON_SRC = (
|
const FAVICON_SRC = (
|
||||||
'theme chunky\n' +
|
'theme chunky\n' +
|
||||||
'define ABC as A, DEF as B\n' +
|
'define ABC as A, DEF as B\n' +
|
||||||
|
@ -47,7 +49,7 @@
|
||||||
results.push({
|
results.push({
|
||||||
file: 'favicon.png',
|
file: 'favicon.png',
|
||||||
code: FAVICON_SRC,
|
code: FAVICON_SRC,
|
||||||
height: 64,
|
size: {width: 16, height: 16},
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +63,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PNG_RESOLUTION = 4;
|
|
||||||
|
|
||||||
/* jshint -W072 */ // Allow several required modules
|
/* jshint -W072 */ // Allow several required modules
|
||||||
requirejs([
|
requirejs([
|
||||||
'sequence/Parser',
|
'sequence/Parser',
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
status.appendChild(statusText);
|
status.appendChild(statusText);
|
||||||
document.body.appendChild(status);
|
document.body.appendChild(status);
|
||||||
|
|
||||||
function renderSample({file, code, height}) {
|
function renderSample({file, code, size}) {
|
||||||
const renderer = new Renderer({themes});
|
const renderer = new Renderer({themes});
|
||||||
const exporter = new Exporter();
|
const exporter = new Exporter();
|
||||||
|
|
||||||
|
@ -124,11 +124,11 @@
|
||||||
const parsed = parser.parse(code);
|
const parsed = parser.parse(code);
|
||||||
const sequence = generator.generate(parsed);
|
const sequence = generator.generate(parsed);
|
||||||
renderer.render(sequence);
|
renderer.render(sequence);
|
||||||
let resolution = PNG_RESOLUTION;
|
if(size) {
|
||||||
if(height) {
|
renderer.width = size.width;
|
||||||
resolution = height / renderer.height;
|
renderer.height = size.height;
|
||||||
}
|
}
|
||||||
exporter.getPNGURL(renderer, resolution, (url) => {
|
exporter.getPNGURL(renderer, PNG_RESOLUTION, (url) => {
|
||||||
raster.setAttribute('src', url);
|
raster.setAttribute('src', url);
|
||||||
downloadPNG.setAttribute('href', url);
|
downloadPNG.setAttribute('href', url);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
define(() => {
|
define(['core/ArrayUtilities'], (array) => {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const TRIMMER = /^([ \t]*)(.*)$/;
|
const TRIMMER = /^([ \t]*)(.*)$/;
|
||||||
|
@ -32,6 +32,26 @@ define(() => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getGlobals({global, prefix = '', suffix = ''}, globals) {
|
||||||
|
const identified = globals[global];
|
||||||
|
if(!identified) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return identified.map((item) => (prefix + item + suffix));
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateGlobals(suggestions, globals = {}) {
|
||||||
|
for(let i = 0; i < suggestions.length;) {
|
||||||
|
if(typeof suggestions[i] === 'object') {
|
||||||
|
const identified = getGlobals(suggestions[i], globals);
|
||||||
|
array.mergeSets(suggestions, identified);
|
||||||
|
suggestions.splice(i, 1);
|
||||||
|
} else {
|
||||||
|
++ i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getHints(cm, options) {
|
function getHints(cm, options) {
|
||||||
const cur = cm.getCursor();
|
const cur = cm.getCursor();
|
||||||
const token = cm.getTokenAt(cur);
|
const token = cm.getTokenAt(cur);
|
||||||
|
@ -52,6 +72,8 @@ define(() => {
|
||||||
comp = comp.concat(token.state.knownAgent);
|
comp = comp.concat(token.state.knownAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
populateGlobals(comp, cm.options.globals);
|
||||||
|
|
||||||
const ranges = makeRanges(cm, cur.line, from, token.end);
|
const ranges = makeRanges(cm, cur.line, from, token.end);
|
||||||
let selfValid = false;
|
let selfValid = false;
|
||||||
const list = (comp
|
const list = (comp
|
||||||
|
|
|
@ -26,11 +26,21 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
',': {type: 'operator', suggest: true, then: {'': 1}},
|
',': {type: 'operator', suggest: true, then: {'': 1}},
|
||||||
'\n': end,
|
'\n': end,
|
||||||
}};
|
}};
|
||||||
const agentListToEnd = {type: 'variable', suggest: 'Agent', then: {
|
const agentListToText = {type: 'variable', suggest: 'Agent', then: {
|
||||||
'': 0,
|
'': 0,
|
||||||
',': {type: 'operator', suggest: true, then: {'': 1}},
|
',': {type: 'operator', suggest: true, then: {'': 1}},
|
||||||
':': {type: 'operator', suggest: true, then: {'': textToEnd}},
|
':': {type: 'operator', suggest: true, then: {'': textToEnd}},
|
||||||
}};
|
}};
|
||||||
|
const agentList2ToText = {type: 'variable', suggest: 'Agent', then: {
|
||||||
|
'': 0,
|
||||||
|
',': {type: 'operator', suggest: true, then: {'': agentListToText}},
|
||||||
|
':': CM_ERROR,
|
||||||
|
}};
|
||||||
|
const singleAgentToText = {type: 'variable', suggest: 'Agent', then: {
|
||||||
|
'': 0,
|
||||||
|
',': CM_ERROR,
|
||||||
|
':': {type: 'operator', suggest: true, then: {'': textToEnd}},
|
||||||
|
}};
|
||||||
const agentToOptText = {type: 'variable', suggest: 'Agent', then: {
|
const agentToOptText = {type: 'variable', suggest: 'Agent', then: {
|
||||||
'': 0,
|
'': 0,
|
||||||
':': {type: 'operator', suggest: true, then: {
|
':': {type: 'operator', suggest: true, then: {
|
||||||
|
@ -46,12 +56,12 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
suggest: [side + ' of ', side + ': '],
|
suggest: [side + ' of ', side + ': '],
|
||||||
then: {
|
then: {
|
||||||
'of': {type: 'keyword', suggest: true, then: {
|
'of': {type: 'keyword', suggest: true, then: {
|
||||||
'': agentListToEnd,
|
'': agentListToText,
|
||||||
}},
|
}},
|
||||||
':': {type: 'operator', suggest: true, then: {
|
':': {type: 'operator', suggest: true, then: {
|
||||||
'': textToEnd,
|
'': textToEnd,
|
||||||
}},
|
}},
|
||||||
'': agentListToEnd,
|
'': agentListToText,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -122,7 +132,17 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
'': textToEnd,
|
'': textToEnd,
|
||||||
}},
|
}},
|
||||||
'theme': {type: 'keyword', suggest: true, then: {
|
'theme': {type: 'keyword', suggest: true, then: {
|
||||||
'': textToEnd,
|
'': {
|
||||||
|
type: 'string',
|
||||||
|
suggest: {
|
||||||
|
global: 'themes',
|
||||||
|
suffix: '\n',
|
||||||
|
},
|
||||||
|
then: {
|
||||||
|
'': 0,
|
||||||
|
'\n': end,
|
||||||
|
},
|
||||||
|
},
|
||||||
}},
|
}},
|
||||||
'terminators': {type: 'keyword', suggest: true, then: {
|
'terminators': {type: 'keyword', suggest: true, then: {
|
||||||
'none': {type: 'keyword', suggest: true, then: {}},
|
'none': {type: 'keyword', suggest: true, then: {}},
|
||||||
|
@ -166,17 +186,17 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
}},
|
}},
|
||||||
'note': {type: 'keyword', suggest: true, then: {
|
'note': {type: 'keyword', suggest: true, then: {
|
||||||
'over': {type: 'keyword', suggest: true, then: {
|
'over': {type: 'keyword', suggest: true, then: {
|
||||||
'': agentListToEnd,
|
'': agentListToText,
|
||||||
}},
|
}},
|
||||||
'left': makeSideNote('left'),
|
'left': makeSideNote('left'),
|
||||||
'right': makeSideNote('right'),
|
'right': makeSideNote('right'),
|
||||||
'between': {type: 'keyword', suggest: true, then: {
|
'between': {type: 'keyword', suggest: true, then: {
|
||||||
'': agentListToEnd,
|
'': agentList2ToText,
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
'state': {type: 'keyword', suggest: 'state over ', then: {
|
'state': {type: 'keyword', suggest: 'state over ', then: {
|
||||||
'over': {type: 'keyword', suggest: true, then: {
|
'over': {type: 'keyword', suggest: true, then: {
|
||||||
'': agentListToEnd,
|
'': singleAgentToText,
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
'text': {type: 'keyword', suggest: true, then: {
|
'text': {type: 'keyword', suggest: true, then: {
|
||||||
|
@ -204,6 +224,9 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmGetVarSuggestions(state, previous, current) {
|
function cmGetVarSuggestions(state, previous, current) {
|
||||||
|
if(typeof current.suggest === 'object' && current.suggest.global) {
|
||||||
|
return [current.suggest];
|
||||||
|
}
|
||||||
if(
|
if(
|
||||||
typeof current.suggest !== 'string' ||
|
typeof current.suggest !== 'string' ||
|
||||||
previous.suggest === current.suggest
|
previous.suggest === current.suggest
|
||||||
|
|
|
@ -589,6 +589,12 @@ define([
|
||||||
this.sizer.detach();
|
this.sizer.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getThemeNames() {
|
||||||
|
return (Array.from(this.themes.keys())
|
||||||
|
.filter((name) => (name !== ''))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getAgentX(name) {
|
getAgentX(name) {
|
||||||
return this.agentInfos.get(name).x;
|
return this.agentInfos.get(name).x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,17 @@ define([
|
||||||
|
|
||||||
function getArrowShort(theme) {
|
function getArrowShort(theme) {
|
||||||
const arrow = theme.connect.arrow;
|
const arrow = theme.connect.arrow;
|
||||||
const h = arrow.height / 2;
|
const join = arrow.attrs['stroke-linejoin'] || 'miter';
|
||||||
const w = arrow.width;
|
|
||||||
const t = arrow.attrs['stroke-width'] * 0.5;
|
const t = arrow.attrs['stroke-width'] * 0.5;
|
||||||
const lineStroke = theme.agentLineAttrs['stroke-width'] * 0.5;
|
const lineStroke = theme.agentLineAttrs['stroke-width'] * 0.5;
|
||||||
const arrowDistance = t * Math.sqrt((w * w) / (h * h) + 1);
|
if(join === 'round') {
|
||||||
return lineStroke + arrowDistance;
|
return lineStroke + t;
|
||||||
|
} else {
|
||||||
|
const h = arrow.height / 2;
|
||||||
|
const w = arrow.width;
|
||||||
|
const arrowDistance = t * Math.sqrt((w * w) / (h * h) + 1);
|
||||||
|
return lineStroke + arrowDistance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Connect extends BaseComponent {
|
class Connect extends BaseComponent {
|
||||||
|
|
|
@ -4,7 +4,7 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
const LINE_HEIGHT = 1.3;
|
const LINE_HEIGHT = 1.3;
|
||||||
|
|
||||||
const SETTINGS = {
|
const SETTINGS = {
|
||||||
titleMargin: 10,
|
titleMargin: 12,
|
||||||
outerMargin: 5,
|
outerMargin: 5,
|
||||||
agentMargin: 8,
|
agentMargin: 8,
|
||||||
actionMargin: 5,
|
actionMargin: 5,
|
||||||
|
@ -40,6 +40,7 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
'fill': 'none',
|
'fill': 'none',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 3,
|
'stroke-width': 3,
|
||||||
|
'stroke-linecap': 'round',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bar: {
|
bar: {
|
||||||
|
@ -48,6 +49,8 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 3,
|
'stroke-width': 3,
|
||||||
'height': 4,
|
'height': 4,
|
||||||
|
'rx': 2,
|
||||||
|
'ry': 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
fade: {
|
fade: {
|
||||||
|
@ -60,7 +63,7 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
},
|
},
|
||||||
|
|
||||||
connect: {
|
connect: {
|
||||||
loopbackRadius: 6,
|
loopbackRadius: 8,
|
||||||
lineAttrs: {
|
lineAttrs: {
|
||||||
'solid': {
|
'solid': {
|
||||||
'fill': 'none',
|
'fill': 'none',
|
||||||
|
@ -71,7 +74,7 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
'fill': 'none',
|
'fill': 'none',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 3,
|
'stroke-width': 3,
|
||||||
'stroke-dasharray': '4, 2',
|
'stroke-dasharray': '10, 4',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
arrow: {
|
arrow: {
|
||||||
|
@ -79,13 +82,14 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
height: 12,
|
height: 12,
|
||||||
attrs: {
|
attrs: {
|
||||||
'fill': '#000000',
|
'fill': '#000000',
|
||||||
'stroke-width': 0,
|
'stroke': '#000000',
|
||||||
'stroke-linejoin': 'miter',
|
'stroke-width': 3,
|
||||||
|
'stroke-linejoin': 'round',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
padding: 6,
|
padding: 6,
|
||||||
margin: {top: 2, bottom: 1},
|
margin: {top: 2, bottom: 3},
|
||||||
attrs: {
|
attrs: {
|
||||||
'font-family': 'sans-serif',
|
'font-family': 'sans-serif',
|
||||||
'font-size': 8,
|
'font-size': 8,
|
||||||
|
@ -100,10 +104,10 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
},
|
},
|
||||||
mask: {
|
mask: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 0,
|
top: 1,
|
||||||
left: 3,
|
left: 5,
|
||||||
right: 3,
|
right: 5,
|
||||||
bottom: 1,
|
bottom: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -116,28 +120,28 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
boxAttrs: {
|
boxAttrs: {
|
||||||
'fill': 'none',
|
'fill': 'none',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1.5,
|
'stroke-width': 4,
|
||||||
'rx': 2,
|
'rx': 5,
|
||||||
'ry': 2,
|
'ry': 5,
|
||||||
},
|
},
|
||||||
section: {
|
section: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 3,
|
top: 3,
|
||||||
bottom: 2,
|
bottom: 4,
|
||||||
},
|
},
|
||||||
mode: {
|
mode: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 1,
|
top: 2,
|
||||||
left: 3,
|
left: 5,
|
||||||
right: 3,
|
right: 5,
|
||||||
bottom: 0,
|
bottom: 1,
|
||||||
},
|
},
|
||||||
boxAttrs: {
|
boxAttrs: {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 3,
|
'stroke-width': 2,
|
||||||
'rx': 2,
|
'rx': 3,
|
||||||
'ry': 2,
|
'ry': 3,
|
||||||
},
|
},
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': 'sans-serif',
|
'font-family': 'sans-serif',
|
||||||
|
@ -149,7 +153,7 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 1,
|
top: 2,
|
||||||
left: 5,
|
left: 5,
|
||||||
right: 3,
|
right: 3,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
|
@ -165,8 +169,8 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
separator: {
|
separator: {
|
||||||
attrs: {
|
attrs: {
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1.5,
|
'stroke-width': 2,
|
||||||
'stroke-dasharray': '4, 2',
|
'stroke-dasharray': '5, 3',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -187,12 +191,13 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
},
|
},
|
||||||
'note': {
|
'note': {
|
||||||
margin: {top: 0, left: 5, right: 5, bottom: 0},
|
margin: {top: 0, left: 5, right: 5, bottom: 0},
|
||||||
padding: {top: 5, left: 5, right: 10, bottom: 5},
|
padding: {top: 3, left: 3, right: 10, bottom: 3},
|
||||||
overlap: {left: 10, right: 10},
|
overlap: {left: 10, right: 10},
|
||||||
boxRenderer: SVGShapes.renderNote.bind(null, {
|
boxRenderer: SVGShapes.renderNote.bind(null, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1,
|
'stroke-width': 2,
|
||||||
|
'stroke-linejoin': 'round',
|
||||||
}, {
|
}, {
|
||||||
'fill': 'none',
|
'fill': 'none',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
|
@ -206,12 +211,12 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
},
|
},
|
||||||
'state': {
|
'state': {
|
||||||
margin: {top: 0, left: 5, right: 5, bottom: 0},
|
margin: {top: 0, left: 5, right: 5, bottom: 0},
|
||||||
padding: {top: 7, left: 7, right: 7, bottom: 7},
|
padding: {top: 5, left: 7, right: 7, bottom: 5},
|
||||||
overlap: {left: 10, right: 10},
|
overlap: {left: 10, right: 10},
|
||||||
boxRenderer: SVGShapes.renderBox.bind(null, {
|
boxRenderer: SVGShapes.renderBox.bind(null, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1,
|
'stroke-width': 3,
|
||||||
'rx': 10,
|
'rx': 10,
|
||||||
'ry': 10,
|
'ry': 10,
|
||||||
}),
|
}),
|
||||||
|
@ -225,6 +230,7 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
|
|
||||||
titleAttrs: {
|
titleAttrs: {
|
||||||
'font-family': 'sans-serif',
|
'font-family': 'sans-serif',
|
||||||
|
'font-weight': 'bolder',
|
||||||
'font-size': 20,
|
'font-size': 20,
|
||||||
'line-height': LINE_HEIGHT,
|
'line-height': LINE_HEIGHT,
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
|
|
Loading…
Reference in New Issue