@ui5/webcomponents-base 0.31.19 → 0.31.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/dist/StaticAreaItem.js +18 -3
- package/dist/UI5Element.js +2 -2
- package/dist/i18nBundle.js +0 -1
- package/dist/resources/bundle.esm.js +12 -12
- package/dist/resources/bundle.esm.js.map +1 -1
- package/dist/theming/CustomStyle.js +23 -3
- package/dist/util/encodeXML.js +35 -0
- package/dist/util/escapeRegex.js +10 -0
- package/dist/util/generateHighlightedMarkup.js +42 -0
- package/hash.txt +1 -0
- package/package.json +2 -2
- package/src/StaticAreaItem.js +18 -3
- package/src/UI5Element.js +2 -2
- package/src/i18nBundle.js +0 -1
- package/src/theming/CustomStyle.js +23 -3
- package/src/util/encodeXML.js +35 -0
- package/src/util/escapeRegex.js +10 -0
- package/src/util/generateHighlightedMarkup.js +42 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { reRenderAllUI5Elements } from "../Render.js";
|
|
2
|
+
import getSharedResource from "../getSharedResource.js";
|
|
2
3
|
import EventProvider from "../EventProvider.js";
|
|
3
4
|
|
|
4
|
-
const eventProvider = new EventProvider();
|
|
5
|
+
const eventProvider = getSharedResource("CustomStyle.eventProvider", new EventProvider());
|
|
5
6
|
const CUSTOM_CSS_CHANGE = "CustomCSSChange";
|
|
6
7
|
|
|
7
8
|
const attachCustomCSSChange = listener => {
|
|
@@ -16,14 +17,33 @@ const fireCustomCSSChange = tag => {
|
|
|
16
17
|
return eventProvider.fireEvent(CUSTOM_CSS_CHANGE, tag);
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
const customCSSFor = {};
|
|
20
|
+
const customCSSFor = getSharedResource("CustomStyle.customCSSFor", {});
|
|
21
|
+
|
|
22
|
+
// Listen to the eventProvider, in case other copies of this CustomStyle module fire this
|
|
23
|
+
// event, and this copy would therefore need to reRender the ui5 webcomponents; but
|
|
24
|
+
// don't reRender if it was this copy that fired the event to begin with.
|
|
25
|
+
let skipRerender;
|
|
26
|
+
attachCustomCSSChange(tag => {
|
|
27
|
+
if (!skipRerender) {
|
|
28
|
+
reRenderAllUI5Elements({ tag });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
20
31
|
|
|
21
32
|
const addCustomCSS = (tag, css) => {
|
|
22
33
|
if (!customCSSFor[tag]) {
|
|
23
34
|
customCSSFor[tag] = [];
|
|
24
35
|
}
|
|
25
36
|
customCSSFor[tag].push(css);
|
|
26
|
-
|
|
37
|
+
|
|
38
|
+
skipRerender = true;
|
|
39
|
+
try {
|
|
40
|
+
// The event is fired and the attached event listeners are all called synchronously
|
|
41
|
+
// The skipRerender flag will be used to avoid calling reRenderAllUI5Elements twice when it is this copy
|
|
42
|
+
// of CustomStyle.js which is firing the `CustomCSSChange` event.
|
|
43
|
+
fireCustomCSSChange(tag);
|
|
44
|
+
} finally {
|
|
45
|
+
skipRerender = false;
|
|
46
|
+
}
|
|
27
47
|
|
|
28
48
|
return reRenderAllUI5Elements({ tag });
|
|
29
49
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const fnToHex = (iChar, iLength) => {
|
|
2
|
+
let sHex = iChar.toString(16);
|
|
3
|
+
if (iLength) {
|
|
4
|
+
sHex = sHex.padStart(iLength, "0");
|
|
5
|
+
}
|
|
6
|
+
return sHex;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const rHtml = /[\x00-\x2b\x2f\x3a-\x40\x5b-\x5e\x60\x7b-\xff\u2028\u2029]/g, // eslint-disable-line no-control-regex
|
|
10
|
+
rHtmlReplace = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/, // eslint-disable-line no-control-regex
|
|
11
|
+
mHtmlLookup = {
|
|
12
|
+
"<": "<",
|
|
13
|
+
">": ">",
|
|
14
|
+
"&": "&",
|
|
15
|
+
"\"": """,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const fnHtml = sChar => {
|
|
19
|
+
let sEncoded = mHtmlLookup[sChar];
|
|
20
|
+
if (!sEncoded) {
|
|
21
|
+
if (rHtmlReplace.test(sChar)) {
|
|
22
|
+
sEncoded = "�";
|
|
23
|
+
} else {
|
|
24
|
+
sEncoded = `&#x${fnToHex(sChar.charCodeAt(0))};`;
|
|
25
|
+
}
|
|
26
|
+
mHtmlLookup[sChar] = sEncoded;
|
|
27
|
+
}
|
|
28
|
+
return sEncoded;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const fnEncodeXML = sString => {
|
|
32
|
+
return sString.replace(rHtml, fnHtml);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default fnEncodeXML;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escape a regular expression text so that it can be used in a regular expression.
|
|
3
|
+
* @param {string} text The string to be interpreted literally
|
|
4
|
+
* @returns Regular expression string to pass to regex
|
|
5
|
+
*/
|
|
6
|
+
function escapeRegex(text) {
|
|
7
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default escapeRegex;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import escapeRegex from "./escapeRegex.js";
|
|
2
|
+
import encodeXML from "./encodeXML.js";
|
|
3
|
+
|
|
4
|
+
// utility to replace all occurances of a string
|
|
5
|
+
function replaceAll(text, find, replace, caseInsensitive) {
|
|
6
|
+
return text.replace(new RegExp(escapeRegex(find), `${caseInsensitive ? "i" : ""}g`), replace);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generate markup for a raw string where a particular text is wrapped with some tag, by default `<b>` (bold) tag.
|
|
11
|
+
* All inputs to this function are considered literal text, and special characters will always be escaped.
|
|
12
|
+
* @param {string} text The text to add highlighting to
|
|
13
|
+
* @param {string} textToHighlight The text which should be highlighted
|
|
14
|
+
* @return {string} the markup HTML which contains all occurrances of the input text surrounded with a `<b>` tag.
|
|
15
|
+
*/
|
|
16
|
+
function generateHighlightedMarkup(text, textToHighlight) {
|
|
17
|
+
if (!text || !textToHighlight) {
|
|
18
|
+
return text;
|
|
19
|
+
}
|
|
20
|
+
// a token is some string that does not appear in either of the input strings
|
|
21
|
+
// repeat the token until it does not appear in the string
|
|
22
|
+
const makeToken = t => {
|
|
23
|
+
const [s, e] = t.split("");
|
|
24
|
+
while (text.indexOf(t) >= 0 || textToHighlight.indexOf(t) >= 0) {
|
|
25
|
+
t = `${s}${t}${e}`;
|
|
26
|
+
}
|
|
27
|
+
return t;
|
|
28
|
+
};
|
|
29
|
+
// It doesn't matter what characters are used as long as all 4 of them are unique
|
|
30
|
+
// And also that encodeXML will not change these characters
|
|
31
|
+
const openToken = makeToken("12");
|
|
32
|
+
const closeToken = makeToken("34");
|
|
33
|
+
// wrap every occurance of the textToHighlight using the open/close tokens (instead of markup at this point)
|
|
34
|
+
let result = encodeXML(replaceAll(text, textToHighlight, match => `${openToken}${match}${closeToken}`, true));
|
|
35
|
+
// now replace the open and close tokens with the markup that we expect
|
|
36
|
+
[[openToken, "<b>"], [closeToken, "</b>"]].forEach(([find, replace]) => {
|
|
37
|
+
result = replaceAll(result, find, replace);
|
|
38
|
+
});
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default generateHighlightedMarkup;
|
package/hash.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
iI/oElKbZhsMENntu1dXYTFaBg0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui5/webcomponents-base",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.23",
|
|
4
4
|
"description": "UI5 Web Components: webcomponents.base",
|
|
5
5
|
"author": "SAP SE (https://www.sap.com)",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"lit-html": "^1.0.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@ui5/webcomponents-tools": "0.31.
|
|
30
|
+
"@ui5/webcomponents-tools": "0.31.23",
|
|
31
31
|
"array-uniq": "^2.0.0",
|
|
32
32
|
"chromedriver": "88.0.0",
|
|
33
33
|
"copy-and-watch": "^0.1.4",
|
package/src/StaticAreaItem.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import updateShadowRoot from "./updateShadowRoot.js";
|
|
2
2
|
import { renderFinished } from "./Render.js";
|
|
3
3
|
import getEffectiveContentDensity from "./util/getEffectiveContentDensity.js";
|
|
4
|
+
import { getEffectiveScopingSuffixForTag } from "./CustomElementsScope.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
@@ -71,10 +72,24 @@ class StaticAreaItem extends HTMLElement {
|
|
|
71
72
|
getStableDomRef(refName) {
|
|
72
73
|
return this.shadowRoot.querySelector(`[data-ui5-stable=${refName}]`);
|
|
73
74
|
}
|
|
74
|
-
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
static getTag() {
|
|
77
|
+
const pureTag = "ui5-static-area-item";
|
|
78
|
+
const suffix = getEffectiveScopingSuffixForTag(pureTag);
|
|
79
|
+
if (!suffix) {
|
|
80
|
+
return pureTag;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return `${pureTag}-${suffix}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static createInstance() {
|
|
87
|
+
if (!customElements.get(StaticAreaItem.getTag())) {
|
|
88
|
+
customElements.define(StaticAreaItem.getTag(), StaticAreaItem);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return document.createElement(this.getTag());
|
|
92
|
+
}
|
|
78
93
|
}
|
|
79
94
|
|
|
80
95
|
export default StaticAreaItem;
|
package/src/UI5Element.js
CHANGED
|
@@ -3,7 +3,7 @@ import { boot } from "./Boot.js";
|
|
|
3
3
|
import UI5ElementMetadata from "./UI5ElementMetadata.js";
|
|
4
4
|
import EventProvider from "./EventProvider.js";
|
|
5
5
|
import getSingletonElementInstance from "./util/getSingletonElementInstance.js";
|
|
6
|
-
import "./StaticAreaItem.js";
|
|
6
|
+
import StaticAreaItem from "./StaticAreaItem.js";
|
|
7
7
|
import updateShadowRoot from "./updateShadowRoot.js";
|
|
8
8
|
import { renderDeferred, renderImmediately, cancelRender } from "./Render.js";
|
|
9
9
|
import { registerTag, isTagRegistered, recordTagRegistrationFailure } from "./CustomElementsRegistry.js";
|
|
@@ -795,7 +795,7 @@ class UI5Element extends HTMLElement {
|
|
|
795
795
|
}
|
|
796
796
|
|
|
797
797
|
if (!this.staticAreaItem) {
|
|
798
|
-
this.staticAreaItem =
|
|
798
|
+
this.staticAreaItem = StaticAreaItem.createInstance();
|
|
799
799
|
this.staticAreaItem.setOwnerElement(this);
|
|
800
800
|
}
|
|
801
801
|
if (!this.staticAreaItem.parentElement) {
|
package/src/i18nBundle.js
CHANGED
|
@@ -39,7 +39,6 @@ const getI18nBundle = packageName => {
|
|
|
39
39
|
if (I18nBundleInstances.has(packageName)) {
|
|
40
40
|
return I18nBundleInstances.get(packageName);
|
|
41
41
|
}
|
|
42
|
-
|
|
43
42
|
const i18nBundle = new I18nBundle(packageName);
|
|
44
43
|
I18nBundleInstances.set(packageName, i18nBundle);
|
|
45
44
|
return i18nBundle;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { reRenderAllUI5Elements } from "../Render.js";
|
|
2
|
+
import getSharedResource from "../getSharedResource.js";
|
|
2
3
|
import EventProvider from "../EventProvider.js";
|
|
3
4
|
|
|
4
|
-
const eventProvider = new EventProvider();
|
|
5
|
+
const eventProvider = getSharedResource("CustomStyle.eventProvider", new EventProvider());
|
|
5
6
|
const CUSTOM_CSS_CHANGE = "CustomCSSChange";
|
|
6
7
|
|
|
7
8
|
const attachCustomCSSChange = listener => {
|
|
@@ -16,14 +17,33 @@ const fireCustomCSSChange = tag => {
|
|
|
16
17
|
return eventProvider.fireEvent(CUSTOM_CSS_CHANGE, tag);
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
const customCSSFor = {};
|
|
20
|
+
const customCSSFor = getSharedResource("CustomStyle.customCSSFor", {});
|
|
21
|
+
|
|
22
|
+
// Listen to the eventProvider, in case other copies of this CustomStyle module fire this
|
|
23
|
+
// event, and this copy would therefore need to reRender the ui5 webcomponents; but
|
|
24
|
+
// don't reRender if it was this copy that fired the event to begin with.
|
|
25
|
+
let skipRerender;
|
|
26
|
+
attachCustomCSSChange(tag => {
|
|
27
|
+
if (!skipRerender) {
|
|
28
|
+
reRenderAllUI5Elements({ tag });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
20
31
|
|
|
21
32
|
const addCustomCSS = (tag, css) => {
|
|
22
33
|
if (!customCSSFor[tag]) {
|
|
23
34
|
customCSSFor[tag] = [];
|
|
24
35
|
}
|
|
25
36
|
customCSSFor[tag].push(css);
|
|
26
|
-
|
|
37
|
+
|
|
38
|
+
skipRerender = true;
|
|
39
|
+
try {
|
|
40
|
+
// The event is fired and the attached event listeners are all called synchronously
|
|
41
|
+
// The skipRerender flag will be used to avoid calling reRenderAllUI5Elements twice when it is this copy
|
|
42
|
+
// of CustomStyle.js which is firing the `CustomCSSChange` event.
|
|
43
|
+
fireCustomCSSChange(tag);
|
|
44
|
+
} finally {
|
|
45
|
+
skipRerender = false;
|
|
46
|
+
}
|
|
27
47
|
|
|
28
48
|
return reRenderAllUI5Elements({ tag });
|
|
29
49
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const fnToHex = (iChar, iLength) => {
|
|
2
|
+
let sHex = iChar.toString(16);
|
|
3
|
+
if (iLength) {
|
|
4
|
+
sHex = sHex.padStart(iLength, "0");
|
|
5
|
+
}
|
|
6
|
+
return sHex;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const rHtml = /[\x00-\x2b\x2f\x3a-\x40\x5b-\x5e\x60\x7b-\xff\u2028\u2029]/g, // eslint-disable-line no-control-regex
|
|
10
|
+
rHtmlReplace = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/, // eslint-disable-line no-control-regex
|
|
11
|
+
mHtmlLookup = {
|
|
12
|
+
"<": "<",
|
|
13
|
+
">": ">",
|
|
14
|
+
"&": "&",
|
|
15
|
+
"\"": """,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const fnHtml = sChar => {
|
|
19
|
+
let sEncoded = mHtmlLookup[sChar];
|
|
20
|
+
if (!sEncoded) {
|
|
21
|
+
if (rHtmlReplace.test(sChar)) {
|
|
22
|
+
sEncoded = "�";
|
|
23
|
+
} else {
|
|
24
|
+
sEncoded = `&#x${fnToHex(sChar.charCodeAt(0))};`;
|
|
25
|
+
}
|
|
26
|
+
mHtmlLookup[sChar] = sEncoded;
|
|
27
|
+
}
|
|
28
|
+
return sEncoded;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const fnEncodeXML = sString => {
|
|
32
|
+
return sString.replace(rHtml, fnHtml);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default fnEncodeXML;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escape a regular expression text so that it can be used in a regular expression.
|
|
3
|
+
* @param {string} text The string to be interpreted literally
|
|
4
|
+
* @returns Regular expression string to pass to regex
|
|
5
|
+
*/
|
|
6
|
+
function escapeRegex(text) {
|
|
7
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default escapeRegex;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import escapeRegex from "./escapeRegex.js";
|
|
2
|
+
import encodeXML from "./encodeXML.js";
|
|
3
|
+
|
|
4
|
+
// utility to replace all occurances of a string
|
|
5
|
+
function replaceAll(text, find, replace, caseInsensitive) {
|
|
6
|
+
return text.replace(new RegExp(escapeRegex(find), `${caseInsensitive ? "i" : ""}g`), replace);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generate markup for a raw string where a particular text is wrapped with some tag, by default `<b>` (bold) tag.
|
|
11
|
+
* All inputs to this function are considered literal text, and special characters will always be escaped.
|
|
12
|
+
* @param {string} text The text to add highlighting to
|
|
13
|
+
* @param {string} textToHighlight The text which should be highlighted
|
|
14
|
+
* @return {string} the markup HTML which contains all occurrances of the input text surrounded with a `<b>` tag.
|
|
15
|
+
*/
|
|
16
|
+
function generateHighlightedMarkup(text, textToHighlight) {
|
|
17
|
+
if (!text || !textToHighlight) {
|
|
18
|
+
return text;
|
|
19
|
+
}
|
|
20
|
+
// a token is some string that does not appear in either of the input strings
|
|
21
|
+
// repeat the token until it does not appear in the string
|
|
22
|
+
const makeToken = t => {
|
|
23
|
+
const [s, e] = t.split("");
|
|
24
|
+
while (text.indexOf(t) >= 0 || textToHighlight.indexOf(t) >= 0) {
|
|
25
|
+
t = `${s}${t}${e}`;
|
|
26
|
+
}
|
|
27
|
+
return t;
|
|
28
|
+
};
|
|
29
|
+
// It doesn't matter what characters are used as long as all 4 of them are unique
|
|
30
|
+
// And also that encodeXML will not change these characters
|
|
31
|
+
const openToken = makeToken("12");
|
|
32
|
+
const closeToken = makeToken("34");
|
|
33
|
+
// wrap every occurance of the textToHighlight using the open/close tokens (instead of markup at this point)
|
|
34
|
+
let result = encodeXML(replaceAll(text, textToHighlight, match => `${openToken}${match}${closeToken}`, true));
|
|
35
|
+
// now replace the open and close tokens with the markup that we expect
|
|
36
|
+
[[openToken, "<b>"], [closeToken, "</b>"]].forEach(([find, replace]) => {
|
|
37
|
+
result = replaceAll(result, find, replace);
|
|
38
|
+
});
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default generateHighlightedMarkup;
|