diff --git a/src/app/cartography/shared/helpers/font-fixer.spec.ts b/src/app/cartography/shared/helpers/font-fixer.spec.ts index 80639920..bab7fa33 100644 --- a/src/app/cartography/shared/helpers/font-fixer.spec.ts +++ b/src/app/cartography/shared/helpers/font-fixer.spec.ts @@ -36,4 +36,16 @@ describe('FontFixer', () => { 'font_weight': 'bold' }); }); + + it('should fix TypeWriter font and 10px size in styles', () => { + const styles = "font-family: TypeWriter; font-size: 10px; font-weight: bold"; + + expect(fixer.fixStyles(styles)).toEqual( 'font-family:Noto Sans;font-size:11px;font-weight:bold'); + }); + + it('should fix TypeWriter font and 10px size in styles with quotes', () => { + const styles = 'font-family: "TypeWriter"; font-size: 10px; font-weight: bold'; + + expect(fixer.fixStyles(styles)).toEqual( 'font-family:Noto Sans;font-size:11px;font-weight:bold'); + }); }); diff --git a/src/app/cartography/shared/helpers/font-fixer.ts b/src/app/cartography/shared/helpers/font-fixer.ts index 28056486..b44545f3 100644 --- a/src/app/cartography/shared/helpers/font-fixer.ts +++ b/src/app/cartography/shared/helpers/font-fixer.ts @@ -1,6 +1,8 @@ +import * as csstree from 'css-tree'; import { Injectable } from "@angular/core"; import { Font } from "../models/font"; + /** * GNS3 GUI doesn't update font when cannot find font in user system, this fixer fixes it */ @@ -18,4 +20,60 @@ export class FontFixer { } return font; } + + public fixStyles(styles: string) { + const ast = csstree.parse(styles, { + 'context': 'declarationList' + }); + + let fontFamilyPointer = null; + let fontSizePointer = null; + let isByIdentifier = true; + + ast.children.forEach((child) => { + if (child.property === 'font-family') { + child.value.children.forEach((value) => { + if (value.type === 'Identifier') { + fontFamilyPointer = value; + } + if (value.type === 'String') { + fontFamilyPointer = value; + isByIdentifier = false; + } + }); + } + if (child.property === 'font-size') { + child.value.children.forEach((value) => { + if (value.type === 'Dimension') { + fontSizePointer = value; + } + }); + } + }); + + if (fontSizePointer && fontFamilyPointer) { + let fontFamilyValue = null; + const fontSizeValue = fontSizePointer.value; + + if (isByIdentifier) { + fontFamilyValue = fontFamilyPointer.name; + } else { + fontFamilyValue = fontFamilyPointer.value; + } + + const fixedFont = this.fix({ + 'font_family': fontFamilyValue.split('"').join(''), + 'font_size': parseInt(fontSizeValue, 10), + } as Font); + + if (isByIdentifier) { + fontFamilyPointer.name = fixedFont.font_family; + } else { + fontFamilyPointer.value = fixedFont.font_family; + } + fontSizePointer.value = fixedFont.font_size; + } + + return csstree.generate(ast); + } } diff --git a/src/app/cartography/shared/widgets/nodes.ts b/src/app/cartography/shared/widgets/nodes.ts index fbdc6cef..fe9a2e7a 100644 --- a/src/app/cartography/shared/widgets/nodes.ts +++ b/src/app/cartography/shared/widgets/nodes.ts @@ -7,9 +7,12 @@ import { SVGSelection } from "../models/types"; import { Symbol } from "../models/symbol"; import { Layer } from "../models/layer"; import { CssFixer } from "../helpers/css-fixer"; +import { FontFixer } from "../helpers/font-fixer"; export class NodesWidget implements Widget { + static NODE_LABEL_MARGIN = 3; + private debug = false; private draggingEnabled = false; @@ -20,10 +23,12 @@ export class NodesWidget implements Widget { private symbols: Symbol[]; private cssFixer: CssFixer; + private fontFixer: FontFixer; constructor() { this.symbols = []; this.cssFixer = new CssFixer(); + this.fontFixer = new FontFixer(); } public setOnContextMenuCallback(onContextMenuCallback: (event: any, node: Node) => void) { @@ -65,7 +70,11 @@ export class NodesWidget implements Widget { selection .select('text.label') // .attr('y', (n: Node) => n.label.y - n.height / 2. + 10) // @todo: server computes y in auto way - .attr('style', (n: Node) => this.cssFixer.fix(n.label.style)) + .attr('style', (n: Node) => { + let styles = this.cssFixer.fix(n.label.style); + styles = this.fontFixer.fixStyles(styles); + return styles; + }) .text((n: Node) => n.label.text) .attr('x', function (this: SVGTextElement, n: Node) { if (n.label.x === null) { @@ -73,7 +82,7 @@ export class NodesWidget implements Widget { const bbox = this.getBBox(); return -bbox.width / 2.; } - return n.label.x; + return n.label.x + NodesWidget.NODE_LABEL_MARGIN; }) .attr('y', function (this: SVGTextElement, n: Node) { let bbox = this.getBBox(); @@ -83,7 +92,7 @@ export class NodesWidget implements Widget { bbox = this.getBBox(); return - n.height / 2. - bbox.height ; } - return n.label.y + bbox.height; + return n.label.y + bbox.height - NodesWidget.NODE_LABEL_MARGIN; }); selection