@elementor/editor-canvas 4.3.0-beta1 → 4.3.0-beta2
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 +90 -34
- package/dist/index.mjs +90 -34
- package/package.json +20 -20
- package/src/__tests__/flex-transformer.test.ts +11 -11
- package/src/__tests__/prop-types.ts +11 -0
- package/src/transformers/shared/__tests__/icon-transformer.test.ts +132 -7
- package/src/transformers/shared/icon-transformer.ts +123 -14
- package/src/transformers/styles/flex-transformer.ts +11 -32
package/dist/index.js
CHANGED
|
@@ -2132,6 +2132,8 @@ function processSvgContent(svgText) {
|
|
|
2132
2132
|
var FONT_AWESOME_JSON = {
|
|
2133
2133
|
width: 0,
|
|
2134
2134
|
height: 1,
|
|
2135
|
+
aliases: 2,
|
|
2136
|
+
unicode: 3,
|
|
2135
2137
|
path: 4
|
|
2136
2138
|
};
|
|
2137
2139
|
var fontAwesomeJsonCache = /* @__PURE__ */ new Map();
|
|
@@ -2152,7 +2154,10 @@ var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2152
2154
|
return { html: null, url: null };
|
|
2153
2155
|
}
|
|
2154
2156
|
const svgText = buildFontAwesomeSvg(iconData);
|
|
2155
|
-
|
|
2157
|
+
if (!svgText) {
|
|
2158
|
+
return { html: null, url: null };
|
|
2159
|
+
}
|
|
2160
|
+
const html = processIconSvgContent(svgText);
|
|
2156
2161
|
return { html, url: null };
|
|
2157
2162
|
});
|
|
2158
2163
|
function getFontAwesomeIconName(iconValue) {
|
|
@@ -2160,14 +2165,22 @@ function getFontAwesomeIconName(iconValue) {
|
|
|
2160
2165
|
return match?.[1] ?? null;
|
|
2161
2166
|
}
|
|
2162
2167
|
function getFontAwesomeJsonFileName(library) {
|
|
2163
|
-
|
|
2168
|
+
const fileName = library.replace(/^fa-/, "");
|
|
2169
|
+
const config = getFontAwesome7EditorConfig();
|
|
2170
|
+
if (!config?.jsonFiles.includes(fileName)) {
|
|
2164
2171
|
return null;
|
|
2165
2172
|
}
|
|
2166
|
-
return
|
|
2173
|
+
return fileName;
|
|
2167
2174
|
}
|
|
2168
|
-
function
|
|
2169
|
-
const
|
|
2170
|
-
|
|
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
|
+
};
|
|
2171
2184
|
}
|
|
2172
2185
|
async function fetchFontAwesomeIcons(jsonFileName, signal) {
|
|
2173
2186
|
const cached = fontAwesomeJsonCache.get(jsonFileName);
|
|
@@ -2181,26 +2194,83 @@ async function fetchFontAwesomeIcons(jsonFileName, signal) {
|
|
|
2181
2194
|
return icons;
|
|
2182
2195
|
}
|
|
2183
2196
|
async function loadFontAwesomeIcons(jsonFileName, signal) {
|
|
2184
|
-
const
|
|
2185
|
-
if (!
|
|
2197
|
+
const config = getFontAwesome7EditorConfig();
|
|
2198
|
+
if (!config?.jsonFiles.includes(jsonFileName)) {
|
|
2186
2199
|
return null;
|
|
2187
2200
|
}
|
|
2188
2201
|
try {
|
|
2189
|
-
const response = await fetch(`${
|
|
2202
|
+
const response = await fetch(`${config.jsonBaseUrl}${jsonFileName}.json`, {
|
|
2203
|
+
signal
|
|
2204
|
+
});
|
|
2190
2205
|
if (!response.ok) {
|
|
2191
2206
|
return null;
|
|
2192
2207
|
}
|
|
2193
2208
|
const data = await response.json();
|
|
2194
|
-
|
|
2209
|
+
const icons = data.icons;
|
|
2210
|
+
if (!icons || typeof icons !== "object") {
|
|
2211
|
+
return null;
|
|
2212
|
+
}
|
|
2213
|
+
return indexFontAwesomeIcons(icons);
|
|
2195
2214
|
} catch {
|
|
2196
2215
|
return null;
|
|
2197
2216
|
}
|
|
2198
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
|
+
}
|
|
2199
2236
|
function buildFontAwesomeSvg(iconData) {
|
|
2200
2237
|
const width = iconData[FONT_AWESOME_JSON.width];
|
|
2201
2238
|
const height = iconData[FONT_AWESOME_JSON.height];
|
|
2202
|
-
const
|
|
2203
|
-
|
|
2239
|
+
const paths = normalizePaths(iconData[FONT_AWESOME_JSON.path]);
|
|
2240
|
+
if (paths.length === 0) {
|
|
2241
|
+
return null;
|
|
2242
|
+
}
|
|
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 !== "");
|
|
2254
|
+
}
|
|
2255
|
+
function escapeSvgPath(path) {
|
|
2256
|
+
return path.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
2257
|
+
}
|
|
2258
|
+
function processIconSvgContent(svgText) {
|
|
2259
|
+
const html = processSvgContent(svgText);
|
|
2260
|
+
if (!html) {
|
|
2261
|
+
return null;
|
|
2262
|
+
}
|
|
2263
|
+
const parser = new DOMParser();
|
|
2264
|
+
const doc = parser.parseFromString(html, "image/svg+xml");
|
|
2265
|
+
const svgElement = doc.querySelector("svg");
|
|
2266
|
+
if (!svgElement) {
|
|
2267
|
+
return null;
|
|
2268
|
+
}
|
|
2269
|
+
svgElement.setAttribute("aria-hidden", "true");
|
|
2270
|
+
svgElement.style.setProperty("width", "100%");
|
|
2271
|
+
svgElement.style.setProperty("height", "100%");
|
|
2272
|
+
svgElement.style.setProperty("overflow", "visible");
|
|
2273
|
+
return svgElement.outerHTML;
|
|
2204
2274
|
}
|
|
2205
2275
|
|
|
2206
2276
|
// src/transformers/shared/image-src-transformer.ts
|
|
@@ -2446,6 +2516,10 @@ var mapToFilterFunctionString = (value) => {
|
|
|
2446
2516
|
};
|
|
2447
2517
|
|
|
2448
2518
|
// src/transformers/styles/flex-transformer.ts
|
|
2519
|
+
var DEFAULT_FLEX_GROW = 0;
|
|
2520
|
+
var DEFAULT_FLEX_SHRINK = 1;
|
|
2521
|
+
var DEFAULT_FLEX_BASIS = "auto";
|
|
2522
|
+
var formatBasis = (basis) => typeof basis === "object" && basis.size !== void 0 ? `${basis.size}${basis.unit || ""}` : basis;
|
|
2449
2523
|
var flexTransformer = createTransformer((value) => {
|
|
2450
2524
|
const grow = value.flexGrow;
|
|
2451
2525
|
const shrink = value.flexShrink;
|
|
@@ -2456,28 +2530,10 @@ var flexTransformer = createTransformer((value) => {
|
|
|
2456
2530
|
if (!hasGrow && !hasShrink && !hasBasis) {
|
|
2457
2531
|
return null;
|
|
2458
2532
|
}
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
return `${grow} ${shrink}`;
|
|
2464
|
-
}
|
|
2465
|
-
if (hasGrow && !hasShrink && hasBasis) {
|
|
2466
|
-
return `${grow} 1 ${typeof basis === "object" && basis.size !== void 0 ? `${basis.size}${basis.unit || ""}` : basis}`;
|
|
2467
|
-
}
|
|
2468
|
-
if (!hasGrow && hasShrink && hasBasis) {
|
|
2469
|
-
return `0 ${shrink} ${typeof basis === "object" && basis.size !== void 0 ? `${basis.size}${basis.unit || ""}` : basis}`;
|
|
2470
|
-
}
|
|
2471
|
-
if (hasGrow && !hasShrink && !hasBasis) {
|
|
2472
|
-
return `${grow}`;
|
|
2473
|
-
}
|
|
2474
|
-
if (!hasGrow && hasShrink && !hasBasis) {
|
|
2475
|
-
return `0 ${shrink}`;
|
|
2476
|
-
}
|
|
2477
|
-
if (!hasGrow && !hasShrink && hasBasis) {
|
|
2478
|
-
return `0 1 ${typeof basis === "object" && basis.size !== void 0 ? `${basis.size}${basis.unit || ""}` : basis}`;
|
|
2479
|
-
}
|
|
2480
|
-
return null;
|
|
2533
|
+
const growOut = hasGrow ? grow : DEFAULT_FLEX_GROW;
|
|
2534
|
+
const shrinkOut = hasShrink ? shrink : DEFAULT_FLEX_SHRINK;
|
|
2535
|
+
const basisOut = hasBasis ? formatBasis(basis) : DEFAULT_FLEX_BASIS;
|
|
2536
|
+
return `${growOut} ${shrinkOut} ${basisOut}`;
|
|
2481
2537
|
});
|
|
2482
2538
|
|
|
2483
2539
|
// src/transformers/styles/font-family-transformer.ts
|
package/dist/index.mjs
CHANGED
|
@@ -2084,6 +2084,8 @@ function processSvgContent(svgText) {
|
|
|
2084
2084
|
var FONT_AWESOME_JSON = {
|
|
2085
2085
|
width: 0,
|
|
2086
2086
|
height: 1,
|
|
2087
|
+
aliases: 2,
|
|
2088
|
+
unicode: 3,
|
|
2087
2089
|
path: 4
|
|
2088
2090
|
};
|
|
2089
2091
|
var fontAwesomeJsonCache = /* @__PURE__ */ new Map();
|
|
@@ -2104,7 +2106,10 @@ var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2104
2106
|
return { html: null, url: null };
|
|
2105
2107
|
}
|
|
2106
2108
|
const svgText = buildFontAwesomeSvg(iconData);
|
|
2107
|
-
|
|
2109
|
+
if (!svgText) {
|
|
2110
|
+
return { html: null, url: null };
|
|
2111
|
+
}
|
|
2112
|
+
const html = processIconSvgContent(svgText);
|
|
2108
2113
|
return { html, url: null };
|
|
2109
2114
|
});
|
|
2110
2115
|
function getFontAwesomeIconName(iconValue) {
|
|
@@ -2112,14 +2117,22 @@ function getFontAwesomeIconName(iconValue) {
|
|
|
2112
2117
|
return match?.[1] ?? null;
|
|
2113
2118
|
}
|
|
2114
2119
|
function getFontAwesomeJsonFileName(library) {
|
|
2115
|
-
|
|
2120
|
+
const fileName = library.replace(/^fa-/, "");
|
|
2121
|
+
const config = getFontAwesome7EditorConfig();
|
|
2122
|
+
if (!config?.jsonFiles.includes(fileName)) {
|
|
2116
2123
|
return null;
|
|
2117
2124
|
}
|
|
2118
|
-
return
|
|
2125
|
+
return fileName;
|
|
2119
2126
|
}
|
|
2120
|
-
function
|
|
2121
|
-
const
|
|
2122
|
-
|
|
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
|
+
};
|
|
2123
2136
|
}
|
|
2124
2137
|
async function fetchFontAwesomeIcons(jsonFileName, signal) {
|
|
2125
2138
|
const cached = fontAwesomeJsonCache.get(jsonFileName);
|
|
@@ -2133,26 +2146,83 @@ async function fetchFontAwesomeIcons(jsonFileName, signal) {
|
|
|
2133
2146
|
return icons;
|
|
2134
2147
|
}
|
|
2135
2148
|
async function loadFontAwesomeIcons(jsonFileName, signal) {
|
|
2136
|
-
const
|
|
2137
|
-
if (!
|
|
2149
|
+
const config = getFontAwesome7EditorConfig();
|
|
2150
|
+
if (!config?.jsonFiles.includes(jsonFileName)) {
|
|
2138
2151
|
return null;
|
|
2139
2152
|
}
|
|
2140
2153
|
try {
|
|
2141
|
-
const response = await fetch(`${
|
|
2154
|
+
const response = await fetch(`${config.jsonBaseUrl}${jsonFileName}.json`, {
|
|
2155
|
+
signal
|
|
2156
|
+
});
|
|
2142
2157
|
if (!response.ok) {
|
|
2143
2158
|
return null;
|
|
2144
2159
|
}
|
|
2145
2160
|
const data = await response.json();
|
|
2146
|
-
|
|
2161
|
+
const icons = data.icons;
|
|
2162
|
+
if (!icons || typeof icons !== "object") {
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
return indexFontAwesomeIcons(icons);
|
|
2147
2166
|
} catch {
|
|
2148
2167
|
return null;
|
|
2149
2168
|
}
|
|
2150
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
|
+
}
|
|
2151
2188
|
function buildFontAwesomeSvg(iconData) {
|
|
2152
2189
|
const width = iconData[FONT_AWESOME_JSON.width];
|
|
2153
2190
|
const height = iconData[FONT_AWESOME_JSON.height];
|
|
2154
|
-
const
|
|
2155
|
-
|
|
2191
|
+
const paths = normalizePaths(iconData[FONT_AWESOME_JSON.path]);
|
|
2192
|
+
if (paths.length === 0) {
|
|
2193
|
+
return null;
|
|
2194
|
+
}
|
|
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 !== "");
|
|
2206
|
+
}
|
|
2207
|
+
function escapeSvgPath(path) {
|
|
2208
|
+
return path.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
2209
|
+
}
|
|
2210
|
+
function processIconSvgContent(svgText) {
|
|
2211
|
+
const html = processSvgContent(svgText);
|
|
2212
|
+
if (!html) {
|
|
2213
|
+
return null;
|
|
2214
|
+
}
|
|
2215
|
+
const parser = new DOMParser();
|
|
2216
|
+
const doc = parser.parseFromString(html, "image/svg+xml");
|
|
2217
|
+
const svgElement = doc.querySelector("svg");
|
|
2218
|
+
if (!svgElement) {
|
|
2219
|
+
return null;
|
|
2220
|
+
}
|
|
2221
|
+
svgElement.setAttribute("aria-hidden", "true");
|
|
2222
|
+
svgElement.style.setProperty("width", "100%");
|
|
2223
|
+
svgElement.style.setProperty("height", "100%");
|
|
2224
|
+
svgElement.style.setProperty("overflow", "visible");
|
|
2225
|
+
return svgElement.outerHTML;
|
|
2156
2226
|
}
|
|
2157
2227
|
|
|
2158
2228
|
// src/transformers/shared/image-src-transformer.ts
|
|
@@ -2398,6 +2468,10 @@ var mapToFilterFunctionString = (value) => {
|
|
|
2398
2468
|
};
|
|
2399
2469
|
|
|
2400
2470
|
// src/transformers/styles/flex-transformer.ts
|
|
2471
|
+
var DEFAULT_FLEX_GROW = 0;
|
|
2472
|
+
var DEFAULT_FLEX_SHRINK = 1;
|
|
2473
|
+
var DEFAULT_FLEX_BASIS = "auto";
|
|
2474
|
+
var formatBasis = (basis) => typeof basis === "object" && basis.size !== void 0 ? `${basis.size}${basis.unit || ""}` : basis;
|
|
2401
2475
|
var flexTransformer = createTransformer((value) => {
|
|
2402
2476
|
const grow = value.flexGrow;
|
|
2403
2477
|
const shrink = value.flexShrink;
|
|
@@ -2408,28 +2482,10 @@ var flexTransformer = createTransformer((value) => {
|
|
|
2408
2482
|
if (!hasGrow && !hasShrink && !hasBasis) {
|
|
2409
2483
|
return null;
|
|
2410
2484
|
}
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
return `${grow} ${shrink}`;
|
|
2416
|
-
}
|
|
2417
|
-
if (hasGrow && !hasShrink && hasBasis) {
|
|
2418
|
-
return `${grow} 1 ${typeof basis === "object" && basis.size !== void 0 ? `${basis.size}${basis.unit || ""}` : basis}`;
|
|
2419
|
-
}
|
|
2420
|
-
if (!hasGrow && hasShrink && hasBasis) {
|
|
2421
|
-
return `0 ${shrink} ${typeof basis === "object" && basis.size !== void 0 ? `${basis.size}${basis.unit || ""}` : basis}`;
|
|
2422
|
-
}
|
|
2423
|
-
if (hasGrow && !hasShrink && !hasBasis) {
|
|
2424
|
-
return `${grow}`;
|
|
2425
|
-
}
|
|
2426
|
-
if (!hasGrow && hasShrink && !hasBasis) {
|
|
2427
|
-
return `0 ${shrink}`;
|
|
2428
|
-
}
|
|
2429
|
-
if (!hasGrow && !hasShrink && hasBasis) {
|
|
2430
|
-
return `0 1 ${typeof basis === "object" && basis.size !== void 0 ? `${basis.size}${basis.unit || ""}` : basis}`;
|
|
2431
|
-
}
|
|
2432
|
-
return null;
|
|
2485
|
+
const growOut = hasGrow ? grow : DEFAULT_FLEX_GROW;
|
|
2486
|
+
const shrinkOut = hasShrink ? shrink : DEFAULT_FLEX_SHRINK;
|
|
2487
|
+
const basisOut = hasBasis ? formatBasis(basis) : DEFAULT_FLEX_BASIS;
|
|
2488
|
+
return `${growOut} ${shrinkOut} ${basisOut}`;
|
|
2433
2489
|
});
|
|
2434
2490
|
|
|
2435
2491
|
// src/transformers/styles/font-family-transformer.ts
|
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-beta2",
|
|
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-beta2",
|
|
41
|
+
"@elementor/editor-controls": "4.3.0-beta2",
|
|
42
|
+
"@elementor/editor-documents": "4.3.0-beta2",
|
|
43
|
+
"@elementor/editor-elements": "4.3.0-beta2",
|
|
44
|
+
"@elementor/editor-interactions": "4.3.0-beta2",
|
|
45
|
+
"@elementor/editor-mcp": "4.3.0-beta2",
|
|
46
|
+
"@elementor/editor-notifications": "4.3.0-beta2",
|
|
47
|
+
"@elementor/editor-props": "4.3.0-beta2",
|
|
48
|
+
"@elementor/editor-responsive": "4.3.0-beta2",
|
|
49
|
+
"@elementor/editor-styles": "4.3.0-beta2",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.3.0-beta2",
|
|
51
|
+
"@elementor/editor-ui": "4.3.0-beta2",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.3.0-beta2",
|
|
53
|
+
"@elementor/events": "4.3.0-beta2",
|
|
54
|
+
"@elementor/http-client": "4.3.0-beta2",
|
|
55
|
+
"@elementor/schema": "4.3.0-beta2",
|
|
56
|
+
"@elementor/twing": "4.3.0-beta2",
|
|
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-beta2",
|
|
59
|
+
"@elementor/wp-media": "4.3.0-beta2",
|
|
60
60
|
"@floating-ui/react": "^0.27.5",
|
|
61
61
|
"@wordpress/i18n": "^5.13.0",
|
|
62
62
|
"dompurify": "^3.2.6"
|
|
@@ -68,7 +68,7 @@ describe( 'flexTransformer', () => {
|
|
|
68
68
|
} );
|
|
69
69
|
|
|
70
70
|
describe( 'when only two values are provided', () => {
|
|
71
|
-
it( 'should return "grow shrink" when grow and shrink are set', () => {
|
|
71
|
+
it( 'should return "grow shrink auto" when grow and shrink are set', () => {
|
|
72
72
|
// Arrange.
|
|
73
73
|
const value: Flex = {
|
|
74
74
|
flexGrow: 1,
|
|
@@ -80,7 +80,7 @@ describe( 'flexTransformer', () => {
|
|
|
80
80
|
const result = flexTransformer( value, { key: 'flex' } );
|
|
81
81
|
|
|
82
82
|
// Assert.
|
|
83
|
-
expect( result ).toBe( '1 2' );
|
|
83
|
+
expect( result ).toBe( '1 2 auto' );
|
|
84
84
|
} );
|
|
85
85
|
|
|
86
86
|
it( 'should return "grow 1 basis" when grow and basis are set', () => {
|
|
@@ -115,7 +115,7 @@ describe( 'flexTransformer', () => {
|
|
|
115
115
|
} );
|
|
116
116
|
|
|
117
117
|
describe( 'when only one value is provided', () => {
|
|
118
|
-
it( 'should return "grow" when only grow is set', () => {
|
|
118
|
+
it( 'should return "grow 1 auto" when only grow is set', () => {
|
|
119
119
|
// Arrange.
|
|
120
120
|
const value: Flex = {
|
|
121
121
|
flexGrow: 1,
|
|
@@ -127,10 +127,10 @@ describe( 'flexTransformer', () => {
|
|
|
127
127
|
const result = flexTransformer( value, { key: 'flex' } );
|
|
128
128
|
|
|
129
129
|
// Assert.
|
|
130
|
-
expect( result ).toBe( '1' );
|
|
130
|
+
expect( result ).toBe( '1 1 auto' );
|
|
131
131
|
} );
|
|
132
132
|
|
|
133
|
-
it( 'should return "0 shrink" when only shrink is set', () => {
|
|
133
|
+
it( 'should return "0 shrink auto" when only shrink is set', () => {
|
|
134
134
|
// Arrange.
|
|
135
135
|
const value: Flex = {
|
|
136
136
|
flexGrow: null,
|
|
@@ -142,7 +142,7 @@ describe( 'flexTransformer', () => {
|
|
|
142
142
|
const result = flexTransformer( value, { key: 'flex' } );
|
|
143
143
|
|
|
144
144
|
// Assert.
|
|
145
|
-
expect( result ).toBe( '0 2' );
|
|
145
|
+
expect( result ).toBe( '0 2 auto' );
|
|
146
146
|
} );
|
|
147
147
|
|
|
148
148
|
it( 'should return "0 1 basis" when only basis is set', () => {
|
|
@@ -238,8 +238,8 @@ describe( 'flexTransformer', () => {
|
|
|
238
238
|
} );
|
|
239
239
|
} );
|
|
240
240
|
|
|
241
|
-
describe( 'CSS
|
|
242
|
-
it( 'should
|
|
241
|
+
describe( 'CSS initial values for omitted longhands', () => {
|
|
242
|
+
it( 'should default shrink and basis when only grow is set', () => {
|
|
243
243
|
// Arrange.
|
|
244
244
|
const value: Flex = {
|
|
245
245
|
flexGrow: 2,
|
|
@@ -251,10 +251,10 @@ describe( 'flexTransformer', () => {
|
|
|
251
251
|
const result = flexTransformer( value, { key: 'flex' } );
|
|
252
252
|
|
|
253
253
|
// Assert.
|
|
254
|
-
expect( result ).toBe( '2' );
|
|
254
|
+
expect( result ).toBe( '2 1 auto' );
|
|
255
255
|
} );
|
|
256
256
|
|
|
257
|
-
it( 'should
|
|
257
|
+
it( 'should default basis when grow and shrink are set', () => {
|
|
258
258
|
// Arrange.
|
|
259
259
|
const value: Flex = {
|
|
260
260
|
flexGrow: 1,
|
|
@@ -266,7 +266,7 @@ describe( 'flexTransformer', () => {
|
|
|
266
266
|
const result = flexTransformer( value, { key: 'flex' } );
|
|
267
267
|
|
|
268
268
|
// Assert.
|
|
269
|
-
expect( result ).toBe( '1 2' );
|
|
269
|
+
expect( result ).toBe( '1 2 auto' );
|
|
270
270
|
} );
|
|
271
271
|
} );
|
|
272
272
|
} );
|
|
@@ -36,6 +36,17 @@ export function linkPropType() {
|
|
|
36
36
|
} );
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
export function iconPropType() {
|
|
40
|
+
return createMockPropType( {
|
|
41
|
+
kind: 'object',
|
|
42
|
+
key: 'icon',
|
|
43
|
+
shape: {
|
|
44
|
+
value: stringPropType(),
|
|
45
|
+
library: stringPropType(),
|
|
46
|
+
},
|
|
47
|
+
} );
|
|
48
|
+
}
|
|
49
|
+
|
|
39
50
|
export function imagePropType() {
|
|
40
51
|
return createMockPropType( {
|
|
41
52
|
kind: 'object',
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { iconPropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
|
|
2
|
+
|
|
3
|
+
import { iconPropType } from '../../../__tests__/prop-types';
|
|
4
|
+
import { initSettingsTransformers } from '../../../init-settings-transformers';
|
|
5
|
+
import { createPropsResolver } from '../../../renderers/create-props-resolver';
|
|
6
|
+
import { settingsTransformersRegistry } from '../../../settings-transformers-registry';
|
|
7
|
+
import { resetFontAwesomeIconsCache } from '../icon-transformer';
|
|
2
8
|
|
|
3
9
|
const STAR_PATH = 'M0 0h100v100H0z';
|
|
4
|
-
const STAR_WIDTH =
|
|
10
|
+
const STAR_WIDTH = 576;
|
|
5
11
|
const STAR_HEIGHT = 512;
|
|
6
12
|
|
|
7
13
|
const mockFetch = ( body: unknown, ok = true ) => {
|
|
@@ -11,17 +17,46 @@ const mockFetch = ( body: unknown, ok = true ) => {
|
|
|
11
17
|
} );
|
|
12
18
|
};
|
|
13
19
|
|
|
20
|
+
function createSavedIcon( iconClass: string, library: string ) {
|
|
21
|
+
return iconPropTypeUtil.create( {
|
|
22
|
+
value: stringPropTypeUtil.create( iconClass ),
|
|
23
|
+
library: stringPropTypeUtil.create( library ),
|
|
24
|
+
} );
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function resolveSavedIcon( iconClass: string, library: string ) {
|
|
28
|
+
const resolve = createPropsResolver( {
|
|
29
|
+
transformers: settingsTransformersRegistry,
|
|
30
|
+
schema: { svg: iconPropType() },
|
|
31
|
+
} );
|
|
32
|
+
|
|
33
|
+
const result = await resolve( {
|
|
34
|
+
props: {
|
|
35
|
+
svg: createSavedIcon( iconClass, library ),
|
|
36
|
+
},
|
|
37
|
+
} );
|
|
38
|
+
|
|
39
|
+
return result.svg;
|
|
40
|
+
}
|
|
41
|
+
|
|
14
42
|
describe( 'iconTransformer', () => {
|
|
15
43
|
const originalElementorCommon = window.elementorCommon;
|
|
16
44
|
|
|
17
45
|
beforeEach( () => {
|
|
18
46
|
jest.clearAllMocks();
|
|
19
47
|
resetFontAwesomeIconsCache();
|
|
48
|
+
initSettingsTransformers();
|
|
20
49
|
window.elementorCommon = {
|
|
21
50
|
config: {
|
|
22
51
|
urls: {
|
|
23
52
|
assets: 'https://example.com/assets/',
|
|
24
53
|
},
|
|
54
|
+
fontAwesome: {
|
|
55
|
+
v7: {
|
|
56
|
+
jsonFiles: [ 'solid', 'regular', 'brands' ],
|
|
57
|
+
jsonBaseUrl: 'https://example.com/assets/lib/font-awesome-7/json/',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
25
60
|
},
|
|
26
61
|
};
|
|
27
62
|
} );
|
|
@@ -40,10 +75,10 @@ describe( 'iconTransformer', () => {
|
|
|
40
75
|
} );
|
|
41
76
|
|
|
42
77
|
// Act.
|
|
43
|
-
const result = await
|
|
78
|
+
const result = await resolveSavedIcon( 'fas fa-star', 'fa-solid' );
|
|
44
79
|
|
|
45
80
|
// Assert.
|
|
46
|
-
expect( global.fetch ).toHaveBeenCalledWith( 'https://example.com/assets/lib/font-awesome/json/solid.json', {
|
|
81
|
+
expect( global.fetch ).toHaveBeenCalledWith( 'https://example.com/assets/lib/font-awesome-7/json/solid.json', {
|
|
47
82
|
signal: undefined,
|
|
48
83
|
} );
|
|
49
84
|
expect( result ).toEqual( {
|
|
@@ -51,6 +86,45 @@ describe( 'iconTransformer', () => {
|
|
|
51
86
|
url: null,
|
|
52
87
|
} );
|
|
53
88
|
expect( ( result as { html: string } ).html ).toContain( 'fill="currentColor"' );
|
|
89
|
+
expect( ( result as { html: string } ).html ).toContain( `viewBox="0 0 ${ STAR_WIDTH } ${ STAR_HEIGHT }"` );
|
|
90
|
+
expect( ( result as { html: string } ).html ).toContain( 'aria-hidden="true"' );
|
|
91
|
+
expect( ( result as { html: string } ).html ).toContain( 'overflow: visible' );
|
|
92
|
+
} );
|
|
93
|
+
|
|
94
|
+
it( 'resolves icons by alias name', async () => {
|
|
95
|
+
// Arrange.
|
|
96
|
+
mockFetch( {
|
|
97
|
+
icons: {
|
|
98
|
+
headphones: [ 448, 512, [ 'headphones-simple' ], 'f025', 'M0 0' ],
|
|
99
|
+
},
|
|
100
|
+
} );
|
|
101
|
+
|
|
102
|
+
// Act.
|
|
103
|
+
const result = await resolveSavedIcon( 'fas fa-headphones-simple', 'fa-solid' );
|
|
104
|
+
|
|
105
|
+
// Assert.
|
|
106
|
+
expect( result ).toEqual( {
|
|
107
|
+
html: expect.stringContaining( 'M0 0' ),
|
|
108
|
+
url: null,
|
|
109
|
+
} );
|
|
110
|
+
} );
|
|
111
|
+
|
|
112
|
+
it( 'renders multiple paths when the icon definition contains an array', async () => {
|
|
113
|
+
// Arrange.
|
|
114
|
+
mockFetch( {
|
|
115
|
+
icons: {
|
|
116
|
+
slash: [ 640, 640, [], 'f715', [ 'M0 0', 'M10 10' ] ],
|
|
117
|
+
},
|
|
118
|
+
} );
|
|
119
|
+
|
|
120
|
+
// Act.
|
|
121
|
+
const result = await resolveSavedIcon( 'fas fa-slash', 'fa-solid' );
|
|
122
|
+
|
|
123
|
+
// Assert.
|
|
124
|
+
const html = ( result as { html: string } ).html;
|
|
125
|
+
expect( html.match( /<path/g ) ).toHaveLength( 2 );
|
|
126
|
+
expect( html ).toContain( 'M0 0' );
|
|
127
|
+
expect( html ).toContain( 'M10 10' );
|
|
54
128
|
} );
|
|
55
129
|
|
|
56
130
|
it( 'returns null html when the icon cannot be resolved', async () => {
|
|
@@ -58,17 +132,68 @@ describe( 'iconTransformer', () => {
|
|
|
58
132
|
mockFetch( { icons: {} } );
|
|
59
133
|
|
|
60
134
|
// Act.
|
|
61
|
-
const result = await
|
|
135
|
+
const result = await resolveSavedIcon( 'fas fa-missing', 'fa-solid' );
|
|
62
136
|
|
|
63
137
|
// Assert.
|
|
64
138
|
expect( result ).toEqual( { html: null, url: null } );
|
|
65
139
|
} );
|
|
66
140
|
|
|
67
|
-
it( '
|
|
141
|
+
it( 'fetches json from the localized font awesome 7 base url', async () => {
|
|
142
|
+
// Arrange.
|
|
143
|
+
const jsonBaseUrl = 'https://cdn.example.com/fa7/json/';
|
|
144
|
+
window.elementorCommon = {
|
|
145
|
+
config: {
|
|
146
|
+
fontAwesome: {
|
|
147
|
+
v7: {
|
|
148
|
+
jsonFiles: [ 'solid', 'regular', 'brands' ],
|
|
149
|
+
jsonBaseUrl,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
mockFetch( {
|
|
155
|
+
icons: {
|
|
156
|
+
star: [ STAR_WIDTH, STAR_HEIGHT, [], 'f005', STAR_PATH ],
|
|
157
|
+
},
|
|
158
|
+
} );
|
|
159
|
+
|
|
68
160
|
// Act.
|
|
69
|
-
|
|
161
|
+
await resolveSavedIcon( 'fas fa-star', 'fa-solid' );
|
|
70
162
|
|
|
71
163
|
// Assert.
|
|
164
|
+
expect( global.fetch ).toHaveBeenCalledWith( `${ jsonBaseUrl }solid.json`, {
|
|
165
|
+
signal: undefined,
|
|
166
|
+
} );
|
|
167
|
+
} );
|
|
168
|
+
|
|
169
|
+
it( 'does not fetch json when library is not an allowed fa7 file', async () => {
|
|
170
|
+
// Arrange.
|
|
171
|
+
mockFetch( { icons: {} } );
|
|
172
|
+
|
|
173
|
+
// Act.
|
|
174
|
+
const result = await resolveSavedIcon( 'fas fa-star', 'fa-../../wp-config' );
|
|
175
|
+
|
|
176
|
+
// Assert.
|
|
177
|
+
expect( global.fetch ).not.toHaveBeenCalled();
|
|
72
178
|
expect( result ).toEqual( { html: null, url: null } );
|
|
73
179
|
} );
|
|
180
|
+
|
|
181
|
+
it( 'returns null html when value or library is missing', async () => {
|
|
182
|
+
// Act.
|
|
183
|
+
const resolve = createPropsResolver( {
|
|
184
|
+
transformers: settingsTransformersRegistry,
|
|
185
|
+
schema: { svg: iconPropType() },
|
|
186
|
+
} );
|
|
187
|
+
const result = await resolve( {
|
|
188
|
+
props: {
|
|
189
|
+
svg: iconPropTypeUtil.create( {
|
|
190
|
+
value: stringPropTypeUtil.create( 'fas fa-star' ),
|
|
191
|
+
library: stringPropTypeUtil.create( '' ),
|
|
192
|
+
} ),
|
|
193
|
+
},
|
|
194
|
+
} );
|
|
195
|
+
|
|
196
|
+
// Assert.
|
|
197
|
+
expect( result.svg ).toEqual( { html: null, url: null } );
|
|
198
|
+
} );
|
|
74
199
|
} );
|
|
@@ -7,11 +7,18 @@ type IconValue = {
|
|
|
7
7
|
library?: unknown;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
type FontAwesomeIconJson = [ number, number, unknown, unknown, string ];
|
|
10
|
+
type FontAwesomeIconJson = [ number, number, unknown[], unknown, string | string[] ];
|
|
11
|
+
|
|
12
|
+
type FontAwesome7EditorConfig = {
|
|
13
|
+
jsonFiles: string[];
|
|
14
|
+
jsonBaseUrl: string;
|
|
15
|
+
};
|
|
11
16
|
|
|
12
17
|
const FONT_AWESOME_JSON = {
|
|
13
18
|
width: 0,
|
|
14
19
|
height: 1,
|
|
20
|
+
aliases: 2,
|
|
21
|
+
unicode: 3,
|
|
15
22
|
path: 4,
|
|
16
23
|
} as const;
|
|
17
24
|
|
|
@@ -40,7 +47,12 @@ export const iconTransformer = createTransformer( async ( value: IconValue, { si
|
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
const svgText = buildFontAwesomeSvg( iconData );
|
|
43
|
-
|
|
50
|
+
|
|
51
|
+
if ( ! svgText ) {
|
|
52
|
+
return { html: null, url: null };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const html = processIconSvgContent( svgText );
|
|
44
56
|
|
|
45
57
|
return { html, url: null };
|
|
46
58
|
} );
|
|
@@ -52,17 +64,32 @@ function getFontAwesomeIconName( iconValue: string ): string | null {
|
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
function getFontAwesomeJsonFileName( library: string ): string | null {
|
|
55
|
-
|
|
67
|
+
const fileName = library.replace( /^fa-/, '' );
|
|
68
|
+
const config = getFontAwesome7EditorConfig();
|
|
69
|
+
|
|
70
|
+
if ( ! config?.jsonFiles.includes( fileName ) ) {
|
|
56
71
|
return null;
|
|
57
72
|
}
|
|
58
73
|
|
|
59
|
-
return
|
|
74
|
+
return fileName;
|
|
60
75
|
}
|
|
61
76
|
|
|
62
|
-
function
|
|
63
|
-
const
|
|
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
|
+
}
|
|
64
88
|
|
|
65
|
-
return
|
|
89
|
+
return {
|
|
90
|
+
jsonFiles: config.jsonFiles,
|
|
91
|
+
jsonBaseUrl: config.jsonBaseUrl,
|
|
92
|
+
};
|
|
66
93
|
}
|
|
67
94
|
|
|
68
95
|
async function fetchFontAwesomeIcons(
|
|
@@ -88,33 +115,115 @@ async function loadFontAwesomeIcons(
|
|
|
88
115
|
jsonFileName: string,
|
|
89
116
|
signal?: AbortSignal
|
|
90
117
|
): Promise< Record< string, FontAwesomeIconJson > | null > {
|
|
91
|
-
const
|
|
118
|
+
const config = getFontAwesome7EditorConfig();
|
|
92
119
|
|
|
93
|
-
if ( !
|
|
120
|
+
if ( ! config?.jsonFiles.includes( jsonFileName ) ) {
|
|
94
121
|
return null;
|
|
95
122
|
}
|
|
96
123
|
|
|
97
124
|
try {
|
|
98
|
-
const response = await fetch( `${
|
|
125
|
+
const response = await fetch( `${ config.jsonBaseUrl }${ jsonFileName }.json`, {
|
|
126
|
+
signal,
|
|
127
|
+
} );
|
|
99
128
|
|
|
100
129
|
if ( ! response.ok ) {
|
|
101
130
|
return null;
|
|
102
131
|
}
|
|
103
132
|
|
|
104
133
|
const data = ( await response.json() ) as { icons?: Record< string, FontAwesomeIconJson > };
|
|
134
|
+
const icons = data.icons;
|
|
105
135
|
|
|
106
|
-
|
|
136
|
+
if ( ! icons || typeof icons !== 'object' ) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return indexFontAwesomeIcons( icons );
|
|
107
141
|
} catch {
|
|
108
142
|
return null;
|
|
109
143
|
}
|
|
110
144
|
}
|
|
111
145
|
|
|
112
|
-
function
|
|
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 {
|
|
113
177
|
const width = iconData[ FONT_AWESOME_JSON.width ];
|
|
114
178
|
const height = iconData[ FONT_AWESOME_JSON.height ];
|
|
115
|
-
const
|
|
179
|
+
const paths = normalizePaths( iconData[ FONT_AWESOME_JSON.path ] );
|
|
180
|
+
|
|
181
|
+
if ( paths.length === 0 ) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const pathMarkup = paths.map( ( path ) => `<path d="${ escapeSvgPath( path ) }"></path>` ).join( '' );
|
|
186
|
+
|
|
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 !== '' );
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function escapeSvgPath( path: string ): string {
|
|
203
|
+
return path.replace( /&/g, '&' ).replace( /"/g, '"' ).replace( /</g, '<' ).replace( />/g, '>' );
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function processIconSvgContent( svgText: string ): string | null {
|
|
207
|
+
const html = processSvgContent( svgText );
|
|
208
|
+
|
|
209
|
+
if ( ! html ) {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const parser = new DOMParser();
|
|
214
|
+
const doc = parser.parseFromString( html, 'image/svg+xml' );
|
|
215
|
+
const svgElement = doc.querySelector( 'svg' );
|
|
216
|
+
|
|
217
|
+
if ( ! svgElement ) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
svgElement.setAttribute( 'aria-hidden', 'true' );
|
|
222
|
+
svgElement.style.setProperty( 'width', '100%' );
|
|
223
|
+
svgElement.style.setProperty( 'height', '100%' );
|
|
224
|
+
svgElement.style.setProperty( 'overflow', 'visible' );
|
|
116
225
|
|
|
117
|
-
return
|
|
226
|
+
return svgElement.outerHTML;
|
|
118
227
|
}
|
|
119
228
|
|
|
120
229
|
export function resetFontAwesomeIconsCache() {
|
|
@@ -6,6 +6,13 @@ type Flex = {
|
|
|
6
6
|
flexBasis?: { size: number; unit: string } | string | null;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
const DEFAULT_FLEX_GROW = 0;
|
|
10
|
+
const DEFAULT_FLEX_SHRINK = 1;
|
|
11
|
+
const DEFAULT_FLEX_BASIS = 'auto';
|
|
12
|
+
|
|
13
|
+
const formatBasis = ( basis: NonNullable< Flex[ 'flexBasis' ] > ) =>
|
|
14
|
+
typeof basis === 'object' && basis.size !== undefined ? `${ basis.size }${ basis.unit || '' }` : basis;
|
|
15
|
+
|
|
9
16
|
export const flexTransformer = createTransformer( ( value: Flex ) => {
|
|
10
17
|
const grow = value.flexGrow;
|
|
11
18
|
const shrink = value.flexShrink;
|
|
@@ -19,37 +26,9 @@ export const flexTransformer = createTransformer( ( value: Flex ) => {
|
|
|
19
26
|
return null;
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}`;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if ( hasGrow && hasShrink && ! hasBasis ) {
|
|
29
|
-
return `${ grow } ${ shrink }`;
|
|
30
|
-
}
|
|
31
|
-
if ( hasGrow && ! hasShrink && hasBasis ) {
|
|
32
|
-
return `${ grow } 1 ${
|
|
33
|
-
typeof basis === 'object' && basis.size !== undefined ? `${ basis.size }${ basis.unit || '' }` : basis
|
|
34
|
-
}`;
|
|
35
|
-
}
|
|
36
|
-
if ( ! hasGrow && hasShrink && hasBasis ) {
|
|
37
|
-
return `0 ${ shrink } ${
|
|
38
|
-
typeof basis === 'object' && basis.size !== undefined ? `${ basis.size }${ basis.unit || '' }` : basis
|
|
39
|
-
}`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if ( hasGrow && ! hasShrink && ! hasBasis ) {
|
|
43
|
-
return `${ grow }`;
|
|
44
|
-
}
|
|
45
|
-
if ( ! hasGrow && hasShrink && ! hasBasis ) {
|
|
46
|
-
return `0 ${ shrink }`;
|
|
47
|
-
}
|
|
48
|
-
if ( ! hasGrow && ! hasShrink && hasBasis ) {
|
|
49
|
-
return `0 1 ${
|
|
50
|
-
typeof basis === 'object' && basis.size !== undefined ? `${ basis.size }${ basis.unit || '' }` : basis
|
|
51
|
-
}`;
|
|
52
|
-
}
|
|
29
|
+
const growOut = hasGrow ? grow : DEFAULT_FLEX_GROW;
|
|
30
|
+
const shrinkOut = hasShrink ? shrink : DEFAULT_FLEX_SHRINK;
|
|
31
|
+
const basisOut = hasBasis ? formatBasis( basis ) : DEFAULT_FLEX_BASIS;
|
|
53
32
|
|
|
54
|
-
return
|
|
33
|
+
return `${ growOut } ${ shrinkOut } ${ basisOut }`;
|
|
55
34
|
} );
|