PluginProbe
Extendify / 3.1.4
Extendify v3.1.4
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / AutoLaunch / functions / fonts.js

fonts.js in Extendify 3.1.4, at src/AutoLaunch/functions/fonts.js

227 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // This was mostly copied 1:1 over from legacy launch
2 import { deepMerge, sleep } from '@shared/lib/utils';
3 import apiFetch from '@wordpress/api-fetch';
4 import { addQueryArgs } from '@wordpress/url';
5
6 export const registerFontFamily = async (fontFamily) => {
7 try {
8 const existingFontFamily = (
9 await apiFetch({
10 path: addQueryArgs('/wp/v2/font-families', {
11 slug: fontFamily.slug,
12 _embed: true,
13 }),
14 })
15 )?.[0];
16
17 if (existingFontFamily) {
18 return {
19 id: existingFontFamily.id,
20 ...existingFontFamily.font_family_settings,
21 fontFace: existingFontFamily._embedded.font_faces.map(
22 ({ id, font_face_settings }) => ({
23 id,
24 ...font_face_settings,
25 }),
26 ),
27 };
28 }
29
30 const newFontFamily = await apiFetch({
31 path: '/wp/v2/font-families',
32 method: 'POST',
33 body: makeFontFamilyFormData(fontFamily),
34 });
35
36 return {
37 id: newFontFamily.id,
38 ...newFontFamily.font_family_settings,
39 fontFace: newFontFamily.fontFaces,
40 };
41 } catch (error) {
42 console.error('Failed to register font family:', error.message);
43 return;
44 }
45 };
46
47 export const registerFontFace = async ({ fontFamilyId, ...fontFace }) => {
48 const max_retries = 2;
49
50 const fontFaceSlug = `${fontFace.fontFamilySlug}-${fontFace.fontWeight}`;
51
52 for (let attempt = 0; attempt <= max_retries; attempt++) {
53 try {
54 // Add delay of 1 second if this is not the first attempt
55 if (attempt > 0) await sleep(1000);
56
57 const response = await apiFetch({
58 path: `/wp/v2/font-families/${fontFamilyId}/font-faces`,
59 method: 'POST',
60 body: makeFontFaceFormData(fontFace),
61 });
62
63 return {
64 id: response.id,
65 ...response.font_face_settings,
66 };
67 } catch (error) {
68 if (attempt <= max_retries) {
69 console.error(
70 `Failed attempt to upload font file ${fontFaceSlug}:`,
71 error.message,
72 );
73 continue;
74 }
75
76 console.error(
77 `Failed to upload font file ${fontFaceSlug} after ${max_retries + 1} attempts.`,
78 );
79
80 return;
81 }
82 }
83 };
84
85 export const installFontFamily = async (fontFamily) => {
86 const fontFaceDownloadRequests = fontFamily.fontFace.map(async (fontFace) => {
87 const file = await fetchFontFaceFile(fontFace.src);
88 if (!file) return;
89 return { ...fontFace, file };
90 });
91
92 const fontFacesWithFile = (
93 await Promise.all(fontFaceDownloadRequests)
94 ).filter(Boolean);
95
96 // If we don't have any font file to install, we don't register the font family.
97 if (!fontFacesWithFile.length) return;
98
99 const registeredFontFamily = await registerFontFamily(fontFamily);
100
101 // If we couldn't register the font family, we don't register the font faces.
102 if (!registeredFontFamily) return;
103
104 // If font family has font faces, it means it was already registered
105 // and doesn't need to be installed.
106 if (registeredFontFamily?.fontFace?.length) {
107 return registeredFontFamily;
108 }
109
110 const fontFaces = fontFacesWithFile.map((fontFace) => ({
111 fontFamilyId: registeredFontFamily.id,
112 fontFamilySlug: registeredFontFamily.slug,
113 ...fontFace,
114 }));
115
116 const registeredFontFaces = [];
117
118 for (const fontFace of fontFaces) {
119 registeredFontFaces.push(await registerFontFace(fontFace));
120 }
121
122 return {
123 ...registeredFontFamily,
124 fontFace: registeredFontFaces.filter(Boolean),
125 };
126 };
127
128 export const installFontFamilies = async (fontFamilies) => {
129 const installedFontFamilies = [];
130
131 for (const fontFamily of fontFamilies) {
132 installedFontFamilies.push(await installFontFamily(fontFamily));
133 }
134
135 return installedFontFamilies.filter(Boolean);
136 };
137
138 export const fetchFontFaceFile = async (url) => {
139 for (let attempt = 0; attempt <= 2; attempt++) {
140 try {
141 // Add delay if this is not the first attempt
142 if (attempt > 0) await sleep(1000);
143
144 const response = await fetch(url);
145
146 if (!response.ok) {
147 throw new Error('Failed to fetch font file.');
148 }
149
150 const blob = await response.blob();
151 const filename = url.split('/').pop();
152
153 return new File([blob], filename, {
154 type: blob.type,
155 });
156 } catch (_) {
157 if (attempt <= 2) continue;
158 return;
159 }
160 }
161 };
162
163 export const makeFontFamilyFormData = ({ name, slug, fontFamily }) => {
164 const formData = new FormData();
165 const fontFamilySettings = { name, slug, fontFamily };
166 formData.append('font_family_settings', JSON.stringify(fontFamilySettings));
167
168 return formData;
169 };
170
171 export const makeFontFaceFormData = ({
172 fontFamilySlug,
173 fontFamily,
174 fontStyle,
175 fontWeight,
176 fontDisplay,
177 unicodeRange,
178 src = [],
179 file = [],
180 }) => {
181 const formData = new FormData();
182 const fontFaceSettings = {
183 fontFamily,
184 fontStyle,
185 fontWeight,
186 fontDisplay,
187 unicodeRange:
188 unicodeRange === undefined || unicodeRange === null ? '' : unicodeRange,
189 src: Array.isArray(src) ? src : [src],
190 };
191 const files = Array.isArray(file) ? file : [file];
192
193 // Add each font file to the form data.
194 files.forEach((file) => {
195 const fileId = `${fontFamilySlug}-${fontWeight}-${fontStyle}`;
196 formData.append(fileId, file, file.name);
197
198 // Use the file ids as src for WP to match and upload the files.
199 if (!src?.length) {
200 fontFaceSettings.src.push(fileId);
201 } else {
202 fontFaceSettings.src = [fileId];
203 }
204 });
205
206 formData.append('font_face_settings', JSON.stringify(fontFaceSettings));
207
208 return formData;
209 };
210
211 export const mergeFontsIntoVariation = (variation, fonts) =>
212 deepMerge(
213 variation,
214 // We set to null first to reset the field.
215 { settings: { typography: { fontFamilies: { custom: null } } } },
216 // We add the installed font families here to activate them.
217 {
218 settings: {
219 typography: {
220 fontFamilies: {
221 custom: fonts.filter(Boolean),
222 },
223 },
224 },
225 },
226 );
227