jq79 0.5.2 → 0.5.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jq79",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Mini reactive component library: single-file components, Svelte-style setup scripts, fine-grained proxy reactivity. Single-file build, zero dependencies.",
5
5
  "keywords": [
6
6
  "reactive",
package/src/jq79.ts CHANGED
@@ -1681,6 +1681,43 @@ const componentPartsFrom = (elements: Element[], hashSource: string): ComponentP
1681
1681
  const importResource = (url: string): Promise<any> =>
1682
1682
  /\.html?([?#]|$)/.test(url) ? fetchComponent(url) : import(url)
1683
1683
 
1684
+ // a relative specifier means "next to the file that wrote it", so it is
1685
+ // resolved against the component's own URL before importResource sees it -
1686
+ // neither of that function's two branches would otherwise land there. The
1687
+ // native import() inside it resolves against *this module* (dist/jq79.js), and
1688
+ // fetch() against the document; a component in a subdirectory gets a 404 from
1689
+ // the first and the page's directory from the second.
1690
+ //
1691
+ // Only `./` and `../` are resolved. A bare specifier ("lodash") belongs to the
1692
+ // import map or the native resolver, and resolving it would quietly turn it
1693
+ // into a path; anything already absolute means one thing under any base. That
1694
+ // keeps this the browser's rule rather than a third one of our own.
1695
+ //
1696
+ // The base is absolutized first, the way hotKey does and for the same reason:
1697
+ // the filename may itself be relative ("./card.html", from an import() in a
1698
+ // parent), and a relative URL cannot be a base.
1699
+ //
1700
+ // What comes back is a path whenever it lands on the page's own origin, and a
1701
+ // full URL only when it doesn't (a component served from a CDN resolves its
1702
+ // siblings on that CDN). Both are the same request, but the path keeps the
1703
+ // value the shape everything downstream already sees - what hotKey keys on,
1704
+ // what devtools shows as the script's name - so only the cross-origin case,
1705
+ // which has no path form, introduces a new one
1706
+ const resolveSpecifier = (spec: string, filename: string | undefined): string => {
1707
+ if (!/^\.\.?\//.test(spec)) return spec
1708
+ try {
1709
+ const page = new URL(document.baseURI)
1710
+ const url = new URL(spec, new URL(filename ?? "", page))
1711
+ // "null" is what an opaque origin (file:, blob:) reports, for both sides
1712
+ // and for anything else - it says the origins are unknown, not equal
1713
+ return url.origin !== "null" && url.origin === page.origin
1714
+ ? `${url.pathname}${url.search}${url.hash}`
1715
+ : url.href
1716
+ } catch {
1717
+ return spec
1718
+ }
1719
+ }
1720
+
1684
1721
  // ---------------------------------------------------------------------------
1685
1722
  // naming scripts for devtools
1686
1723
  //
@@ -2353,10 +2390,15 @@ export class Component79 {
2353
2390
 
2354
2391
  // import() calls whose specifier was pre-resolved by a bundler (the
2355
2392
  // modules map) get the bundled module; everything else falls back to the
2356
- // runtime importResource (fetch for .html, native import otherwise)
2393
+ // runtime importResource (fetch for .html, native import otherwise),
2394
+ // relative to this component's file. The map is keyed by the literal
2395
+ // specifier the script wrote, so it is consulted *before* resolution -
2396
+ // what the bundler hoisted and what the source says are the same string
2357
2397
  const modules = this.modules
2358
2398
  const $import = (url: string): Promise<any> =>
2359
- modules && url in modules ? Promise.resolve(modules[url]) : importResource(url)
2399
+ modules && url in modules
2400
+ ? Promise.resolve(modules[url])
2401
+ : importResource(resolveSpecifier(url, this.filename))
2360
2402
 
2361
2403
  // the writeback half of :model, from the child's side: one argument is the
2362
2404
  // value for the default model (the bare :model), two are a name and a