Rename files to mjs and get Jasmine testing inside NodeJS working [#32]
|
@ -2,3 +2,4 @@
|
|||
.DS_Store
|
||||
xcuserdata
|
||||
xcshareddata
|
||||
ephemeral
|
||||
|
|
|
@ -7,18 +7,18 @@
|
|||
<FileRef
|
||||
location = "container:scripts">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "container:spec">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "container:styles">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "container:web">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "container:.gitignore">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "container:.eslintrc.js">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:rollup.config.js">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "container:editor-dev.htm">
|
||||
</FileRef>
|
||||
|
|
|
@ -40,10 +40,10 @@ web modules unless a flag is set (FireFox 60 will support them fully).
|
|||
The editor and library page do not require web modules, so should have
|
||||
wider support.
|
||||
|
||||
To run the linter, run the command:
|
||||
To run the non-browser tests and linter, run the command:
|
||||
|
||||
```shell
|
||||
npm run lint;
|
||||
npm test;
|
||||
```
|
||||
|
||||
And to rebuild the minified sources, run:
|
||||
|
@ -52,7 +52,18 @@ And to rebuild the minified sources, run:
|
|||
npm run minify;
|
||||
```
|
||||
|
||||
Currently there are no command-line tests; only the browser tests.
|
||||
## Commands
|
||||
|
||||
The available commands are:
|
||||
|
||||
* `npm start`: runs a webserver on
|
||||
[localhost:8080](http://localhost:8080)
|
||||
* `npm test`: runs the `unit-test` and `lint` commands
|
||||
* `npm run unit-test`: runs non-browser-based unit tests in NodeJS
|
||||
* `npm run lint`: runs the linter against all source and test files
|
||||
* `npm run minify`: runs the `minify-lib` and `minify-web` commands
|
||||
* `npm run minify-lib`: minifies the library code in `/lib`
|
||||
* `npm run minify-web`: minifies the web code in `/weblib`
|
||||
|
||||
## Project Structure
|
||||
|
||||
|
@ -78,18 +89,19 @@ Useful helpers can also be found in `/scripts/core/*` and
|
|||
`/scripts/svg/*`.
|
||||
|
||||
The live editor (index.htm & editor-dev.htm) uses the source in
|
||||
`/scripts/editor.js` and `/scripts/interface/*`. Other pages use
|
||||
sources in the root of `/scripts` as their entry-points.
|
||||
`/web/editor.mjs` and `/web/interface/*`. Other pages use sources in
|
||||
the root of `/web` as their entry-points.
|
||||
|
||||
## Testing
|
||||
|
||||
The testing library used here is [Jasmine](https://jasmine.github.io/).
|
||||
|
||||
All test files follow the naming convention of `<filename>_spec.js`,
|
||||
and must be listed in `/scripts/spec.js`. Linting automatically applies
|
||||
to all files with a `.js` extension.
|
||||
All test files follow the naming convention of `<filename>_spec.mjs`
|
||||
(commandline and browser) or `_webspec.mjs` (browser-only). Browser
|
||||
tests must be listed in `/spec/support/browser_specs.mjs`. Linting
|
||||
automatically applies to all files with a `.js` or `.mjs` extension.
|
||||
|
||||
You can run the tests by opening `test.htm` in a browser.
|
||||
You can run the browser tests by opening `test.htm` in a browser.
|
||||
|
||||
The current state of automated testing is:
|
||||
|
||||
|
@ -97,12 +109,12 @@ The current state of automated testing is:
|
|||
* `Parser` and `Generator` stages have a good level of testing
|
||||
* Rendering methods (SVG generation) have a minimal level of testing;
|
||||
there are some high-level tests in
|
||||
`/scripts/sequence/SequenceDiagram_spec.js`, and a series of image
|
||||
comparison tests in `/scripts/sequence/Readme_spec.js` (testing that
|
||||
`/scripts/sequence/SequenceDiagram_spec.mjs`, and a series of image
|
||||
comparison tests in `/scripts/sequence/Readme_spec.mjs` (testing that
|
||||
the readme screenshots roughly match the current behaviour). Finally
|
||||
`/scripts/sequence/SequenceDiagram_visual_spec.js` uses coarse image
|
||||
`/scripts/sequence/SequenceDiagram_visual_spec.mjs` uses coarse image
|
||||
comparison to test components and interactions using baseline SVGs
|
||||
from `test-images`.
|
||||
from `spec/images`.
|
||||
* The editor has a minimal level of testing.
|
||||
|
||||
If you suspect a failing test is not related to your changes, you can
|
||||
|
@ -129,7 +141,7 @@ polyfils are included.
|
|||
### Testing & Linting
|
||||
|
||||
Ensure that all unit tests are passing and files pass linting. This can
|
||||
be done by opening `test.htm` in a browser and running `npm run lint`
|
||||
be done by opening `test.htm` in a browser and running `npm test`
|
||||
in a command window. At a minimum, you should ensure that tests are
|
||||
passing in Google Chrome, but testing in other supported browsers is
|
||||
even better.
|
||||
|
@ -150,7 +162,7 @@ npm run minify;
|
|||
```
|
||||
|
||||
This will update the files in `/lib` and `/weblib`. The minified code
|
||||
is a self-contained copy of the `/scripts/sequence/SequenceDiagram.js`
|
||||
is a self-contained copy of the `/scripts/sequence/SequenceDiagram.mjs`
|
||||
script, with some boiler-plate added to allow loading into a page in a
|
||||
variety of ways.
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ reference it with #issue-number.
|
|||
|
||||
Checklist: (tick with [x])
|
||||
|
||||
- [ ] Any new spec files are listed in `scripts/specs.js`.
|
||||
- [ ] Any new spec files are listed in `spec/support/browser_specs.mjs`.
|
||||
- [ ] Tests are passing in Google Chrome.
|
||||
- [ ] Linting is passing (`npm run lint`)
|
||||
- [ ] No dead code is left behind.
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
data-integrity="sha256-HYX1RusN7a369vYuOd1mGvxLcNL4z/MihkahAI2CH8k="
|
||||
>
|
||||
|
||||
<script src="scripts/editor.js" type="module"></script>
|
||||
<script src="web/editor.mjs" type="module"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -1239,8 +1239,19 @@
|
|||
}
|
||||
}
|
||||
|
||||
const nodejs = (typeof window === 'undefined');
|
||||
|
||||
// Thanks, https://stackoverflow.com/a/23522755/1180785
|
||||
const safari = (/^((?!chrome|android).)*safari/i).test(navigator.userAgent);
|
||||
const safari = (
|
||||
!nodejs &&
|
||||
(/^((?!chrome|android).)*safari/i).test(window.navigator.userAgent)
|
||||
);
|
||||
|
||||
// Thanks, https://stackoverflow.com/a/9851769/1180785
|
||||
const firefox = (
|
||||
!nodejs &&
|
||||
typeof window.InstallTrigger !== 'undefined'
|
||||
);
|
||||
|
||||
class Exporter {
|
||||
constructor() {
|
||||
|
@ -6620,9 +6631,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Thanks, https://stackoverflow.com/a/9851769/1180785
|
||||
const firefox = (typeof window.InstallTrigger !== 'undefined');
|
||||
|
||||
function merge(state, newState) {
|
||||
for(const k in state) {
|
||||
if(Object.prototype.hasOwnProperty.call(state, k)) {
|
||||
|
@ -7115,16 +7123,16 @@
|
|||
return this.dom.el(tag, namespace);
|
||||
}
|
||||
|
||||
box(attrs, position) {
|
||||
return this.el('rect').attrs(attrs).attrs(position);
|
||||
box(attrs, {height, width, x, y}) {
|
||||
return this.el('rect').attrs(attrs).attrs({height, width, x, y});
|
||||
}
|
||||
|
||||
boxFactory(attrs) {
|
||||
return this.box.bind(this, attrs);
|
||||
}
|
||||
|
||||
line(attrs, position) {
|
||||
return this.el('line').attrs(attrs).attrs(position);
|
||||
line(attrs, {x1, x2, y1, y2}) {
|
||||
return this.el('line').attrs(attrs).attrs({x1, x2, y1, y2});
|
||||
}
|
||||
|
||||
lineFactory(attrs) {
|
||||
|
@ -7160,11 +7168,11 @@
|
|||
return this.cross.bind(this, attrs);
|
||||
}
|
||||
|
||||
note(attrs, flickAttrs, position) {
|
||||
const x0 = position.x;
|
||||
const x1 = position.x + position.width;
|
||||
const y0 = position.y;
|
||||
const y1 = position.y + position.height;
|
||||
note(attrs, flickAttrs, {height, width, x, y}) {
|
||||
const x0 = x;
|
||||
const x1 = x + width;
|
||||
const y0 = y;
|
||||
const y1 = y + height;
|
||||
const flick = 7;
|
||||
|
||||
return this.el('g').add(
|
||||
|
@ -7191,13 +7199,13 @@
|
|||
return this.note.bind(this, attrs, flickAttrs);
|
||||
}
|
||||
|
||||
formattedText(attrs = {}, formatted = [], position = {}) {
|
||||
formattedText(attrs = {}, formatted = [], {x, y} = {}) {
|
||||
const container = this.el('g');
|
||||
const txt = new SVGTextBlock(container, this, {
|
||||
attrs,
|
||||
formatted,
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
x,
|
||||
y,
|
||||
});
|
||||
return Object.assign(container, {
|
||||
set: (state) => txt.set(state),
|
||||
|
@ -9544,7 +9552,9 @@
|
|||
|
||||
function pickDocument(container) {
|
||||
if(container) {
|
||||
return container.ownerDocument;
|
||||
return container.ownerDocument || null;
|
||||
} else if(typeof window === 'undefined') {
|
||||
return null;
|
||||
} else {
|
||||
return window.document;
|
||||
}
|
||||
|
@ -9921,6 +9931,10 @@
|
|||
convert(els);
|
||||
}
|
||||
|
||||
function getDefaultThemeNames() {
|
||||
return themes.map((theme) => theme.name);
|
||||
}
|
||||
|
||||
Object.assign(SequenceDiagram, {
|
||||
Exporter,
|
||||
Generator,
|
||||
|
@ -9930,6 +9944,7 @@
|
|||
convert,
|
||||
convertAll,
|
||||
extractCodeFromSVG,
|
||||
getDefaultThemeNames,
|
||||
registerCodeMirrorMode,
|
||||
renderAll,
|
||||
themes,
|
||||
|
|
|
@ -111,6 +111,12 @@
|
|||
"integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
|
||||
"dev": true
|
||||
},
|
||||
"arr-union": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
|
||||
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
|
||||
"dev": true
|
||||
},
|
||||
"array-union": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
|
||||
|
@ -144,6 +150,12 @@
|
|||
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
|
||||
"dev": true
|
||||
},
|
||||
"async-array-reduce": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/async-array-reduce/-/async-array-reduce-0.2.1.tgz",
|
||||
"integrity": "sha1-yL4BCitc0A3qlsgRFgNGk9/dgtE=",
|
||||
"dev": true
|
||||
},
|
||||
"babel-code-frame": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||
|
@ -580,6 +592,24 @@
|
|||
"fill-range": "2.2.3"
|
||||
}
|
||||
},
|
||||
"expand-tilde": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz",
|
||||
"integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"os-homedir": "1.0.2"
|
||||
}
|
||||
},
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extendable": "0.1.1"
|
||||
}
|
||||
},
|
||||
"external-editor": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
|
@ -683,6 +713,12 @@
|
|||
"for-in": "1.0.2"
|
||||
}
|
||||
},
|
||||
"fs-exists-sync": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz",
|
||||
"integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=",
|
||||
"dev": true
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
|
@ -728,6 +764,28 @@
|
|||
"is-glob": "2.0.1"
|
||||
}
|
||||
},
|
||||
"global-modules": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz",
|
||||
"integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"global-prefix": "0.1.5",
|
||||
"is-windows": "0.2.0"
|
||||
}
|
||||
},
|
||||
"global-prefix": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz",
|
||||
"integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"homedir-polyfill": "1.0.1",
|
||||
"ini": "1.3.5",
|
||||
"is-windows": "0.2.0",
|
||||
"which": "1.3.0"
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"version": "11.4.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.4.0.tgz",
|
||||
|
@ -769,12 +827,30 @@
|
|||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"has-glob": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/has-glob/-/has-glob-0.1.1.tgz",
|
||||
"integrity": "sha1-omHEwqbGZ+DHe3AKfyl8Oe86pYk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "2.0.1"
|
||||
}
|
||||
},
|
||||
"he": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
|
||||
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
|
||||
"dev": true
|
||||
},
|
||||
"homedir-polyfill": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz",
|
||||
"integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"parse-passwd": "1.0.0"
|
||||
}
|
||||
},
|
||||
"http-proxy": {
|
||||
"version": "1.16.2",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz",
|
||||
|
@ -838,6 +914,12 @@
|
|||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"dev": true
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
|
||||
|
@ -980,6 +1062,18 @@
|
|||
"integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-valid-glob": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz",
|
||||
"integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=",
|
||||
"dev": true
|
||||
},
|
||||
"is-windows": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz",
|
||||
"integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=",
|
||||
"dev": true
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
|
@ -1001,6 +1095,22 @@
|
|||
"isarray": "1.0.0"
|
||||
}
|
||||
},
|
||||
"jasmine": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.1.0.tgz",
|
||||
"integrity": "sha1-K9Wf1+xuwOistk4J9Fpo7SrRlSo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "7.1.2",
|
||||
"jasmine-core": "3.1.0"
|
||||
}
|
||||
},
|
||||
"jasmine-core": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz",
|
||||
"integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||
|
@ -1038,6 +1148,15 @@
|
|||
"is-buffer": "1.1.6"
|
||||
}
|
||||
},
|
||||
"lazy-cache": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz",
|
||||
"integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"set-getter": "0.1.0"
|
||||
}
|
||||
},
|
||||
"levn": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||
|
@ -1070,6 +1189,23 @@
|
|||
"yallist": "2.1.2"
|
||||
}
|
||||
},
|
||||
"matched": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/matched/-/matched-0.4.4.tgz",
|
||||
"integrity": "sha1-Vte36xgDPwz5vFLrIJD6x9weifo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"arr-union": "3.1.0",
|
||||
"async-array-reduce": "0.2.1",
|
||||
"extend-shallow": "2.0.1",
|
||||
"fs-exists-sync": "0.1.0",
|
||||
"glob": "7.1.2",
|
||||
"has-glob": "0.1.1",
|
||||
"is-valid-glob": "0.3.0",
|
||||
"lazy-cache": "2.0.2",
|
||||
"resolve-dir": "0.1.1"
|
||||
}
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "2.3.11",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
|
||||
|
@ -1242,6 +1378,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"os-homedir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
|
||||
"dev": true
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
|
@ -1266,6 +1408,12 @@
|
|||
"integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=",
|
||||
"dev": true
|
||||
},
|
||||
"parse-passwd": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
|
||||
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
|
||||
"dev": true
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
|
@ -1488,6 +1636,16 @@
|
|||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
},
|
||||
"resolve-dir": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz",
|
||||
"integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"expand-tilde": "1.2.2",
|
||||
"global-modules": "0.2.3"
|
||||
}
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
|
||||
|
@ -1538,6 +1696,15 @@
|
|||
"integrity": "sha512-MlxPQTkMtiRUtyhIJ7FpBvTzWtar8eFBA+V7/J6Deg9fSgIIHwL6bJKK1Wl1uWSWtOrWhOmtsMwb9F6aagP/Pg==",
|
||||
"dev": true
|
||||
},
|
||||
"rollup-plugin-multi-entry": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-multi-entry/-/rollup-plugin-multi-entry-2.0.2.tgz",
|
||||
"integrity": "sha512-TY72fCVJvcEAQBpBzkXykoYQx2fz0B20EVtcbh0WZaYr5eBu3U1dRPzgMt6aO8MePWWOdcmgoBtG6PhmYJr4Ew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"matched": "0.4.4"
|
||||
}
|
||||
},
|
||||
"rollup-pluginutils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz",
|
||||
|
@ -1590,6 +1757,15 @@
|
|||
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
|
||||
"dev": true
|
||||
},
|
||||
"set-getter": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz",
|
||||
"integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-object-path": "0.3.0"
|
||||
}
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||
|
@ -1626,6 +1802,15 @@
|
|||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz",
|
||||
"integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"source-map": "0.6.1"
|
||||
}
|
||||
},
|
||||
"sourcemap-codec": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.1.tgz",
|
||||
|
@ -1727,6 +1912,15 @@
|
|||
"os-tmpdir": "1.0.2"
|
||||
}
|
||||
},
|
||||
"to-object-path": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
|
||||
"integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"kind-of": "3.2.2"
|
||||
}
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
|
||||
|
|
15
package.json
|
@ -15,19 +15,26 @@
|
|||
"lib/sequence-diagram.js"
|
||||
],
|
||||
"main": "lib/sequence-diagram",
|
||||
"module": "source/standalone",
|
||||
"module": "scripts/standalone",
|
||||
"scripts": {
|
||||
"lint": "eslint scripts --ext .js --ignore-pattern '!.eslintrc.js' --ignore-pattern '*FontData.js'",
|
||||
"minify": "rollup --config rollup.config.js && uglifyjs --compress --mangle --warn --output lib/sequence-diagram.min.js -- lib/sequence-diagram.js && uglifyjs --compress --mangle --warn --output weblib/editor.min.js -- weblib/editor.js",
|
||||
"start": "http-server"
|
||||
"lint": "eslint . --config spec/support/eslintrc.js --ignore-path spec/support/eslintignore --ext .js --ext .mjs",
|
||||
"minify-lib": "rollup --config scripts/rollup.config.js && uglifyjs --compress --mangle --warn --output lib/sequence-diagram.min.js -- lib/sequence-diagram.js",
|
||||
"minify-web": "rollup --config web/rollup.config.js && uglifyjs --compress --mangle --warn --output weblib/editor.min.js -- weblib/editor.js",
|
||||
"minify": "npm run minify-lib && npm run minify-web",
|
||||
"start": "http-server",
|
||||
"test": "npm run unit-test && npm run lint",
|
||||
"unit-test": "rollup --config spec/support/rollup.config.js && node -r source-map-support/register node_modules/.bin/jasmine --config=spec/support/jasmine.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-plugin-jasmine": "^2.9.3",
|
||||
"http-server": "^0.10.0",
|
||||
"jasmine": "^3.1.0",
|
||||
"requirejs": "2.3.5",
|
||||
"rollup": "^0.57.1",
|
||||
"rollup-plugin-hypothetical": "^2.1.0",
|
||||
"rollup-plugin-multi-entry": "^2.0.2",
|
||||
"source-map-support": "^0.5.4",
|
||||
"uglify-es": "^3.1.10"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<link rel="apple-touch-icon" href="apple-touch-icon.png">
|
||||
|
||||
<link rel="stylesheet" href="styles/readmeImages.css">
|
||||
<script src="scripts/readmeImages.js" type="module"></script>
|
||||
<script src="web/readmeImages.mjs" type="module"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
mergeSets,
|
||||
remove,
|
||||
removeAll,
|
||||
} from './ArrayUtilities.js';
|
||||
} from './ArrayUtilities.mjs';
|
||||
|
||||
describe('ArrayUtilities', () => {
|
||||
function ignoreCase(a, b) {
|
|
@ -1,4 +1,4 @@
|
|||
import EventObject from './EventObject.js';
|
||||
import EventObject from './EventObject.mjs';
|
||||
|
||||
describe('EventObject', () => {
|
||||
let o = null;
|
|
@ -1,4 +1,4 @@
|
|||
import Random from './Random.js';
|
||||
import Random from './Random.mjs';
|
||||
|
||||
describe('Random', () => {
|
||||
let random = null;
|
|
@ -0,0 +1,15 @@
|
|||
export const nodejs = (typeof window === 'undefined');
|
||||
|
||||
export const headless = nodejs;
|
||||
|
||||
// Thanks, https://stackoverflow.com/a/23522755/1180785
|
||||
export const safari = (
|
||||
!nodejs &&
|
||||
(/^((?!chrome|android).)*safari/i).test(window.navigator.userAgent)
|
||||
);
|
||||
|
||||
// Thanks, https://stackoverflow.com/a/9851769/1180785
|
||||
export const firefox = (
|
||||
!nodejs &&
|
||||
typeof window.InstallTrigger !== 'undefined'
|
||||
);
|
|
@ -104,6 +104,39 @@ class ElementNode {
|
|||
return false;
|
||||
}
|
||||
|
||||
getElementsByTagName(tag) {
|
||||
const result = [];
|
||||
this.traverseDescendants((o) => {
|
||||
if(o.tagName === tag) {
|
||||
result.push(o);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
getElementsByClassName(className) {
|
||||
const result = [];
|
||||
const check = ' ' + className + ' ';
|
||||
this.traverseDescendants((o) => {
|
||||
const cls = ' ' + (o.getAttribute('class') || '') + ' ';
|
||||
if(cls.indexOf(check) !== -1) {
|
||||
result.push(o);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
traverseDescendants(fn) {
|
||||
if(fn(this) === false) {
|
||||
return;
|
||||
}
|
||||
for(const child of this.childNodes) {
|
||||
if(child.traverseDescendants) {
|
||||
child.traverseDescendants(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get firstChild() {
|
||||
return this.childNodes[0] || null;
|
||||
}
|
||||
|
@ -195,7 +228,7 @@ class ElementNode {
|
|||
}
|
||||
}
|
||||
|
||||
export default class VirtualDocument {
|
||||
export class VirtualDocument {
|
||||
createElement(tag) {
|
||||
return new ElementNode(this, tag, '');
|
||||
}
|
||||
|
@ -208,3 +241,9 @@ export default class VirtualDocument {
|
|||
return new TextNode(content);
|
||||
}
|
||||
}
|
||||
|
||||
export class Event {
|
||||
constructor(type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import VirtualDocument from './VirtualDocument.js';
|
||||
import {Event, VirtualDocument} from './VirtualDocument.mjs';
|
||||
|
||||
describe('VirtualDocument', () => {
|
||||
const doc = new VirtualDocument();
|
|
@ -1,4 +1,4 @@
|
|||
import ImageRegion from './ImageRegion.js';
|
||||
import ImageRegion from './ImageRegion.mjs';
|
||||
|
||||
export function makeGaussianKernel(size) {
|
||||
const sz = Math.ceil(size * 3);
|
|
@ -1,5 +1,5 @@
|
|||
import ImageRegion from './ImageRegion.js';
|
||||
import {blur2D} from './Blur.js';
|
||||
import ImageRegion from './ImageRegion.mjs';
|
||||
import {blur2D} from './Blur.mjs';
|
||||
|
||||
describe('Blur', () => {
|
||||
const PRECISION = 0.01;
|
|
@ -1,4 +1,4 @@
|
|||
import ImageRegion from './ImageRegion.js';
|
||||
import ImageRegion from './ImageRegion.mjs';
|
||||
|
||||
function compose(input1, input2, fn, {target = null} = {}) {
|
||||
input1.checkCompatible(input2);
|
|
@ -1,5 +1,5 @@
|
|||
import ImageRegion from './ImageRegion.js';
|
||||
import {subtract} from './Composition.js';
|
||||
import ImageRegion from './ImageRegion.mjs';
|
||||
import {subtract} from './Composition.mjs';
|
||||
|
||||
describe('Composition', () => {
|
||||
let inputA = null;
|
|
@ -1,9 +1,13 @@
|
|||
/* eslint-disable max-statements */
|
||||
|
||||
import ImageRegion from './ImageRegion.js';
|
||||
import ImageRegion from './ImageRegion.mjs';
|
||||
import {nodejs} from '../core/browser.mjs';
|
||||
|
||||
describe('ImageRegion', () => {
|
||||
function makeCanvas(w, h) {
|
||||
if(nodejs) {
|
||||
return pending('No canvas support in NodeJS');
|
||||
}
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
|
@ -1,6 +1,7 @@
|
|||
import './Blur.js';
|
||||
import './Composition.js';
|
||||
import ImageRegion from './ImageRegion.js';
|
||||
import './Blur.mjs';
|
||||
import './Composition.mjs';
|
||||
import ImageRegion from './ImageRegion.mjs';
|
||||
import {headless} from '../core/browser.mjs';
|
||||
|
||||
function getThresholds({
|
||||
pixelThresh = 2,
|
||||
|
@ -74,20 +75,22 @@ export const matchers = {
|
|||
return {pass: true};
|
||||
}
|
||||
|
||||
let message = 'Expected images to be similar';
|
||||
if(!headless) {
|
||||
document.body.appendChild(makeImageComparison(
|
||||
actual,
|
||||
expected,
|
||||
options,
|
||||
'Image comparison (expected similar)'
|
||||
));
|
||||
|
||||
const details = (options.details ?
|
||||
message += ' (see below for comparison)';
|
||||
}
|
||||
message += '.' + (options.details ?
|
||||
' Details: ' + options.details : ''
|
||||
);
|
||||
|
||||
return {
|
||||
message: 'Expected images to be similar ' +
|
||||
'(see below for comparison).' + details,
|
||||
message,
|
||||
pass: false,
|
||||
};
|
||||
},
|
||||
|
@ -97,20 +100,22 @@ export const matchers = {
|
|||
return {pass: true};
|
||||
}
|
||||
|
||||
let message = 'Expected images to differ';
|
||||
if(!headless) {
|
||||
document.body.appendChild(makeImageComparison(
|
||||
actual,
|
||||
expected,
|
||||
options,
|
||||
'Image comparison (expected different)'
|
||||
));
|
||||
|
||||
const details = (options.details ?
|
||||
message += ' (see below for comparison)';
|
||||
}
|
||||
message += '.' + (options.details ?
|
||||
' Details: ' + options.details : ''
|
||||
);
|
||||
|
||||
return {
|
||||
message: 'Expected images to differ ' +
|
||||
'(see below for comparison).' + details,
|
||||
message,
|
||||
pass: false,
|
||||
};
|
||||
},
|
|
@ -1,5 +1,5 @@
|
|||
import {isSimilar, matchers} from './ImageSimilarity.js';
|
||||
import ImageRegion from './ImageRegion.js';
|
||||
import {isSimilar, matchers} from './ImageSimilarity.mjs';
|
||||
import ImageRegion from './ImageRegion.mjs';
|
||||
|
||||
describe('ImageSimilarity', () => {
|
||||
let inputA = null;
|
|
@ -1,26 +0,0 @@
|
|||
import ComponentsLibrary from './ComponentsLibrary.js';
|
||||
import SequenceDiagram from '../sequence/SequenceDiagram.js';
|
||||
|
||||
const themes = new SequenceDiagram().getThemeNames().slice(1);
|
||||
|
||||
function checkSample(src) {
|
||||
it('renders without error', () => {
|
||||
expect(() => new SequenceDiagram(src)).not.toThrow();
|
||||
});
|
||||
|
||||
themes.forEach((themeName) => {
|
||||
it('renders without error in ' + themeName + ' theme', () => {
|
||||
expect(() => new SequenceDiagram(
|
||||
'theme ' + themeName + '\n' + src
|
||||
)).not.toThrow();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('Components Library', () => {
|
||||
ComponentsLibrary.forEach(({title, code, preview}) => {
|
||||
describe(title, () => {
|
||||
checkSample(preview || code);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,31 +0,0 @@
|
|||
// Jasmine test configuration.
|
||||
// See specs.js for the list of spec files
|
||||
|
||||
jasmine.executeAllTests = window.onload;
|
||||
window.onload = null;
|
||||
|
||||
const matchers = {
|
||||
toBeNear: () => ({
|
||||
compare: (actual, expected, range) => {
|
||||
if(
|
||||
typeof expected !== 'number' ||
|
||||
typeof range !== 'number' ||
|
||||
range < 0
|
||||
) {
|
||||
throw new Error(
|
||||
'Invalid toBeNear(' + expected + ',' + range + ')'
|
||||
);
|
||||
}
|
||||
if(typeof actual !== 'number') {
|
||||
throw new Error('Expected a number, got ' + actual);
|
||||
}
|
||||
return {
|
||||
pass: Math.abs(actual - expected) <= range,
|
||||
};
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
jasmine.addMatchers(matchers);
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
export default [
|
||||
{
|
||||
input: 'scripts/standalone.mjs',
|
||||
output: {
|
||||
file: 'lib/sequence-diagram.js',
|
||||
format: 'iife',
|
||||
name: 'SequenceDiagram',
|
||||
},
|
||||
},
|
||||
];
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable complexity */ // Temporary ignore while switching linter
|
||||
|
||||
import {last, mergeSets} from '../core/ArrayUtilities.js';
|
||||
import {last, mergeSets} from '../core/ArrayUtilities.mjs';
|
||||
|
||||
const TRIMMER = /^([ \t]*)(.*)$/;
|
||||
const SQUASH = {
|
|
@ -2,7 +2,7 @@
|
|||
/* eslint-disable sort-keys */ // Maybe later
|
||||
/* eslint-disable complexity */ // Temporary ignore while switching linter
|
||||
|
||||
import {flatMap, last, mergeSets} from '../core/ArrayUtilities.js';
|
||||
import {flatMap, last, mergeSets} from '../core/ArrayUtilities.mjs';
|
||||
|
||||
const CM_ERROR = {type: 'error line-error', suggest: false, then: {'': 0}};
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
/* eslint-disable max-statements */
|
||||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import SequenceDiagram from './SequenceDiagram.js';
|
||||
import SequenceDiagram from './SequenceDiagram.mjs';
|
||||
|
||||
const CM = window.CodeMirror;
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
// Thanks, https://stackoverflow.com/a/23522755/1180785
|
||||
const safari = (/^((?!chrome|android).)*safari/i).test(navigator.userAgent);
|
||||
import {safari} from '../core/browser.mjs';
|
||||
|
||||
export default class Exporter {
|
||||
constructor() {
|
|
@ -10,7 +10,7 @@ import {
|
|||
mergeSets,
|
||||
remove,
|
||||
removeAll,
|
||||
} from '../core/ArrayUtilities.js';
|
||||
} from '../core/ArrayUtilities.mjs';
|
||||
|
||||
class AgentState {
|
||||
constructor({
|
|
@ -2,7 +2,7 @@
|
|||
/* eslint-disable max-statements */
|
||||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import Generator from './Generator.js';
|
||||
import Generator from './Generator.mjs';
|
||||
|
||||
describe('Sequence Generator', () => {
|
||||
const generator = new Generator();
|
|
@ -1,4 +1,4 @@
|
|||
import parser from './LabelPatternParser.js';
|
||||
import parser from './LabelPatternParser.mjs';
|
||||
|
||||
describe('Label Pattern Parser', () => {
|
||||
it('converts simple text', () => {
|
|
@ -1,8 +1,8 @@
|
|||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import {dom, textSizerFactory} from '../stubs/TestDOM.js';
|
||||
import SVG from '../svg/SVG.js';
|
||||
import parser from './MarkdownParser.js';
|
||||
import {dom, textSizerFactory} from '../../spec/stubs/TestDOM.mjs';
|
||||
import SVG from '../svg/SVG.mjs';
|
||||
import parser from './MarkdownParser.mjs';
|
||||
|
||||
describe('Markdown Parser', () => {
|
||||
it('converts simple text', () => {
|
|
@ -3,10 +3,10 @@
|
|||
/* eslint-disable complexity */ // Temporary ignore while switching linter
|
||||
/* eslint-disable no-param-reassign */ // Also temporary
|
||||
|
||||
import {combine, last} from '../core/ArrayUtilities.js';
|
||||
import Tokeniser from './Tokeniser.js';
|
||||
import labelPatternParser from './LabelPatternParser.js';
|
||||
import markdownParser from './MarkdownParser.js';
|
||||
import {combine, last} from '../core/ArrayUtilities.mjs';
|
||||
import Tokeniser from './Tokeniser.mjs';
|
||||
import labelPatternParser from './LabelPatternParser.mjs';
|
||||
import markdownParser from './MarkdownParser.mjs';
|
||||
|
||||
const BLOCK_TYPES = {
|
||||
'if': {
|
|
@ -2,7 +2,7 @@
|
|||
/* eslint-disable max-statements */
|
||||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import Parser from './Parser.js';
|
||||
import Parser from './Parser.mjs';
|
||||
|
||||
describe('Sequence Parser', () => {
|
||||
const parser = new Parser();
|
|
@ -1,6 +1,6 @@
|
|||
import ImageRegion from '../image/ImageRegion.js';
|
||||
import SequenceDiagram from './SequenceDiagram.js';
|
||||
import {matchers} from '../image/ImageSimilarity.js';
|
||||
import ImageRegion from '../image/ImageRegion.mjs';
|
||||
import SequenceDiagram from './SequenceDiagram.mjs';
|
||||
import {matchers} from '../image/ImageSimilarity.mjs';
|
||||
|
||||
const RESOLUTION = 4;
|
||||
|
|
@ -1,21 +1,21 @@
|
|||
/* eslint-disable max-lines */
|
||||
|
||||
import './components/AgentCap.js';
|
||||
import './components/AgentHighlight.js';
|
||||
import './components/Block.js';
|
||||
import './components/Connect.js';
|
||||
import './components/Divider.js';
|
||||
import './components/Marker.js';
|
||||
import './components/Note.js';
|
||||
import './components/Parallel.js';
|
||||
import './components/AgentCap.mjs';
|
||||
import './components/AgentHighlight.mjs';
|
||||
import './components/Block.mjs';
|
||||
import './components/Connect.mjs';
|
||||
import './components/Divider.mjs';
|
||||
import './components/Marker.mjs';
|
||||
import './components/Note.mjs';
|
||||
import './components/Parallel.mjs';
|
||||
import {
|
||||
cleanRenderPreResult,
|
||||
getComponents,
|
||||
} from './components/BaseComponent.js';
|
||||
import DOMWrapper from '../core/DOMWrapper.js';
|
||||
import EventObject from '../core/EventObject.js';
|
||||
import SVG from '../svg/SVG.js';
|
||||
import {mergeSets} from '../core/ArrayUtilities.js';
|
||||
} from './components/BaseComponent.mjs';
|
||||
import DOMWrapper from '../core/DOMWrapper.mjs';
|
||||
import EventObject from '../core/EventObject.mjs';
|
||||
import SVG from '../svg/SVG.mjs';
|
||||
import {mergeSets} from '../core/ArrayUtilities.mjs';
|
||||
|
||||
function findExtremes(agentInfos, agentIDs) {
|
||||
let min = null;
|
|
@ -1,21 +1,18 @@
|
|||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import {Factory as BasicThemeFactory} from './themes/Basic.js';
|
||||
import Renderer from './Renderer.js';
|
||||
import {VirtualDocument, textSizerFactory} from '../../spec/stubs/TestDOM.mjs';
|
||||
import {Factory as BasicThemeFactory} from './themes/Basic.mjs';
|
||||
import Renderer from './Renderer.mjs';
|
||||
|
||||
describe('Sequence Renderer', () => {
|
||||
let renderer = null;
|
||||
|
||||
beforeEach(() => {
|
||||
renderer = new Renderer({
|
||||
document: new VirtualDocument(),
|
||||
themes: [new BasicThemeFactory()],
|
||||
document: window.document,
|
||||
textSizerFactory,
|
||||
});
|
||||
document.body.appendChild(renderer.dom());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(renderer.dom());
|
||||
});
|
||||
|
||||
describe('.dom', () => {
|
|
@ -1,13 +1,13 @@
|
|||
import {Factory as BasicThemeFactory} from './themes/Basic.js';
|
||||
import {Factory as ChunkyThemeFactory} from './themes/Chunky.js';
|
||||
import EventObject from '../core/EventObject.js';
|
||||
import Exporter from './Exporter.js';
|
||||
import Generator from './Generator.js';
|
||||
import {Factory as MonospaceThemeFactory} from './themes/Monospace.js';
|
||||
import Parser from './Parser.js';
|
||||
import Renderer from './Renderer.js';
|
||||
import {Factory as SketchThemeFactory} from './themes/Sketch.js';
|
||||
import {getHints} from './CodeMirrorHints.js';
|
||||
import {Factory as BasicThemeFactory} from './themes/Basic.mjs';
|
||||
import {Factory as ChunkyThemeFactory} from './themes/Chunky.mjs';
|
||||
import EventObject from '../core/EventObject.mjs';
|
||||
import Exporter from './Exporter.mjs';
|
||||
import Generator from './Generator.mjs';
|
||||
import {Factory as MonospaceThemeFactory} from './themes/Monospace.mjs';
|
||||
import Parser from './Parser.mjs';
|
||||
import Renderer from './Renderer.mjs';
|
||||
import {Factory as SketchThemeFactory} from './themes/Sketch.mjs';
|
||||
import {getHints} from './CodeMirrorHints.mjs';
|
||||
|
||||
const themes = [
|
||||
new BasicThemeFactory(),
|
||||
|
@ -65,7 +65,9 @@ function renderAll(diagrams) {
|
|||
|
||||
function pickDocument(container) {
|
||||
if(container) {
|
||||
return container.ownerDocument;
|
||||
return container.ownerDocument || null;
|
||||
} else if(typeof window === 'undefined') {
|
||||
return null;
|
||||
} else {
|
||||
return window.document;
|
||||
}
|
||||
|
@ -442,6 +444,10 @@ function convertAll(root = null, className = 'sequence-diagram') {
|
|||
convert(els);
|
||||
}
|
||||
|
||||
function getDefaultThemeNames() {
|
||||
return themes.map((theme) => theme.name);
|
||||
}
|
||||
|
||||
Object.assign(SequenceDiagram, {
|
||||
Exporter,
|
||||
Generator,
|
||||
|
@ -451,6 +457,7 @@ Object.assign(SequenceDiagram, {
|
|||
convert,
|
||||
convertAll,
|
||||
extractCodeFromSVG,
|
||||
getDefaultThemeNames,
|
||||
registerCodeMirrorMode,
|
||||
renderAll,
|
||||
themes,
|
|
@ -1,9 +1,10 @@
|
|||
import Exporter from './Exporter.js';
|
||||
import Generator from './Generator.js';
|
||||
import Parser from './Parser.js';
|
||||
import Renderer from './Renderer.js';
|
||||
import SequenceDiagram from './SequenceDiagram.js';
|
||||
import {textSizerFactory} from '../stubs/TestDOM.js';
|
||||
import {VirtualDocument, textSizerFactory} from '../../spec/stubs/TestDOM.mjs';
|
||||
import Exporter from './Exporter.mjs';
|
||||
import Generator from './Generator.mjs';
|
||||
import Parser from './Parser.mjs';
|
||||
import Renderer from './Renderer.mjs';
|
||||
import SequenceDiagram from './SequenceDiagram.mjs';
|
||||
import {nodejs} from '../core/browser.mjs';
|
||||
|
||||
describe('SequenceDiagram', () => {
|
||||
function getSimplifiedContent(d) {
|
||||
|
@ -18,6 +19,7 @@ describe('SequenceDiagram', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
diagram = new SequenceDiagram({
|
||||
document: new VirtualDocument(),
|
||||
namespace: '',
|
||||
textSizerFactory,
|
||||
});
|
||||
|
@ -167,6 +169,11 @@ describe('SequenceDiagram', () => {
|
|||
});
|
||||
|
||||
it('measures OS fonts correctly on the first render', (done) => {
|
||||
if(nodejs) {
|
||||
pending('NodeJS font rendering not implemented yet');
|
||||
return;
|
||||
}
|
||||
|
||||
const code = 'title message';
|
||||
const sd = new SequenceDiagram(code);
|
||||
const widthImmediate = sd.getSize().width;
|
||||
|
@ -187,6 +194,11 @@ describe('SequenceDiagram', () => {
|
|||
});
|
||||
|
||||
it('measures embedded fonts correctly on the first render', (done) => {
|
||||
if(nodejs) {
|
||||
pending('NodeJS font rendering not implemented yet');
|
||||
return;
|
||||
}
|
||||
|
||||
const code = 'theme sketch\ntitle message';
|
||||
const sd = new SequenceDiagram(code);
|
||||
const widthImmediate = sd.getSize().width;
|
|
@ -1,12 +1,12 @@
|
|||
import ImageRegion from '../image/ImageRegion.js';
|
||||
import SequenceDiagram from './SequenceDiagram.js';
|
||||
import TESTS from './test-images/list.js';
|
||||
import {matchers} from '../image/ImageSimilarity.js';
|
||||
import ImageRegion from '../image/ImageRegion.mjs';
|
||||
import SequenceDiagram from './SequenceDiagram.mjs';
|
||||
import TESTS from '../../spec/images/list.mjs';
|
||||
import {matchers} from '../image/ImageSimilarity.mjs';
|
||||
|
||||
describe('SequenceDiagram Visuals', () => {
|
||||
const RESOLUTION = 4;
|
||||
|
||||
const IMAGE_BASE_PATH = 'scripts/sequence/test-images/';
|
||||
const IMAGE_BASE_PATH = 'spec/images/';
|
||||
|
||||
const COLLAPSE_REGEX = new RegExp(/# collapse/g);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import CMMode from './CodeMirrorMode.js';
|
||||
import CMMode from './CodeMirrorMode.mjs';
|
||||
|
||||
function execAt(str, reg, i) {
|
||||
reg.lastIndex = i;
|
|
@ -1,4 +1,4 @@
|
|||
import Tokeniser from './Tokeniser.js';
|
||||
import Tokeniser from './Tokeniser.mjs';
|
||||
|
||||
describe('Sequence Tokeniser', () => {
|
||||
const tokeniser = new Tokeniser();
|
|
@ -1,5 +1,5 @@
|
|||
import BaseComponent, {register} from './BaseComponent.js';
|
||||
import {mergeSets, removeAll} from '../../core/ArrayUtilities.js';
|
||||
import BaseComponent, {register} from './BaseComponent.mjs';
|
||||
import {mergeSets, removeAll} from '../../core/ArrayUtilities.mjs';
|
||||
|
||||
const OUTLINE_ATTRS = {
|
||||
'class': 'outline',
|
|
@ -1,5 +1,5 @@
|
|||
import AgentCap from './AgentCap.js';
|
||||
import {getComponents} from './BaseComponent.js';
|
||||
import AgentCap from './AgentCap.mjs';
|
||||
import {getComponents} from './BaseComponent.mjs';
|
||||
|
||||
describe('AgentCap', () => {
|
||||
it('registers itself with the component store', () => {
|
|
@ -1,4 +1,4 @@
|
|||
import BaseComponent, {register} from './BaseComponent.js';
|
||||
import BaseComponent, {register} from './BaseComponent.mjs';
|
||||
|
||||
export default class AgentHighlight extends BaseComponent {
|
||||
radius(highlighted, env) {
|
|
@ -1,5 +1,5 @@
|
|||
import AgentHighlight from './AgentHighlight.js';
|
||||
import {getComponents} from './BaseComponent.js';
|
||||
import AgentHighlight from './AgentHighlight.mjs';
|
||||
import {getComponents} from './BaseComponent.mjs';
|
||||
|
||||
describe('AgentHighlight', () => {
|
||||
const highlight = new AgentHighlight();
|
|
@ -1,5 +1,5 @@
|
|||
import BaseComponent, {register} from './BaseComponent.js';
|
||||
import {mergeSets, removeAll} from '../../core/ArrayUtilities.js';
|
||||
import BaseComponent, {register} from './BaseComponent.mjs';
|
||||
import {mergeSets, removeAll} from '../../core/ArrayUtilities.mjs';
|
||||
|
||||
const OUTLINE_ATTRS = {
|
||||
'class': 'outline',
|
|
@ -1,5 +1,5 @@
|
|||
import {BlockBegin, BlockEnd, BlockSplit} from './Block.js';
|
||||
import {getComponents} from './BaseComponent.js';
|
||||
import {BlockBegin, BlockEnd, BlockSplit} from './Block.mjs';
|
||||
import {getComponents} from './BaseComponent.mjs';
|
||||
|
||||
describe('Block', () => {
|
||||
it('registers itself with the component store', () => {
|
|
@ -1,7 +1,7 @@
|
|||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import BaseComponent, {register} from './BaseComponent.js';
|
||||
import {mergeSets} from '../../core/ArrayUtilities.js';
|
||||
import BaseComponent, {register} from './BaseComponent.mjs';
|
||||
import {mergeSets} from '../../core/ArrayUtilities.mjs';
|
||||
|
||||
const OUTLINE_ATTRS = {
|
||||
'class': 'outline',
|
|
@ -1,5 +1,5 @@
|
|||
import {Connect, ConnectDelayBegin, ConnectDelayEnd} from './Connect.js';
|
||||
import {getComponents} from './BaseComponent.js';
|
||||
import {Connect, ConnectDelayBegin, ConnectDelayEnd} from './Connect.mjs';
|
||||
import {getComponents} from './BaseComponent.mjs';
|
||||
|
||||
describe('Connect', () => {
|
||||
it('registers itself with the component store', () => {
|
|
@ -1,4 +1,4 @@
|
|||
import BaseComponent, {register} from './BaseComponent.js';
|
||||
import BaseComponent, {register} from './BaseComponent.mjs';
|
||||
|
||||
const OUTLINE_ATTRS = {
|
||||
'class': 'outline',
|
|
@ -1,5 +1,5 @@
|
|||
import Divider from './Divider.js';
|
||||
import {getComponents} from './BaseComponent.js';
|
||||
import Divider from './Divider.mjs';
|
||||
import {getComponents} from './BaseComponent.mjs';
|
||||
|
||||
describe('Divider', () => {
|
||||
describe('Divider', () => {
|
|
@ -1,4 +1,4 @@
|
|||
import BaseComponent, {register} from './BaseComponent.js';
|
||||
import BaseComponent, {register} from './BaseComponent.mjs';
|
||||
|
||||
export class Mark extends BaseComponent {
|
||||
makeState(state) {
|
|
@ -1,5 +1,5 @@
|
|||
import {Async, Mark} from './Marker.js';
|
||||
import {getComponents} from './BaseComponent.js';
|
||||
import {Async, Mark} from './Marker.mjs';
|
||||
import {getComponents} from './BaseComponent.mjs';
|
||||
|
||||
const mark = new Mark();
|
||||
const async = new Async();
|
|
@ -1,7 +1,7 @@
|
|||
/* eslint-disable complexity */ // Temporary ignore while switching linter
|
||||
/* eslint-disable no-param-reassign */ // Also temporary
|
||||
|
||||
import BaseComponent, {register} from './BaseComponent.js';
|
||||
import BaseComponent, {register} from './BaseComponent.mjs';
|
||||
|
||||
const OUTLINE_ATTRS = {
|
||||
'class': 'outline',
|
|
@ -1,5 +1,5 @@
|
|||
import {NoteBetween, NoteOver, NoteSide} from './Note.js';
|
||||
import {getComponents} from './BaseComponent.js';
|
||||
import {NoteBetween, NoteOver, NoteSide} from './Note.mjs';
|
||||
import {getComponents} from './BaseComponent.mjs';
|
||||
|
||||
describe('NoteOver', () => {
|
||||
it('registers itself with the component store', () => {
|
|
@ -1,8 +1,8 @@
|
|||
import BaseComponent, {
|
||||
cleanRenderPreResult,
|
||||
register,
|
||||
} from './BaseComponent.js';
|
||||
import {mergeSets} from '../../core/ArrayUtilities.js';
|
||||
} from './BaseComponent.mjs';
|
||||
import {mergeSets} from '../../core/ArrayUtilities.mjs';
|
||||
|
||||
function nullableMax(a = null, b = null) {
|
||||
if(a === null) {
|
|
@ -1,5 +1,5 @@
|
|||
import Parallel from './Parallel.js';
|
||||
import {getComponents} from './BaseComponent.js';
|
||||
import Parallel from './Parallel.mjs';
|
||||
import {getComponents} from './BaseComponent.mjs';
|
||||
|
||||
describe('Parallel', () => {
|
||||
it('registers itself with the component store', () => {
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import BaseTheme, {WavePattern} from './BaseTheme.js';
|
||||
import BaseTheme, {WavePattern} from './BaseTheme.mjs';
|
||||
|
||||
const FONT = 'sans-serif';
|
||||
const LINE_HEIGHT = 1.3;
|
|
@ -1,6 +1,6 @@
|
|||
import {dom, textSizerFactory} from '../../stubs/TestDOM.js';
|
||||
import {Factory} from './Basic.js';
|
||||
import SVG from '../../svg/SVG.js';
|
||||
import {dom, textSizerFactory} from '../../../spec/stubs/TestDOM.mjs';
|
||||
import {Factory} from './Basic.mjs';
|
||||
import SVG from '../../svg/SVG.mjs';
|
||||
|
||||
describe('Basic Theme', () => {
|
||||
const svg = new SVG(dom, textSizerFactory);
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import BaseTheme, {WavePattern} from './BaseTheme.js';
|
||||
import BaseTheme, {WavePattern} from './BaseTheme.mjs';
|
||||
|
||||
const FONT = 'sans-serif';
|
||||
const LINE_HEIGHT = 1.3;
|
|
@ -1,6 +1,6 @@
|
|||
import {dom, textSizerFactory} from '../../stubs/TestDOM.js';
|
||||
import {Factory} from './Chunky.js';
|
||||
import SVG from '../../svg/SVG.js';
|
||||
import {dom, textSizerFactory} from '../../../spec/stubs/TestDOM.mjs';
|
||||
import {Factory} from './Chunky.mjs';
|
||||
import SVG from '../../svg/SVG.mjs';
|
||||
|
||||
describe('Chunky Theme', () => {
|
||||
const svg = new SVG(dom, textSizerFactory);
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import BaseTheme, {WavePattern} from './BaseTheme.js';
|
||||
import BaseTheme, {WavePattern} from './BaseTheme.mjs';
|
||||
|
||||
const FONT = 'monospace';
|
||||
const LINE_HEIGHT = 1.3;
|
|
@ -1,6 +1,6 @@
|
|||
import {dom, textSizerFactory} from '../../stubs/TestDOM.js';
|
||||
import {Factory} from './Monospace.js';
|
||||
import SVG from '../../svg/SVG.js';
|
||||
import {dom, textSizerFactory} from '../../../spec/stubs/TestDOM.mjs';
|
||||
import {Factory} from './Monospace.mjs';
|
||||
import SVG from '../../svg/SVG.mjs';
|
||||
|
||||
describe('Monospace Theme', () => {
|
||||
const svg = new SVG(dom, textSizerFactory);
|
|
@ -1,9 +1,9 @@
|
|||
/* eslint-disable max-lines */
|
||||
/* eslint-disable sort-keys */ // Maybe later
|
||||
|
||||
import BaseTheme from './BaseTheme.js';
|
||||
import Handlee from './HandleeFontData.js';
|
||||
import Random from '../../core/Random.js';
|
||||
import BaseTheme from './BaseTheme.mjs';
|
||||
import Handlee from './HandleeFontData.mjs';
|
||||
import Random from '../../core/Random.mjs';
|
||||
|
||||
const FONT = Handlee.name;
|
||||
const FONT_FAMILY = '\'' + FONT + '\',cursive';
|
|
@ -1,6 +1,6 @@
|
|||
import {dom, textSizerFactory} from '../../stubs/TestDOM.js';
|
||||
import {Factory} from './Sketch.js';
|
||||
import SVG from '../../svg/SVG.js';
|
||||
import {dom, textSizerFactory} from '../../../spec/stubs/TestDOM.mjs';
|
||||
import {Factory} from './Sketch.mjs';
|
||||
import SVG from '../../svg/SVG.mjs';
|
||||
|
||||
describe('Sketch Theme', () => {
|
||||
const svg = new SVG(dom, textSizerFactory);
|
|
@ -1,37 +0,0 @@
|
|||
import './core/ArrayUtilities_spec.js';
|
||||
import './core/EventObject_spec.js';
|
||||
import './core/Random_spec.js';
|
||||
import './core/documents/VirtualDocument_spec.js';
|
||||
import './svg/SVG_spec.js';
|
||||
import './svg/SVGTextBlock_spec.js';
|
||||
import './svg/PatternedLine_spec.js';
|
||||
import './interface/Interface_spec.js';
|
||||
import './interface/ComponentsLibrary_spec.js';
|
||||
import './image/ImageRegion_spec.js';
|
||||
import './image/Blur_spec.js';
|
||||
import './image/Composition_spec.js';
|
||||
import './image/ImageSimilarity_spec.js';
|
||||
import './sequence/SequenceDiagram_spec.js';
|
||||
import './sequence/SequenceDiagram_visual_spec.js';
|
||||
import './sequence/Readme_spec.js';
|
||||
import './sequence/Tokeniser_spec.js';
|
||||
import './sequence/Parser_spec.js';
|
||||
import './sequence/MarkdownParser_spec.js';
|
||||
import './sequence/LabelPatternParser_spec.js';
|
||||
import './sequence/Generator_spec.js';
|
||||
import './sequence/Renderer_spec.js';
|
||||
import './sequence/CodeMirrorMode_spec.js';
|
||||
import './sequence/themes/Basic_spec.js';
|
||||
import './sequence/themes/Monospace_spec.js';
|
||||
import './sequence/themes/Chunky_spec.js';
|
||||
import './sequence/themes/Sketch_spec.js';
|
||||
import './sequence/components/AgentCap_spec.js';
|
||||
import './sequence/components/AgentHighlight_spec.js';
|
||||
import './sequence/components/Block_spec.js';
|
||||
import './sequence/components/Connect_spec.js';
|
||||
import './sequence/components/Divider_spec.js';
|
||||
import './sequence/components/Marker_spec.js';
|
||||
import './sequence/components/Note_spec.js';
|
||||
import './sequence/components/Parallel_spec.js';
|
||||
|
||||
jasmine.executeAllTests();
|
|
@ -1,4 +1,4 @@
|
|||
import SequenceDiagram from './sequence/SequenceDiagram.js';
|
||||
import SequenceDiagram from './sequence/SequenceDiagram.mjs';
|
||||
|
||||
const def = window.define;
|
||||
if(def && def.amd) {
|
|
@ -1,4 +1,4 @@
|
|||
import PatternedLine from './PatternedLine.js';
|
||||
import PatternedLine from './PatternedLine.mjs';
|
||||
|
||||
describe('PatternedLine', () => {
|
||||
function simplify(path, dp) {
|
|
@ -1,5 +1,5 @@
|
|||
import {SVGTextBlock, TextSizer} from './SVGTextBlock.js';
|
||||
import PatternedLine from './PatternedLine.js';
|
||||
import {SVGTextBlock, TextSizer} from './SVGTextBlock.mjs';
|
||||
import PatternedLine from './PatternedLine.mjs';
|
||||
|
||||
const NS = 'http://www.w3.org/2000/svg';
|
||||
|
||||
|
@ -214,16 +214,16 @@ export default class SVG {
|
|||
return this.dom.el(tag, namespace);
|
||||
}
|
||||
|
||||
box(attrs, position) {
|
||||
return this.el('rect').attrs(attrs).attrs(position);
|
||||
box(attrs, {height, width, x, y}) {
|
||||
return this.el('rect').attrs(attrs).attrs({height, width, x, y});
|
||||
}
|
||||
|
||||
boxFactory(attrs) {
|
||||
return this.box.bind(this, attrs);
|
||||
}
|
||||
|
||||
line(attrs, position) {
|
||||
return this.el('line').attrs(attrs).attrs(position);
|
||||
line(attrs, {x1, x2, y1, y2}) {
|
||||
return this.el('line').attrs(attrs).attrs({x1, x2, y1, y2});
|
||||
}
|
||||
|
||||
lineFactory(attrs) {
|
||||
|
@ -259,11 +259,11 @@ export default class SVG {
|
|||
return this.cross.bind(this, attrs);
|
||||
}
|
||||
|
||||
note(attrs, flickAttrs, position) {
|
||||
const x0 = position.x;
|
||||
const x1 = position.x + position.width;
|
||||
const y0 = position.y;
|
||||
const y1 = position.y + position.height;
|
||||
note(attrs, flickAttrs, {height, width, x, y}) {
|
||||
const x0 = x;
|
||||
const x1 = x + width;
|
||||
const y0 = y;
|
||||
const y1 = y + height;
|
||||
const flick = 7;
|
||||
|
||||
return this.el('g').add(
|
||||
|
@ -290,13 +290,13 @@ export default class SVG {
|
|||
return this.note.bind(this, attrs, flickAttrs);
|
||||
}
|
||||
|
||||
formattedText(attrs = {}, formatted = [], position = {}) {
|
||||
formattedText(attrs = {}, formatted = [], {x, y} = {}) {
|
||||
const container = this.el('g');
|
||||
const txt = new SVGTextBlock(container, this, {
|
||||
attrs,
|
||||
formatted,
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
x,
|
||||
y,
|
||||
});
|
||||
return Object.assign(container, {
|
||||
set: (state) => txt.set(state),
|
|
@ -1,5 +1,4 @@
|
|||
// Thanks, https://stackoverflow.com/a/9851769/1180785
|
||||
const firefox = (typeof window.InstallTrigger !== 'undefined');
|
||||
import {firefox} from '../core/browser.mjs';
|
||||
|
||||
function merge(state, newState) {
|
||||
for(const k in state) {
|
|
@ -1,6 +1,7 @@
|
|||
import {DOMWrapper, dom, textSizerFactory} from '../stubs/TestDOM.js';
|
||||
import {SVGTextBlock, TextSizer} from './SVGTextBlock.js';
|
||||
import SVG from './SVG.js';
|
||||
import {DOMWrapper, dom, textSizerFactory} from '../../spec/stubs/TestDOM.mjs';
|
||||
import {SVGTextBlock, TextSizer} from './SVGTextBlock.mjs';
|
||||
import SVG from './SVG.mjs';
|
||||
import {nodejs} from '../core/browser.mjs';
|
||||
|
||||
describe('SVGTextBlock', () => {
|
||||
const attrs = {'font-size': 10, 'line-height': 1.5};
|
||||
|
@ -128,6 +129,11 @@ describe('SVGTextBlock', () => {
|
|||
});
|
||||
|
||||
describe('TextSizer', () => {
|
||||
if(nodejs) {
|
||||
// TextSizer is for browsers only
|
||||
return;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
svg = new SVG(
|
||||
new DOMWrapper(window.document),
|
|
@ -1,5 +1,5 @@
|
|||
import {dom, textSizerFactory} from '../stubs/TestDOM.js';
|
||||
import SVG from './SVG.js';
|
||||
import {dom, textSizerFactory} from '../../spec/stubs/TestDOM.mjs';
|
||||
import SVG from './SVG.mjs';
|
||||
|
||||
describe('SVG', () => {
|
||||
const expectedNS = 'http://www.w3.org/2000/svg';
|
|
@ -0,0 +1,23 @@
|
|||
beforeAll(() => {
|
||||
jasmine.addMatchers({
|
||||
toBeNear: () => ({
|
||||
compare: (actual, expected, range) => {
|
||||
if(
|
||||
typeof expected !== 'number' ||
|
||||
typeof range !== 'number' ||
|
||||
range < 0
|
||||
) {
|
||||
throw new Error(
|
||||
'Invalid toBeNear(' + expected + ',' + range + ')'
|
||||
);
|
||||
}
|
||||
if(typeof actual !== 'number') {
|
||||
throw new Error('Expected a number, got ' + actual);
|
||||
}
|
||||
return {
|
||||
pass: Math.abs(actual - expected) <= range,
|
||||
};
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 992 B After Width: | Height: | Size: 992 B |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 27 KiB |