@elementor/editor-canvas 4.4.0-1077 → 4.4.0-1079
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.js +24 -113
- package/dist/index.mjs +22 -108
- package/package.json +20 -20
- package/src/transformers/shared/__tests__/icon-transformer.test.ts +2 -2
- package/src/transformers/shared/icon-transformer.ts +24 -169
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
|
});
|
|
@@ -3505,7 +3416,7 @@ var ReplacementBase = class {
|
|
|
3505
3416
|
// src/legacy/replacements/inline-editing/canvas-inline-editor.tsx
|
|
3506
3417
|
var React10 = __toESM(require("react"));
|
|
3507
3418
|
var import_react18 = require("react");
|
|
3508
|
-
var
|
|
3419
|
+
var import_editor_controls3 = require("@elementor/editor-controls");
|
|
3509
3420
|
var import_ui5 = require("@elementor/ui");
|
|
3510
3421
|
var import_react19 = require("@floating-ui/react");
|
|
3511
3422
|
|
|
@@ -3676,7 +3587,7 @@ var CanvasInlineEditor = ({
|
|
|
3676
3587
|
return null;
|
|
3677
3588
|
}
|
|
3678
3589
|
return /* @__PURE__ */ React10.createElement(import_ui5.ThemeProvider, null, /* @__PURE__ */ React10.createElement(InlineEditingOverlay, { expectedTag, rootElement, id }), /* @__PURE__ */ React10.createElement(
|
|
3679
|
-
|
|
3590
|
+
import_editor_controls3.InlineEditor,
|
|
3680
3591
|
{
|
|
3681
3592
|
onEditorCreate: setEditor,
|
|
3682
3593
|
mountElement: contentElement,
|
|
@@ -3728,7 +3639,7 @@ var InlineEditingToolbar = ({ anchor, editor, id }) => {
|
|
|
3728
3639
|
pointerEvents: "none"
|
|
3729
3640
|
}
|
|
3730
3641
|
},
|
|
3731
|
-
/* @__PURE__ */ React10.createElement(
|
|
3642
|
+
/* @__PURE__ */ React10.createElement(import_editor_controls3.InlineEditorToolbar, { editor, elementId: id })
|
|
3732
3643
|
));
|
|
3733
3644
|
};
|
|
3734
3645
|
|
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
|
|
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.4.0-
|
|
4
|
+
"version": "4.4.0-1079",
|
|
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.4.0-
|
|
41
|
-
"@elementor/editor-controls": "4.4.0-
|
|
42
|
-
"@elementor/editor-documents": "4.4.0-
|
|
43
|
-
"@elementor/editor-elements": "4.4.0-
|
|
44
|
-
"@elementor/editor-interactions": "4.4.0-
|
|
45
|
-
"@elementor/editor-mcp": "4.4.0-
|
|
46
|
-
"@elementor/editor-notifications": "4.4.0-
|
|
47
|
-
"@elementor/editor-props": "4.4.0-
|
|
48
|
-
"@elementor/editor-responsive": "4.4.0-
|
|
49
|
-
"@elementor/editor-styles": "4.4.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "4.4.0-
|
|
51
|
-
"@elementor/editor-ui": "4.4.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "4.4.0-
|
|
53
|
-
"@elementor/events": "4.4.0-
|
|
54
|
-
"@elementor/http-client": "4.4.0-
|
|
55
|
-
"@elementor/schema": "4.4.0-
|
|
56
|
-
"@elementor/twing": "4.4.0-
|
|
40
|
+
"@elementor/editor": "4.4.0-1079",
|
|
41
|
+
"@elementor/editor-controls": "4.4.0-1079",
|
|
42
|
+
"@elementor/editor-documents": "4.4.0-1079",
|
|
43
|
+
"@elementor/editor-elements": "4.4.0-1079",
|
|
44
|
+
"@elementor/editor-interactions": "4.4.0-1079",
|
|
45
|
+
"@elementor/editor-mcp": "4.4.0-1079",
|
|
46
|
+
"@elementor/editor-notifications": "4.4.0-1079",
|
|
47
|
+
"@elementor/editor-props": "4.4.0-1079",
|
|
48
|
+
"@elementor/editor-responsive": "4.4.0-1079",
|
|
49
|
+
"@elementor/editor-styles": "4.4.0-1079",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.4.0-1079",
|
|
51
|
+
"@elementor/editor-ui": "4.4.0-1079",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.4.0-1079",
|
|
53
|
+
"@elementor/events": "4.4.0-1079",
|
|
54
|
+
"@elementor/http-client": "4.4.0-1079",
|
|
55
|
+
"@elementor/schema": "4.4.0-1079",
|
|
56
|
+
"@elementor/twing": "4.4.0-1079",
|
|
57
57
|
"@elementor/ui": "1.37.5",
|
|
58
|
-
"@elementor/utils": "4.4.0-
|
|
59
|
-
"@elementor/wp-media": "4.4.0-
|
|
58
|
+
"@elementor/utils": "4.4.0-1079",
|
|
59
|
+
"@elementor/wp-media": "4.4.0-1079",
|
|
60
60
|
"@floating-ui/react": "^0.27.5",
|
|
61
61
|
"@wordpress/i18n": "^5.13.0",
|
|
62
62
|
"dompurify": "^3.2.6"
|
|
@@ -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
|
-
}
|