@elementor/editor-canvas 4.3.0-beta2 → 4.3.0-beta3
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/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +43 -113
- package/dist/index.mjs +41 -108
- package/package.json +20 -20
- package/src/legacy/create-nested-templated-element-type.ts +31 -1
- package/src/legacy/types.ts +1 -0
- package/src/transformers/shared/__tests__/icon-transformer.test.ts +2 -2
- package/src/transformers/shared/icon-transformer.ts +24 -169
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -2107,6 +2107,9 @@ var timeRangeTransformer = createTransformer((value) => {
|
|
|
2107
2107
|
};
|
|
2108
2108
|
});
|
|
2109
2109
|
|
|
2110
|
+
// src/transformers/shared/icon-transformer.ts
|
|
2111
|
+
var import_editor_controls = require("@elementor/editor-controls");
|
|
2112
|
+
|
|
2110
2113
|
// src/transformers/shared/process-svg-content.ts
|
|
2111
2114
|
var import_dompurify2 = __toESM(require("dompurify"));
|
|
2112
2115
|
var SVG_INLINE_STYLES = "width: 100%; height: 100%; overflow: unset;";
|
|
@@ -2129,128 +2132,36 @@ function processSvgContent(svgText) {
|
|
|
2129
2132
|
}
|
|
2130
2133
|
|
|
2131
2134
|
// src/transformers/shared/icon-transformer.ts
|
|
2132
|
-
var
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
aliases: 2,
|
|
2136
|
-
unicode: 3,
|
|
2137
|
-
path: 4
|
|
2138
|
-
};
|
|
2139
|
-
var fontAwesomeJsonCache = /* @__PURE__ */ new Map();
|
|
2135
|
+
var EMPTY_ICON_RESULT = { html: null, url: null };
|
|
2136
|
+
var ICON_SVG_SIZE = "100%";
|
|
2137
|
+
var ICON_SVG_OVERFLOW = "visible";
|
|
2140
2138
|
var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
2141
2139
|
const iconValue = typeof value.value === "string" ? value.value : null;
|
|
2142
2140
|
const library = typeof value.library === "string" ? value.library : null;
|
|
2143
2141
|
if (!iconValue || !library) {
|
|
2144
|
-
return
|
|
2142
|
+
return EMPTY_ICON_RESULT;
|
|
2145
2143
|
}
|
|
2146
|
-
const iconName =
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
return { html: null, url: null };
|
|
2144
|
+
const iconName = (0, import_editor_controls.getFontAwesome7IconName)(iconValue);
|
|
2145
|
+
if (!iconName) {
|
|
2146
|
+
return EMPTY_ICON_RESULT;
|
|
2150
2147
|
}
|
|
2151
|
-
const
|
|
2152
|
-
const iconData = icons?.[iconName];
|
|
2148
|
+
const iconData = await (0, import_editor_controls.resolveFontAwesome7Icon)(library, iconName, signal);
|
|
2153
2149
|
if (!iconData) {
|
|
2154
|
-
return
|
|
2150
|
+
return EMPTY_ICON_RESULT;
|
|
2155
2151
|
}
|
|
2156
2152
|
const svgText = buildFontAwesomeSvg(iconData);
|
|
2157
2153
|
if (!svgText) {
|
|
2158
|
-
return
|
|
2154
|
+
return EMPTY_ICON_RESULT;
|
|
2159
2155
|
}
|
|
2160
2156
|
const html = processIconSvgContent(svgText);
|
|
2161
2157
|
return { html, url: null };
|
|
2162
2158
|
});
|
|
2163
|
-
function getFontAwesomeIconName(iconValue) {
|
|
2164
|
-
const match = iconValue.match(/^fa\S*\s+fa-(.+)$/);
|
|
2165
|
-
return match?.[1] ?? null;
|
|
2166
|
-
}
|
|
2167
|
-
function getFontAwesomeJsonFileName(library) {
|
|
2168
|
-
const fileName = library.replace(/^fa-/, "");
|
|
2169
|
-
const config = getFontAwesome7EditorConfig();
|
|
2170
|
-
if (!config?.jsonFiles.includes(fileName)) {
|
|
2171
|
-
return null;
|
|
2172
|
-
}
|
|
2173
|
-
return fileName;
|
|
2174
|
-
}
|
|
2175
|
-
function getFontAwesome7EditorConfig() {
|
|
2176
|
-
const config = window.elementorCommon?.config?.fontAwesome?.v7;
|
|
2177
|
-
if (!config || !Array.isArray(config.jsonFiles) || typeof config.jsonBaseUrl !== "string" || config.jsonBaseUrl === "") {
|
|
2178
|
-
return null;
|
|
2179
|
-
}
|
|
2180
|
-
return {
|
|
2181
|
-
jsonFiles: config.jsonFiles,
|
|
2182
|
-
jsonBaseUrl: config.jsonBaseUrl
|
|
2183
|
-
};
|
|
2184
|
-
}
|
|
2185
|
-
async function fetchFontAwesomeIcons(jsonFileName, signal) {
|
|
2186
|
-
const cached = fontAwesomeJsonCache.get(jsonFileName);
|
|
2187
|
-
if (cached) {
|
|
2188
|
-
return cached;
|
|
2189
|
-
}
|
|
2190
|
-
const icons = await loadFontAwesomeIcons(jsonFileName, signal);
|
|
2191
|
-
if (icons) {
|
|
2192
|
-
fontAwesomeJsonCache.set(jsonFileName, icons);
|
|
2193
|
-
}
|
|
2194
|
-
return icons;
|
|
2195
|
-
}
|
|
2196
|
-
async function loadFontAwesomeIcons(jsonFileName, signal) {
|
|
2197
|
-
const config = getFontAwesome7EditorConfig();
|
|
2198
|
-
if (!config?.jsonFiles.includes(jsonFileName)) {
|
|
2199
|
-
return null;
|
|
2200
|
-
}
|
|
2201
|
-
try {
|
|
2202
|
-
const response = await fetch(`${config.jsonBaseUrl}${jsonFileName}.json`, {
|
|
2203
|
-
signal
|
|
2204
|
-
});
|
|
2205
|
-
if (!response.ok) {
|
|
2206
|
-
return null;
|
|
2207
|
-
}
|
|
2208
|
-
const data = await response.json();
|
|
2209
|
-
const icons = data.icons;
|
|
2210
|
-
if (!icons || typeof icons !== "object") {
|
|
2211
|
-
return null;
|
|
2212
|
-
}
|
|
2213
|
-
return indexFontAwesomeIcons(icons);
|
|
2214
|
-
} catch {
|
|
2215
|
-
return null;
|
|
2216
|
-
}
|
|
2217
|
-
}
|
|
2218
|
-
function indexFontAwesomeIcons(icons) {
|
|
2219
|
-
const index = {};
|
|
2220
|
-
for (const [name, iconData] of Object.entries(icons)) {
|
|
2221
|
-
if (!isValidIconTuple(iconData)) {
|
|
2222
|
-
continue;
|
|
2223
|
-
}
|
|
2224
|
-
index[name] = iconData;
|
|
2225
|
-
for (const alias of iconData[FONT_AWESOME_JSON.aliases]) {
|
|
2226
|
-
if (typeof alias === "string" && alias !== "" && !index[alias]) {
|
|
2227
|
-
index[alias] = iconData;
|
|
2228
|
-
}
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
return index;
|
|
2232
|
-
}
|
|
2233
|
-
function isValidIconTuple(iconData) {
|
|
2234
|
-
return Array.isArray(iconData) && iconData.length >= 5 && typeof iconData[FONT_AWESOME_JSON.width] === "number" && typeof iconData[FONT_AWESOME_JSON.height] === "number" && Array.isArray(iconData[FONT_AWESOME_JSON.aliases]);
|
|
2235
|
-
}
|
|
2236
2159
|
function buildFontAwesomeSvg(iconData) {
|
|
2237
|
-
|
|
2238
|
-
const height = iconData[FONT_AWESOME_JSON.height];
|
|
2239
|
-
const paths = normalizePaths(iconData[FONT_AWESOME_JSON.path]);
|
|
2240
|
-
if (paths.length === 0) {
|
|
2160
|
+
if (iconData.paths.length === 0) {
|
|
2241
2161
|
return null;
|
|
2242
2162
|
}
|
|
2243
|
-
const pathMarkup = paths.map((path) => `<path d="${escapeSvgPath(path)}"></path>`).join("");
|
|
2244
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}">${pathMarkup}</svg>`;
|
|
2245
|
-
}
|
|
2246
|
-
function normalizePaths(pathData) {
|
|
2247
|
-
if (typeof pathData === "string" && pathData !== "") {
|
|
2248
|
-
return [pathData];
|
|
2249
|
-
}
|
|
2250
|
-
if (!Array.isArray(pathData)) {
|
|
2251
|
-
return [];
|
|
2252
|
-
}
|
|
2253
|
-
return pathData.filter((path) => typeof path === "string" && path !== "");
|
|
2163
|
+
const pathMarkup = iconData.paths.map((path) => `<path d="${escapeSvgPath(path)}"></path>`).join("");
|
|
2164
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${iconData.width} ${iconData.height}">${pathMarkup}</svg>`;
|
|
2254
2165
|
}
|
|
2255
2166
|
function escapeSvgPath(path) {
|
|
2256
2167
|
return path.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -2267,9 +2178,9 @@ function processIconSvgContent(svgText) {
|
|
|
2267
2178
|
return null;
|
|
2268
2179
|
}
|
|
2269
2180
|
svgElement.setAttribute("aria-hidden", "true");
|
|
2270
|
-
svgElement.style.setProperty("width",
|
|
2271
|
-
svgElement.style.setProperty("height",
|
|
2272
|
-
svgElement.style.setProperty("overflow",
|
|
2181
|
+
svgElement.style.setProperty("width", ICON_SVG_SIZE);
|
|
2182
|
+
svgElement.style.setProperty("height", ICON_SVG_SIZE);
|
|
2183
|
+
svgElement.style.setProperty("overflow", ICON_SVG_OVERFLOW);
|
|
2273
2184
|
return svgElement.outerHTML;
|
|
2274
2185
|
}
|
|
2275
2186
|
|
|
@@ -2665,10 +2576,10 @@ var transformSkewTransformer = createTransformer((value) => {
|
|
|
2665
2576
|
});
|
|
2666
2577
|
|
|
2667
2578
|
// src/transformers/styles/transition-transformer.ts
|
|
2668
|
-
var
|
|
2579
|
+
var import_editor_controls2 = require("@elementor/editor-controls");
|
|
2669
2580
|
var getAllowedProperties = () => {
|
|
2670
2581
|
const allowedProperties = /* @__PURE__ */ new Set();
|
|
2671
|
-
|
|
2582
|
+
import_editor_controls2.transitionProperties.forEach((category) => {
|
|
2672
2583
|
category.properties.forEach((property) => {
|
|
2673
2584
|
allowedProperties.add(property.value);
|
|
2674
2585
|
});
|
|
@@ -3111,6 +3022,7 @@ function createTemplatedElementView({
|
|
|
3111
3022
|
}
|
|
3112
3023
|
|
|
3113
3024
|
// src/legacy/create-nested-templated-element-type.ts
|
|
3025
|
+
var STYLES_REFERENCE_UNTRACKED = /* @__PURE__ */ Symbol("styles-reference-untracked");
|
|
3114
3026
|
function canBeNestedTemplated(element) {
|
|
3115
3027
|
return canBeTemplated(element) && "support_nesting" in element && !!element.support_nesting;
|
|
3116
3028
|
}
|
|
@@ -3170,6 +3082,7 @@ function createNestedTemplatedElementView({
|
|
|
3170
3082
|
return AtomicElementBaseView.extend({
|
|
3171
3083
|
_abortController: null,
|
|
3172
3084
|
_lastResolvedSettingsHash: null,
|
|
3085
|
+
_lastRenderedStyles: STYLES_REFERENCE_UNTRACKED,
|
|
3173
3086
|
_domUpdateWasSkipped: false,
|
|
3174
3087
|
template: false,
|
|
3175
3088
|
attributes() {
|
|
@@ -3206,6 +3119,23 @@ function createNestedTemplatedElementView({
|
|
|
3206
3119
|
this._initAlpine();
|
|
3207
3120
|
});
|
|
3208
3121
|
this.model.trigger("render:complete");
|
|
3122
|
+
this._notifyStylesChanged();
|
|
3123
|
+
},
|
|
3124
|
+
// `document/elements/create` fires before the nested template has fully painted, so the
|
|
3125
|
+
// styles provider rebuilds CSS too early and misses the new local class IDs. Dispatching
|
|
3126
|
+
// ELEMENT_STYLE_CHANGE_EVENT here — after the template and all children are in the DOM —
|
|
3127
|
+
// gives the provider a second chance to regenerate CSS against the live class names.
|
|
3128
|
+
//
|
|
3129
|
+
// The reference-equality guard prevents a parent re-render from emitting one event per
|
|
3130
|
+
// unchanged descendant. Use a sentinel for the initial state — otherwise elements with no
|
|
3131
|
+
// local styles (undefined === undefined) would never notify, and descendants like e-heading
|
|
3132
|
+
// that rely on this post-paint refresh would lose their CSS after detach.
|
|
3133
|
+
_notifyStylesChanged() {
|
|
3134
|
+
const styles = this.model.get("styles");
|
|
3135
|
+
if (this._lastRenderedStyles !== STYLES_REFERENCE_UNTRACKED && styles === this._lastRenderedStyles) {
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
this._lastRenderedStyles = styles;
|
|
3209
3139
|
window.dispatchEvent(new CustomEvent(import_editor_elements6.ELEMENT_STYLE_CHANGE_EVENT));
|
|
3210
3140
|
},
|
|
3211
3141
|
async _renderTemplate() {
|
|
@@ -3505,7 +3435,7 @@ var ReplacementBase = class {
|
|
|
3505
3435
|
// src/legacy/replacements/inline-editing/canvas-inline-editor.tsx
|
|
3506
3436
|
var React10 = __toESM(require("react"));
|
|
3507
3437
|
var import_react18 = require("react");
|
|
3508
|
-
var
|
|
3438
|
+
var import_editor_controls3 = require("@elementor/editor-controls");
|
|
3509
3439
|
var import_ui5 = require("@elementor/ui");
|
|
3510
3440
|
var import_react19 = require("@floating-ui/react");
|
|
3511
3441
|
|
|
@@ -3676,7 +3606,7 @@ var CanvasInlineEditor = ({
|
|
|
3676
3606
|
return null;
|
|
3677
3607
|
}
|
|
3678
3608
|
return /* @__PURE__ */ React10.createElement(import_ui5.ThemeProvider, null, /* @__PURE__ */ React10.createElement(InlineEditingOverlay, { expectedTag, rootElement, id }), /* @__PURE__ */ React10.createElement(
|
|
3679
|
-
|
|
3609
|
+
import_editor_controls3.InlineEditor,
|
|
3680
3610
|
{
|
|
3681
3611
|
onEditorCreate: setEditor,
|
|
3682
3612
|
mountElement: contentElement,
|
|
@@ -3728,7 +3658,7 @@ var InlineEditingToolbar = ({ anchor, editor, id }) => {
|
|
|
3728
3658
|
pointerEvents: "none"
|
|
3729
3659
|
}
|
|
3730
3660
|
},
|
|
3731
|
-
/* @__PURE__ */ React10.createElement(
|
|
3661
|
+
/* @__PURE__ */ React10.createElement(import_editor_controls3.InlineEditorToolbar, { editor, elementId: id })
|
|
3732
3662
|
));
|
|
3733
3663
|
};
|
|
3734
3664
|
|
package/dist/index.mjs
CHANGED
|
@@ -2059,6 +2059,12 @@ var timeRangeTransformer = createTransformer((value) => {
|
|
|
2059
2059
|
};
|
|
2060
2060
|
});
|
|
2061
2061
|
|
|
2062
|
+
// src/transformers/shared/icon-transformer.ts
|
|
2063
|
+
import {
|
|
2064
|
+
getFontAwesome7IconName,
|
|
2065
|
+
resolveFontAwesome7Icon
|
|
2066
|
+
} from "@elementor/editor-controls";
|
|
2067
|
+
|
|
2062
2068
|
// src/transformers/shared/process-svg-content.ts
|
|
2063
2069
|
import DOMPurify2 from "dompurify";
|
|
2064
2070
|
var SVG_INLINE_STYLES = "width: 100%; height: 100%; overflow: unset;";
|
|
@@ -2081,128 +2087,36 @@ function processSvgContent(svgText) {
|
|
|
2081
2087
|
}
|
|
2082
2088
|
|
|
2083
2089
|
// src/transformers/shared/icon-transformer.ts
|
|
2084
|
-
var
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
aliases: 2,
|
|
2088
|
-
unicode: 3,
|
|
2089
|
-
path: 4
|
|
2090
|
-
};
|
|
2091
|
-
var fontAwesomeJsonCache = /* @__PURE__ */ new Map();
|
|
2090
|
+
var EMPTY_ICON_RESULT = { html: null, url: null };
|
|
2091
|
+
var ICON_SVG_SIZE = "100%";
|
|
2092
|
+
var ICON_SVG_OVERFLOW = "visible";
|
|
2092
2093
|
var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
2093
2094
|
const iconValue = typeof value.value === "string" ? value.value : null;
|
|
2094
2095
|
const library = typeof value.library === "string" ? value.library : null;
|
|
2095
2096
|
if (!iconValue || !library) {
|
|
2096
|
-
return
|
|
2097
|
+
return EMPTY_ICON_RESULT;
|
|
2097
2098
|
}
|
|
2098
|
-
const iconName =
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
return { html: null, url: null };
|
|
2099
|
+
const iconName = getFontAwesome7IconName(iconValue);
|
|
2100
|
+
if (!iconName) {
|
|
2101
|
+
return EMPTY_ICON_RESULT;
|
|
2102
2102
|
}
|
|
2103
|
-
const
|
|
2104
|
-
const iconData = icons?.[iconName];
|
|
2103
|
+
const iconData = await resolveFontAwesome7Icon(library, iconName, signal);
|
|
2105
2104
|
if (!iconData) {
|
|
2106
|
-
return
|
|
2105
|
+
return EMPTY_ICON_RESULT;
|
|
2107
2106
|
}
|
|
2108
2107
|
const svgText = buildFontAwesomeSvg(iconData);
|
|
2109
2108
|
if (!svgText) {
|
|
2110
|
-
return
|
|
2109
|
+
return EMPTY_ICON_RESULT;
|
|
2111
2110
|
}
|
|
2112
2111
|
const html = processIconSvgContent(svgText);
|
|
2113
2112
|
return { html, url: null };
|
|
2114
2113
|
});
|
|
2115
|
-
function getFontAwesomeIconName(iconValue) {
|
|
2116
|
-
const match = iconValue.match(/^fa\S*\s+fa-(.+)$/);
|
|
2117
|
-
return match?.[1] ?? null;
|
|
2118
|
-
}
|
|
2119
|
-
function getFontAwesomeJsonFileName(library) {
|
|
2120
|
-
const fileName = library.replace(/^fa-/, "");
|
|
2121
|
-
const config = getFontAwesome7EditorConfig();
|
|
2122
|
-
if (!config?.jsonFiles.includes(fileName)) {
|
|
2123
|
-
return null;
|
|
2124
|
-
}
|
|
2125
|
-
return fileName;
|
|
2126
|
-
}
|
|
2127
|
-
function getFontAwesome7EditorConfig() {
|
|
2128
|
-
const config = window.elementorCommon?.config?.fontAwesome?.v7;
|
|
2129
|
-
if (!config || !Array.isArray(config.jsonFiles) || typeof config.jsonBaseUrl !== "string" || config.jsonBaseUrl === "") {
|
|
2130
|
-
return null;
|
|
2131
|
-
}
|
|
2132
|
-
return {
|
|
2133
|
-
jsonFiles: config.jsonFiles,
|
|
2134
|
-
jsonBaseUrl: config.jsonBaseUrl
|
|
2135
|
-
};
|
|
2136
|
-
}
|
|
2137
|
-
async function fetchFontAwesomeIcons(jsonFileName, signal) {
|
|
2138
|
-
const cached = fontAwesomeJsonCache.get(jsonFileName);
|
|
2139
|
-
if (cached) {
|
|
2140
|
-
return cached;
|
|
2141
|
-
}
|
|
2142
|
-
const icons = await loadFontAwesomeIcons(jsonFileName, signal);
|
|
2143
|
-
if (icons) {
|
|
2144
|
-
fontAwesomeJsonCache.set(jsonFileName, icons);
|
|
2145
|
-
}
|
|
2146
|
-
return icons;
|
|
2147
|
-
}
|
|
2148
|
-
async function loadFontAwesomeIcons(jsonFileName, signal) {
|
|
2149
|
-
const config = getFontAwesome7EditorConfig();
|
|
2150
|
-
if (!config?.jsonFiles.includes(jsonFileName)) {
|
|
2151
|
-
return null;
|
|
2152
|
-
}
|
|
2153
|
-
try {
|
|
2154
|
-
const response = await fetch(`${config.jsonBaseUrl}${jsonFileName}.json`, {
|
|
2155
|
-
signal
|
|
2156
|
-
});
|
|
2157
|
-
if (!response.ok) {
|
|
2158
|
-
return null;
|
|
2159
|
-
}
|
|
2160
|
-
const data = await response.json();
|
|
2161
|
-
const icons = data.icons;
|
|
2162
|
-
if (!icons || typeof icons !== "object") {
|
|
2163
|
-
return null;
|
|
2164
|
-
}
|
|
2165
|
-
return indexFontAwesomeIcons(icons);
|
|
2166
|
-
} catch {
|
|
2167
|
-
return null;
|
|
2168
|
-
}
|
|
2169
|
-
}
|
|
2170
|
-
function indexFontAwesomeIcons(icons) {
|
|
2171
|
-
const index = {};
|
|
2172
|
-
for (const [name, iconData] of Object.entries(icons)) {
|
|
2173
|
-
if (!isValidIconTuple(iconData)) {
|
|
2174
|
-
continue;
|
|
2175
|
-
}
|
|
2176
|
-
index[name] = iconData;
|
|
2177
|
-
for (const alias of iconData[FONT_AWESOME_JSON.aliases]) {
|
|
2178
|
-
if (typeof alias === "string" && alias !== "" && !index[alias]) {
|
|
2179
|
-
index[alias] = iconData;
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
}
|
|
2183
|
-
return index;
|
|
2184
|
-
}
|
|
2185
|
-
function isValidIconTuple(iconData) {
|
|
2186
|
-
return Array.isArray(iconData) && iconData.length >= 5 && typeof iconData[FONT_AWESOME_JSON.width] === "number" && typeof iconData[FONT_AWESOME_JSON.height] === "number" && Array.isArray(iconData[FONT_AWESOME_JSON.aliases]);
|
|
2187
|
-
}
|
|
2188
2114
|
function buildFontAwesomeSvg(iconData) {
|
|
2189
|
-
|
|
2190
|
-
const height = iconData[FONT_AWESOME_JSON.height];
|
|
2191
|
-
const paths = normalizePaths(iconData[FONT_AWESOME_JSON.path]);
|
|
2192
|
-
if (paths.length === 0) {
|
|
2115
|
+
if (iconData.paths.length === 0) {
|
|
2193
2116
|
return null;
|
|
2194
2117
|
}
|
|
2195
|
-
const pathMarkup = paths.map((path) => `<path d="${escapeSvgPath(path)}"></path>`).join("");
|
|
2196
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}">${pathMarkup}</svg>`;
|
|
2197
|
-
}
|
|
2198
|
-
function normalizePaths(pathData) {
|
|
2199
|
-
if (typeof pathData === "string" && pathData !== "") {
|
|
2200
|
-
return [pathData];
|
|
2201
|
-
}
|
|
2202
|
-
if (!Array.isArray(pathData)) {
|
|
2203
|
-
return [];
|
|
2204
|
-
}
|
|
2205
|
-
return pathData.filter((path) => typeof path === "string" && path !== "");
|
|
2118
|
+
const pathMarkup = iconData.paths.map((path) => `<path d="${escapeSvgPath(path)}"></path>`).join("");
|
|
2119
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${iconData.width} ${iconData.height}">${pathMarkup}</svg>`;
|
|
2206
2120
|
}
|
|
2207
2121
|
function escapeSvgPath(path) {
|
|
2208
2122
|
return path.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -2219,9 +2133,9 @@ function processIconSvgContent(svgText) {
|
|
|
2219
2133
|
return null;
|
|
2220
2134
|
}
|
|
2221
2135
|
svgElement.setAttribute("aria-hidden", "true");
|
|
2222
|
-
svgElement.style.setProperty("width",
|
|
2223
|
-
svgElement.style.setProperty("height",
|
|
2224
|
-
svgElement.style.setProperty("overflow",
|
|
2136
|
+
svgElement.style.setProperty("width", ICON_SVG_SIZE);
|
|
2137
|
+
svgElement.style.setProperty("height", ICON_SVG_SIZE);
|
|
2138
|
+
svgElement.style.setProperty("overflow", ICON_SVG_OVERFLOW);
|
|
2225
2139
|
return svgElement.outerHTML;
|
|
2226
2140
|
}
|
|
2227
2141
|
|
|
@@ -3068,6 +2982,7 @@ function createTemplatedElementView({
|
|
|
3068
2982
|
}
|
|
3069
2983
|
|
|
3070
2984
|
// src/legacy/create-nested-templated-element-type.ts
|
|
2985
|
+
var STYLES_REFERENCE_UNTRACKED = /* @__PURE__ */ Symbol("styles-reference-untracked");
|
|
3071
2986
|
function canBeNestedTemplated(element) {
|
|
3072
2987
|
return canBeTemplated(element) && "support_nesting" in element && !!element.support_nesting;
|
|
3073
2988
|
}
|
|
@@ -3127,6 +3042,7 @@ function createNestedTemplatedElementView({
|
|
|
3127
3042
|
return AtomicElementBaseView.extend({
|
|
3128
3043
|
_abortController: null,
|
|
3129
3044
|
_lastResolvedSettingsHash: null,
|
|
3045
|
+
_lastRenderedStyles: STYLES_REFERENCE_UNTRACKED,
|
|
3130
3046
|
_domUpdateWasSkipped: false,
|
|
3131
3047
|
template: false,
|
|
3132
3048
|
attributes() {
|
|
@@ -3163,6 +3079,23 @@ function createNestedTemplatedElementView({
|
|
|
3163
3079
|
this._initAlpine();
|
|
3164
3080
|
});
|
|
3165
3081
|
this.model.trigger("render:complete");
|
|
3082
|
+
this._notifyStylesChanged();
|
|
3083
|
+
},
|
|
3084
|
+
// `document/elements/create` fires before the nested template has fully painted, so the
|
|
3085
|
+
// styles provider rebuilds CSS too early and misses the new local class IDs. Dispatching
|
|
3086
|
+
// ELEMENT_STYLE_CHANGE_EVENT here — after the template and all children are in the DOM —
|
|
3087
|
+
// gives the provider a second chance to regenerate CSS against the live class names.
|
|
3088
|
+
//
|
|
3089
|
+
// The reference-equality guard prevents a parent re-render from emitting one event per
|
|
3090
|
+
// unchanged descendant. Use a sentinel for the initial state — otherwise elements with no
|
|
3091
|
+
// local styles (undefined === undefined) would never notify, and descendants like e-heading
|
|
3092
|
+
// that rely on this post-paint refresh would lose their CSS after detach.
|
|
3093
|
+
_notifyStylesChanged() {
|
|
3094
|
+
const styles = this.model.get("styles");
|
|
3095
|
+
if (this._lastRenderedStyles !== STYLES_REFERENCE_UNTRACKED && styles === this._lastRenderedStyles) {
|
|
3096
|
+
return;
|
|
3097
|
+
}
|
|
3098
|
+
this._lastRenderedStyles = styles;
|
|
3166
3099
|
window.dispatchEvent(new CustomEvent(ELEMENT_STYLE_CHANGE_EVENT2));
|
|
3167
3100
|
},
|
|
3168
3101
|
async _renderTemplate() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "4.3.0-
|
|
4
|
+
"version": "4.3.0-beta3",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,26 +37,26 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "4.3.0-
|
|
41
|
-
"@elementor/editor-controls": "4.3.0-
|
|
42
|
-
"@elementor/editor-documents": "4.3.0-
|
|
43
|
-
"@elementor/editor-elements": "4.3.0-
|
|
44
|
-
"@elementor/editor-interactions": "4.3.0-
|
|
45
|
-
"@elementor/editor-mcp": "4.3.0-
|
|
46
|
-
"@elementor/editor-notifications": "4.3.0-
|
|
47
|
-
"@elementor/editor-props": "4.3.0-
|
|
48
|
-
"@elementor/editor-responsive": "4.3.0-
|
|
49
|
-
"@elementor/editor-styles": "4.3.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "4.3.0-
|
|
51
|
-
"@elementor/editor-ui": "4.3.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "4.3.0-
|
|
53
|
-
"@elementor/events": "4.3.0-
|
|
54
|
-
"@elementor/http-client": "4.3.0-
|
|
55
|
-
"@elementor/schema": "4.3.0-
|
|
56
|
-
"@elementor/twing": "4.3.0-
|
|
40
|
+
"@elementor/editor": "4.3.0-beta3",
|
|
41
|
+
"@elementor/editor-controls": "4.3.0-beta3",
|
|
42
|
+
"@elementor/editor-documents": "4.3.0-beta3",
|
|
43
|
+
"@elementor/editor-elements": "4.3.0-beta3",
|
|
44
|
+
"@elementor/editor-interactions": "4.3.0-beta3",
|
|
45
|
+
"@elementor/editor-mcp": "4.3.0-beta3",
|
|
46
|
+
"@elementor/editor-notifications": "4.3.0-beta3",
|
|
47
|
+
"@elementor/editor-props": "4.3.0-beta3",
|
|
48
|
+
"@elementor/editor-responsive": "4.3.0-beta3",
|
|
49
|
+
"@elementor/editor-styles": "4.3.0-beta3",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.3.0-beta3",
|
|
51
|
+
"@elementor/editor-ui": "4.3.0-beta3",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.3.0-beta3",
|
|
53
|
+
"@elementor/events": "4.3.0-beta3",
|
|
54
|
+
"@elementor/http-client": "4.3.0-beta3",
|
|
55
|
+
"@elementor/schema": "4.3.0-beta3",
|
|
56
|
+
"@elementor/twing": "4.3.0-beta3",
|
|
57
57
|
"@elementor/ui": "1.37.5",
|
|
58
|
-
"@elementor/utils": "4.3.0-
|
|
59
|
-
"@elementor/wp-media": "4.3.0-
|
|
58
|
+
"@elementor/utils": "4.3.0-beta3",
|
|
59
|
+
"@elementor/wp-media": "4.3.0-beta3",
|
|
60
60
|
"@floating-ui/react": "^0.27.5",
|
|
61
61
|
"@wordpress/i18n": "^5.13.0",
|
|
62
62
|
"dompurify": "^3.2.6"
|
|
@@ -12,7 +12,13 @@ import {
|
|
|
12
12
|
setupTwigRenderer,
|
|
13
13
|
waitForChildrenToComplete,
|
|
14
14
|
} from './twig-rendering-utils';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
type ElementModel,
|
|
17
|
+
type ElementType,
|
|
18
|
+
type ElementView,
|
|
19
|
+
type LegacyWindow,
|
|
20
|
+
type NestedTemplatedElementViewClass,
|
|
21
|
+
} from './types';
|
|
16
22
|
|
|
17
23
|
export type NestedTemplatedElementConfig = TemplatedElementConfig & {
|
|
18
24
|
allowed_child_types?: string[];
|
|
@@ -21,6 +27,8 @@ export type NestedTemplatedElementConfig = TemplatedElementConfig & {
|
|
|
21
27
|
|
|
22
28
|
export type ModelExtensions = Record< string, unknown >;
|
|
23
29
|
|
|
30
|
+
const STYLES_REFERENCE_UNTRACKED = Symbol( 'styles-reference-untracked' );
|
|
31
|
+
|
|
24
32
|
export type CreateNestedTemplatedElementTypeOptions = {
|
|
25
33
|
type: string;
|
|
26
34
|
renderer: DomRenderer;
|
|
@@ -108,6 +116,7 @@ export function createNestedTemplatedElementView( {
|
|
|
108
116
|
return AtomicElementBaseView.extend( {
|
|
109
117
|
_abortController: null as AbortController | null,
|
|
110
118
|
_lastResolvedSettingsHash: null as string | null,
|
|
119
|
+
_lastRenderedStyles: STYLES_REFERENCE_UNTRACKED as typeof STYLES_REFERENCE_UNTRACKED | ElementModel[ 'styles' ],
|
|
111
120
|
_domUpdateWasSkipped: false,
|
|
112
121
|
|
|
113
122
|
template: false,
|
|
@@ -164,6 +173,27 @@ export function createNestedTemplatedElementView( {
|
|
|
164
173
|
} );
|
|
165
174
|
|
|
166
175
|
this.model.trigger( 'render:complete' );
|
|
176
|
+
this._notifyStylesChanged();
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
// `document/elements/create` fires before the nested template has fully painted, so the
|
|
180
|
+
// styles provider rebuilds CSS too early and misses the new local class IDs. Dispatching
|
|
181
|
+
// ELEMENT_STYLE_CHANGE_EVENT here — after the template and all children are in the DOM —
|
|
182
|
+
// gives the provider a second chance to regenerate CSS against the live class names.
|
|
183
|
+
//
|
|
184
|
+
// The reference-equality guard prevents a parent re-render from emitting one event per
|
|
185
|
+
// unchanged descendant. Use a sentinel for the initial state — otherwise elements with no
|
|
186
|
+
// local styles (undefined === undefined) would never notify, and descendants like e-heading
|
|
187
|
+
// that rely on this post-paint refresh would lose their CSS after detach.
|
|
188
|
+
_notifyStylesChanged() {
|
|
189
|
+
const styles = this.model.get( 'styles' );
|
|
190
|
+
|
|
191
|
+
if ( this._lastRenderedStyles !== STYLES_REFERENCE_UNTRACKED && styles === this._lastRenderedStyles ) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
this._lastRenderedStyles = styles;
|
|
196
|
+
|
|
167
197
|
window.dispatchEvent( new CustomEvent( ELEMENT_STYLE_CHANGE_EVENT ) );
|
|
168
198
|
},
|
|
169
199
|
|
package/src/legacy/types.ts
CHANGED
|
@@ -229,6 +229,7 @@ export type ElementModel = {
|
|
|
229
229
|
elType: string;
|
|
230
230
|
settings: BackboneModel< Props >;
|
|
231
231
|
editor_settings: Record< string, unknown >;
|
|
232
|
+
styles?: V1ElementModelProps[ 'styles' ];
|
|
232
233
|
widgetType: string;
|
|
233
234
|
editSettings?: BackboneModel< { inactive?: boolean } >;
|
|
234
235
|
elements?: BackboneCollection< ElementModel >;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { resetFontAwesome7IconsCache } from '@elementor/editor-controls';
|
|
1
2
|
import { iconPropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
|
|
2
3
|
|
|
3
4
|
import { iconPropType } from '../../../__tests__/prop-types';
|
|
4
5
|
import { initSettingsTransformers } from '../../../init-settings-transformers';
|
|
5
6
|
import { createPropsResolver } from '../../../renderers/create-props-resolver';
|
|
6
7
|
import { settingsTransformersRegistry } from '../../../settings-transformers-registry';
|
|
7
|
-
import { resetFontAwesomeIconsCache } from '../icon-transformer';
|
|
8
8
|
|
|
9
9
|
const STAR_PATH = 'M0 0h100v100H0z';
|
|
10
10
|
const STAR_WIDTH = 576;
|
|
@@ -44,7 +44,7 @@ describe( 'iconTransformer', () => {
|
|
|
44
44
|
|
|
45
45
|
beforeEach( () => {
|
|
46
46
|
jest.clearAllMocks();
|
|
47
|
-
|
|
47
|
+
resetFontAwesome7IconsCache();
|
|
48
48
|
initSettingsTransformers();
|
|
49
49
|
window.elementorCommon = {
|
|
50
50
|
config: {
|
|
@@ -1,55 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type FontAwesome7IconDefinition,
|
|
3
|
+
getFontAwesome7IconName,
|
|
4
|
+
resolveFontAwesome7Icon,
|
|
5
|
+
} from '@elementor/editor-controls';
|
|
6
|
+
|
|
1
7
|
import { createTransformer } from '../create-transformer';
|
|
2
8
|
import type { TransformerOptions } from '../types';
|
|
3
9
|
import { processSvgContent } from './process-svg-content';
|
|
4
10
|
|
|
11
|
+
const EMPTY_ICON_RESULT = { html: null, url: null };
|
|
12
|
+
const ICON_SVG_SIZE = '100%';
|
|
13
|
+
const ICON_SVG_OVERFLOW = 'visible';
|
|
14
|
+
|
|
5
15
|
type IconValue = {
|
|
6
16
|
value?: unknown;
|
|
7
17
|
library?: unknown;
|
|
8
18
|
};
|
|
9
19
|
|
|
10
|
-
type FontAwesomeIconJson = [ number, number, unknown[], unknown, string | string[] ];
|
|
11
|
-
|
|
12
|
-
type FontAwesome7EditorConfig = {
|
|
13
|
-
jsonFiles: string[];
|
|
14
|
-
jsonBaseUrl: string;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const FONT_AWESOME_JSON = {
|
|
18
|
-
width: 0,
|
|
19
|
-
height: 1,
|
|
20
|
-
aliases: 2,
|
|
21
|
-
unicode: 3,
|
|
22
|
-
path: 4,
|
|
23
|
-
} as const;
|
|
24
|
-
|
|
25
|
-
const fontAwesomeJsonCache = new Map< string, Record< string, FontAwesomeIconJson > >();
|
|
26
|
-
|
|
27
20
|
export const iconTransformer = createTransformer( async ( value: IconValue, { signal }: TransformerOptions ) => {
|
|
28
21
|
const iconValue = typeof value.value === 'string' ? value.value : null;
|
|
29
22
|
const library = typeof value.library === 'string' ? value.library : null;
|
|
30
23
|
|
|
31
24
|
if ( ! iconValue || ! library ) {
|
|
32
|
-
return
|
|
25
|
+
return EMPTY_ICON_RESULT;
|
|
33
26
|
}
|
|
34
27
|
|
|
35
|
-
const iconName =
|
|
36
|
-
const jsonFileName = getFontAwesomeJsonFileName( library );
|
|
28
|
+
const iconName = getFontAwesome7IconName( iconValue );
|
|
37
29
|
|
|
38
|
-
if ( ! iconName
|
|
39
|
-
return
|
|
30
|
+
if ( ! iconName ) {
|
|
31
|
+
return EMPTY_ICON_RESULT;
|
|
40
32
|
}
|
|
41
33
|
|
|
42
|
-
const
|
|
43
|
-
const iconData = icons?.[ iconName ];
|
|
34
|
+
const iconData = await resolveFontAwesome7Icon( library, iconName, signal );
|
|
44
35
|
|
|
45
36
|
if ( ! iconData ) {
|
|
46
|
-
return
|
|
37
|
+
return EMPTY_ICON_RESULT;
|
|
47
38
|
}
|
|
48
39
|
|
|
49
40
|
const svgText = buildFontAwesomeSvg( iconData );
|
|
50
41
|
|
|
51
42
|
if ( ! svgText ) {
|
|
52
|
-
return
|
|
43
|
+
return EMPTY_ICON_RESULT;
|
|
53
44
|
}
|
|
54
45
|
|
|
55
46
|
const html = processIconSvgContent( svgText );
|
|
@@ -57,146 +48,14 @@ export const iconTransformer = createTransformer( async ( value: IconValue, { si
|
|
|
57
48
|
return { html, url: null };
|
|
58
49
|
} );
|
|
59
50
|
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return match?.[ 1 ] ?? null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function getFontAwesomeJsonFileName( library: string ): string | null {
|
|
67
|
-
const fileName = library.replace( /^fa-/, '' );
|
|
68
|
-
const config = getFontAwesome7EditorConfig();
|
|
69
|
-
|
|
70
|
-
if ( ! config?.jsonFiles.includes( fileName ) ) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return fileName;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function getFontAwesome7EditorConfig(): FontAwesome7EditorConfig | null {
|
|
78
|
-
const config = window.elementorCommon?.config?.fontAwesome?.v7;
|
|
79
|
-
|
|
80
|
-
if (
|
|
81
|
-
! config ||
|
|
82
|
-
! Array.isArray( config.jsonFiles ) ||
|
|
83
|
-
typeof config.jsonBaseUrl !== 'string' ||
|
|
84
|
-
config.jsonBaseUrl === ''
|
|
85
|
-
) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
jsonFiles: config.jsonFiles,
|
|
91
|
-
jsonBaseUrl: config.jsonBaseUrl,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async function fetchFontAwesomeIcons(
|
|
96
|
-
jsonFileName: string,
|
|
97
|
-
signal?: AbortSignal
|
|
98
|
-
): Promise< Record< string, FontAwesomeIconJson > | null > {
|
|
99
|
-
const cached = fontAwesomeJsonCache.get( jsonFileName );
|
|
100
|
-
|
|
101
|
-
if ( cached ) {
|
|
102
|
-
return cached;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const icons = await loadFontAwesomeIcons( jsonFileName, signal );
|
|
106
|
-
|
|
107
|
-
if ( icons ) {
|
|
108
|
-
fontAwesomeJsonCache.set( jsonFileName, icons );
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return icons;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async function loadFontAwesomeIcons(
|
|
115
|
-
jsonFileName: string,
|
|
116
|
-
signal?: AbortSignal
|
|
117
|
-
): Promise< Record< string, FontAwesomeIconJson > | null > {
|
|
118
|
-
const config = getFontAwesome7EditorConfig();
|
|
119
|
-
|
|
120
|
-
if ( ! config?.jsonFiles.includes( jsonFileName ) ) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
const response = await fetch( `${ config.jsonBaseUrl }${ jsonFileName }.json`, {
|
|
126
|
-
signal,
|
|
127
|
-
} );
|
|
128
|
-
|
|
129
|
-
if ( ! response.ok ) {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const data = ( await response.json() ) as { icons?: Record< string, FontAwesomeIconJson > };
|
|
134
|
-
const icons = data.icons;
|
|
135
|
-
|
|
136
|
-
if ( ! icons || typeof icons !== 'object' ) {
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return indexFontAwesomeIcons( icons );
|
|
141
|
-
} catch {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function indexFontAwesomeIcons( icons: Record< string, FontAwesomeIconJson > ): Record< string, FontAwesomeIconJson > {
|
|
147
|
-
const index: Record< string, FontAwesomeIconJson > = {};
|
|
148
|
-
|
|
149
|
-
for ( const [ name, iconData ] of Object.entries( icons ) ) {
|
|
150
|
-
if ( ! isValidIconTuple( iconData ) ) {
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
index[ name ] = iconData;
|
|
155
|
-
|
|
156
|
-
for ( const alias of iconData[ FONT_AWESOME_JSON.aliases ] ) {
|
|
157
|
-
if ( typeof alias === 'string' && alias !== '' && ! index[ alias ] ) {
|
|
158
|
-
index[ alias ] = iconData;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return index;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function isValidIconTuple( iconData: unknown ): iconData is FontAwesomeIconJson {
|
|
167
|
-
return (
|
|
168
|
-
Array.isArray( iconData ) &&
|
|
169
|
-
iconData.length >= 5 &&
|
|
170
|
-
typeof iconData[ FONT_AWESOME_JSON.width ] === 'number' &&
|
|
171
|
-
typeof iconData[ FONT_AWESOME_JSON.height ] === 'number' &&
|
|
172
|
-
Array.isArray( iconData[ FONT_AWESOME_JSON.aliases ] )
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function buildFontAwesomeSvg( iconData: FontAwesomeIconJson ): string | null {
|
|
177
|
-
const width = iconData[ FONT_AWESOME_JSON.width ];
|
|
178
|
-
const height = iconData[ FONT_AWESOME_JSON.height ];
|
|
179
|
-
const paths = normalizePaths( iconData[ FONT_AWESOME_JSON.path ] );
|
|
180
|
-
|
|
181
|
-
if ( paths.length === 0 ) {
|
|
51
|
+
function buildFontAwesomeSvg( iconData: FontAwesome7IconDefinition ): string | null {
|
|
52
|
+
if ( iconData.paths.length === 0 ) {
|
|
182
53
|
return null;
|
|
183
54
|
}
|
|
184
55
|
|
|
185
|
-
const pathMarkup = paths.map( ( path ) => `<path d="${ escapeSvgPath( path ) }"></path>` ).join( '' );
|
|
56
|
+
const pathMarkup = iconData.paths.map( ( path ) => `<path d="${ escapeSvgPath( path ) }"></path>` ).join( '' );
|
|
186
57
|
|
|
187
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${ width } ${ height }">${ pathMarkup }</svg>`;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function normalizePaths( pathData: string | string[] ): string[] {
|
|
191
|
-
if ( typeof pathData === 'string' && pathData !== '' ) {
|
|
192
|
-
return [ pathData ];
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if ( ! Array.isArray( pathData ) ) {
|
|
196
|
-
return [];
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return pathData.filter( ( path ): path is string => typeof path === 'string' && path !== '' );
|
|
58
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${ iconData.width } ${ iconData.height }">${ pathMarkup }</svg>`;
|
|
200
59
|
}
|
|
201
60
|
|
|
202
61
|
function escapeSvgPath( path: string ): string {
|
|
@@ -219,13 +78,9 @@ function processIconSvgContent( svgText: string ): string | null {
|
|
|
219
78
|
}
|
|
220
79
|
|
|
221
80
|
svgElement.setAttribute( 'aria-hidden', 'true' );
|
|
222
|
-
svgElement.style.setProperty( 'width',
|
|
223
|
-
svgElement.style.setProperty( 'height',
|
|
224
|
-
svgElement.style.setProperty( 'overflow',
|
|
81
|
+
svgElement.style.setProperty( 'width', ICON_SVG_SIZE );
|
|
82
|
+
svgElement.style.setProperty( 'height', ICON_SVG_SIZE );
|
|
83
|
+
svgElement.style.setProperty( 'overflow', ICON_SVG_OVERFLOW );
|
|
225
84
|
|
|
226
85
|
return svgElement.outerHTML;
|
|
227
86
|
}
|
|
228
|
-
|
|
229
|
-
export function resetFontAwesomeIconsCache() {
|
|
230
|
-
fontAwesomeJsonCache.clear();
|
|
231
|
-
}
|