Browse Source

Handle default svg properly in component image when reloading from storage (#4373)

* [FIX] handle default svg properly in ComponentImage

* edded tests

* remove relative src reference in test

* single qoute
pull/4378/head
Singwai Chan 4 years ago
committed by GitHub
parent
commit
5274e65528
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      package.json
  2. 13
      src/dom_components/model/ComponentImage.js
  3. 7
      src/utils/mixins.ts
  4. 37
      test/specs/dom_components/model/ComponentImage.js
  5. 2
      test/specs/navigator/view/ItemView.js
  6. 29
      test/specs/utils/Mixins.ts
  7. 2
      test/specs/utils/Sorter.js
  8. 57
      yarn.lock

10
package.json

@ -27,6 +27,7 @@
"@babel/cli": "^7.15.7",
"@babel/preset-typescript": "^7.16.7",
"@types/backbone": "^1.4.15",
"@types/jest": "^28.1.1",
"@typescript-eslint/parser": "^5.22.0",
"@vuepress/plugin-google-analytics": "^1.8.2",
"documentation": "^13.2.5",
@ -76,12 +77,17 @@
]
},
"jest": {
"moduleFileExtensions": [
"js",
"ts"
],
"verbose": true,
"testURL": "http://localhost/",
"modulePaths": [
"./src"
"<rootDir>/src"
],
"testMatch": [
"<rootDir>/test/specs/**/*.js"
"<rootDir>/test/specs/**/*.(t|j)s"
],
"setupFiles": [
"<rootDir>/test/setup.js"

13
src/dom_components/model/ComponentImage.js

@ -1,6 +1,6 @@
import { result } from 'underscore';
import Component from './Component';
import { toLowerCase } from 'utils/mixins';
import { toLowerCase, buildBase64UrlFromSvg } from 'utils/mixins';
const svgAttrs =
'xmlns="http://www.w3.org/2000/svg" width="100" viewBox="0 0 24 24" style="fill: rgba(0,0,0,0.15); transform: scale(0.75)"';
@ -35,7 +35,9 @@ export default Component.extend(
initialize(o, opt) {
Component.prototype.initialize.apply(this, arguments);
const { src } = this.get('attributes');
if (src) this.set('src', src, { silent: 1 });
if (src && buildBase64UrlFromSvg(this.defaults.src) !== src) {
this.set('src', src, { silent: 1 });
}
},
initToolbar(...args) {
@ -86,14 +88,17 @@ export default Component.extend(
let result = src;
if (src && src.substr(0, 4) === '<svg') {
result = `data:image/svg+xml;base64,${window.btoa(src)}`;
result = buildBase64UrlFromSvg(src);
}
return result;
},
isDefaultSrc() {
return this.get('src') === result(this, 'defaults').src;
return (
this.get('src') === result(this, 'defaults').src ||
this.get('src') === buildBase64UrlFromSvg(result(this, 'defaults').src)
);
},
/**

7
src/utils/mixins.ts

@ -280,6 +280,13 @@ const createId = (length = 16) => {
return result;
};
export const buildBase64UrlFromSvg = (svg: string) => {
if (svg && svg.substr(0, 4) === '<svg') {
return `data:image/svg+xml;base64,${window.btoa(svg)}`;
}
return svg
};
export {
on,
off,

37
test/specs/dom_components/model/ComponentImage.js

@ -1,11 +1,42 @@
import Component from 'dom_components/model/Component';
import ComponentImage from 'dom_components/model/ComponentImage';
import Editor from 'editor/model/Editor';
import Backbone from 'backbone';
import { buildBase64UrlFromSvg } from 'utils/mixins';
const $ = Backbone.$;
describe('ComponentImage', () => {
let componentImage;
let dcomp;
let compOpts;
let em;
beforeEach(() => {
componentImage = new ComponentImage();
em = new Editor({ avoidDefaults: true });
dcomp = em.get('DomComponents');
em.get('PageManager').onLoad();
compOpts = {
em,
componentTypes: dcomp.componentTypes,
domc: dcomp,
};
componentImage = new ComponentImage({}, compOpts);
});
describe('.initialize', () => {
test('when a base 64 default image is provided, it uses the default image', () => {
let imageUrl = buildBase64UrlFromSvg(ComponentImage.getDefaults().src);
let componentImage = new ComponentImage({ attributes: { src: imageUrl } }, { ...compOpts });
expect(componentImage.get('src')).toEqual(ComponentImage.getDefaults().src);
expect(componentImage.isDefaultSrc()).toBeTruthy();
});
test('when a image url is provided, it uses the image url', () => {
let imageUrl = 'https://mock.com/image.png';
let componentImage = new ComponentImage({ attributes: { src: imageUrl } }, { ...compOpts });
expect(componentImage.get('src')).toEqual(imageUrl);
expect(componentImage.isDefaultSrc()).toBeFalsy();
});
});
test('`src` property is defined after initializing', () => {
@ -17,9 +48,7 @@ describe('ComponentImage', () => {
const fakeAttributes = {};
beforeEach(() => {
spyOn(Component.prototype, 'getAttrToHTML').and.returnValue(
fakeAttributes
);
spyOn(Component.prototype, 'getAttrToHTML').and.returnValue(fakeAttributes);
getSrcResultSpy = spyOn(componentImage, 'getSrcResult');
});

2
test/specs/navigator/view/ItemView.js

@ -1,6 +1,6 @@
import ItemView from 'navigator/view/ItemView';
import config from 'navigator/config/config';
import EditorModel from '../../../../src/editor/model/Editor';
import EditorModel from 'editor/model/Editor';
describe('ItemView', () => {
let itemView, fakeModel, fakeModelStyle;

29
test/specs/utils/Mixins.ts

@ -0,0 +1,29 @@
import { buildBase64UrlFromSvg } from 'utils/mixins';
describe('.buildBase64UrlFromSvg', () => {
it('returns original when a none svg is provided', () => {
const input = 'something else';
expect(buildBase64UrlFromSvg(input)).toEqual(input)
})
it('returns base64 image when an svg is provided', () => {
const input = `<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6" />
<line x1="8" y1="2" x2="8" y2="18" />
<line x1="16" y1="6" x2="16" y2="22" />
</svg>`;
const output = 'data:image/svg+xml;base64,PHN2ZwogICAgICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgICAgIHdpZHRoPSIyNCIKICAgICAgaGVpZ2h0PSIyNCIKICAgICAgdmlld0JveD0iMCAwIDI0IDI0IgogICAgICBmaWxsPSJub25lIgogICAgICBzdHJva2U9ImN1cnJlbnRDb2xvciIKICAgICAgc3Ryb2tlLXdpZHRoPSIyIgogICAgICBzdHJva2UtbGluZWNhcD0icm91bmQiCiAgICAgIHN0cm9rZS1saW5lam9pbj0icm91bmQiCiAgICA+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iMSA2IDEgMjIgOCAxOCAxNiAyMiAyMyAxOCAyMyAyIDE2IDYgOCAyIDEgNiIgLz4KICAgICAgPGxpbmUgeDE9IjgiIHkxPSIyIiB4Mj0iOCIgeTI9IjE4IiAvPgogICAgICA8bGluZSB4MT0iMTYiIHkxPSI2IiB4Mj0iMTYiIHkyPSIyMiIgLz4KICAgIDwvc3ZnPg=='
expect(buildBase64UrlFromSvg(input)).toEqual(output)
})
});

2
test/specs/utils/Sorter.js

@ -1,5 +1,5 @@
import Backbone from 'backbone';
import Sorter from '../../../src/utils/Sorter.js';
import Sorter from 'utils/Sorter';
import ComponentTextView from 'dom_components/view/ComponentTextView';
import Component from 'dom_components/model/Component';
const $ = Backbone.$;

57
yarn.lock

@ -1283,6 +1283,14 @@
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
"@types/jest@^28.1.1":
version "28.1.1"
resolved "https://registry.npmjs.org/@types/jest/-/jest-28.1.1.tgz#8c9ba63702a11f8c386ee211280e8b68cb093cd1"
integrity sha512-C2p7yqleUKtCkVjlOur9BWVA4HgUQmEj/HWCt5WzZ5mLXrWnyIfl0wGuArc+kBXsy0ZZfLp+7dywB4HtSVYGVA==
dependencies:
jest-matcher-utils "^27.0.0"
pretty-format "^27.0.0"
"@types/jquery@*":
version "3.5.14"
resolved "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz"
@ -2191,6 +2199,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
ansi-styles@^5.0.0:
version "5.2.0"
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
any-observable@^0.3.0:
version "0.3.0"
resolved "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz"
@ -4089,6 +4102,11 @@ diff-sequences@^24.9.0:
version "24.9.0"
resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz"
diff-sequences@^27.5.1:
version "27.5.1"
resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
diff@^3.5.0:
version "3.5.0"
resolved "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz"
@ -6535,6 +6553,16 @@ jest-diff@^24.9.0:
jest-get-type "^24.9.0"
pretty-format "^24.9.0"
jest-diff@^27.5.1:
version "27.5.1"
resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def"
integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==
dependencies:
chalk "^4.0.0"
diff-sequences "^27.5.1"
jest-get-type "^27.5.1"
pretty-format "^27.5.1"
jest-docblock@^24.3.0:
version "24.9.0"
resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz"
@ -6576,6 +6604,11 @@ jest-get-type@^24.9.0:
version "24.9.0"
resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz"
jest-get-type@^27.5.1:
version "27.5.1"
resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==
jest-haste-map@^24.9.0:
version "24.9.0"
resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz"
@ -6631,6 +6664,16 @@ jest-matcher-utils@^24.9.0:
jest-get-type "^24.9.0"
pretty-format "^24.9.0"
jest-matcher-utils@^27.0.0:
version "27.5.1"
resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
dependencies:
chalk "^4.0.0"
jest-diff "^27.5.1"
jest-get-type "^27.5.1"
pretty-format "^27.5.1"
jest-message-util@^24.9.0:
version "24.9.0"
resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz"
@ -9119,6 +9162,15 @@ pretty-format@^24.9.0:
ansi-styles "^3.2.0"
react-is "^16.8.4"
pretty-format@^27.0.0, pretty-format@^27.5.1:
version "27.5.1"
resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
dependencies:
ansi-regex "^5.0.1"
ansi-styles "^5.0.0"
react-is "^17.0.1"
pretty-time@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz"
@ -9340,6 +9392,11 @@ react-is@^16.8.4:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
react-is@^17.0.1:
version "17.0.2"
resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
read-pkg-up@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz"

Loading…
Cancel
Save