@codecademy/brand 3.36.2-alpha.7b9e1afbb4.0 → 3.36.2-alpha.89d0f59c01.0

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.
@@ -3,70 +3,22 @@ let workerPromise;
3
3
  const initErr = 'Search worker not initialized';
4
4
  export const searchWorker = {
5
5
  init() {
6
- // eslint-disable-next-line no-console
7
- console.log('[searchWorker.init] Initializing search worker');
8
6
  if (!workerPromise) {
9
- // eslint-disable-next-line no-console
10
- console.log('[searchWorker.init] Creating new worker promise');
11
7
  workerPromise = (async () => {
12
- try {
13
- // eslint-disable-next-line no-console
14
- console.log('[searchWorker.init] Importing worker module');
15
- // lazy load worker
16
- const {
17
- createSearchWorker
18
- } = await import('./worker');
19
- // eslint-disable-next-line no-console
20
- console.log('[searchWorker.init] Worker module imported, creating worker');
21
- const worker = createSearchWorker();
22
- // eslint-disable-next-line no-console
23
- console.log('[searchWorker.init] Worker created successfully');
24
- return worker;
25
- } catch (error) {
26
- // eslint-disable-next-line no-console
27
- console.error('[searchWorker.init] Error creating worker:', error);
28
- throw error;
29
- }
8
+ // lazy load worker
9
+ const {
10
+ createSearchWorker
11
+ } = await import('./worker');
12
+ return createSearchWorker();
30
13
  })();
31
- } else {
32
- // eslint-disable-next-line no-console
33
- console.log('[searchWorker.init] Worker already initialized');
34
14
  }
35
15
  },
36
16
  async autocomplete(query) {
37
- // eslint-disable-next-line no-console
38
- console.log('[searchWorker.autocomplete] Query:', query);
39
17
  if (!workerPromise) throw new Error(initErr);
40
- try {
41
- const worker = await workerPromise;
42
- // eslint-disable-next-line no-console
43
- console.log('[searchWorker.autocomplete] Worker ready, calling with query:', query);
44
- const result = await worker(SearchAction.Autocomplete, query);
45
- // eslint-disable-next-line no-console
46
- console.log('[searchWorker.autocomplete] Result received:', result);
47
- return result;
48
- } catch (error) {
49
- // eslint-disable-next-line no-console
50
- console.error('[searchWorker.autocomplete] Error:', error);
51
- throw error;
52
- }
18
+ return (await workerPromise)(SearchAction.Autocomplete, query);
53
19
  },
54
20
  async searchAsYouType(query) {
55
- // eslint-disable-next-line no-console
56
- console.log('[searchWorker.searchAsYouType] Query:', query);
57
21
  if (!workerPromise) throw new Error(initErr);
58
- try {
59
- const worker = await workerPromise;
60
- // eslint-disable-next-line no-console
61
- console.log('[searchWorker.searchAsYouType] Worker ready, calling with query:', query);
62
- const result = await worker(SearchAction.SearchAsYouType, query);
63
- // eslint-disable-next-line no-console
64
- console.log('[searchWorker.searchAsYouType] Result received:', result);
65
- return result;
66
- } catch (error) {
67
- // eslint-disable-next-line no-console
68
- console.error('[searchWorker.searchAsYouType] Error:', error);
69
- throw error;
70
- }
22
+ return (await workerPromise)(SearchAction.SearchAsYouType, query);
71
23
  }
72
24
  };
@@ -28,6 +28,9 @@ function getPortalOrigin() {
28
28
  // for standard envs, use portal app in the same env
29
29
  if (envs.some(s => `https://${s}.codecademy.com` === origin)) return origin;
30
30
 
31
+ // for PR envs (e.g. pr-40229-monolith.dev-eks.codecademy.com)
32
+ if (origin.includes('.dev-eks.codecademy.com')) return origin;
33
+
31
34
  // for local, use local portal-app, replace if origin port is monolith or le
32
35
  if (origin.includes('localhost')) return origin.replace(/:\d{4}/, ':3100');
33
36
 
@@ -35,65 +38,15 @@ function getPortalOrigin() {
35
38
  return 'https://staging.codecademy.com';
36
39
  }
37
40
  export function serializeSearchWorkerSrc() {
38
- // eslint-disable-next-line no-console
39
- console.log('[serializeSearchWorkerSrc] Starting serialization');
40
- try {
41
- // eslint-disable-next-line no-console
42
- console.log('[serializeSearchWorkerSrc] Getting portal origin');
43
- const BASE_URL = `${getPortalOrigin()}/api/portal/search`;
44
- // eslint-disable-next-line no-console
45
- console.log('[serializeSearchWorkerSrc] BASE_URL:', BASE_URL);
46
-
47
- // eslint-disable-next-line no-console
48
- console.log('[serializeSearchWorkerSrc] Converting worker function to string');
49
- const fnAsStr = worker.toString().trim();
50
- // eslint-disable-next-line no-console
51
- console.log('[serializeSearchWorkerSrc] Worker function string length:', fnAsStr.length);
52
- // eslint-disable-next-line no-console
53
- console.log('[serializeSearchWorkerSrc] Full worker function:', fnAsStr);
54
-
55
- // in a prod build, webpack will handle removing comments
41
+ const BASE_URL = `${getPortalOrigin()}/api/portal/search`;
42
+ const fnAsStr = worker.toString().trim();
56
43
 
57
- const startIndex = fnAsStr.indexOf('{');
58
- // eslint-disable-next-line no-console
59
- console.log('[serializeSearchWorkerSrc] Start index of first {:', startIndex);
60
- const result = fnAsStr.slice(fnAsStr.indexOf('{') + 1, -1) // remove wrapping function, which may have been renamed by minification
61
- .replaceAll(' ', '') // remove indentation
62
- .replaceAll('{BASE_URL}', BASE_URL) // interpolate base url
63
- .replaceAll('{SEARCH}', window.location.search); // interpolate search query
44
+ // in a prod build, webpack will handle removing comments
64
45
 
65
- // Check for external dependencies that would break the worker
66
- const externalDeps = [];
67
- if (result.includes('Object(h.a)') || result.includes('h.a')) {
68
- externalDeps.push('h (Babel async helper)');
69
- }
70
- if (result.includes('p.a.mark') || result.includes('p.a.wrap')) {
71
- externalDeps.push('p (Regenerator runtime)');
72
- }
73
- if (result.includes('_createForOfIteratorHelper')) {
74
- externalDeps.push('_createForOfIteratorHelper (Babel helper)');
75
- }
76
- if (externalDeps.length > 0) {
77
- // eslint-disable-next-line no-console
78
- console.error('[serializeSearchWorkerSrc] ERROR: Worker code contains external dependencies that will not be available in worker context:', externalDeps);
79
- // eslint-disable-next-line no-console
80
- console.error('[serializeSearchWorkerSrc] This is likely because the worker function uses async/await or modern JS features that Babel transpiles with external helpers.');
81
- // eslint-disable-next-line no-console
82
- console.error('[serializeSearchWorkerSrc] The worker function needs to be self-contained or the build configuration needs to be adjusted to inline helpers.');
83
- }
84
-
85
- // eslint-disable-next-line no-console
86
- console.log('[serializeSearchWorkerSrc] Serialization complete, result length:', result.length);
87
- // eslint-disable-next-line no-console
88
- console.log('[serializeSearchWorkerSrc] First 500 chars of result:', result.substring(0, 500));
89
- // eslint-disable-next-line no-console
90
- console.log('[serializeSearchWorkerSrc] Full result:', result);
91
- return result;
92
- } catch (error) {
93
- // eslint-disable-next-line no-console
94
- console.error('[serializeSearchWorkerSrc] Error during serialization:', error);
95
- throw error;
96
- }
46
+ return fnAsStr.slice(fnAsStr.indexOf('{') + 1, -1) // remove wrapping function, which may have been renamed by minification
47
+ .replaceAll(' ', '') // remove indentation
48
+ .replaceAll('{BASE_URL}', BASE_URL) // interpolate base url
49
+ .replaceAll('{SEARCH}', window.location.search); // interpolate search query
97
50
  }
98
51
 
99
52
  /*
@@ -176,7 +129,8 @@ function worker() {
176
129
  }),
177
130
  method: 'POST'
178
131
  }).then(f => f.json()).then(searchAsYouTypeResults => {
179
- for (const entry of searchAsYouTypeResults.top) {
132
+ for (let i = 0; i < searchAsYouTypeResults.top.length; i++) {
133
+ const entry = searchAsYouTypeResults.top[i];
180
134
  const t = preparseTitle({
181
135
  value: entry.title,
182
136
  popularity: 0
@@ -204,17 +158,17 @@ function worker() {
204
158
  // Bonus scores are includes in certain cases
205
159
  function getTotalScore(q, t, charScores) {
206
160
  let fromChars = 0;
207
- for (const s of charScores) {
208
- fromChars += s;
161
+ for (let i = 0; i < charScores.length; i++) {
162
+ fromChars += charScores[i];
209
163
  }
210
164
  const fromPopularity = (t.popularity || 0) * popularityStrength;
211
165
  let bonus = 0;
212
166
  // for each complete word present in both the title and query
213
- for (const qw of q.words) {
167
+ q.words.forEach(qw => {
214
168
  if (t.words.has(qw)) {
215
169
  bonus += 100;
216
170
  }
217
- }
171
+ });
218
172
 
219
173
  // if the title starts with the query
220
174
  if (t.lower.startsWith(q.query)) {
@@ -338,9 +292,11 @@ function worker() {
338
292
  // "authentication" or other words ending in "ion"
339
293
  const minMatchLength = Math.ceil(avgQueryWordLength ** 0.65);
340
294
  const charScores = [];
341
- for (const cmcs of cmcsForTitleChars) {
295
+ for (let i = 0; i < cmcsForTitleChars.length; i++) {
296
+ const cmcs = cmcsForTitleChars[i];
342
297
  let score = 0;
343
- for (const cmc of cmcs) {
298
+ for (let j = 0; j < cmcs.length; j++) {
299
+ const cmc = cmcs[j];
344
300
  // if the string of consecutive matching chars meets the minMatchLength
345
301
  // or if it's a standalone word in the query (e.g "C")
346
302
  if (cmc.value.length >= minMatchLength || q.words.has(cmc.value)) {
@@ -5,74 +5,27 @@ const mockWorker = () => ({
5
5
  postMessage: () => null
6
6
  });
7
7
  export function createSearchWorker() {
8
- // eslint-disable-next-line no-console
9
- console.log('[createSearchWorker] Starting worker creation');
10
- try {
11
- // eslint-disable-next-line no-console
12
- console.log('[createSearchWorker] Serializing worker source');
13
- const src = serializeSearchWorkerSrc();
14
- // eslint-disable-next-line no-console
15
- console.log('[createSearchWorker] Worker source serialized, length:', src.length);
16
-
17
- // eslint-disable-next-line no-console
18
- console.log('[createSearchWorker] Creating blob');
19
- const blob = new Blob([src], {
20
- type: 'text/javascript'
21
- });
22
- // eslint-disable-next-line no-console
23
- console.log('[createSearchWorker] Blob created');
24
-
25
- // eslint-disable-next-line no-console
26
- console.log('[createSearchWorker] Creating object URL');
27
- const dataUrl = URL.createObjectURL?.(blob);
28
- // eslint-disable-next-line no-console
29
- console.log('[createSearchWorker] Object URL created:', dataUrl);
30
-
31
- // eslint-disable-next-line no-console
32
- console.log('[createSearchWorker] Checking Worker availability');
33
- const w = typeof Worker === 'undefined' ? mockWorker() : new Worker(dataUrl);
34
- // eslint-disable-next-line no-console
35
- console.log('[createSearchWorker] Worker instance created');
36
- const results = new PromiseLookup({
37
- onKeyInit: (action, query) => {
38
- // eslint-disable-next-line no-console
39
- console.log('[createSearchWorker.onKeyInit] Posting message to worker:', {
40
- action,
41
- query
42
- });
43
- w.postMessage({
44
- action,
45
- query
46
- });
47
- }
48
- });
49
- w.onmessage = ({
50
- data
51
- }) => {
52
- // eslint-disable-next-line no-console
53
- console.log('[createSearchWorker.onmessage] Received message from worker:', data);
54
- const {
55
- query,
56
- result,
57
- action
58
- } = data;
59
- results.resolve(action, query, result);
60
- };
61
-
62
- // Add error handler for the worker
63
- if ('onerror' in w) {
64
- w.onerror = error => {
65
- // eslint-disable-next-line no-console
66
- console.error('[createSearchWorker] Worker error:', error);
67
- };
68
- }
69
-
70
- // eslint-disable-next-line no-console
71
- console.log('[createSearchWorker] Worker fully configured');
72
- return (action, query) => results.get(action, query);
73
- } catch (error) {
74
- // eslint-disable-next-line no-console
75
- console.error('[createSearchWorker] Error creating worker:', error);
76
- throw error;
77
- }
8
+ const src = serializeSearchWorkerSrc();
9
+ const blob = new Blob([src], {
10
+ type: 'text/javascript'
11
+ });
12
+ const dataUrl = URL.createObjectURL?.(blob);
13
+ const w = typeof Worker === 'undefined' ? mockWorker() : new Worker(dataUrl);
14
+ const results = new PromiseLookup({
15
+ onKeyInit: (action, query) => w.postMessage({
16
+ action,
17
+ query
18
+ })
19
+ });
20
+ w.onmessage = ({
21
+ data
22
+ }) => {
23
+ const {
24
+ query,
25
+ result,
26
+ action
27
+ } = data;
28
+ results.resolve(action, query, result);
29
+ };
30
+ return (action, query) => results.get(action, query);
78
31
  }
@@ -5,31 +5,14 @@
5
5
 
6
6
  import { ALLOWED_HOSTS } from './consts';
7
7
  export function safelyRedirect(url) {
8
- // eslint-disable-next-line no-console
9
- console.log('[safelyRedirect] Attempting to redirect to:', url);
10
8
  try {
11
- // eslint-disable-next-line no-console
12
- console.log('[safelyRedirect] Sanitizing URL');
13
9
  const sanitizedURL = sanitizeURL(url);
14
- // eslint-disable-next-line no-console
15
- console.log('[safelyRedirect] Sanitized URL:', sanitizedURL);
16
- const isRelative = isRelativeUrl(sanitizedURL);
17
- // eslint-disable-next-line no-console
18
- console.log('[safelyRedirect] Is relative URL:', isRelative);
19
- const hasAllowed = hasAllowedHost(sanitizedURL);
20
- // eslint-disable-next-line no-console
21
- console.log('[safelyRedirect] Has allowed host:', hasAllowed);
22
- if (isRelative || hasAllowed) {
23
- // eslint-disable-next-line no-console
24
- console.log('[safelyRedirect] Redirecting to:', sanitizedURL);
10
+ if (isRelativeUrl(sanitizedURL) || hasAllowedHost(sanitizedURL)) {
25
11
  window.location.assign(sanitizedURL);
26
12
  } else {
27
13
  throw new Error(`Invalid redirect url: ${sanitizedURL}`);
28
14
  }
29
- } catch (error) {
30
- // eslint-disable-next-line no-console
31
- console.error('[safelyRedirect] Error during redirect:', error);
32
- }
15
+ } catch (error) {}
33
16
  }
34
17
  function hasAllowedHost(url) {
35
18
  const parsedUrl = new URL(url);
@@ -54,35 +37,13 @@ function isRelativeUrl(url) {
54
37
  // supports already encoded urls by decoding and re-encoding.
55
38
  // params are handled separately to allow for the encoding of / characters
56
39
  function sanitizeURL(url) {
57
- // eslint-disable-next-line no-console
58
- console.log('[sanitizeURL] Input URL:', url);
59
- try {
60
- const [path, params] = url.split('?', 2);
61
- // eslint-disable-next-line no-console
62
- console.log('[sanitizeURL] Path:', path, 'Params:', params);
63
- const sanitizedPath = encodeURI(decodeURI(path));
64
- // eslint-disable-next-line no-console
65
- console.log('[sanitizeURL] Sanitized path:', sanitizedPath);
66
- if (!params) return sanitizedPath;
67
-
68
- // eslint-disable-next-line no-console
69
- console.log('[sanitizeURL] Creating URLSearchParams with:', params);
70
- const urlParams = new URLSearchParams(params);
71
- // eslint-disable-next-line no-console
72
- console.log('[sanitizeURL] URLSearchParams created');
73
- urlParams.forEach((value, key) => {
74
- // eslint-disable-next-line no-console
75
- console.log('[sanitizeURL] Processing param:', key, '=', value);
76
- const decoded = decodeURIComponent(value);
77
- urlParams.set(key, decoded);
78
- });
79
- const result = `${sanitizedPath}?${urlParams.toString()}`;
80
- // eslint-disable-next-line no-console
81
- console.log('[sanitizeURL] Final result:', result);
82
- return result;
83
- } catch (error) {
84
- // eslint-disable-next-line no-console
85
- console.error('[sanitizeURL] Error sanitizing URL:', error);
86
- throw error;
87
- }
40
+ const [path, params] = url.split('?', 2);
41
+ const sanitizedPath = encodeURI(decodeURI(path));
42
+ if (!params) return sanitizedPath;
43
+ const urlParams = new URLSearchParams(params);
44
+ urlParams.forEach((value, key) => {
45
+ const decoded = decodeURIComponent(value);
46
+ urlParams.set(key, decoded);
47
+ });
48
+ return `${sanitizedPath}?${urlParams.toString()}`;
88
49
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codecademy/brand",
3
3
  "description": "Brand component library for Codecademy",
4
- "version": "3.36.2-alpha.7b9e1afbb4.0",
4
+ "version": "3.36.2-alpha.89d0f59c01.0",
5
5
  "author": "Codecademy Engineering <dev@codecademy.com>",
6
6
  "dependencies": {
7
7
  "@emotion/is-prop-valid": "^1.2.1",