@ui5/webcomponents-base 0.0.0-bef62af04 → 0.0.0-c638668a1
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/.eslintignore +3 -1
- package/CHANGELOG.md +97 -0
- package/README.md +26 -2
- package/bundle.esm.js +6 -2
- package/dist/Boot.js +32 -14
- package/dist/CSP.js +59 -0
- package/dist/CustomElementsRegistry.js +60 -4
- package/dist/Device.js +15 -1
- package/dist/EventProvider.js +19 -25
- package/dist/FeaturesRegistry.js +4 -1
- package/dist/FontFace.js +7 -95
- package/dist/InitialConfiguration.js +11 -7
- package/dist/Keys.js +29 -0
- package/dist/ManagedStyles.js +83 -0
- package/dist/Render.js +3 -1
- package/dist/Runtimes.js +107 -0
- package/dist/StaticAreaItem.js +14 -9
- package/dist/SystemCSSVars.js +4 -25
- package/dist/UI5Element.js +20 -23
- package/dist/UI5ElementMetadata.js +17 -1
- package/dist/asset-registries/Icons.js +25 -14
- package/dist/asset-registries/Illustrations.js +10 -3
- package/dist/asset-registries/LocaleData.js +11 -2
- package/dist/assets-meta/IconCollectionsAlias.js +18 -0
- package/dist/config/Theme.js +14 -0
- package/dist/css/FontFace.css +45 -0
- package/dist/css/OverrideFontFace.css +32 -0
- package/dist/css/SystemCSSVars.css +17 -0
- package/dist/delegate/ItemNavigation.js +66 -0
- package/dist/features/F6Navigation.js +106 -0
- package/dist/generated/AssetParameters.js +1 -1
- package/dist/generated/VersionInfo.js +10 -0
- package/dist/generated/css/FontFace.css.js +5 -0
- package/dist/generated/css/OverrideFontFace.css.js +5 -0
- package/dist/generated/css/SystemCSSVars.css.js +5 -0
- package/dist/i18nBundle.js +33 -2
- package/dist/renderer/LitRenderer.js +6 -4
- package/dist/renderer/directives/style-map.js +72 -0
- package/dist/resources/bundle.esm.js +19 -8
- package/dist/resources/bundle.esm.js.map +1 -1
- package/dist/sap/base/Log.js +2 -10
- package/dist/sap/base/assert.js +1 -5
- package/dist/sap/base/security/encodeCSS.js +14 -0
- package/dist/sap/base/security/encodeXML.js +23 -0
- package/dist/sap/base/strings/toHex.js +8 -0
- package/dist/test-resources/elements/WithStaticArea.js +2 -1
- package/dist/test-resources/pages/AllTestElements.html +3 -0
- package/dist/test-resources/pages/i18n.html +1 -3
- package/dist/test-resources/specs/ConfigurationChange.spec.js +9 -9
- package/dist/test-resources/specs/ConfigurationScript.spec.js +24 -24
- package/dist/test-resources/specs/ConfigurationURL.spec.js +33 -33
- package/dist/test-resources/specs/CustomTheme.spec.js +7 -7
- package/dist/test-resources/specs/EventProvider.spec.js +63 -0
- package/dist/test-resources/specs/StaticArea.spec.js +55 -13
- package/dist/test-resources/specs/Theming.spec.js +11 -11
- package/dist/test-resources/specs/UI5ElementInvalidation.js +29 -29
- package/dist/test-resources/specs/UI5ElementLifecycle.js +11 -11
- package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +11 -11
- package/dist/test-resources/specs/UI5ElementMetadataExt.js +8 -8
- package/dist/test-resources/specs/UI5ElementPropertyValidation.js +6 -6
- package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +36 -36
- package/dist/test-resources/specs/UI5ElementShadowDOM.js +9 -9
- package/dist/test-resources/specs/UI5ElementSlots.js +9 -9
- package/dist/theming/CustomStyle.js +23 -3
- package/dist/theming/applyTheme.js +11 -10
- package/dist/theming/getEffectiveLinksHrefs.js +20 -0
- package/dist/theming/getStylesString.js +4 -2
- package/dist/theming/getThemeDesignerTheme.js +25 -5
- package/dist/theming/preloadLinks.js +23 -0
- package/dist/updateShadowRoot.js +8 -4
- package/dist/util/FocusableElements.js +8 -6
- package/dist/util/createLinkInHead.js +19 -0
- package/dist/util/escapeRegex.js +10 -0
- package/dist/util/generateHighlightedMarkup.js +42 -0
- package/dist/util/isNodeHidden.js +1 -1
- package/hash.txt +1 -1
- package/lib/generate-asset-parameters/index.js +0 -1
- package/lib/generate-styles/index.js +18 -0
- package/lib/generate-version-info/index.js +27 -0
- package/package-scripts.js +11 -6
- package/package.json +9 -11
- package/src/Boot.js +32 -14
- package/src/CSP.js +59 -0
- package/src/CustomElementsRegistry.js +60 -4
- package/src/Device.js +15 -1
- package/src/EventProvider.js +19 -25
- package/src/FeaturesRegistry.js +4 -1
- package/src/FontFace.js +7 -95
- package/src/InitialConfiguration.js +11 -7
- package/src/Keys.js +29 -0
- package/src/ManagedStyles.js +83 -0
- package/src/Render.js +3 -1
- package/src/Runtimes.js +107 -0
- package/src/StaticAreaItem.js +14 -9
- package/src/SystemCSSVars.js +4 -25
- package/src/UI5Element.js +20 -23
- package/src/UI5ElementMetadata.js +17 -1
- package/src/asset-registries/Icons.js +25 -14
- package/src/asset-registries/Illustrations.js +10 -3
- package/src/asset-registries/LocaleData.js +11 -2
- package/src/assets-meta/IconCollectionsAlias.js +18 -0
- package/src/config/Theme.js +14 -0
- package/src/css/FontFace.css +45 -0
- package/src/css/OverrideFontFace.css +32 -0
- package/src/css/SystemCSSVars.css +17 -0
- package/src/delegate/ItemNavigation.js +66 -0
- package/src/features/F6Navigation.js +106 -0
- package/src/i18nBundle.js +33 -2
- package/src/renderer/LitRenderer.js +6 -4
- package/src/renderer/directives/style-map.js +72 -0
- package/src/theming/CustomStyle.js +23 -3
- package/src/theming/applyTheme.js +11 -10
- package/src/theming/getEffectiveLinksHrefs.js +20 -0
- package/src/theming/getStylesString.js +4 -2
- package/src/theming/getThemeDesignerTheme.js +25 -5
- package/src/theming/preloadLinks.js +23 -0
- package/src/updateShadowRoot.js +8 -4
- package/src/util/FocusableElements.js +8 -6
- package/src/util/createLinkInHead.js +19 -0
- package/src/util/escapeRegex.js +10 -0
- package/src/util/generateHighlightedMarkup.js +42 -0
- package/src/util/isNodeHidden.js +1 -1
- package/used-modules.txt +4 -1
- package/dist/config/AssetsPath.js +0 -17
- package/dist/theming/createThemePropertiesStyleTag.js +0 -20
- package/dist/util/encodeCSS.js +0 -24
- package/src/config/AssetsPath.js +0 -17
- package/src/theming/createThemePropertiesStyleTag.js +0 -20
- package/src/util/encodeCSS.js +0 -24
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getUrl } from "../CSP.js";
|
|
2
|
+
|
|
3
|
+
const flatten = arr => {
|
|
4
|
+
return arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatten(val) : val), []);
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const getEffectiveLinksHrefs = (ElementClass, forStaticArea = false) => {
|
|
8
|
+
let stylesData = ElementClass[forStaticArea ? "staticAreaStyles" : "styles"];
|
|
9
|
+
if (!stylesData) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!Array.isArray(stylesData)) {
|
|
14
|
+
stylesData = [stylesData];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return flatten(stylesData).filter(data => !!data).map(data => getUrl(data.packageName, data.fileName));
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default getEffectiveLinksHrefs;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const getStylesString = styles => {
|
|
2
2
|
if (Array.isArray(styles)) {
|
|
3
|
-
return flatten(styles.filter(style => !!style)).
|
|
3
|
+
return flatten(styles.filter(style => !!style)).map(style => {
|
|
4
|
+
return typeof style === "string" ? style : style.content;
|
|
5
|
+
}).join(" ");
|
|
4
6
|
}
|
|
5
7
|
|
|
6
|
-
return styles;
|
|
8
|
+
return typeof styles === "string" ? styles : styles.content;
|
|
7
9
|
};
|
|
8
10
|
|
|
9
11
|
const flatten = arr => {
|
|
@@ -1,15 +1,26 @@
|
|
|
1
|
+
const warnings = new Set();
|
|
2
|
+
|
|
1
3
|
const getThemeMetadata = () => {
|
|
2
4
|
// Check if the class was already applied, most commonly to the link/style tag with the CSS Variables
|
|
3
|
-
let el = document.querySelector(".sapThemeMetaData-Base-baseLib");
|
|
5
|
+
let el = document.querySelector(".sapThemeMetaData-Base-baseLib") || document.querySelector(".sapThemeMetaData-UI5-sap-ui-core");
|
|
4
6
|
if (el) {
|
|
5
7
|
return getComputedStyle(el).backgroundImage;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
el = document.createElement("span");
|
|
9
11
|
el.style.display = "none";
|
|
12
|
+
|
|
13
|
+
// Try with sapThemeMetaData-Base-baseLib first
|
|
10
14
|
el.classList.add("sapThemeMetaData-Base-baseLib");
|
|
11
15
|
document.body.appendChild(el);
|
|
12
|
-
|
|
16
|
+
let metadata = getComputedStyle(el).backgroundImage;
|
|
17
|
+
|
|
18
|
+
// Try with sapThemeMetaData-UI5-sap-ui-core only if the previous selector was not found
|
|
19
|
+
if (metadata === "none") {
|
|
20
|
+
el.classList.add("sapThemeMetaData-UI5-sap-ui-core");
|
|
21
|
+
metadata = getComputedStyle(el).backgroundImage;
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
document.body.removeChild(el);
|
|
14
25
|
|
|
15
26
|
return metadata;
|
|
@@ -24,14 +35,20 @@ const parseThemeMetadata = metadataString => {
|
|
|
24
35
|
try {
|
|
25
36
|
paramsString = decodeURIComponent(paramsString);
|
|
26
37
|
} catch (ex) {
|
|
27
|
-
|
|
38
|
+
if (!warnings.has("decode")) {
|
|
39
|
+
console.warn("Malformed theme metadata string, unable to decodeURIComponent"); // eslint-disable-line
|
|
40
|
+
warnings.add("decode");
|
|
41
|
+
}
|
|
28
42
|
return;
|
|
29
43
|
}
|
|
30
44
|
}
|
|
31
45
|
try {
|
|
32
46
|
return JSON.parse(paramsString);
|
|
33
47
|
} catch (ex) {
|
|
34
|
-
|
|
48
|
+
if (!warnings.has("parse")) {
|
|
49
|
+
console.warn("Malformed theme metadata string, unable to parse JSON"); // eslint-disable-line
|
|
50
|
+
warnings.add("parse");
|
|
51
|
+
}
|
|
35
52
|
}
|
|
36
53
|
}
|
|
37
54
|
};
|
|
@@ -44,7 +61,10 @@ const processThemeMetadata = metadata => {
|
|
|
44
61
|
themeName = metadata.Path.match(/\.([^.]+)\.css_variables$/)[1];
|
|
45
62
|
baseThemeName = metadata.Extends[0];
|
|
46
63
|
} catch (ex) {
|
|
47
|
-
|
|
64
|
+
if (!warnings.has("object")) {
|
|
65
|
+
console.warn("Malformed theme metadata Object", metadata); // eslint-disable-line
|
|
66
|
+
warnings.add("object");
|
|
67
|
+
}
|
|
48
68
|
return;
|
|
49
69
|
}
|
|
50
70
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import getEffectiveLinksHrefs from "./getEffectiveLinksHrefs.js";
|
|
2
|
+
import createLinkInHead from "../util/createLinkInHead.js";
|
|
3
|
+
import { shouldUseLinks, shouldPreloadLinks } from "../CSP.js";
|
|
4
|
+
|
|
5
|
+
const preloaded = new Set();
|
|
6
|
+
|
|
7
|
+
const preloadLinks = ElementClass => {
|
|
8
|
+
if (!shouldUseLinks() || !shouldPreloadLinks()) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const linksHrefs = getEffectiveLinksHrefs(ElementClass, false) || [];
|
|
13
|
+
const staticAreaLinksHrefs = getEffectiveLinksHrefs(ElementClass, true) || [];
|
|
14
|
+
|
|
15
|
+
[...linksHrefs, ...staticAreaLinksHrefs].forEach(href => {
|
|
16
|
+
if (!preloaded.has(href)) {
|
|
17
|
+
createLinkInHead(href, { rel: "preload", as: "style" });
|
|
18
|
+
preloaded.add(href);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default preloadLinks;
|
package/dist/updateShadowRoot.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import executeTemplate from "./renderer/executeTemplate.js";
|
|
2
2
|
import getConstructableStyle from "./theming/getConstructableStyle.js";
|
|
3
3
|
import getEffectiveStyle from "./theming/getEffectiveStyle.js";
|
|
4
|
+
import getEffectiveLinksHrefs from "./theming/getEffectiveLinksHrefs.js";
|
|
4
5
|
import isLegacyBrowser from "./isLegacyBrowser.js";
|
|
6
|
+
import { shouldUseLinks } from "./CSP.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Updates the shadow root of a UI5Element or its static area item
|
|
@@ -9,18 +11,20 @@ import isLegacyBrowser from "./isLegacyBrowser.js";
|
|
|
9
11
|
* @param forStaticArea
|
|
10
12
|
*/
|
|
11
13
|
const updateShadowRoot = (element, forStaticArea = false) => {
|
|
12
|
-
let
|
|
14
|
+
let styleStrOrHrefsArr;
|
|
13
15
|
const template = forStaticArea ? "staticAreaTemplate" : "template";
|
|
14
16
|
const shadowRoot = forStaticArea ? element.staticAreaItem.shadowRoot : element.shadowRoot;
|
|
15
17
|
const renderResult = executeTemplate(element.constructor[template], element);
|
|
16
18
|
|
|
17
|
-
if (
|
|
19
|
+
if (shouldUseLinks()) {
|
|
20
|
+
styleStrOrHrefsArr = getEffectiveLinksHrefs(element.constructor, forStaticArea);
|
|
21
|
+
} else if (document.adoptedStyleSheets) { // Chrome
|
|
18
22
|
shadowRoot.adoptedStyleSheets = getConstructableStyle(element.constructor, forStaticArea);
|
|
19
23
|
} else if (!isLegacyBrowser()) { // FF, Safari
|
|
20
|
-
|
|
24
|
+
styleStrOrHrefsArr = getEffectiveStyle(element.constructor, forStaticArea);
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
element.constructor.render(renderResult, shadowRoot,
|
|
27
|
+
element.constructor.render(renderResult, shadowRoot, styleStrOrHrefsArr, { host: element });
|
|
24
28
|
};
|
|
25
29
|
|
|
26
30
|
export default updateShadowRoot;
|
|
@@ -5,27 +5,27 @@ const isFocusTrap = el => {
|
|
|
5
5
|
return el.hasAttribute("data-ui5-focus-trap");
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
const getFirstFocusableElement = async container => {
|
|
8
|
+
const getFirstFocusableElement = async (container, startFromContainer) => {
|
|
9
9
|
if (!container || isNodeHidden(container)) {
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
return findFocusableElement(container, true);
|
|
13
|
+
return findFocusableElement(container, true, startFromContainer);
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const getLastFocusableElement = async container => {
|
|
16
|
+
const getLastFocusableElement = async (container, startFromContainer) => {
|
|
17
17
|
if (!container || isNodeHidden(container)) {
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
return findFocusableElement(container, false);
|
|
21
|
+
return findFocusableElement(container, false, startFromContainer);
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
const isElemFocusable = el => {
|
|
25
25
|
return el.hasAttribute("data-ui5-focus-redirect") || !isNodeHidden(el);
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const findFocusableElement = async (container, forward) => {
|
|
28
|
+
const findFocusableElement = async (container, forward, startFromContainer) => {
|
|
29
29
|
let child;
|
|
30
30
|
|
|
31
31
|
if (container.shadowRoot) {
|
|
@@ -33,8 +33,10 @@ const findFocusableElement = async (container, forward) => {
|
|
|
33
33
|
} else if (container.assignedNodes && container.assignedNodes()) {
|
|
34
34
|
const assignedElements = container.assignedNodes();
|
|
35
35
|
child = forward ? assignedElements[0] : assignedElements[assignedElements.length - 1];
|
|
36
|
+
} else if (startFromContainer) {
|
|
37
|
+
child = container;
|
|
36
38
|
} else {
|
|
37
|
-
child = forward ? container.
|
|
39
|
+
child = forward ? container.firstElementChild : container.lastElementChild;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
let focusableDescendant;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a <link> tag in the <head> tag
|
|
3
|
+
* @param href - the CSS
|
|
4
|
+
* @param attributes - optional attributes to add to the tag
|
|
5
|
+
* @returns {HTMLElement}
|
|
6
|
+
*/
|
|
7
|
+
const createLinkInHead = (href, attributes = {}) => {
|
|
8
|
+
const link = document.createElement("link");
|
|
9
|
+
link.type = "text/css";
|
|
10
|
+
link.rel = "stylesheet";
|
|
11
|
+
|
|
12
|
+
Object.entries(attributes).forEach(pair => link.setAttribute(...pair));
|
|
13
|
+
|
|
14
|
+
link.href = href;
|
|
15
|
+
document.head.appendChild(link);
|
|
16
|
+
return link;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default createLinkInHead;
|
|
@@ -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 "../sap/base/security/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;
|
|
@@ -3,7 +3,7 @@ const isNodeHidden = node => {
|
|
|
3
3
|
return false;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
return (node.offsetWidth <= 0 && node.offsetHeight <= 0) || node.style.visibility === "hidden";
|
|
6
|
+
return (node.offsetWidth <= 0 && node.offsetHeight <= 0) || (node.style && node.style.visibility === "hidden");
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export default isNodeHidden;
|
package/hash.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
3/RoL3qyFujE4/1ZN8MtO1MKjUE=
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const mkdirp = require('mkdirp');
|
|
4
|
+
const CleanCSS = require('clean-css');
|
|
5
|
+
|
|
6
|
+
mkdirp.sync("dist/generated/css/");
|
|
7
|
+
fs.readdirSync("src/css/").filter(file => file.endsWith(".css")).forEach(file => {
|
|
8
|
+
let content = fs.readFileSync(path.join("src/css/", file));
|
|
9
|
+
const res = new CleanCSS().minify(`${content}`);
|
|
10
|
+
content = `export default {
|
|
11
|
+
packageName: "@ui5/webcomponents-base",
|
|
12
|
+
fileName: "${file}",
|
|
13
|
+
content: \`${res.styles}\`
|
|
14
|
+
};`;
|
|
15
|
+
|
|
16
|
+
fs.writeFileSync(path.join("dist/generated/css/", `${file}.js`), content);
|
|
17
|
+
});
|
|
18
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const mkdirp = require('mkdirp');
|
|
3
|
+
|
|
4
|
+
const version = JSON.parse(fs.readFileSync("package.json")).version;
|
|
5
|
+
|
|
6
|
+
// Parse version
|
|
7
|
+
const matches = version.match(/^([0-9]+)\.([0-9]+)\.([0-9]+)(.*)$/);
|
|
8
|
+
if (!matches) {
|
|
9
|
+
throw new Error("Unsupported version format");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const isNext = version.match(/[a-f0-9]{9}$/);
|
|
13
|
+
const buildTime = Math.floor(new Date().getTime() / 1000);
|
|
14
|
+
|
|
15
|
+
const fileContent = `const VersionInfo = {
|
|
16
|
+
version: "${version}",
|
|
17
|
+
major: ${matches[1]},
|
|
18
|
+
minor: ${matches[2]},
|
|
19
|
+
patch: ${matches[3]},
|
|
20
|
+
suffix: "${matches[4]}",
|
|
21
|
+
isNext: ${isNext ? "true" : "false"},
|
|
22
|
+
buildTime: ${buildTime},
|
|
23
|
+
};
|
|
24
|
+
export default VersionInfo;`;
|
|
25
|
+
|
|
26
|
+
mkdirp.sync("dist/generated/");
|
|
27
|
+
fs.writeFileSync("dist/generated/VersionInfo.js", fileContent);
|
package/package-scripts.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const resolve = require("resolve");
|
|
2
2
|
|
|
3
3
|
const assetParametersScript = resolve.sync("@ui5/webcomponents-base/lib/generate-asset-parameters/index.js");
|
|
4
|
+
const stylesScript = resolve.sync("@ui5/webcomponents-base/lib/generate-styles/index.js");
|
|
5
|
+
const versionScript = resolve.sync("@ui5/webcomponents-base/lib/generate-version-info/index.js");
|
|
4
6
|
const serve = resolve.sync("@ui5/webcomponents-tools/lib/serve/index.js");
|
|
5
7
|
const generateHash = resolve.sync("@ui5/webcomponents-tools/lib/hash/generate.js");
|
|
6
8
|
const hashIsUpToDate = resolve.sync("@ui5/webcomponents-tools/lib/hash/upToDate.js");
|
|
@@ -12,17 +14,17 @@ const UP_TO_DATE = `node "${hashIsUpToDate}" dist/ hash.txt && echo "Up to date.
|
|
|
12
14
|
const scripts = {
|
|
13
15
|
clean: "rimraf dist && rimraf .port",
|
|
14
16
|
lint: "eslint . --config config/.eslintrc.js",
|
|
15
|
-
prepare: "nps clean integrate copy generateAssetParameters",
|
|
17
|
+
prepare: "nps clean integrate copy generateAssetParameters generateVersionInfo generateStyles",
|
|
16
18
|
integrate: {
|
|
17
19
|
default: "nps integrate.copy-used-modules integrate.copy-overlay integrate.replace-amd integrate.replace-export-true integrate.replace-export-false integrate.amd-to-es6 integrate.replace-global-core-usage integrate.esm-abs-to-rel integrate.third-party",
|
|
18
|
-
"copy-used-modules": `node ${copyUsedModules} ./used-modules.txt dist/`,
|
|
20
|
+
"copy-used-modules": `node "${copyUsedModules}" ./used-modules.txt dist/`,
|
|
19
21
|
"copy-overlay": `copy-and-watch "overlay/**/*.js" dist/`,
|
|
20
22
|
"replace-amd": "replace-in-file sap.ui.define define dist/**/*.js",
|
|
21
23
|
"replace-export-true": `replace-in-file ", /* bExport= */ true" "" dist/**/*.js`,
|
|
22
24
|
"replace-export-false": `replace-in-file ", /* bExport= */ false" "" dist/**/*.js`,
|
|
23
25
|
"amd-to-es6": "amdtoes6 --src=dist/ --replace --glob=**/*.js",
|
|
24
|
-
"replace-global-core-usage": `node ${replaceGlobalCore} dist/`,
|
|
25
|
-
"esm-abs-to-rel": `node ${esmAbsToRel} dist/ dist/`,
|
|
26
|
+
"replace-global-core-usage": `node "${replaceGlobalCore}" dist/`,
|
|
27
|
+
"esm-abs-to-rel": `node "${esmAbsToRel}" dist/ dist/`,
|
|
26
28
|
"third-party": {
|
|
27
29
|
default: "nps integrate.third-party.copy integrate.third-party.fix",
|
|
28
30
|
copy: "mkdirp dist/sap/ui/thirdparty/ && copy-and-watch ../../node_modules/@openui5/sap.ui.core/src/sap/ui/thirdparty/caja-html-sanitizer.js dist/sap/ui/thirdparty/",
|
|
@@ -35,15 +37,18 @@ const scripts = {
|
|
|
35
37
|
},
|
|
36
38
|
copy: {
|
|
37
39
|
default: "nps copy.src copy.test",
|
|
38
|
-
src: `copy-and-watch "src/**/*.js" dist/`,
|
|
40
|
+
src: `copy-and-watch "src/**/*.{js,css}" dist/`,
|
|
39
41
|
test: `copy-and-watch "test/**/*.*" dist/test-resources`,
|
|
40
42
|
},
|
|
41
43
|
generateAssetParameters: `node "${assetParametersScript}"`,
|
|
44
|
+
generateVersionInfo: `node "${versionScript}"`,
|
|
45
|
+
generateStyles: `node "${stylesScript}"`,
|
|
42
46
|
watch: {
|
|
43
|
-
default: 'concurrently "nps watch.test" "nps watch.src" "nps watch.bundle"',
|
|
47
|
+
default: 'concurrently "nps watch.test" "nps watch.src" "nps watch.bundle" "nps watch.styles"',
|
|
44
48
|
src: 'nps "copy.src --watch --skip-initial-copy"',
|
|
45
49
|
test: 'nps "copy.test --watch --skip-initial-copy"',
|
|
46
50
|
bundle: "rollup --config config/rollup.config.js -w --environment DEV",
|
|
51
|
+
styles: 'chokidar "src/css/*.css" -c "nps generateStyles"'
|
|
47
52
|
},
|
|
48
53
|
dev: 'concurrently "nps serve" "nps watch"',
|
|
49
54
|
start: "nps prepare dev",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui5/webcomponents-base",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-c638668a1",
|
|
4
4
|
"description": "UI5 Web Components: webcomponents.base",
|
|
5
5
|
"author": "SAP SE (https://www.sap.com)",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -32,19 +32,17 @@
|
|
|
32
32
|
"prepublishOnly": "npm run clean && npm run build"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"lit-html": "2.0.
|
|
35
|
+
"lit-html": "2.0.1"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@
|
|
39
|
-
"@
|
|
40
|
-
"@
|
|
41
|
-
"
|
|
42
|
-
"
|
|
38
|
+
"@buxlabs/amd-to-es6": "0.16.1",
|
|
39
|
+
"@openui5/sap.ui.core": "1.94.0",
|
|
40
|
+
"@ui5/webcomponents-tools": "0.0.0-c638668a1",
|
|
41
|
+
"chromedriver": "96.0.0",
|
|
42
|
+
"clean-css": "^5.2.2",
|
|
43
43
|
"copy-and-watch": "^0.1.5",
|
|
44
44
|
"eslint": "^7.22.0",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"path-exists-cli": "^1.0.0",
|
|
48
|
-
"replace-in-file": "^6.2.0"
|
|
45
|
+
"mkdirp": "^1.0.4",
|
|
46
|
+
"resolve": "^1.20.0"
|
|
49
47
|
}
|
|
50
48
|
}
|
package/src/Boot.js
CHANGED
|
@@ -4,9 +4,10 @@ import insertFontFace from "./FontFace.js";
|
|
|
4
4
|
import insertSystemCSSVars from "./SystemCSSVars.js";
|
|
5
5
|
import { getTheme } from "./config/Theme.js";
|
|
6
6
|
import applyTheme from "./theming/applyTheme.js";
|
|
7
|
+
import { registerCurrentRuntime } from "./Runtimes.js";
|
|
7
8
|
import { getFeature } from "./FeaturesRegistry.js";
|
|
8
9
|
|
|
9
|
-
let
|
|
10
|
+
let bootPromise;
|
|
10
11
|
const eventProvider = new EventProvider();
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -19,22 +20,39 @@ const attachBoot = listener => {
|
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
const boot = async () => {
|
|
22
|
-
if (
|
|
23
|
-
return;
|
|
23
|
+
if (bootPromise) {
|
|
24
|
+
return bootPromise;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
/* eslint-disable no-alert, no-async-promise-executor */
|
|
28
|
+
/*
|
|
29
|
+
Note(since we disable eslint rule):
|
|
30
|
+
If an async executor function throws an error, the error will be lost and won't cause the newly-constructed Promise to reject.
|
|
31
|
+
This could make it difficult to debug and handle some errors.
|
|
32
|
+
*/
|
|
33
|
+
bootPromise = new Promise(async resolve => {
|
|
34
|
+
registerCurrentRuntime();
|
|
35
|
+
|
|
36
|
+
const OpenUI5Support = getFeature("OpenUI5Support");
|
|
37
|
+
const F6Navigation = getFeature("F6Navigation");
|
|
38
|
+
if (OpenUI5Support) {
|
|
39
|
+
await OpenUI5Support.init();
|
|
40
|
+
} else if (F6Navigation) {
|
|
41
|
+
F6Navigation.init();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
await whenDOMReady();
|
|
45
|
+
await applyTheme(getTheme());
|
|
46
|
+
OpenUI5Support && OpenUI5Support.attachListeners();
|
|
47
|
+
insertFontFace();
|
|
48
|
+
insertSystemCSSVars();
|
|
49
|
+
await eventProvider.fireEventAsync("boot");
|
|
50
|
+
|
|
51
|
+
resolve();
|
|
52
|
+
});
|
|
53
|
+
/* eslint-enable no-alert, no-async-promise-executor */
|
|
30
54
|
|
|
31
|
-
|
|
32
|
-
await applyTheme(getTheme());
|
|
33
|
-
OpenUI5Support && OpenUI5Support.attachListeners();
|
|
34
|
-
insertFontFace();
|
|
35
|
-
insertSystemCSSVars();
|
|
36
|
-
await eventProvider.fireEventAsync("boot");
|
|
37
|
-
booted = true;
|
|
55
|
+
return bootPromise;
|
|
38
56
|
};
|
|
39
57
|
|
|
40
58
|
export {
|
package/src/CSP.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const roots = new Map();
|
|
2
|
+
let useLinks = false;
|
|
3
|
+
let preloadLinks = true;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Use this function to provide the path to the directory where the css resources for the given package will be served from
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
* @param packageName name of the package that is being configured
|
|
10
|
+
* @param root path, accessible by the server that will serve the css resources
|
|
11
|
+
*/
|
|
12
|
+
const setPackageCSSRoot = (packageName, root) => {
|
|
13
|
+
roots.set(packageName, root);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const getUrl = (packageName, path) => {
|
|
17
|
+
return `${roots.get(packageName)}${path}`;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Call this function to enable or disable the usage of <link> tags instead of <style> tags to achieve CSP compliance
|
|
22
|
+
* Example: "setUseLinks(true)" will unconditionally use <link> tags for all browsers;
|
|
23
|
+
* Example: "setUseLinks(!document.adoptedStyleSheets) will only enable the usage of <link> tags for browsers that do not support constructable stylesheets.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
* @param use whether links will be used
|
|
27
|
+
*/
|
|
28
|
+
const setUseLinks = use => {
|
|
29
|
+
useLinks = use;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Call this function to enable or disable the preloading of <link> tags.
|
|
34
|
+
* Note: only taken into account when <link> tags are being used.
|
|
35
|
+
* Note: links are being preloaded by default, so call "setPreloadLinks(false)" to opt out of this.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
* @param preload
|
|
39
|
+
*/
|
|
40
|
+
const setPreloadLinks = preload => {
|
|
41
|
+
preloadLinks = preload;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const shouldUseLinks = () => {
|
|
45
|
+
return useLinks;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const shouldPreloadLinks = () => {
|
|
49
|
+
return preloadLinks;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
setPackageCSSRoot,
|
|
54
|
+
getUrl,
|
|
55
|
+
setUseLinks,
|
|
56
|
+
setPreloadLinks,
|
|
57
|
+
shouldUseLinks,
|
|
58
|
+
shouldPreloadLinks,
|
|
59
|
+
};
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import setToArray from "./util/setToArray.js";
|
|
2
|
+
import getSharedResource from "./getSharedResource.js";
|
|
3
|
+
import { getCurrentRuntimeIndex, compareRuntimes, getAllRuntimes } from "./Runtimes.js";
|
|
4
|
+
|
|
5
|
+
const Tags = getSharedResource("Tags", new Map());
|
|
2
6
|
|
|
3
7
|
const Definitions = new Set();
|
|
4
|
-
|
|
8
|
+
let Failures = {};
|
|
5
9
|
let failureTimeout;
|
|
6
10
|
|
|
11
|
+
const UNKNOWN_RUNTIME = "unknown";
|
|
12
|
+
|
|
7
13
|
const registerTag = tag => {
|
|
8
14
|
Definitions.add(tag);
|
|
15
|
+
Tags.set(tag, getCurrentRuntimeIndex());
|
|
9
16
|
};
|
|
10
17
|
|
|
11
18
|
const isTagRegistered = tag => {
|
|
@@ -17,18 +24,67 @@ const getAllRegisteredTags = () => {
|
|
|
17
24
|
};
|
|
18
25
|
|
|
19
26
|
const recordTagRegistrationFailure = tag => {
|
|
20
|
-
|
|
27
|
+
let tagRegRuntimeIndex = Tags.get(tag);
|
|
28
|
+
if (tagRegRuntimeIndex === undefined) {
|
|
29
|
+
tagRegRuntimeIndex = UNKNOWN_RUNTIME; // If the tag is taken, but not registered in Tags, then a version before 1.1.0 defined it => use the "unknown" key
|
|
30
|
+
}
|
|
31
|
+
Failures[tagRegRuntimeIndex] = Failures[tagRegRuntimeIndex] || new Set();
|
|
32
|
+
Failures[tagRegRuntimeIndex].add(tag);
|
|
33
|
+
|
|
21
34
|
if (!failureTimeout) {
|
|
22
35
|
failureTimeout = setTimeout(() => {
|
|
23
36
|
displayFailedRegistrations();
|
|
37
|
+
Failures = {};
|
|
24
38
|
failureTimeout = undefined;
|
|
25
39
|
}, 1000);
|
|
26
40
|
}
|
|
27
41
|
};
|
|
28
42
|
|
|
29
43
|
const displayFailedRegistrations = () => {
|
|
30
|
-
|
|
31
|
-
|
|
44
|
+
const allRuntimes = getAllRuntimes();
|
|
45
|
+
const currentRuntimeIndex = getCurrentRuntimeIndex();
|
|
46
|
+
const currentRuntime = allRuntimes[currentRuntimeIndex];
|
|
47
|
+
|
|
48
|
+
let message = `Multiple UI5 Web Components instances detected.`;
|
|
49
|
+
|
|
50
|
+
if (allRuntimes.length > 1) {
|
|
51
|
+
message = `${message}\nLoading order (versions before 1.1.0 not listed): ${allRuntimes.map(runtime => `\n${runtime.description}`).join("")}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
Object.keys(Failures).forEach(otherRuntimeIndex => {
|
|
55
|
+
let comparison;
|
|
56
|
+
let otherRuntime;
|
|
57
|
+
|
|
58
|
+
if (otherRuntimeIndex === UNKNOWN_RUNTIME) { // version < 1.1.0 defined the tag
|
|
59
|
+
comparison = 1; // the current runtime is considered newer
|
|
60
|
+
otherRuntime = {
|
|
61
|
+
description: `Older unknown runtime`,
|
|
62
|
+
};
|
|
63
|
+
} else {
|
|
64
|
+
comparison = compareRuntimes(currentRuntimeIndex, otherRuntimeIndex);
|
|
65
|
+
otherRuntime = allRuntimes[otherRuntimeIndex];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let compareWord;
|
|
69
|
+
if (comparison > 0) {
|
|
70
|
+
compareWord = "an older";
|
|
71
|
+
} else if (comparison < 0) {
|
|
72
|
+
compareWord = "a newer";
|
|
73
|
+
} else {
|
|
74
|
+
compareWord = "the same";
|
|
75
|
+
}
|
|
76
|
+
message = `${message}\n\n"${currentRuntime.description}" failed to define ${Failures[otherRuntimeIndex].size} tag(s) as they were defined by a runtime of ${compareWord} version "${otherRuntime.description}": ${setToArray(Failures[otherRuntimeIndex]).sort().join(", ")}.`;
|
|
77
|
+
|
|
78
|
+
if (comparison > 0) {
|
|
79
|
+
message = `${message}\nWARNING! If your code uses features of the above web components, unavailable in ${otherRuntime.description}, it might not work as expected!`;
|
|
80
|
+
} else {
|
|
81
|
+
message = `${message}\nSince the above web components were defined by the same or newer version runtime, they should be compatible with your code.`;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
message = `${message}\n\nTo prevent other runtimes from defining tags that you use, consider using scoping or have third-party libraries use scoping: https://github.com/SAP/ui5-webcomponents/blob/master/docs/2-advanced/03-scoping.md.`;
|
|
86
|
+
|
|
87
|
+
console.warn(message); // eslint-disable-line
|
|
32
88
|
};
|
|
33
89
|
|
|
34
90
|
export {
|