From 4bedc49b4dc3575c068432b5d90292ad4ab57494 Mon Sep 17 00:00:00 2001 From: "Ashley Engelund (weedySeaDragon @ github)" Date: Fri, 23 Sep 2022 11:34:52 -0700 Subject: [PATCH 01/10] define ENTITY_NAME that allows some non-alphanumeric chars; spec re-arrange --- src/diagrams/er/parser/erDiagram.jison | 6 +- src/diagrams/er/parser/erDiagram.spec.js | 156 ++++++++++++++++++----- 2 files changed, 129 insertions(+), 33 deletions(-) diff --git a/src/diagrams/er/parser/erDiagram.jison b/src/diagrams/er/parser/erDiagram.jison index ceae4f18cf..067851e3cc 100644 --- a/src/diagrams/er/parser/erDiagram.jison +++ b/src/diagrams/er/parser/erDiagram.jison @@ -24,6 +24,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili [\n]+ return 'NEWLINE'; \s+ /* skip whitespace */ [\s]+ return 'SPACE'; +\"[A-Za-z0-9\!\@\#\$\^\&\*\(\)\-_\=\+\[\]\{\};:\.\?]+\" return 'ENTITY_NAME'; \"[^"]*\" return 'WORD'; "erDiagram" return 'ER_DIAGRAM'; "{" { this.begin("block"); return 'BLOCK_START'; } @@ -102,8 +103,8 @@ statement ; entityName - : 'ALPHANUM' { $$ = $1; /*console.log('Entity: ' + $1);*/ } - | 'ALPHANUM' '.' entityName { $$ = $1 + $2 + $3; } + : 'ALPHANUM' { $$ = $1; } + | 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); } ; attributes @@ -156,6 +157,7 @@ relType role : 'WORD' { $$ = $1.replace(/"/g, ''); } + | 'ENTITY_NAME' { $$ = $1.replace(/"/g, ''); } | 'ALPHANUM' { $$ = $1; } ; diff --git a/src/diagrams/er/parser/erDiagram.spec.js b/src/diagrams/er/parser/erDiagram.spec.js index 409176f782..27d9350b73 100644 --- a/src/diagrams/er/parser/erDiagram.spec.js +++ b/src/diagrams/er/parser/erDiagram.spec.js @@ -1,6 +1,6 @@ import { setConfig } from '../../../config'; import erDb from '../erDb'; -import erDiagram from './erDiagram'; +import erDiagram from './erDiagram'; // jison file setConfig({ securityLevel: 'strict', @@ -21,14 +21,112 @@ describe('when parsing ER diagram it...', function () { expect(erDb.getRelationships().length).toBe(0); }); - it('should allow hyphens and underscores in entity names', function () { - const line1 = 'DUCK-BILLED-PLATYPUS'; - const line2 = 'CHARACTER_SET'; - erDiagram.parser.parse(`erDiagram\n${line1}\n${line2}`); - - const entities = erDb.getEntities(); - expect(entities.hasOwnProperty('DUCK-BILLED-PLATYPUS')).toBe(true); - expect(entities.hasOwnProperty('CHARACTER_SET')).toBe(true); + describe('entity name', () => { + it('cannot be empty quotes ""', function () { + const name = '""'; + expect(() => { + erDiagram.parser.parse(`erDiagram\n ${name}\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(false); + }).toThrow(); + }); + describe('has non A-Za-z0-9_- chars', function () { + const allowed = [ + '!', + '@', + '#', + '$', + '^', + '&', + '*', + '(', + ')', + '-', + '_', + '=', + '+', + '[', + ']', + '{', + '}', + ';', + ':', + '.', + '?', + ]; + + allowed.forEach((allowedChar) => { + const singleOccurrence = `Blo${allowedChar}rf`; + const repeatedOccurrence = `Blo${allowedChar}${allowedChar}rf`; + const cannontStartWith = `${allowedChar}Blorf`; + const endsWith = `Blorf${allowedChar}`; + + it(`${singleOccurrence} fails if not surrounded by quotes`, function () { + const name = singleOccurrence; + expect(() => { + erDiagram.parser.parse(`erDiagram\n ${name}\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(false); + }).toThrow(); + }); + + it(`"${singleOccurrence}" single occurrence`, function () { + const name = singleOccurrence; + erDiagram.parser.parse(`erDiagram\n "${name}"\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(true); + }); + + it(`"${repeatedOccurrence}" repeated occurrence`, function () { + const name = repeatedOccurrence; + erDiagram.parser.parse(`erDiagram\n "${name}"\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(true); + }); + + it(`"${singleOccurrence}" ends with`, function () { + const name = endsWith; + erDiagram.parser.parse(`erDiagram\n "${name}"\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(true); + }); + + it(`"${cannontStartWith}" cannot start with the character`, function () { + const name = repeatedOccurrence; + expect(() => { + erDiagram.parser.parse(`erDiagram\n "${name}"\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(false); + }).toThrow(); + }); + }); + + const allCombined = allowed.join(''); + + it(`a${allCombined} (all non-alphanumerics) in one, starting with 'a'`, function () { + const name = 'a' + allCombined; + erDiagram.parser.parse(`erDiagram\n "${name}"\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(true); + }); + }); + + it('cannot contain % because it interfers with parsing comments', function () { + expect(() => { + erDiagram.parser.parse(`erDiagram\n "Blo%rf"\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(false); + }).toThrow(); + }); + + it('can contain - _ ', function () { + const hyphens = 'DUCK-BILLED-PLATYPUS'; + const underscores = 'CHARACTER_SET'; + erDiagram.parser.parse(`erDiagram\n${hyphens}\n${underscores}\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty('DUCK-BILLED-PLATYPUS')).toBe(true); + expect(entities.hasOwnProperty('CHARACTER_SET')).toBe(true); + }); }); it('should allow an entity with a single attribute to be defined', function () { @@ -447,27 +545,23 @@ describe('when parsing ER diagram it...', function () { }).toThrowError(); }); - it('should allow an empty quoted label', function () { - erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : ""'); - const rels = erDb.getRelationships(); - expect(rels[0].roleA).toBe(''); - }); - - it('should allow an non-empty quoted label', function () { - erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : "places"'); - const rels = erDb.getRelationships(); - expect(rels[0].roleA).toBe('places'); - }); - - it('should allow an non-empty unquoted label', function () { - erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : places'); - const rels = erDb.getRelationships(); - expect(rels[0].roleA).toBe('places'); - }); - - it('should allow an entity name with a dot', function () { - erDiagram.parser.parse('erDiagram\nCUSTOMER.PROP ||--|{ ORDER : places'); - const rels = erDb.getRelationships(); - expect(rels[0].entityA).toBe('CUSTOMER.PROP'); + describe('relationship labels', function () { + it('should allow an empty quoted label', function () { + erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : ""'); + const rels = erDb.getRelationships(); + expect(rels[0].roleA).toBe(''); + }); + + it('should allow an non-empty quoted label', function () { + erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : "places"'); + const rels = erDb.getRelationships(); + expect(rels[0].roleA).toBe('places'); + }); + + it('should allow an non-empty unquoted label', function () { + erDiagram.parser.parse('erDiagram\nCUSTOMER ||--|{ ORDER : places'); + const rels = erDb.getRelationships(); + expect(rels[0].roleA).toBe('places'); + }); }); }); From 9ec935f10965701eb312889796644dcb91aa9fab Mon Sep 17 00:00:00 2001 From: "Ashley Engelund (weedySeaDragon @ github)" Date: Fri, 23 Sep 2022 11:35:31 -0700 Subject: [PATCH 02/10] add ts-ignore for jison in vite.config.cts --- vite.config.cts | 1 + 1 file changed, 1 insertion(+) diff --git a/vite.config.cts b/vite.config.cts index 9698854bb8..5a9b65a5fd 100644 --- a/vite.config.cts +++ b/vite.config.cts @@ -1,3 +1,4 @@ +// @ts-ignore no @types for jison import { Generator } from 'jison'; import { defineConfig } from 'vitest/config'; From 3c1bad17925af484949e6c0eb91981ba36cfb2f5 Mon Sep 17 00:00:00 2001 From: "Ashley Engelund (weedySeaDragon @ github)" Date: Sat, 24 Sep 2022 15:38:06 -0700 Subject: [PATCH 03/10] er jison: allow more chars in Entity name; clean up spec --- src/diagrams/er/parser/erDiagram.jison | 2 +- src/diagrams/er/parser/erDiagram.spec.js | 64 +++++++++++++----------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/diagrams/er/parser/erDiagram.jison b/src/diagrams/er/parser/erDiagram.jison index 067851e3cc..6294599b56 100644 --- a/src/diagrams/er/parser/erDiagram.jison +++ b/src/diagrams/er/parser/erDiagram.jison @@ -24,7 +24,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili [\n]+ return 'NEWLINE'; \s+ /* skip whitespace */ [\s]+ return 'SPACE'; -\"[A-Za-z0-9\!\@\#\$\^\&\*\(\)\-_\=\+\[\]\{\};:\.\?]+\" return 'ENTITY_NAME'; +\"[^"%\r\n\v\b\\]+\" return 'ENTITY_NAME'; \"[^"]*\" return 'WORD'; "erDiagram" return 'ER_DIAGRAM'; "{" { this.begin("block"); return 'BLOCK_START'; } diff --git a/src/diagrams/er/parser/erDiagram.spec.js b/src/diagrams/er/parser/erDiagram.spec.js index 27d9350b73..1d891ffeab 100644 --- a/src/diagrams/er/parser/erDiagram.spec.js +++ b/src/diagrams/er/parser/erDiagram.spec.js @@ -31,29 +31,10 @@ describe('when parsing ER diagram it...', function () { }).toThrow(); }); describe('has non A-Za-z0-9_- chars', function () { - const allowed = [ - '!', - '@', - '#', - '$', - '^', - '&', - '*', - '(', - ')', - '-', - '_', - '=', - '+', - '[', - ']', - '{', - '}', - ';', - ':', - '.', - '?', - ]; + // these were entered using the Mac keyboard utility. + const chars = + "~ ` ! @ # $ ^ & * ( ) - _ = + [ ] { } | / ; : ' . ? ¡ ⁄ ™ € £ ‹ ¢ › ∞ fi § ‡ • ° ª · º ‚ ≠ ± œ Œ ∑ „ ® † ˇ ¥ Á ¨ ˆ ˆ Ø π ∏ “ « » å Å ß Í ∂ Î ƒ Ï © ˙ Ó ∆ Ô ˚  ¬ Ò … Ú æ Æ Ω ¸ ≈ π ˛ ç Ç √ ◊ ∫ ı ˜ µ  ≤ ¯ ≥ ˘ ÷ ¿"; + const allowed = chars.split(' '); allowed.forEach((allowedChar) => { const singleOccurrence = `Blo${allowedChar}rf`; @@ -118,14 +99,39 @@ describe('when parsing ER diagram it...', function () { expect(entities.hasOwnProperty(name)).toBe(false); }).toThrow(); }); + it('cannot contain \\ because it could start and escape code', function () { + expect(() => { + erDiagram.parser.parse(`erDiagram\n "Blo\\rf"\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(name)).toBe(false); + }).toThrow(); + }); + + it('cannot newline, backspace, or vertical characters', function () { + const disallowed = ['\n', '\r', '\b', '\v']; + disallowed.forEach((badChar) => { + const badName = `Blo${badChar}rf`; + expect(() => { + erDiagram.parser.parse(`erDiagram\n "${badName}"\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(badName)).toBe(false); + }).toThrow(); + }); + }); + + // skip this: jison cannot handle non-english letters + it.skip('[skipped test] can contain àáâäæãåā', function () { + const beyondEnglishName = 'DUCK-àáâäæãåā'; + erDiagram.parser.parse(`erDiagram\n${beyondEnglishName}\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(beyondEnglishName)).toBe(true); + }); - it('can contain - _ ', function () { - const hyphens = 'DUCK-BILLED-PLATYPUS'; - const underscores = 'CHARACTER_SET'; - erDiagram.parser.parse(`erDiagram\n${hyphens}\n${underscores}\n`); + it('can contain - _ without needing ""', function () { + const hyphensUnderscore = 'DUCK-BILLED_PLATYPUS'; + erDiagram.parser.parse(`erDiagram\n${hyphensUnderscore}\n`); const entities = erDb.getEntities(); - expect(entities.hasOwnProperty('DUCK-BILLED-PLATYPUS')).toBe(true); - expect(entities.hasOwnProperty('CHARACTER_SET')).toBe(true); + expect(entities.hasOwnProperty(hyphensUnderscore)).toBe(true); }); }); From d3288793290e90ebbb043dd488d762dcffa9a8a5 Mon Sep 17 00:00:00 2001 From: "Ashley Engelund (weedySeaDragon @ github)" Date: Sat, 24 Sep 2022 15:40:02 -0700 Subject: [PATCH 04/10] add uuid; graph node ids can no longer be based on entity names; make unique id --- package.json | 4 +- yarn.lock | 155 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 150 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index d03d5fca84..acf466a10b 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ }, "dependencies": { "@braintree/sanitize-url": "^6.0.0", + "@types/uuid": "^8.3.4", "d3": "^7.0.0", "dagre": "^0.8.5", "dagre-d3": "^0.6.4", @@ -76,7 +77,8 @@ "lodash": "^4.17.21", "moment-mini": "^2.24.0", "non-layered-tidy-tree-layout": "^2.0.2", - "stylis": "^4.1.2" + "stylis": "^4.1.2", + "uuid": "^9.0.0" }, "devDependencies": { "@applitools/eyes-cypress": "^3.25.7", diff --git a/yarn.lock b/yarn.lock index afcda016f3..7fa7eaa940 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1770,11 +1770,21 @@ dependencies: esbuild-wasm "0.15.8" +"@esbuild/android-arm@0.15.9": + version "0.15.9" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.9.tgz#7e1221604ab88ed5021ead74fa8cca4405e1e431" + integrity sha512-VZPy/ETF3fBG5PiinIkA0W/tlsvlEgJccyN2DzWZEl0DlVKRbu91PvY2D6Lxgluj4w9QtYHjOWjAT44C+oQ+EQ== + "@esbuild/linux-loong64@0.15.8": version "0.15.8" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.8.tgz#d64575fc46bf4eb689352aa9f8a139271b6e1647" integrity sha512-pE5RQsOTSERCtfZdfCT25wzo7dfhOSlhAXcsZmuvRYhendOv7djcdvtINdnDp2DAjP17WXlBB4nBO6sHLczmsg== +"@esbuild/linux-loong64@0.15.9": + version "0.15.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.9.tgz#b658a97babf1f40783354af7039b84c3fdfc3fc3" + integrity sha512-O+NfmkfRrb3uSsTa4jE3WApidSe3N5++fyOVGP1SmMZi4A3BZELkhUUvj5hwmMuNdlpzAZ8iAPz2vmcR7DCFQA== + "@eslint/eslintrc@^1.3.2": version "1.3.2" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356" @@ -2412,6 +2422,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== +"@types/uuid@^8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== + "@types/yauzl@^2.9.1": version "2.9.2" resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.2.tgz#c48e5d56aff1444409e39fa164b0b4d4552a7b7a" @@ -4811,95 +4826,171 @@ esbuild-android-64@0.15.8: dependencies: esbuild-wasm "0.15.8" +esbuild-android-64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.9.tgz#4a7eb320ca8d3a305f14792061fd9614ccebb7c0" + integrity sha512-HQCX7FJn9T4kxZQkhPjNZC7tBWZqJvhlLHPU2SFzrQB/7nDXjmTIFpFTjt7Bd1uFpeXmuwf5h5fZm+x/hLnhbw== + esbuild-android-arm64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.8.tgz#cd62afe08652ac146014386d3adbe7a9d33db1b0" integrity sha512-ReAMDAHuo0H1h9LxRabI6gwYPn8k6WiUeyxuMvx17yTrJO+SCnIfNc/TSPFvDwtK9MiyiKG/2dBYHouT/M0BXQ== +esbuild-android-arm64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.9.tgz#c948e5686df20857ad361ec67e070d40d7cab985" + integrity sha512-E6zbLfqbFVCNEKircSHnPiSTsm3fCRxeIMPfrkS33tFjIAoXtwegQfVZqMGR0FlsvVxp2NEDOUz+WW48COCjSg== + esbuild-darwin-64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.8.tgz#eb668dc973165f85aefecdca8aa60231acb2f705" integrity sha512-KaKcGfJ+yto7Fo5gAj3xwxHMd1fBIKatpCHK8znTJLVv+9+NN2/tIPBqA4w5rBwjX0UqXDeIE2v1xJP+nGEXgA== +esbuild-darwin-64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.9.tgz#25f564fa4b39c1cec84dc46bce5634fdbce1d5e4" + integrity sha512-gI7dClcDN/HHVacZhTmGjl0/TWZcGuKJ0I7/xDGJwRQQn7aafZGtvagOFNmuOq+OBFPhlPv1T6JElOXb0unkSQ== + esbuild-darwin-arm64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.8.tgz#91c110daa46074fdfc18f411247ca0d1228aacc3" integrity sha512-8tjEaBgAKnXCkP7bhEJmEqdG9HEV6oLkF36BrMzpfW2rgaw0c48Zrxe+9RlfeGvs6gDF4w+agXyTjikzsS3izw== +esbuild-darwin-arm64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.9.tgz#60faea3ed95d15239536aa88d06bb82b29278a86" + integrity sha512-VZIMlcRN29yg/sv7DsDwN+OeufCcoTNaTl3Vnav7dL/nvsApD7uvhVRbgyMzv0zU/PP0xRhhIpTyc7lxEzHGSw== + esbuild-freebsd-64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.8.tgz#22270945a9bf9107c340eb73922e122bbe84f8ad" integrity sha512-jaxcsGHYzn2L0/lffON2WfH4Nc+d/EwozVTP5K2v016zxMb5UQMhLoJzvLgBqHT1SG0B/mO+a+THnJCMVg15zw== +esbuild-freebsd-64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.9.tgz#0339ef1c90a919175e7816788224517896657a0e" + integrity sha512-uM4z5bTvuAXqPxrI204txhlsPIolQPWRMLenvGuCPZTnnGlCMF2QLs0Plcm26gcskhxewYo9LkkmYSS5Czrb5A== + esbuild-freebsd-arm64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.8.tgz#0efe2741fbcaa2cfd31b9f94bd3ca7385b68c469" integrity sha512-2xp2UlljMvX8HExtcg7VHaeQk8OBU0CSl1j18B5CcZmSDkLF9p3utuMXIopG3a08fr9Hv+Dz6+seSXUow/G51w== -esbuild-jest@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/esbuild-jest/-/esbuild-jest-0.5.0.tgz#7a9964bfdecafca3b675a8aeb08193bcdba8b9d7" - integrity sha512-AMZZCdEpXfNVOIDvURlqYyHwC8qC1/BFjgsrOiSL1eyiIArVtHL8YAC83Shhn16cYYoAWEW17yZn0W/RJKJKHQ== - dependencies: - "@babel/core" "^7.12.17" - "@babel/plugin-transform-modules-commonjs" "^7.12.13" - babel-jest "^26.6.3" +esbuild-freebsd-arm64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.9.tgz#32abfc0be3ae3dd38e5a86a9beadbbcf592f1b57" + integrity sha512-HHDjT3O5gWzicGdgJ5yokZVN9K9KG05SnERwl9nBYZaCjcCgj/sX8Ps1jvoFSfNCO04JSsHSOWo4qvxFuj8FoA== esbuild-linux-32@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.8.tgz#6fc98659105da5c0d1fedfce3b7b9fa24ebee0d4" integrity sha512-9u1E54BRz1FQMl86iaHK146+4ID2KYNxL3trLZT4QLLx3M7Q9n4lGG3lrzqUatGR2cKy8c33b0iaCzsItZWkFg== +esbuild-linux-32@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.9.tgz#93581348a4da7ed2b29bc5539f2605ad7fcee77b" + integrity sha512-AQIdE8FugGt1DkcekKi5ycI46QZpGJ/wqcMr7w6YUmOmp2ohQ8eO4sKUsOxNOvYL7hGEVwkndSyszR6HpVHLFg== + esbuild-linux-64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.8.tgz#8e738c926d145cdd4e9bcb2febc96d89dc27dc09" integrity sha512-4HxrsN9eUzJXdVGMTYA5Xler82FuZUu21bXKN42zcLHHNKCAMPUzD62I+GwDhsdgUBAUj0tRXDdsQHgaP6v0HA== +esbuild-linux-64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.9.tgz#0d171e7946c95d0d3ed4826026af2c5632d7dcc4" + integrity sha512-4RXjae7g6Qs7StZyiYyXTZXBlfODhb1aBVAjd+ANuPmMhWthQilWo7rFHwJwL7DQu1Fjej2sODAVwLbcIVsAYQ== + esbuild-linux-arm64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.8.tgz#a12675e5a56e8ef08dea49da8eed51a87b0e60d6" integrity sha512-1OCm7Aq0tEJT70PbxmHSGYDLYP8DKH8r4Nk7/XbVzWaduo9beCjGBB+tGZIHK6DdTQ3h00/4Tb/70YMH/bOtKg== +esbuild-linux-arm64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.9.tgz#9838795a3720cbe736d3bc20621bd366eac22f24" + integrity sha512-a+bTtxJmYmk9d+s2W4/R1SYKDDAldOKmWjWP0BnrWtDbvUBNOm++du0ysPju4mZVoEFgS1yLNW+VXnG/4FNwdQ== + esbuild-linux-arm@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.8.tgz#6424da1e8a3ece78681ebee4a70477b40c36ab35" integrity sha512-7DVBU9SFjX4+vBwt8tHsUCbE6Vvl6y6FQWHAgyw1lybC5gULqn/WnjHYHN2/LJaZRsDBvxWT4msEgwLGq1Wd3Q== +esbuild-linux-arm@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.9.tgz#dce96cd817bc7376f6af3967649c4ab1f2f79506" + integrity sha512-3Zf2GVGUOI7XwChH3qrnTOSqfV1V4CAc/7zLVm4lO6JT6wbJrTgEYCCiNSzziSju+J9Jhf9YGWk/26quWPC6yQ== + esbuild-linux-mips64le@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.8.tgz#5b39a16272cb4eaaad1f24938c057b19fb5a0ee5" integrity sha512-yeFoNPVFPEzZvFYBfUQNG2TjGRaCyV1E27OcOg4LOtnGrxb2wA+mkW3luckyv1CEyd00mpAg7UdHx8nlx3ghgA== +esbuild-linux-mips64le@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.9.tgz#0335a0739e61aa97cb9b4a018e3facfcca9cdcfd" + integrity sha512-Zn9HSylDp89y+TRREMDoGrc3Z4Hs5u56ozZLQCiZAUx2+HdbbXbWdjmw3FdTJ/i7t5Cew6/Q+6kfO3KCcFGlyw== + esbuild-linux-ppc64le@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.8.tgz#98ea8cfae8227180b45b2d952b2cbb072900944f" integrity sha512-CEyMMUUNabXibw8OSNmBXhOIGhnjNVl5Lpseiuf00iKN0V47oqDrbo4dsHz1wH62m49AR8iG8wpDlTqfYgKbtg== +esbuild-linux-ppc64le@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.9.tgz#18482afb95b8a705e2da0a59d7131bff221281f9" + integrity sha512-OEiOxNAMH9ENFYqRsWUj3CWyN3V8P3ZXyfNAtX5rlCEC/ERXrCEFCJji/1F6POzsXAzxvUJrTSTCy7G6BhA6Fw== + esbuild-linux-riscv64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.8.tgz#6334607025eb449d8dd402d7810721dc15a6210f" integrity sha512-OCGSOaspMUjexSCU8ZiA0UnV/NiRU+s2vIfEcAQWQ6u32R+2luyfh/4ZaY6jFbylJE07Esc/yRvb9Q5fXuClXA== +esbuild-linux-riscv64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.9.tgz#03b6f9708272c117006b9ce1c9ae8aab91b5a5b6" + integrity sha512-ukm4KsC3QRausEFjzTsOZ/qqazw0YvJsKmfoZZm9QW27OHjk2XKSQGGvx8gIEswft/Sadp03/VZvAaqv5AIwNA== + esbuild-linux-s390x@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.8.tgz#874f1a3507c32cce1d2ce0d2f28ac1496c094eab" integrity sha512-RHdpdfxRTSrZXZJlFSLazFU4YwXLB5Rgf6Zr5rffqSsO4y9JybgtKO38bFwxZNlDXliYISXN/YROKrG9s7mZQA== +esbuild-linux-s390x@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.9.tgz#65fb645623d575780f155f0ee52935e62f9cca4f" + integrity sha512-uDOQEH55wQ6ahcIKzQr3VyjGc6Po/xblLGLoUk3fVL1qjlZAibtQr6XRfy5wPJLu/M2o0vQKLq4lyJ2r1tWKcw== + esbuild-netbsd-64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.8.tgz#2e03d87ed811400d5d1fa8c7629b9fd97a574231" integrity sha512-VolFFRatBH09T5QMWhiohAWCOien1R1Uz9K0BRVVTBgBaVBt7eArsXTKxVhUgRf2vwu2c2SXkuP0r7HLG0eozw== +esbuild-netbsd-64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.9.tgz#7894297bb9e11f3d2f6f31efecd1be4e181f0d54" + integrity sha512-yWgxaYTQz+TqX80wXRq6xAtb7GSBAp6gqLKfOdANg9qEmAI1Bxn04IrQr0Mzm4AhxvGKoHzjHjMgXbCCSSDxcw== + esbuild-openbsd-64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.8.tgz#8fdbc6399563ac61ff546449e2226a2b1477216c" integrity sha512-HTAPlg+n4kUeE/isQxlCfsOz0xJGNoT5LJ9oYZWFKABfVf4Ycu7Zlf5ITgOnrdheTkz8JeL/gISIOCFAoOXrSA== +esbuild-openbsd-64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.9.tgz#0f9d4c6b6772ae50d491d68ad4cc028300dda7c0" + integrity sha512-JmS18acQl4iSAjrEha1MfEmUMN4FcnnrtTaJ7Qg0tDCOcgpPPQRLGsZqhes0vmx8VA6IqRyScqXvaL7+Q0Uf3A== + esbuild-sunos-64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.8.tgz#db657b5c09c0c0161d67ddafca1b710a2e7ce96b" integrity sha512-qMP/jR/FzcIOwKj+W+Lb+8Cfr8GZHbHUJxAPi7DUhNZMQ/6y7sOgRzlOSpRrbbUntrRZh0MqOyDhJ3Gpo6L1QA== +esbuild-sunos-64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.9.tgz#c32b7ce574b08f814de810ce7c1e34b843768126" + integrity sha512-UKynGSWpzkPmXW3D2UMOD9BZPIuRaSqphxSCwScfEE05Be3KAmvjsBhht1fLzKpiFVJb0BYMd4jEbWMyJ/z1hQ== + esbuild-wasm@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.15.8.tgz#60fb8c5dc1a5538421857a2fa5fbb9eab908dcbb" @@ -4910,16 +5001,59 @@ esbuild-windows-32@0.15.8: resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.8.tgz#bbb9fe20a8b6bba4428642cacf45a0fb7b2f3783" integrity sha512-RKR1QHh4iWzjUhkP8Yqi75PPz/KS+b8zw3wUrzw6oAkj+iU5Qtyj61ZDaSG3Qf2vc6hTIUiPqVTqBH0NpXFNwg== +esbuild-windows-32@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.9.tgz#37a8f7cfccdb2177cd46613a1a1e1fcb419d36df" + integrity sha512-aqXvu4/W9XyTVqO/hw3rNxKE1TcZiEYHPsXM9LwYmKSX9/hjvfIJzXwQBlPcJ/QOxedfoMVH0YnhhQ9Ffb0RGA== + esbuild-windows-64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.8.tgz#cedee65505209c8d371d7228b60785c08f43e04d" integrity sha512-ag9ptYrsizgsR+PQE8QKeMqnosLvAMonQREpLw4evA4FFgOBMLEat/dY/9txbpozTw9eEOYyD3a4cE9yTu20FA== +esbuild-windows-64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.9.tgz#5fe1e76fc13dd7f520febecaea110b6f1649c7b2" + integrity sha512-zm7h91WUmlS4idMtjvCrEeNhlH7+TNOmqw5dJPJZrgFaxoFyqYG6CKDpdFCQXdyKpD5yvzaQBOMVTCBVKGZDEg== + esbuild-windows-arm64@0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.8.tgz#1d75235290bf23a111e6c0b03febd324af115cb1" integrity sha512-dbpAb0VyPaUs9mgw65KRfQ9rqiWCHpNzrJusoPu+LpEoswosjt/tFxN7cd2l68AT4qWdBkzAjDLRon7uqMeWcg== +esbuild-windows-arm64@0.15.9: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.9.tgz#98504428f7ba7d2cfc11940be68ee1139173fdce" + integrity sha512-yQEVIv27oauAtvtuhJVfSNMztJJX47ismRS6Sv2QMVV9RM+6xjbMWuuwM2nxr5A2/gj/mu2z9YlQxiwoFRCfZA== + +esbuild@^0.15.6: + version "0.15.9" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.9.tgz#33fb18b67b85004b6f7616bec955ca4b3e58935d" + integrity sha512-OnYr1rkMVxtmMHIAKZLMcEUlJmqcbxBz9QoBU8G9v455na0fuzlT/GLu6l+SRghrk0Mm2fSSciMmzV43Q8e0Gg== + optionalDependencies: + "@esbuild/android-arm" "0.15.9" + "@esbuild/linux-loong64" "0.15.9" + esbuild-android-64 "0.15.9" + esbuild-android-arm64 "0.15.9" + esbuild-darwin-64 "0.15.9" + esbuild-darwin-arm64 "0.15.9" + esbuild-freebsd-64 "0.15.9" + esbuild-freebsd-arm64 "0.15.9" + esbuild-linux-32 "0.15.9" + esbuild-linux-64 "0.15.9" + esbuild-linux-arm "0.15.9" + esbuild-linux-arm64 "0.15.9" + esbuild-linux-mips64le "0.15.9" + esbuild-linux-ppc64le "0.15.9" + esbuild-linux-riscv64 "0.15.9" + esbuild-linux-s390x "0.15.9" + esbuild-netbsd-64 "0.15.9" + esbuild-openbsd-64 "0.15.9" + esbuild-sunos-64 "0.15.9" + esbuild-windows-32 "0.15.9" + esbuild-windows-64 "0.15.9" + esbuild-windows-arm64 "0.15.9" + esbuild@^0.15.8: version "0.15.8" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.8.tgz#75daa25d03f6dd9cc9355030eba2b93555b42cd4" @@ -10539,6 +10673,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + uvu@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.3.tgz#3d83c5bc1230f153451877bfc7f4aea2392219ae" From 481b5cde0fc30a555cc9ec7bb79fa38a85eb3448 Mon Sep 17 00:00:00 2001 From: "Ashley Engelund (weedySeaDragon @ github)" Date: Sat, 24 Sep 2022 16:02:55 -0700 Subject: [PATCH 05/10] (minor) fix ==; remove unused imports; fix typos; add comments --- src/diagrams/er/erRenderer.js | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/diagrams/er/erRenderer.js b/src/diagrams/er/erRenderer.js index d1258a5474..f04fc5fe22 100644 --- a/src/diagrams/er/erRenderer.js +++ b/src/diagrams/er/erRenderer.js @@ -1,7 +1,5 @@ import graphlib from 'graphlib'; import { line, curveBasis, select } from 'd3'; -// import erDb from './erDb'; -// import erParser from './parser/erDiagram'; import dagre from 'dagre'; import { getConfig } from '../../config'; import { log } from '../../logger'; @@ -31,8 +29,10 @@ export const setConf = function (cnf) { * * @param groupNode The svg group node for the entity * @param entityTextNode The svg node for the entity label text - * @param attributes An array of attributes defined for the entity (each attribute has a type and a name) - * @returns {object} The bounding box of the entity, after attributes have been added. The bounding box has a .width and .height + * @param attributes An array of attributes defined for the entity (each attribute has a type and a + * name) + * @returns {object} The bounding box of the entity, after attributes have been added. The bounding + * box has a .width and .height */ const drawAttributes = (groupNode, entityTextNode, attributes) => { const heightPadding = conf.entityPadding / 3; // Padding internal to attribute boxes @@ -288,7 +288,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => { heightOffset += attributeNode.height + heightPadding * 2; // Flip the attribute style for row banding - attribStyle = attribStyle == 'attributeBoxOdd' ? 'attributeBoxEven' : 'attributeBoxOdd'; + attribStyle = attribStyle === 'attributeBoxOdd' ? 'attributeBoxEven' : 'attributeBoxOdd'; }); } else { // Ensure the entity box is a decent size without any attributes @@ -382,9 +382,16 @@ const adjustEntities = function (svgNode, graph) { ); } }); - return; }; +/** + * Construct a name for an edge based on the names of the 2 entities and the role (relationship) + * between them. Remove any spaces from it + * + * @param rel - A (parsed) relationship (e.g. one of the objects in the list returned by + * erDb.getRelationships) + * @returns {string} + */ const getEdgeName = function (rel) { return (rel.entityA + rel.roleA + rel.entityB).replace(/\s/g, ''); }; @@ -393,7 +400,7 @@ const getEdgeName = function (rel) { * Add each relationship to the graph * * @param relationships The relationships to be added - * @param g The graph + * @param {Graph} g The graph * @returns {Array} The array of relationships */ const addRelationships = function (relationships, g) { @@ -535,8 +542,6 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) { .attr('height', labelBBox.height) .attr('fill', 'white') .attr('fill-opacity', '85%'); - - return; }; /** @@ -552,7 +557,7 @@ export const draw = function (text, id, _version, diagObj) { log.info('Drawing ER diagram'); // diag.db.clear(); const securityLevel = getConfig().securityLevel; - // Handle root and Document for when rendering in sanbox mode + // Handle root and Document for when rendering in sandbox mode let sandboxElement; if (securityLevel === 'sandbox') { sandboxElement = select('#i' + id); @@ -581,7 +586,7 @@ export const draw = function (text, id, _version, diagObj) { // 1. Create all the entities in the svg node at 0,0, but with the correct dimensions (allowing for text content) // 2. Make sure they are all added to the graph // 3. Add all the edges (relationships) to the graph as well - // 4. Let dagre do its magic to layout the graph. This assigns: + // 4. Let dagre do its magic to lay out the graph. This assigns: // - the centre co-ordinates for each node, bearing in mind the dimensions and edge relationships // - the path co-ordinates for each edge // But it has no impact on the svg child nodes - the diagram remains with every entity rooted at 0,0 From 91091c614f78ce3a92f2cadc1fe30ec50a1b0857 Mon Sep 17 00:00:00 2001 From: "Ashley Engelund (weedySeaDragon @ github)" Date: Sat, 24 Sep 2022 16:05:20 -0700 Subject: [PATCH 06/10] store and reference entity by unique id, not name (elements, graph, etc.) --- src/diagrams/er/erRenderer.js | 71 +++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/src/diagrams/er/erRenderer.js b/src/diagrams/er/erRenderer.js index f04fc5fe22..a6277f27da 100644 --- a/src/diagrams/er/erRenderer.js +++ b/src/diagrams/er/erRenderer.js @@ -7,9 +7,17 @@ import erMarkers from './erMarkers'; import { configureSvgSize } from '../../setupGraphViewbox'; import addSVGAccessibilityFields from '../../accessibility'; import { parseGenericTypes } from '../common/common'; +import { v4 as uuid4 } from 'uuid'; +/** Regex used to remove chars from the entity name so the result can be used in an id */ +const BAD_ID_CHARS_REGEXP = /[^A-Za-z0-9]([\W])*/g; + +// Configuration let conf = {}; +// Map so we can look up the id of an entity based on the name +let entityNameIds = new Map(); + /** * Allows the top-level API module to inject config specific to this renderer, storing it in the * local conf object. Note that generic config still needs to be retrieved using getConfig() @@ -313,15 +321,18 @@ const drawEntities = function (svgNode, entities, graph) { const keys = Object.keys(entities); let firstOne; - keys.forEach(function (id) { + keys.forEach(function (entityName) { + const entityId = generateId(entityName, 'entity'); + entityNameIds.set(entityName, entityId); + // Create a group for each entity - const groupNode = svgNode.append('g').attr('id', id); + const groupNode = svgNode.append('g').attr('id', entityId); - firstOne = firstOne === undefined ? id : firstOne; + firstOne = firstOne === undefined ? entityId : firstOne; // Label the entity - this is done first so that we can get the bounding box // which then determines the size of the rectangle - const textId = 'entity-' + id; + const textId = 'text-' + entityId; const textNode = groupNode .append('text') .attr('class', 'er entityLabel') @@ -334,12 +345,12 @@ const drawEntities = function (svgNode, entities, graph) { 'style', 'font-family: ' + getConfig().fontFamily + '; font-size: ' + conf.fontSize + 'px' ) - .text(id); + .text(entityName); const { width: entityWidth, height: entityHeight } = drawAttributes( groupNode, textNode, - entities[id].attributes + entities[entityName].attributes ); // Draw the rectangle - insert it before the text so that the text is not obscured @@ -356,12 +367,12 @@ const drawEntities = function (svgNode, entities, graph) { const rectBBox = rectNode.node().getBBox(); - // Add the entity to the graph - graph.setNode(id, { + // Add the entity to the graph using the entityId + graph.setNode(entityId, { width: rectBBox.width, height: rectBBox.height, shape: 'rect', - id: id, + id: entityId, }); }); return firstOne; @@ -405,7 +416,12 @@ const getEdgeName = function (rel) { */ const addRelationships = function (relationships, g) { relationships.forEach(function (r) { - g.setEdge(r.entityA, r.entityB, { relationship: r }, getEdgeName(r)); + g.setEdge( + entityNameIds.get(r.entityA), + entityNameIds.get(r.entityB), + { relationship: r }, + getEdgeName(r) + ); }); return relationships; }; // addRelationships @@ -425,7 +441,11 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) { relCnt++; // Find the edge relating to this relationship - const edge = g.edge(rel.entityA, rel.entityB, getEdgeName(rel)); + const edge = g.edge( + entityNameIds.get(rel.entityA), + entityNameIds.get(rel.entityB), + getEdgeName(rel) + ); // Get a function that will generate the line path const lineFunction = line() @@ -652,6 +672,35 @@ export const draw = function (text, id, _version, diagObj) { addSVGAccessibilityFields(diagObj.db, svg, id); }; // draw +/** + * Return a unique id based on the given string. Start with the prefix, then a hyphen, then the + * simplified str, then a hyphen, then a unique uuid. (Hyphens are only included if needed.) + * Although the official XML standard for ids says that many more characters are valid in the id, + * this keeps things simple by accepting only A-Za-z0-9. + * + * @param {string} [str?=''] Given string to use as the basis for the id. Default is `''` + * @param {string} [prefix?=''] String to put at the start, followed by '-'. Default is `''` + * @param str + * @param prefix + * @returns {string} + * @see https://www.w3.org/TR/xml/#NT-Name + */ +export function generateId(str = '', prefix = '') { + const simplifiedStr = str.replace(BAD_ID_CHARS_REGEXP, ''); + return `${strWithHyphen(prefix)}${strWithHyphen(simplifiedStr)}${uuid4()}`; +} + +/** + * Append a hyphen to a string only if the string isn't empty + * + * @param {string} str + * @returns {string} + * @todo This could be moved into a string utility file/class. + */ +function strWithHyphen(str = '') { + return str.length > 0 ? `${str}-` : ''; +} + export default { setConf, draw, From eb1c6894f58eebbd2216b05a14a75af47d184d0c Mon Sep 17 00:00:00 2001 From: "Ashley Engelund (weedySeaDragon @ github)" Date: Sat, 24 Sep 2022 16:05:59 -0700 Subject: [PATCH 07/10] change demo ER diagram to include attributes, names with various chars --- demos/er.html | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/demos/er.html b/demos/er.html index 1e5d4062d1..d7b822dbd8 100644 --- a/demos/er.html +++ b/demos/er.html @@ -16,17 +16,35 @@
 erDiagram
-title This is a title
-accDescription Test a description
-CUSTOMER ||--o{ ORDER : places
-ORDER ||--|{ LINE-ITEM : contains
-CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
+  %% title This is a title
+  %% accDescription Test a description
+
+  "Person.CUSTOMER"||--o{ ORDER : places
+
+  ORDER ||--|{ LINE-ITEM : contains
+
+  "Person.CUSTOMER" }|..|{ "Address/StreetAddress::[DELIVERY-ADDRESS]" : uses
+
+  "Address/StreetAddress::[DELIVERY-ADDRESS]" {
+      int customerID FK
+      string line1 "this is the first address line comment"
+      string line2
+      string city
+      string region
+      string state
+      string postal_code
+      string country
+      }
+
+      "a_~`!@#$^&*()-_=+[]{}|/;:'.?¡⁄™€£‹¢›∞fi§‡•°ª·º‚≠±œŒ∑„®†ˇ¥Á¨ˆˆØπ∏“«»åÅßÍ∂΃ϩ˙Ó∆Ô˚¬Ò…ÚæÆΩ¸≈π˛çÇ√◊∫ı˜µÂ≤¯≥˘÷¿" {
+        string name "this is an entity with an absurd name just to show characters that are now acceptable as long as they are within double quotes"
+      }