From b8427b841323fe2c8dc14584b0b10c30159d2023 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ulrich-Matthias=20Sch=C3=A4fer?= Date: Sat, 25 Apr 2020 15:20:44 +1000 Subject: [PATCH] sort out unused regex, add parser and regex tests, fix textable tests --- spec/helpers.js | 6 +- spec/runSVGDomTest.js | 8 +- spec/setupSVGDom.js | 4 +- spec/spec/modules/core/parser.js | 28 ++++ spec/spec/modules/core/regex.js | 245 +++++++++++++++++++++++++++++ spec/spec/modules/core/textable.js | 16 +- src/modules/core/regex.js | 10 +- svg.js.d.ts | 2 - 8 files changed, 291 insertions(+), 28 deletions(-) create mode 100644 spec/spec/modules/core/parser.js create mode 100644 spec/spec/modules/core/regex.js diff --git a/spec/helpers.js b/spec/helpers.js index 0fa2a1f..d6d1405 100644 --- a/spec/helpers.js +++ b/spec/helpers.js @@ -1,9 +1,9 @@ import { getWindow } from '../src/utils/window.js' -import { ns } from '../src/modules/core/namespaces.js' +import { svg } from '../src/modules/core/namespaces.js' function tag (name, attrs, children) { const doc = getWindow().document - const el = doc.createElementNS(ns, name) + const el = doc.createElementNS(svg, name) let i for (i in attrs) { @@ -158,4 +158,6 @@ export function clear () { // remove if present fixtures && fixtures.parentNode.removeChild(fixtures) canvas.parentNode.removeChild(canvas) + + ;[ ...doc.querySelectorAll('svg') ].forEach((el) => el.parentNode.removeChild(el)) } diff --git a/spec/runSVGDomTest.js b/spec/runSVGDomTest.js index 3f2276e..3ce24cf 100644 --- a/spec/runSVGDomTest.js +++ b/spec/runSVGDomTest.js @@ -9,14 +9,12 @@ import Jasmine from 'jasmine' const jasmine = new Jasmine() jasmine.loadConfig({ - spec_dir: 'spec/', + spec_dir: '/', spec_files: [ - 'spec/types/*.js', - 'spec/utils/*.js', - 'spec/elements/*.js' + 'spec/spec/*/**/*.js' ], helpers: [ - 'setupSVGDom.js' + 'spec/setupSVGDom.js' ] }) diff --git a/spec/setupSVGDom.js b/spec/setupSVGDom.js index 1d9ff95..72e5383 100644 --- a/spec/setupSVGDom.js +++ b/spec/setupSVGDom.js @@ -1,4 +1,4 @@ -import { createSVGWindow } from 'svgdom' +import { createHTMLWindow } from 'svgdom' /* globals beforeEach, afterEach, jasmine */ import { buildCanvas, clear } from './helpers.js' @@ -7,7 +7,7 @@ import { registerWindow } from '../src/main.js' jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 function setup () { - const win = createSVGWindow() + const win = createHTMLWindow() registerWindow(win, win.document) buildCanvas() // buildFixtures() diff --git a/spec/spec/modules/core/parser.js b/spec/spec/modules/core/parser.js new file mode 100644 index 0000000..c7acc4e --- /dev/null +++ b/spec/spec/modules/core/parser.js @@ -0,0 +1,28 @@ +/* globals describe, expect, it */ + +import parser from '../../../../src/modules/core/parser.js' +import { getWindow } from '../../../../src/utils/window.js' + +describe('parser.js', () => { + describe('parser()', () => { + it('returns an object with svg and path', () => { + const nodes = parser() + expect(nodes.path).toBeDefined() + expect(nodes.svg).toBeDefined() + }) + + it('creates an svg node in the dom', () => { + expect(getWindow().document.querySelector('svg')).toBe(null) + const nodes = parser() + expect(getWindow().document.querySelector('svg')).toBe(nodes.svg.node) + }) + + it('reuses parser instance when it was removed', () => { + const nodes = parser() + nodes.svg.remove() + const nodes2 = parser() + expect(nodes.svg).toBe(nodes2.svg) + expect(nodes.path).toBe(nodes2.path) + }) + }) +}) diff --git a/spec/spec/modules/core/regex.js b/spec/spec/modules/core/regex.js new file mode 100644 index 0000000..d3db682 --- /dev/null +++ b/spec/spec/modules/core/regex.js @@ -0,0 +1,245 @@ +/* globals describe, expect, it */ + +import { regex } from '../../../../src/main.js' + +describe('regex.js', () => { + describe('numberAndUnit', () => { + it('matches number and unit 12px', () => { + const match = '12px'.match(regex.numberAndUnit) + expect(match[1]).toBe('12') + expect(match[5]).toBe('px') + }) + + it('matches number and unit 12', () => { + const match = '12'.match(regex.numberAndUnit) + expect(match[1]).toBe('12') + expect(match[5]).toBe('') + }) + + it('matches number and unit 12%', () => { + const match = '12%'.match(regex.numberAndUnit) + expect(match[1]).toBe('12') + expect(match[5]).toBe('%') + }) + + it('matches number and unit -12%', () => { + const match = '-12%'.match(regex.numberAndUnit) + expect(match[1]).toBe('-12') + expect(match[5]).toBe('%') + }) + + it('matches number and unit -12.123%', () => { + const match = '-12.123%'.match(regex.numberAndUnit) + expect(match[1]).toBe('-12.123') + expect(match[5]).toBe('%') + }) + + it('matches number and unit -12.123e12%', () => { + const match = '-12.123e12%'.match(regex.numberAndUnit) + expect(match[1]).toBe('-12.123e12') + expect(match[5]).toBe('%') + }) + }) + + describe('hex', () => { + it('matches a 6 digit hex', () => { + const match = '#123456'.match(regex.hex) + expect(match[1]).toBe('12') + expect(match[2]).toBe('34') + expect(match[3]).toBe('56') + }) + + /* it('doesnt matches without #', () => { + const match = '123456'.match(regex.hex) + expect(match).toBe(null) + }) */ + + it('doesnt matches other then 0-f #', () => { + const match = '#09afhz'.match(regex.hex) + expect(match).toBe(null) + }) + + it('doesnt matches non full hex', () => { + const match = '#aaa'.match(regex.hex) + expect(match).toBe(null) + }) + }) + + describe('rgb', () => { + it('matches rgb values of rgb(...) command', () => { + const match = 'rgb(12,34,56)'.match(regex.rgb) + expect(match[1]).toBe('12') + expect(match[2]).toBe('34') + expect(match[3]).toBe('56') + }) + + it('doesnt match in the wrong format', () => { + expect('rgb( 12 , 34 , 56)'.match(regex.rgb)).toBe(null) + expect('12,34,56'.match(regex.rgb)).toBe(null) + expect('(12,34,56)'.match(regex.rgb)).toBe(null) + expect('rgb(aa,34,56)'.match(regex.rgb)).toBe(null) + expect('rgb(12,34)'.match(regex.rgb)).toBe(null) + }) + }) + + describe('reference', () => { + it('matches a reference', () => { + const match = '#soMe_cRazy-1_id'.match(regex.reference) + expect(match[1]).toBe('#soMe_cRazy-1_id') + }) + + it('tries to match malformed references', () => { + const match = '#some_crazy%-1_id'.match(regex.reference) + expect(match[0]).toBe('#some_crazy') + }) + }) + + describe('transforms', () => { + it('splits a transform chain', () => { + const split = 'rotate(34) translate(1,2), translate(1 , 3),rotate(12) , something(1,2,3)'.split(regex.transforms) + expect(split).toEqual([ 'rotate(34', 'translate(1,2', 'translate(1 , 3', 'rotate(12', 'something(1,2,3', '' ]) + }) + }) + + describe('whitespace', () => { + it('replaces all whitespaces', () => { + expect(' \n \r \t '.replace(regex.whitespace, ' ')).toBe(' ') + }) + }) + + describe('isHex', () => { + it('returns true when testing hex values', () => { + expect(regex.isHex.test('#123')).toBe(true) + expect(regex.isHex.test('#abc')).toBe(true) + expect(regex.isHex.test('#123456')).toBe(true) + expect(regex.isHex.test('#abcdef')).toBe(true) + expect(regex.isHex.test('#16fde9')).toBe(true) + }) + + it('returns false when testing non hex values', () => { + expect(regex.isHex.test('#12')).toBe(false) + expect(regex.isHex.test('abc')).toBe(false) + expect(regex.isHex.test('#1234563')).toBe(false) + expect(regex.isHex.test('#kasdhs')).toBe(false) + }) + }) + + describe('isRgb', () => { + it('returns true when testing rgb values', () => { + expect(regex.isRgb.test('rgb(1,2,3)')).toBe(true) + expect(regex.isRgb.test('rgb( 3, 1,3)')).toBe(true) + }) + + it('returns false when testing non rgb values', () => { + expect(regex.isRgb.test('hsl(1,2,3)')).toBe(false) + expect(regex.isRgb.test('#123')).toBe(false) + expect(regex.isRgb.test('something')).toBe(false) + }) + }) + + describe('isBlank', () => { + it('returns true if something is blank', () => { + expect(regex.isBlank.test('')).toBe(true) + expect(regex.isBlank.test(' ')).toBe(true) + expect(regex.isBlank.test('\n')).toBe(true) + expect(regex.isBlank.test('\r')).toBe(true) + expect(regex.isBlank.test('\t')).toBe(true) + expect(regex.isBlank.test(' \n\r\t')).toBe(true) + }) + + it('returns false if something is not blank', () => { + expect(regex.isBlank.test('a')).toBe(false) + expect(regex.isBlank.test('1')).toBe(false) + }) + }) + + describe('isNumber', () => { + it('returns true if something is a number', () => { + expect(regex.isNumber.test('123')).toBe(true) + expect(regex.isNumber.test('-123')).toBe(true) + expect(regex.isNumber.test('-12.3')).toBe(true) + expect(regex.isNumber.test('-12.3e12')).toBe(true) + expect(regex.isNumber.test('-12.3e-12')).toBe(true) + expect(regex.isNumber.test('+12.3e-12')).toBe(true) + expect(regex.isNumber.test('+12.3E-12')).toBe(true) + }) + + it('returns false if something is not a number', () => { + expect(regex.isNumber.test('a')).toBe(false) + expect(regex.isNumber.test('-a')).toBe(false) + expect(regex.isNumber.test('-12a')).toBe(false) + expect(regex.isNumber.test('-12.3a12')).toBe(false) + expect(regex.isNumber.test('-12.3e-1a')).toBe(false) + expect(regex.isNumber.test('12.12.12')).toBe(false) + expect(regex.isNumber.test('12.12e12.3')).toBe(false) + expect(regex.isNumber.test('12.12e12e4')).toBe(false) + }) + }) + + describe('isImage', () => { + it('returns true if something is an image filename', () => { + expect(regex.isImage.test('a.jpg')).toBe(true) + expect(regex.isImage.test('a.jpeg')).toBe(true) + expect(regex.isImage.test('a.png')).toBe(true) + expect(regex.isImage.test('a.gif')).toBe(true) + expect(regex.isImage.test('a.svg')).toBe(true) + }) + + it('returns false if something is not an image filename', () => { + expect(regex.isImage.test('a.abc')).toBe(false) + expect(regex.isImage.test('a.txt')).toBe(false) + expect(regex.isImage.test('a.doc')).toBe(false) + }) + }) + + describe('delimiter', () => { + it('splits at whitespace and comma', () => { + const split = '1,2 3 , 4 5,, 6'.split(regex.delimiter) + expect(split).toEqual([ '1', '2', '3', '4', '5', '6' ]) + }) + }) + + describe('hyphen', () => { + it('matches all hyphens which are preceeded by something but not an exponent', () => { + expect(regex.hyphen.test('a-')).toBe(true) + expect(regex.hyphen.test('e-')).toBe(false) + }) + + it('replaces all hyphens and their preceeding char which is not an exponent', () => { + expect(' - e- ---E-'.replace(regex.hyphen, '.')).toBe(' . e-..E-') + }) + }) + + describe('pathLetters', () => { + it('replaces all path letters', () => { + expect('MLHVCSQTAZBImlhvcsqtazbi'.replace(regex.pathLetters, '.')).toBe('..........BI..........bi') + }) + }) + + describe('isPathLetter', () => { + it('returns true if something is a path letter', () => { + 'MLHVCSQTAZmlhvcsqtaz'.split('').forEach((l) => { + expect(regex.isPathLetter.test(l)).toBe(true) + }) + }) + + it('returns false if something is not path letter', () => { + '123biuBIU$%&'.split('').forEach((l) => { + expect(regex.isPathLetter.test(l)).toBe(false) + }) + }) + }) + + describe('numbersWithDots', () => { + it('matches numbers of the form 3.13.123', () => { + const match = '-123.23.45 +123.324 43.43.54.65 123 33 .24 .34.34 -.54 .54-.65 123.34e34.21'.match(regex.numbersWithDots) + expect(match).toEqual([ '3.23.45', '3.43.54.65', '.34.34', '3.34e34.21' ]) + }) + }) + + describe('dots', () => { + it('replaces all dots', () => { + expect('..asd..'.replace(regex.dots, 'a')).toBe('aaasdaa') + }) + }) +}) diff --git a/spec/spec/modules/core/textable.js b/spec/spec/modules/core/textable.js index c634fb5..1293575 100644 --- a/spec/spec/modules/core/textable.js +++ b/spec/spec/modules/core/textable.js @@ -7,7 +7,7 @@ describe('textable.js', () => { beforeEach(() => { canvas = SVG().addTo(container) - text = canvas.text('Hello World') + text = canvas.text('Hello World\nIn two lines') tspan = text.get(0) }) @@ -39,27 +39,25 @@ describe('textable.js', () => { }) describe('y()', () => { - it('returns the value of x without an argument on a text', () => { + it('returns the value of y without an argument on a text', () => { expect(text.y(0).y()).toBe(0) }) - it('sets the x value of the bbox with the first argument on a text', () => { + it('sets the y value of the bbox with the first argument on a text', () => { text.y(123) expect(text.bbox().y).toBe(123) }) - it('sets the value of all lines', () => { + it('sets the y position of first line', () => { text.y(200) - text.each(function () { - expect(this.y()).toBe(text.y()) - }) + expect(text.first().y()).toBe(text.y()) }) - it('returns the value of x without an argument on a tspan', () => { + it('returns the value of y without an argument on a tspan', () => { expect(tspan.y(10).y()).toBe(10) }) - it('sets the x value of the bbox with the first argument on a tspan', () => { + it('sets the y value of the bbox with the first argument on a tspan', () => { tspan.y(123) expect(tspan.bbox().y).toBe(123) }) diff --git a/src/modules/core/regex.js b/src/modules/core/regex.js index 2b7b89e..b8adb83 100644 --- a/src/modules/core/regex.js +++ b/src/modules/core/regex.js @@ -8,7 +8,7 @@ export const hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i export const rgb = /rgb\((\d+),(\d+),(\d+)\)/ // Parse reference id -export const reference = /(#[a-z0-9\-_]+)/i +export const reference = /(#[a-z_][a-z0-9\-_]*)/i // splits a transformation chain export const transforms = /\)\s*,?\s*/ @@ -22,18 +22,12 @@ export const isHex = /^#[a-f0-9]{3,6}$/i // Test rgb value export const isRgb = /^rgb\(/ -// Test css declaration -export const isCss = /[^:]+:[^;]+;?/ - // Test for blank string export const isBlank = /^(\s+)?$/ // Test for numeric string export const isNumber = /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i -// Test for percent value -export const isPercent = /^-?[\d.]+%$/ - // Test for image url export const isImage = /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i @@ -42,7 +36,7 @@ export const delimiter = /[\s,]+/ // The following regex are used to parse the d attribute of a path -// Matches all hyphens which are not after an exponent +// Matches all hyphens which are preceeded by something but not an exponent export const hyphen = /([^e])-/gi // Replaces and tests for all path letters diff --git a/svg.js.d.ts b/svg.js.d.ts index 8dd99e2..e397e05 100644 --- a/svg.js.d.ts +++ b/svg.js.d.ts @@ -95,12 +95,10 @@ declare module "@svgdotjs/svg.js" { hex: RegExp; hyphen: RegExp; isBlank: RegExp; - isCss: RegExp; isHex: RegExp; isImage: RegExp; isNumber: RegExp; isPathLetter: RegExp; - isPercent: RegExp; isRgb: RegExp; numberAndUnit: RegExp; numbersWithDots: RegExp; -- 2.39.5