unvendor: Replace SVGInject

8b8f2f1144bf3b27e15306d65368fc3cde9bace7

Cohee <18619528+Cohee1207@users.noreply.github.com>

8 files changed, +17 -701Ignore whitespace
.eslintrc.cjs+0 -1
@@ -55,7 +55,6 @@ module.exports = {
5555 Popper: 'readonly',
5656 showdown: 'readonly',
5757 showdownKatex: 'readonly',
58- SVGInject: 'readonly',
5958 toastr: 'readonly',
6059 isProbablyReaderable: 'readonly',
6160 SillyTavern: 'readonly',
package-lock.json+7 -0
@@ -13,6 +13,7 @@
1313 "@adobe/css-tools": "^4.4.0",
1414 "@agnai/sentencepiece-js": "^1.1.1",
1515 "@agnai/web-tokenizers": "^0.1.3",
16+ "@iconfu/svg-inject": "^1.2.3",
1617 "@mozilla/readability": "^0.5.0",
1718 "@zeldafan0225/ai_horde": "^5.1.0",
1819 "archiver": "^7.0.1",
@@ -287,6 +288,12 @@
287288 "dev": true,
288289 "license": "BSD-3-Clause"
289290 },
291+ "node_modules/@iconfu/svg-inject": {
292+ "version": "1.2.3",
293+ "resolved": "https://registry.npmjs.org/@iconfu/svg-inject/-/svg-inject-1.2.3.tgz",
294+ "integrity": "sha512-3v1MUAJqmJS4jmhHoCkSxt+EdJrjPHlLXrWocCT25kCxnxJto8028Z6CC406EL11KA53SDZgI/QQA5GEJAoiRw==",
295+ "license": "MIT"
296+ },
290297 "node_modules/@isaacs/cliui": {
291298 "version": "8.0.2",
292299 "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
package.json+1 -0
@@ -3,6 +3,7 @@
33 "@adobe/css-tools": "^4.4.0",
44 "@agnai/sentencepiece-js": "^1.1.1",
55 "@agnai/web-tokenizers": "^0.1.3",
6+ "@iconfu/svg-inject": "^1.2.3",
67 "@mozilla/readability": "^0.5.0",
78 "@zeldafan0225/ai_horde": "^5.1.0",
89 "archiver": "^7.0.1",
public/global.d.ts+0 -1
@@ -3,7 +3,6 @@ declare var droll;
33declare var Popper;
44declare var showdown;
55declare var showdownKatex;
6-declare var SVGInject;
76declare var ai;
87
98declare var SillyTavern: {
public/index.html+0 -1
@@ -6759,7 +6759,6 @@
67596759 <script src="lib/droll.js"></script>
67606760 <script src="lib/pagination.js"></script>
67616761 <script src="lib/toolcool-color-picker.js"></script>
6762- <script src="lib/svg-inject.js"></script>
67636762 <script src="lib/jquery.izoomify.js"></script>
67646763 <script type="module" src="lib/structured-clone/monkey-patch.js"></script>
67656764 <script type="module" src="lib/swiped-events.js"></script>
public/lib.js+7 -0
@@ -14,6 +14,7 @@ import ePub from 'epubjs';
1414import * as pdfjsLib from 'pdfjs-dist/webpack.mjs';
1515import DiffMatchPatch from 'diff-match-patch';
1616import { isProbablyReaderable, Readability } from '@mozilla/readability';
17+import SVGInject from '@iconfu/svg-inject';
1718
1819/**
1920 * Expose the libraries to the 'window' object.
@@ -48,6 +49,10 @@ export function initLibraryShims() {
4849 // @ts-ignore
4950 window.diff_match_patch = DiffMatchPatch;
5051 }
52+ if (!('SVGInject' in window)) {
53+ // @ts-ignore
54+ window.SVGInject = SVGInject;
55+ }
5156}
5257
5358export default {
@@ -64,6 +69,7 @@ export default {
6469 DiffMatchPatch,
6570 Readability,
6671 isProbablyReaderable,
72+ SVGInject,
6773};
6874
6975export {
@@ -80,4 +86,5 @@ export {
8086 DiffMatchPatch,
8187 Readability,
8288 isProbablyReaderable,
89+ SVGInject,
8390};
public/lib/svg-inject.js+0 -697
@@ -1,697 +0,0 @@
1-/**
2- * SVGInject - Version 1.2.3
3- * A tiny, intuitive, robust, caching solution for injecting SVG files inline into the DOM.
4- *
5- * https://github.com/iconfu/svg-inject
6- *
7- * Copyright (c) 2018 INCORS, the creators of iconfu.com
8- * @license MIT License - https://github.com/iconfu/svg-inject/blob/master/LICENSE
9- */
10-
11-(function(window, document) {
12- // constants for better minification
13- var _CREATE_ELEMENT_ = 'createElement';
14- var _GET_ELEMENTS_BY_TAG_NAME_ = 'getElementsByTagName';
15- var _LENGTH_ = 'length';
16- var _STYLE_ = 'style';
17- var _TITLE_ = 'title';
18- var _UNDEFINED_ = 'undefined';
19- var _SET_ATTRIBUTE_ = 'setAttribute';
20- var _GET_ATTRIBUTE_ = 'getAttribute';
21-
22- var NULL = null;
23-
24- // constants
25- var __SVGINJECT = '__svgInject';
26- var ID_SUFFIX = '--inject-';
27- var ID_SUFFIX_REGEX = new RegExp(ID_SUFFIX + '\\d+', "g");
28- var LOAD_FAIL = 'LOAD_FAIL';
29- var SVG_NOT_SUPPORTED = 'SVG_NOT_SUPPORTED';
30- var SVG_INVALID = 'SVG_INVALID';
31- var ATTRIBUTE_EXCLUSION_NAMES = ['src', 'alt', 'onload', 'onerror'];
32- var A_ELEMENT = document[_CREATE_ELEMENT_]('a');
33- var IS_SVG_SUPPORTED = typeof SVGRect != _UNDEFINED_;
34- var DEFAULT_OPTIONS = {
35- useCache: true,
36- copyAttributes: true,
37- makeIdsUnique: true
38- };
39- // Map of IRI referenceable tag names to properties that can reference them. This is defined in
40- // https://www.w3.org/TR/SVG11/linking.html#processingIRI
41- var IRI_TAG_PROPERTIES_MAP = {
42- clipPath: ['clip-path'],
43- 'color-profile': NULL,
44- cursor: NULL,
45- filter: NULL,
46- linearGradient: ['fill', 'stroke'],
47- marker: ['marker', 'marker-end', 'marker-mid', 'marker-start'],
48- mask: NULL,
49- pattern: ['fill', 'stroke'],
50- radialGradient: ['fill', 'stroke']
51- };
52- var INJECTED = 1;
53- var FAIL = 2;
54-
55- var uniqueIdCounter = 1;
56- var xmlSerializer;
57- var domParser;
58-
59-
60- // creates an SVG document from an SVG string
61- function svgStringToSvgDoc(svgStr) {
62- domParser = domParser || new DOMParser();
63- return domParser.parseFromString(svgStr, 'text/xml');
64- }
65-
66-
67- // searializes an SVG element to an SVG string
68- function svgElemToSvgString(svgElement) {
69- xmlSerializer = xmlSerializer || new XMLSerializer();
70- return xmlSerializer.serializeToString(svgElement);
71- }
72-
73-
74- // Returns the absolute url for the specified url
75- function getAbsoluteUrl(url) {
76- A_ELEMENT.href = url;
77- return A_ELEMENT.href;
78- }
79-
80-
81- // Load svg with an XHR request
82- function loadSvg(url, callback, errorCallback) {
83- if (url) {
84- var req = new XMLHttpRequest();
85- req.onreadystatechange = function() {
86- if (req.readyState == 4) {
87- // readyState is DONE
88- var status = req.status;
89- if (status == 200) {
90- // request status is OK
91- callback(req.responseXML, req.responseText.trim());
92- } else if (status >= 400) {
93- // request status is error (4xx or 5xx)
94- errorCallback();
95- } else if (status == 0) {
96- // request status 0 can indicate a failed cross-domain call
97- errorCallback();
98- }
99- }
100- };
101- req.open('GET', url, true);
102- req.send();
103- }
104- }
105-
106-
107- // Copy attributes from img element to svg element
108- function copyAttributes(imgElem, svgElem) {
109- var attribute;
110- var attributeName;
111- var attributeValue;
112- var attributes = imgElem.attributes;
113- for (var i = 0; i < attributes[_LENGTH_]; i++) {
114- attribute = attributes[i];
115- attributeName = attribute.name;
116- // Only copy attributes not explicitly excluded from copying
117- if (ATTRIBUTE_EXCLUSION_NAMES.indexOf(attributeName) == -1) {
118- attributeValue = attribute.value;
119- // If img attribute is "title", insert a title element into SVG element
120- if (attributeName == _TITLE_) {
121- var titleElem;
122- var firstElementChild = svgElem.firstElementChild;
123- if (firstElementChild && firstElementChild.localName.toLowerCase() == _TITLE_) {
124- // If the SVG element's first child is a title element, keep it as the title element
125- titleElem = firstElementChild;
126- } else {
127- // If the SVG element's first child element is not a title element, create a new title
128- // ele,emt and set it as the first child
129- titleElem = document[_CREATE_ELEMENT_ + 'NS']('http://www.w3.org/2000/svg', _TITLE_);
130- svgElem.insertBefore(titleElem, firstElementChild);
131- }
132- // Set new title content
133- titleElem.textContent = attributeValue;
134- } else {
135- // Set img attribute to svg element
136- svgElem[_SET_ATTRIBUTE_](attributeName, attributeValue);
137- }
138- }
139- }
140- }
141-
142-
143- // This function appends a suffix to IDs of referenced elements in the <defs> in order to to avoid ID collision
144- // between multiple injected SVGs. The suffix has the form "--inject-X", where X is a running number which is
145- // incremented with each injection. References to the IDs are adjusted accordingly.
146- // We assume tha all IDs within the injected SVG are unique, therefore the same suffix can be used for all IDs of one
147- // injected SVG.
148- // If the onlyReferenced argument is set to true, only those IDs will be made unique that are referenced from within the SVG
149- function makeIdsUnique(svgElem, onlyReferenced) {
150- var idSuffix = ID_SUFFIX + uniqueIdCounter++;
151- // Regular expression for functional notations of an IRI references. This will find occurences in the form
152- // url(#anyId) or url("#anyId") (for Internet Explorer) and capture the referenced ID
153- var funcIriRegex = /url\("?#([a-zA-Z][\w:.-]*)"?\)/g;
154- // Get all elements with an ID. The SVG spec recommends to put referenced elements inside <defs> elements, but
155- // this is not a requirement, therefore we have to search for IDs in the whole SVG.
156- var idElements = svgElem.querySelectorAll('[id]');
157- var idElem;
158- // An object containing referenced IDs as keys is used if only referenced IDs should be uniquified.
159- // If this object does not exist, all IDs will be uniquified.
160- var referencedIds = onlyReferenced ? [] : NULL;
161- var tagName;
162- var iriTagNames = {};
163- var iriProperties = [];
164- var changed = false;
165- var i, j;
166-
167- if (idElements[_LENGTH_]) {
168- // Make all IDs unique by adding the ID suffix and collect all encountered tag names
169- // that are IRI referenceable from properities.
170- for (i = 0; i < idElements[_LENGTH_]; i++) {
171- tagName = idElements[i].localName; // Use non-namespaced tag name
172- // Make ID unique if tag name is IRI referenceable
173- if (tagName in IRI_TAG_PROPERTIES_MAP) {
174- iriTagNames[tagName] = 1;
175- }
176- }
177- // Get all properties that are mapped to the found IRI referenceable tags
178- for (tagName in iriTagNames) {
179- (IRI_TAG_PROPERTIES_MAP[tagName] || [tagName]).forEach(function (mappedProperty) {
180- // Add mapped properties to array of iri referencing properties.
181- // Use linear search here because the number of possible entries is very small (maximum 11)
182- if (iriProperties.indexOf(mappedProperty) < 0) {
183- iriProperties.push(mappedProperty);
184- }
185- });
186- }
187- if (iriProperties[_LENGTH_]) {
188- // Add "style" to properties, because it may contain references in the form 'style="fill:url(#myFill)"'
189- iriProperties.push(_STYLE_);
190- }
191- // Run through all elements of the SVG and replace IDs in references.
192- // To get all descending elements, getElementsByTagName('*') seems to perform faster than querySelectorAll('*').
193- // Since svgElem.getElementsByTagName('*') does not return the svg element itself, we have to handle it separately.
194- var descElements = svgElem[_GET_ELEMENTS_BY_TAG_NAME_]('*');
195- var element = svgElem;
196- var propertyName;
197- var value;
198- var newValue;
199- for (i = -1; element != NULL;) {
200- if (element.localName == _STYLE_) {
201- // If element is a style element, replace IDs in all occurences of "url(#anyId)" in text content
202- value = element.textContent;
203- newValue = value && value.replace(funcIriRegex, function(match, id) {
204- if (referencedIds) {
205- referencedIds[id] = 1;
206- }
207- return 'url(#' + id + idSuffix + ')';
208- });
209- if (newValue !== value) {
210- element.textContent = newValue;
211- }
212- } else if (element.hasAttributes()) {
213- // Run through all property names for which IDs were found
214- for (j = 0; j < iriProperties[_LENGTH_]; j++) {
215- propertyName = iriProperties[j];
216- value = element[_GET_ATTRIBUTE_](propertyName);
217- newValue = value && value.replace(funcIriRegex, function(match, id) {
218- if (referencedIds) {
219- referencedIds[id] = 1;
220- }
221- return 'url(#' + id + idSuffix + ')';
222- });
223- if (newValue !== value) {
224- element[_SET_ATTRIBUTE_](propertyName, newValue);
225- }
226- }
227- // Replace IDs in xlink:ref and href attributes
228- ['xlink:href', 'href'].forEach(function(refAttrName) {
229- var iri = element[_GET_ATTRIBUTE_](refAttrName);
230- if (/^\s*#/.test(iri)) { // Check if iri is non-null and internal reference
231- iri = iri.trim();
232- element[_SET_ATTRIBUTE_](refAttrName, iri + idSuffix);
233- if (referencedIds) {
234- // Add ID to referenced IDs
235- referencedIds[iri.substring(1)] = 1;
236- }
237- }
238- });
239- }
240- element = descElements[++i];
241- }
242- for (i = 0; i < idElements[_LENGTH_]; i++) {
243- idElem = idElements[i];
244- // If set of referenced IDs exists, make only referenced IDs unique,
245- // otherwise make all IDs unique.
246- if (!referencedIds || referencedIds[idElem.id]) {
247- // Add suffix to element's ID
248- idElem.id += idSuffix;
249- changed = true;
250- }
251- }
252- }
253- // return true if SVG element has changed
254- return changed;
255- }
256-
257-
258- // For cached SVGs the IDs are made unique by simply replacing the already inserted unique IDs with a
259- // higher ID counter. This is much more performant than a call to makeIdsUnique().
260- function makeIdsUniqueCached(svgString) {
261- return svgString.replace(ID_SUFFIX_REGEX, ID_SUFFIX + uniqueIdCounter++);
262- }
263-
264-
265- // Inject SVG by replacing the img element with the SVG element in the DOM
266- function inject(imgElem, svgElem, absUrl, options) {
267- if (svgElem) {
268- svgElem[_SET_ATTRIBUTE_]('data-inject-url', absUrl);
269- var parentNode = imgElem.parentNode;
270- if (parentNode) {
271- if (options.copyAttributes) {
272- copyAttributes(imgElem, svgElem);
273- }
274- // Invoke beforeInject hook if set
275- var beforeInject = options.beforeInject;
276- var injectElem = (beforeInject && beforeInject(imgElem, svgElem)) || svgElem;
277- // Replace img element with new element. This is the actual injection.
278- parentNode.replaceChild(injectElem, imgElem);
279- // Mark img element as injected
280- imgElem[__SVGINJECT] = INJECTED;
281- removeOnLoadAttribute(imgElem);
282- // Invoke afterInject hook if set
283- var afterInject = options.afterInject;
284- if (afterInject) {
285- afterInject(imgElem, injectElem);
286- }
287- }
288- } else {
289- svgInvalid(imgElem, options);
290- }
291- }
292-
293-
294- // Merges any number of options objects into a new object
295- function mergeOptions() {
296- var mergedOptions = {};
297- var args = arguments;
298- // Iterate over all specified options objects and add all properties to the new options object
299- for (var i = 0; i < args[_LENGTH_]; i++) {
300- var argument = args[i];
301- for (var key in argument) {
302- if (argument.hasOwnProperty(key)) {
303- mergedOptions[key] = argument[key];
304- }
305- }
306- }
307- return mergedOptions;
308- }
309-
310-
311- // Adds the specified CSS to the document's <head> element
312- function addStyleToHead(css) {
313- var head = document[_GET_ELEMENTS_BY_TAG_NAME_]('head')[0];
314- if (head) {
315- var style = document[_CREATE_ELEMENT_](_STYLE_);
316- style.type = 'text/css';
317- style.appendChild(document.createTextNode(css));
318- head.appendChild(style);
319- }
320- }
321-
322-
323- // Builds an SVG element from the specified SVG string
324- function buildSvgElement(svgStr, verify) {
325- if (verify) {
326- var svgDoc;
327- try {
328- // Parse the SVG string with DOMParser
329- svgDoc = svgStringToSvgDoc(svgStr);
330- } catch(e) {
331- return NULL;
332- }
333- if (svgDoc[_GET_ELEMENTS_BY_TAG_NAME_]('parsererror')[_LENGTH_]) {
334- // DOMParser does not throw an exception, but instead puts parsererror tags in the document
335- return NULL;
336- }
337- return svgDoc.documentElement;
338- } else {
339- var div = document.createElement('div');
340- div.innerHTML = svgStr;
341- return div.firstElementChild;
342- }
343- }
344-
345-
346- function removeOnLoadAttribute(imgElem) {
347- // Remove the onload attribute. Should only be used to remove the unstyled image flash protection and
348- // make the element visible, not for removing the event listener.
349- imgElem.removeAttribute('onload');
350- }
351-
352-
353- function errorMessage(msg) {
354- console.error('SVGInject: ' + msg);
355- }
356-
357-
358- function fail(imgElem, status, options) {
359- imgElem[__SVGINJECT] = FAIL;
360- if (options.onFail) {
361- options.onFail(imgElem, status);
362- } else {
363- errorMessage(status);
364- }
365- }
366-
367-
368- function svgInvalid(imgElem, options) {
369- removeOnLoadAttribute(imgElem);
370- fail(imgElem, SVG_INVALID, options);
371- }
372-
373-
374- function svgNotSupported(imgElem, options) {
375- removeOnLoadAttribute(imgElem);
376- fail(imgElem, SVG_NOT_SUPPORTED, options);
377- }
378-
379-
380- function loadFail(imgElem, options) {
381- fail(imgElem, LOAD_FAIL, options);
382- }
383-
384-
385- function removeEventListeners(imgElem) {
386- imgElem.onload = NULL;
387- imgElem.onerror = NULL;
388- }
389-
390-
391- function imgNotSet(msg) {
392- errorMessage('no img element');
393- }
394-
395-
396- function createSVGInject(globalName, options) {
397- var defaultOptions = mergeOptions(DEFAULT_OPTIONS, options);
398- var svgLoadCache = {};
399-
400- if (IS_SVG_SUPPORTED) {
401- // If the browser supports SVG, add a small stylesheet that hides the <img> elements until
402- // injection is finished. This avoids showing the unstyled SVGs before style is applied.
403- addStyleToHead('img[onload^="' + globalName + '("]{visibility:hidden;}');
404- }
405-
406-
407- /**
408- * SVGInject
409- *
410- * Injects the SVG specified in the `src` attribute of the specified `img` element or array of `img`
411- * elements. Returns a Promise object which resolves if all passed in `img` elements have either been
412- * injected or failed to inject (Only if a global Promise object is available like in all modern browsers
413- * or through a polyfill).
414- *
415- * Options:
416- * useCache: If set to `true` the SVG will be cached using the absolute URL. Default value is `true`.
417- * copyAttributes: If set to `true` the attributes will be copied from `img` to `svg`. Dfault value
418- * is `true`.
419- * makeIdsUnique: If set to `true` the ID of elements in the `<defs>` element that can be references by
420- * property values (for example 'clipPath') are made unique by appending "--inject-X", where X is a
421- * running number which increases with each injection. This is done to avoid duplicate IDs in the DOM.
422- * beforeLoad: Hook before SVG is loaded. The `img` element is passed as a parameter. If the hook returns
423- * a string it is used as the URL instead of the `img` element's `src` attribute.
424- * afterLoad: Hook after SVG is loaded. The loaded `svg` element and `svg` string are passed as a
425- * parameters. If caching is active this hook will only get called once for injected SVGs with the
426- * same absolute path. Changes to the `svg` element in this hook will be applied to all injected SVGs
427- * with the same absolute path. It's also possible to return an `svg` string or `svg` element which
428- * will then be used for the injection.
429- * beforeInject: Hook before SVG is injected. The `img` and `svg` elements are passed as parameters. If
430- * any html element is returned it gets injected instead of applying the default SVG injection.
431- * afterInject: Hook after SVG is injected. The `img` and `svg` elements are passed as parameters.
432- * onAllFinish: Hook after all `img` elements passed to an SVGInject() call have either been injected or
433- * failed to inject.
434- * onFail: Hook after injection fails. The `img` element and a `status` string are passed as an parameter.
435- * The `status` can be either `'SVG_NOT_SUPPORTED'` (the browser does not support SVG),
436- * `'SVG_INVALID'` (the SVG is not in a valid format) or `'LOAD_FAILED'` (loading of the SVG failed).
437- *
438- * @param {HTMLImageElement} img - an img element or an array of img elements
439- * @param {Object} [options] - optional parameter with [options](#options) for this injection.
440- */
441- function SVGInject(img, options) {
442- options = mergeOptions(defaultOptions, options);
443-
444- var run = function(resolve) {
445- var allFinish = function() {
446- var onAllFinish = options.onAllFinish;
447- if (onAllFinish) {
448- onAllFinish();
449- }
450- resolve && resolve();
451- };
452-
453- if (img && typeof img[_LENGTH_] != _UNDEFINED_) {
454- // an array like structure of img elements
455- var injectIndex = 0;
456- var injectCount = img[_LENGTH_];
457-
458- if (injectCount == 0) {
459- allFinish();
460- } else {
461- var finish = function() {
462- if (++injectIndex == injectCount) {
463- allFinish();
464- }
465- };
466-
467- for (var i = 0; i < injectCount; i++) {
468- SVGInjectElement(img[i], options, finish);
469- }
470- }
471- } else {
472- // only one img element
473- SVGInjectElement(img, options, allFinish);
474- }
475- };
476-
477- // return a Promise object if globally available
478- return typeof Promise == _UNDEFINED_ ? run() : new Promise(run);
479- }
480-
481-
482- // Injects a single svg element. Options must be already merged with the default options.
483- function SVGInjectElement(imgElem, options, callback) {
484- if (imgElem) {
485- var svgInjectAttributeValue = imgElem[__SVGINJECT];
486- if (!svgInjectAttributeValue) {
487- removeEventListeners(imgElem);
488-
489- if (!IS_SVG_SUPPORTED) {
490- svgNotSupported(imgElem, options);
491- callback();
492- return;
493- }
494- // Invoke beforeLoad hook if set. If the beforeLoad returns a value use it as the src for the load
495- // URL path. Else use the imgElem's src attribute value.
496- var beforeLoad = options.beforeLoad;
497- var src = (beforeLoad && beforeLoad(imgElem)) || imgElem[_GET_ATTRIBUTE_]('src');
498-
499- if (!src) {
500- // If no image src attribute is set do no injection. This can only be reached by using javascript
501- // because if no src attribute is set the onload and onerror events do not get called
502- if (src === '') {
503- loadFail(imgElem, options);
504- }
505- callback();
506- return;
507- }
508-
509- // set array so later calls can register callbacks
510- var onFinishCallbacks = [];
511- imgElem[__SVGINJECT] = onFinishCallbacks;
512-
513- var onFinish = function() {
514- callback();
515- onFinishCallbacks.forEach(function(onFinishCallback) {
516- onFinishCallback();
517- });
518- };
519-
520- var absUrl = getAbsoluteUrl(src);
521- var useCacheOption = options.useCache;
522- var makeIdsUniqueOption = options.makeIdsUnique;
523-
524- var setSvgLoadCacheValue = function(val) {
525- if (useCacheOption) {
526- svgLoadCache[absUrl].forEach(function(svgLoad) {
527- svgLoad(val);
528- });
529- svgLoadCache[absUrl] = val;
530- }
531- };
532-
533- if (useCacheOption) {
534- var svgLoad = svgLoadCache[absUrl];
535-
536- var handleLoadValue = function(loadValue) {
537- if (loadValue === LOAD_FAIL) {
538- loadFail(imgElem, options);
539- } else if (loadValue === SVG_INVALID) {
540- svgInvalid(imgElem, options);
541- } else {
542- var hasUniqueIds = loadValue[0];
543- var svgString = loadValue[1];
544- var uniqueIdsSvgString = loadValue[2];
545- var svgElem;
546-
547- if (makeIdsUniqueOption) {
548- if (hasUniqueIds === NULL) {
549- // IDs for the SVG string have not been made unique before. This may happen if previous
550- // injection of a cached SVG have been run with the option makedIdsUnique set to false
551- svgElem = buildSvgElement(svgString, false);
552- hasUniqueIds = makeIdsUnique(svgElem, false);
553-
554- loadValue[0] = hasUniqueIds;
555- loadValue[2] = hasUniqueIds && svgElemToSvgString(svgElem);
556- } else if (hasUniqueIds) {
557- // Make IDs unique for already cached SVGs with better performance
558- svgString = makeIdsUniqueCached(uniqueIdsSvgString);
559- }
560- }
561-
562- svgElem = svgElem || buildSvgElement(svgString, false);
563-
564- inject(imgElem, svgElem, absUrl, options);
565- }
566- onFinish();
567- };
568-
569- if (typeof svgLoad != _UNDEFINED_) {
570- // Value for url exists in cache
571- if (svgLoad.isCallbackQueue) {
572- // Same url has been cached, but value has not been loaded yet, so add to callbacks
573- svgLoad.push(handleLoadValue);
574- } else {
575- handleLoadValue(svgLoad);
576- }
577- return;
578- } else {
579- var svgLoad = [];
580- // set property isCallbackQueue to Array to differentiate from array with cached loaded values
581- svgLoad.isCallbackQueue = true;
582- svgLoadCache[absUrl] = svgLoad;
583- }
584- }
585-
586- // Load the SVG because it is not cached or caching is disabled
587- loadSvg(absUrl, function(svgXml, svgString) {
588- // Use the XML from the XHR request if it is an instance of Document. Otherwise
589- // (for example of IE9), create the svg document from the svg string.
590- var svgElem = svgXml instanceof Document ? svgXml.documentElement : buildSvgElement(svgString, true);
591-
592- var afterLoad = options.afterLoad;
593- if (afterLoad) {
594- // Invoke afterLoad hook which may modify the SVG element. After load may also return a new
595- // svg element or svg string
596- var svgElemOrSvgString = afterLoad(svgElem, svgString) || svgElem;
597- if (svgElemOrSvgString) {
598- // Update svgElem and svgString because of modifications to the SVG element or SVG string in
599- // the afterLoad hook, so the modified SVG is also used for all later cached injections
600- var isString = typeof svgElemOrSvgString == 'string';
601- svgString = isString ? svgElemOrSvgString : svgElemToSvgString(svgElem);
602- svgElem = isString ? buildSvgElement(svgElemOrSvgString, true) : svgElemOrSvgString;
603- }
604- }
605-
606- if (svgElem instanceof SVGElement) {
607- var hasUniqueIds = NULL;
608- if (makeIdsUniqueOption) {
609- hasUniqueIds = makeIdsUnique(svgElem, false);
610- }
611-
612- if (useCacheOption) {
613- var uniqueIdsSvgString = hasUniqueIds && svgElemToSvgString(svgElem);
614- // set an array with three entries to the load cache
615- setSvgLoadCacheValue([hasUniqueIds, svgString, uniqueIdsSvgString]);
616- }
617-
618- inject(imgElem, svgElem, absUrl, options);
619- } else {
620- svgInvalid(imgElem, options);
621- setSvgLoadCacheValue(SVG_INVALID);
622- }
623- onFinish();
624- }, function() {
625- loadFail(imgElem, options);
626- setSvgLoadCacheValue(LOAD_FAIL);
627- onFinish();
628- });
629- } else {
630- if (Array.isArray(svgInjectAttributeValue)) {
631- // svgInjectAttributeValue is an array. Injection is not complete so register callback
632- svgInjectAttributeValue.push(callback);
633- } else {
634- callback();
635- }
636- }
637- } else {
638- imgNotSet();
639- }
640- }
641-
642-
643- /**
644- * Sets the default [options](#options) for SVGInject.
645- *
646- * @param {Object} [options] - default [options](#options) for an injection.
647- */
648- SVGInject.setOptions = function(options) {
649- defaultOptions = mergeOptions(defaultOptions, options);
650- };
651-
652-
653- // Create a new instance of SVGInject
654- SVGInject.create = createSVGInject;
655-
656-
657- /**
658- * Used in onerror Event of an `<img>` element to handle cases when the loading the original src fails
659- * (for example if file is not found or if the browser does not support SVG). This triggers a call to the
660- * options onFail hook if available. The optional second parameter will be set as the new src attribute
661- * for the img element.
662- *
663- * @param {HTMLImageElement} img - an img element
664- * @param {String} [fallbackSrc] - optional parameter fallback src
665- */
666- SVGInject.err = function(img, fallbackSrc) {
667- if (img) {
668- if (img[__SVGINJECT] != FAIL) {
669- removeEventListeners(img);
670-
671- if (!IS_SVG_SUPPORTED) {
672- svgNotSupported(img, defaultOptions);
673- } else {
674- removeOnLoadAttribute(img);
675- loadFail(img, defaultOptions);
676- }
677- if (fallbackSrc) {
678- removeOnLoadAttribute(img);
679- img.src = fallbackSrc;
680- }
681- }
682- } else {
683- imgNotSet();
684- }
685- };
686-
687- window[globalName] = SVGInject;
688-
689- return SVGInject;
690- }
691-
692- var SVGInjectInstance = createSVGInject('SVGInject');
693-
694- if (typeof module == 'object' && typeof module.exports == 'object') {
695- module.exports = SVGInjectInstance;
696- }
697-})(window, document);
697 \ No newline at end of file
public/script.js+2 -1
@@ -5,6 +5,7 @@ import {
55 localforage,
66 Handlebars,
77 DiffMatchPatch,
8+ SVGInject,
89 initLibraryShims,
910 default as libs,
1011} from './lib.js';
@@ -2136,7 +2137,7 @@ function insertSVGIcon(mes, extra) {
21362137 mes.find('.timestamp').after(image);
21372138 }
21382139
21392140 await SVGInject(thisimage);
21402141 };
21412142}
21422143