Skip to content

Commit be135b2

Browse files
committed
Refactor: Continuing to work on CDN script
1 parent 97f2e9c commit be135b2

File tree

3 files changed

+190
-20
lines changed

3 files changed

+190
-20
lines changed

scripts/cdn/templates/core-index.html.template

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,6 @@
77
<link rel="preconnect" href="https://fonts.googleapis.com">
88
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
99
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,300;0,400;0,700;1,400&display=swap" rel="stylesheet">
10-
<script>
11-
// By default, redirect to JS file unless ?info is in the URL
12-
(function() {
13-
var urlParams = new URLSearchParams(window.location.search);
14-
// Only show the info page if ?info is explicitly set
15-
if (!urlParams.has('info')) {
16-
window.location.href = 'CORE_ENTRY';
17-
}
18-
})();
19-
</script>
2010
<style>
2111
:root {
2212
--primary: #2185d0;
@@ -119,7 +109,7 @@
119109
<p>Or use the bare import (which will use the main entry point):</p>
120110
<pre><code>import { ... } from 'https://cdn.semantic-ui.com/@semantic-ui/core/CORE_VERSION/';</code></pre>
121111

122-
<p class="info-note"><strong>Note:</strong> By default, all paths redirect to JavaScript files. Add <code>?info</code> to URLs to see package information and directory listings.</p>
112+
<p class="info-note"><strong>Note:</strong> By default, all paths redirect to JavaScript files. Add <code>?list</code> to URLs to see package information and directory listings.</p>
123113

124114
<h2>Files</h2>
125115
<p>Main entry point: <a href="./CORE_ENTRY">./CORE_ENTRY</a></p>

scripts/cdn/templates/latest-redirect.html.template

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@
66
// Add the appropriate meta refresh tag dynamically based on path
77
var isLatestPath = window.location.pathname.includes('/latest');
88
var prefix = isLatestPath ? '../' : '';
9-
var hasInfo = window.location.search.indexOf('info') !== -1;
10-
var target = hasInfo ? (prefix + '${VERSION}/?info') : (prefix + '${VERSION}/index.js');
9+
var hasJS = window.location.search.indexOf('js') !== -1;
10+
var target = hasJS ? (prefix + '${VERSION}/index.js') : (prefix + '${VERSION}/');
1111
document.write('<meta http-equiv="refresh" content="0;URL=' + target + '">');
1212
</script>
13-
<!-- Fallback for when JavaScript is disabled -->
14-
<noscript>
15-
<meta http-equiv="refresh" content="0;URL=${VERSION}/index.js">
16-
</noscript>
1713
<link rel="preconnect" href="https://fonts.googleapis.com">
1814
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
1915
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,300;0,400;0,700;1,400&display=swap" rel="stylesheet">
@@ -26,11 +22,11 @@
2622
var urlParams = new URLSearchParams(window.location.search);
2723

2824
if (urlParams.has('js')) {
29-
// Default behavior: show listing
25+
// Redirect to JS file (note this will not work with importmaps because of mime type)
3026
window.location.href = prefix + '${VERSION}/index.js';
3127
} else {
32-
// JS redirect behavior (note this will not work with importmaps because of mime-type)
33-
window.location.href = prefix + '${VERSION}/?info';
28+
// HTML list redirect behavior
29+
window.location.href = prefix + '${VERSION}/';
3430
}
3531
})();
3632
</script>
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/**
2+
* Resolves the best entry point for a package based on modern package.json fields
3+
* Prioritizes browser-compatible ES modules entry points.
4+
*
5+
* Based on CDN best practices from Skypack, Unpkg, and jsDelivr
6+
*
7+
* @param {Object} packageJson - The package.json contents as an object
8+
* @param {string} [mode='production'] - Whether to resolve 'development' or 'production' entry points when available
9+
* @returns {string} The resolved entry point path
10+
*/
11+
export function resolveEntry(packageJson, mode = 'production') {
12+
// For CDN purposes:
13+
// - 'production' means we want the optimized/minified versions (default)
14+
// - 'development' means we want the debug/unminified versions
15+
const isDev = mode === 'development';
16+
// Normalize the entry path - ensure we get a usable string path
17+
function normalizePath(entry) {
18+
if (!entry) return null;
19+
20+
// Handle the case where entry is an object (exports map)
21+
if (typeof entry === 'object') {
22+
// Try to find a usable string path in the object
23+
if (entry.browser && typeof entry.browser === 'string') {
24+
return entry.browser.replace(/^\.\//, '');
25+
}
26+
27+
if (entry.import && typeof entry.import === 'string') {
28+
return entry.import.replace(/^\.\//, '');
29+
}
30+
31+
if (entry.default && typeof entry.default === 'string') {
32+
return entry.default.replace(/^\.\//, '');
33+
}
34+
35+
// If we can't find a string, return a safe fallback
36+
return 'index.js';
37+
}
38+
39+
if (typeof entry !== 'string') return 'index.js';
40+
41+
// Convert paths like "./dist/index.js" or "dist/index.js" to standard format
42+
return entry.replace(/^\.\//, '');
43+
}
44+
45+
let entryPoint = null;
46+
47+
// 1. MODERN: Check exports field first (highest priority)
48+
if (packageJson.exports) {
49+
const exports = packageJson.exports;
50+
51+
// Handle string shorthand
52+
if (typeof exports === 'string') {
53+
entryPoint = normalizePath(exports);
54+
if (entryPoint) return entryPoint;
55+
}
56+
57+
// Handle main entry point (.)
58+
const mainExport = exports['.'];
59+
if (mainExport) {
60+
// String format
61+
if (typeof mainExport === 'string') {
62+
entryPoint = normalizePath(mainExport);
63+
if (entryPoint) return entryPoint;
64+
}
65+
66+
// Object format with conditions - priority order for browser ESM
67+
if (typeof mainExport === 'object') {
68+
// Handle complex browser conditions (with nested development/default)
69+
if (mainExport.browser) {
70+
if (typeof mainExport.browser === 'string') {
71+
// Simple string path
72+
entryPoint = normalizePath(mainExport.browser);
73+
if (entryPoint) return entryPoint;
74+
} else if (typeof mainExport.browser === 'object') {
75+
// Object with conditional exports (like lit-html has)
76+
77+
// Pick development or default based on mode
78+
const preferredKey = isDev ? 'development' : 'default';
79+
80+
if (mainExport.browser[preferredKey]) {
81+
entryPoint = normalizePath(mainExport.browser[preferredKey]);
82+
if (entryPoint) return entryPoint;
83+
}
84+
85+
// Fallback to any available key if preferred not found
86+
const fallbackKey = isDev ? 'default' : 'development';
87+
if (mainExport.browser[fallbackKey]) {
88+
entryPoint = normalizePath(mainExport.browser[fallbackKey]);
89+
if (entryPoint) return entryPoint;
90+
}
91+
92+
// Handle nested browser.import pattern
93+
if (mainExport.browser.import) {
94+
entryPoint = normalizePath(mainExport.browser.import);
95+
if (entryPoint) return entryPoint;
96+
}
97+
}
98+
}
99+
100+
// Handle nested import.browser pattern
101+
if (mainExport.import?.browser) {
102+
entryPoint = normalizePath(mainExport.import.browser);
103+
if (entryPoint) return entryPoint;
104+
}
105+
106+
// Direct development/production export based on mode
107+
if (isDev && mainExport.development) {
108+
if (typeof mainExport.development === 'string') {
109+
entryPoint = normalizePath(mainExport.development);
110+
if (entryPoint) return entryPoint;
111+
}
112+
113+
// Handle nested structure
114+
if (typeof mainExport.development === 'object') {
115+
if (mainExport.development.browser) {
116+
entryPoint = normalizePath(mainExport.development.browser);
117+
if (entryPoint) return entryPoint;
118+
}
119+
120+
if (mainExport.development.import) {
121+
entryPoint = normalizePath(mainExport.development.import);
122+
if (entryPoint) return entryPoint;
123+
}
124+
}
125+
} else if (!isDev && mainExport.production) {
126+
if (typeof mainExport.production === 'string') {
127+
entryPoint = normalizePath(mainExport.production);
128+
if (entryPoint) return entryPoint;
129+
}
130+
131+
// Handle nested structure
132+
if (typeof mainExport.production === 'object') {
133+
if (mainExport.production.browser) {
134+
entryPoint = normalizePath(mainExport.production.browser);
135+
if (entryPoint) return entryPoint;
136+
}
137+
138+
if (mainExport.production.import) {
139+
entryPoint = normalizePath(mainExport.production.import);
140+
if (entryPoint) return entryPoint;
141+
}
142+
}
143+
}
144+
145+
// Basic ES modules
146+
if (mainExport.import) {
147+
if (typeof mainExport.import === 'string') {
148+
entryPoint = normalizePath(mainExport.import);
149+
if (entryPoint) return entryPoint;
150+
}
151+
}
152+
153+
// Default condition
154+
if (mainExport.default) {
155+
entryPoint = normalizePath(mainExport.default);
156+
if (entryPoint) return entryPoint;
157+
}
158+
}
159+
}
160+
}
161+
162+
// 2. Traditional fields - browser, module, main
163+
164+
// Browser field (string format)
165+
if (typeof packageJson.browser === 'string') {
166+
entryPoint = normalizePath(packageJson.browser);
167+
if (entryPoint) return entryPoint;
168+
}
169+
170+
// Module field for ES modules
171+
if (packageJson.module) {
172+
entryPoint = normalizePath(packageJson.module);
173+
if (entryPoint) return entryPoint;
174+
}
175+
176+
// Standard main field
177+
if (packageJson.main) {
178+
entryPoint = normalizePath(packageJson.main);
179+
if (entryPoint) return entryPoint;
180+
}
181+
182+
// Default fallback to index.js
183+
return 'index.js';
184+
}

0 commit comments

Comments
 (0)