@rocket/js 0.2.0 → 0.2.1

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.
@@ -1,2 +1,2 @@
1
- export { ssrRender } from "../src/ssr.js";
1
+ export { html, render, ssrRender } from "../src/ssr.js";
2
2
  //# sourceMappingURL=ssr.d.ts.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Keeps browser packages shared between a Site Author project and a linked Rocket checkout.
3
+ * Packages absent from the project are left to normal Node resolution, which falls back to
4
+ * Rocket's dependency.
5
+ *
6
+ * @returns {import('@web/dev-server-core').Plugin}
7
+ */
8
+ export function preferProjectPackagesPlugin(): import("@web/dev-server-core").Plugin;
9
+ //# sourceMappingURL=prefer-project-packages-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer-project-packages-plugin.d.ts","sourceRoot":"","sources":["../../src/prefer-project-packages-plugin.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,+CAFa,OAAO,sBAAsB,EAAE,MAAM,CAsBjD"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Resolve a bare package import from the Site Author project using browser ESM conditions.
3
+ * Built-in modules and packages absent from the project are left to another resolver.
4
+ *
5
+ * @param {string} specifier
6
+ */
7
+ export function resolveProjectBrowserPackage(specifier: string): string | undefined;
8
+ //# sourceMappingURL=project-package-resolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-package-resolution.d.ts","sourceRoot":"","sources":["../../src/project-package-resolution.js"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,wDAFW,MAAM,sBAahB"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/resolve.js"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,6BAJW,MAAM,QACN,UAAU,GACR,MAAM,CAQlB"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/resolve.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,6BAJW,MAAM,QACN,UAAU,GACR,MAAM,CAWlB"}
@@ -3,4 +3,7 @@
3
3
  * @returns {Promise<string>}
4
4
  */
5
5
  export function ssrRender(template: string | import("lit").TemplateResult): Promise<string>;
6
+ import { html } from 'lit';
7
+ import { render } from '@lit-labs/ssr';
8
+ export { html, render };
6
9
  //# sourceMappingURL=ssr.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../../src/ssr.js"],"names":[],"mappings":"AAIA;;;GAGG;AACH,oCAHW,MAAM,GAAG,OAAO,KAAK,EAAE,cAAc,GACnC,OAAO,CAAC,MAAM,CAAC,CAO3B"}
1
+ {"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../../src/ssr.js"],"names":[],"mappings":"AAOA;;;GAGG;AACH,oCAHW,MAAM,GAAG,OAAO,KAAK,EAAE,cAAc,GACnC,OAAO,CAAC,MAAM,CAAC,CAO3B;qBAboB,KAAK;uBAFH,eAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/transform.js"],"names":[],"mappings":"AA8BA;;GAEG;AACH,2BAFW,MAAM,mBAoChB;AAED;;;GAGG;AACH,qCAHW,MAAM,QACN,MAAM,mBAqChB;AAqSD;;GAEG;AACH,qCAFW,OAAO,OAAO,EAAE,IAAI,WAI9B"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/transform.js"],"names":[],"mappings":"AA8BA;;GAEG;AACH,2BAFW,MAAM,mBAoChB;AAED;;;GAGG;AACH,qCAHW,MAAM,QACN,MAAM,mBAsChB;AAoSD;;GAEG;AACH,qCAFW,OAAO,OAAO,EAAE,IAAI,WAI9B"}
package/exports/ssr.js CHANGED
@@ -1 +1 @@
1
- export { ssrRender } from '../src/ssr.js';
1
+ export { html, render, ssrRender } from '../src/ssr.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rocket/js",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "HTML-first static-site metaframework for content sites and Web Component docs.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -77,6 +77,7 @@
77
77
  "bootstrap-icons": "^1.13.1",
78
78
  "commander": "^15.0.0",
79
79
  "es-module-lexer": "^2.1.0",
80
+ "import-meta-resolve": "^4.2.0",
80
81
  "lit": "^3.3.3",
81
82
  "parse5": "^8.0.1",
82
83
  "puppeteer-core": "^25.1.0",
@@ -250,7 +250,6 @@ export class RocketJsDemo extends LitElement {
250
250
  background-color: #eee;
251
251
  width: 100%;
252
252
  overflow: hidden;
253
- z-index: 0;
254
253
  }
255
254
 
256
255
  #resize {
@@ -280,6 +279,7 @@ export class RocketJsDemo extends LitElement {
280
279
  max-width: 100%;
281
280
  min-width: min-content;
282
281
  background: white;
282
+ z-index: 0;
283
283
  }
284
284
 
285
285
  #bottom {
package/src/icons.js CHANGED
@@ -723,7 +723,11 @@ async function iconSourceFiles(source) {
723
723
  */
724
724
  function packageRoot(packageName) {
725
725
  try {
726
- return path.dirname(require.resolve(`${packageName}/package.json`, { paths: [process.cwd()] }));
726
+ return path.dirname(
727
+ require.resolve(`${packageName}/package.json`, {
728
+ paths: [process.cwd(), import.meta.dirname],
729
+ }),
730
+ );
727
731
  } catch (error) {
728
732
  throw new Error(`Could not resolve Icon package ${JSON.stringify(packageName)}.`, {
729
733
  cause: error,
package/src/main.js CHANGED
@@ -5,6 +5,7 @@ import customRocketPlugin from './wds-plugin.js';
5
5
  import { MessageChannel } from 'node:worker_threads';
6
6
  import { customElements } from '@lit-labs/ssr-dom-shim';
7
7
  import { readConfig } from './config.js';
8
+ import { preferProjectPackagesPlugin } from './prefer-project-packages-plugin.js';
8
9
 
9
10
  const configFilePath = process.argv[2] || undefined;
10
11
  const startOptions = readStartOptions(process.argv[3]);
@@ -40,6 +41,7 @@ let devServerConfig = {
40
41
  defaultIconLibrary: config.defaultIconLibrary,
41
42
  watch: startOptions.watch,
42
43
  }),
44
+ preferProjectPackagesPlugin(),
43
45
  ],
44
46
  open: startOptions.open ?? true,
45
47
  nodeResolve: { exportConditions: ['browser'] },
@@ -0,0 +1,31 @@
1
+ import { resolveProjectBrowserPackage } from './project-package-resolution.js';
2
+ import { resolve } from './resolve.js';
3
+
4
+ /**
5
+ * Keeps browser packages shared between a Site Author project and a linked Rocket checkout.
6
+ * Packages absent from the project are left to normal Node resolution, which falls back to
7
+ * Rocket's dependency.
8
+ *
9
+ * @returns {import('@web/dev-server-core').Plugin}
10
+ */
11
+ export function preferProjectPackagesPlugin() {
12
+ /** @type {Map<string, string | undefined>} */
13
+ const resolvedImports = new Map();
14
+
15
+ return {
16
+ name: 'rocket-prefer-project-packages',
17
+ resolveImport({ source }) {
18
+ if (resolvedImports.has(source)) {
19
+ return resolvedImports.get(source);
20
+ }
21
+ let resolved;
22
+ try {
23
+ resolved = resolveProjectBrowserPackage(source) ? resolve(source, import.meta) : undefined;
24
+ } catch {
25
+ resolved = undefined;
26
+ }
27
+ resolvedImports.set(source, resolved);
28
+ return resolved;
29
+ },
30
+ };
31
+ }
@@ -0,0 +1,36 @@
1
+ import { moduleResolve } from 'import-meta-resolve';
2
+ import path from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+
5
+ const browserImportConditions = new Set(['browser', 'import', 'module']);
6
+
7
+ /**
8
+ * Resolve a bare package import from the Site Author project using browser ESM conditions.
9
+ * Built-in modules and packages absent from the project are left to another resolver.
10
+ *
11
+ * @param {string} specifier
12
+ */
13
+ export function resolveProjectBrowserPackage(specifier) {
14
+ if (!isPackageSpecifier(specifier)) {
15
+ return undefined;
16
+ }
17
+ try {
18
+ const projectParent = pathToFileURL(path.join(process.cwd(), 'package.json'));
19
+ const resolved = moduleResolve(specifier, projectParent, browserImportConditions, false);
20
+ return resolved.protocol === 'file:' ? resolved.href : undefined;
21
+ } catch {
22
+ return undefined;
23
+ }
24
+ }
25
+
26
+ /**
27
+ * @param {string} specifier
28
+ */
29
+ function isPackageSpecifier(specifier) {
30
+ return (
31
+ !specifier.startsWith('.') &&
32
+ !specifier.startsWith('/') &&
33
+ !specifier.startsWith('#') &&
34
+ !URL.canParse(specifier)
35
+ );
36
+ }
package/src/resolve.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import path from 'path';
2
2
  import { fileURLToPath } from 'url';
3
+ import { resolveProjectBrowserPackage } from './project-package-resolution.js';
3
4
 
4
5
  /**
5
6
  * @param {string} url
@@ -9,7 +10,36 @@ import { fileURLToPath } from 'url';
9
10
  export function resolve(url, meta) {
10
11
  // get current directory
11
12
  const outputFilePath = process.cwd();
12
- const resolvedPath = meta.resolve(url);
13
+ const resolvedPath = resolveProjectBrowserPackage(url) ?? meta.resolve(url);
13
14
  const rel = path.relative(outputFilePath, fileURLToPath(resolvedPath));
14
- return (process.env.ENVIRONMENT === 'BUILD' ? '/../' : '/') + rel.split(path.sep).join('/');
15
+ if (process.env.ENVIRONMENT === 'BUILD') {
16
+ return `/../${toBrowserPath(rel)}`;
17
+ }
18
+ return developmentBrowserPath(rel);
19
+ }
20
+
21
+ /**
22
+ * Web Dev Server represents files outside its root with a path that records how many parent
23
+ * directories to traverse. Browsers normalize ordinary `/../` segments before making a request,
24
+ * so linked packages need this explicit form.
25
+ *
26
+ * @param {string} relativePath
27
+ */
28
+ function developmentBrowserPath(relativePath) {
29
+ const parts = relativePath.split(path.sep);
30
+ let outsideRootDepth = 0;
31
+ while (parts[outsideRootDepth] === '..') {
32
+ outsideRootDepth += 1;
33
+ }
34
+ const browserPath = parts.slice(outsideRootDepth).join('/');
35
+ return outsideRootDepth
36
+ ? `/__wds-outside-root__/${outsideRootDepth}/${browserPath}`
37
+ : `/${browserPath}`;
38
+ }
39
+
40
+ /**
41
+ * @param {string} filePath
42
+ */
43
+ function toBrowserPath(filePath) {
44
+ return filePath.split(path.sep).join('/');
15
45
  }
package/src/ssr.js CHANGED
@@ -1,6 +1,9 @@
1
1
  /** Runs on: imported-js */
2
2
  import { render } from '@lit-labs/ssr';
3
3
  import { collectResult } from '@lit-labs/ssr/lib/render-result.js';
4
+ import { html } from 'lit';
5
+
6
+ export { html, render };
4
7
 
5
8
  /**
6
9
  * @param {string | import('lit').TemplateResult} template
package/src/transform.js CHANGED
@@ -90,10 +90,11 @@ export async function mdToJsSingleDemo(md, demo) {
90
90
 
91
91
  const code = /** @type {{client: string; server: string}} */ (result.data.code);
92
92
 
93
- const litImport = hasTopLevelHtmlBinding(code.server) ? '' : "import { html } from 'lit'";
93
+ const runtimeImport = hasTopLevelHtmlBinding(code.server)
94
+ ? "import { render } from '@rocket/js/ssr.js';"
95
+ : "import { html, render } from '@rocket/js/ssr.js';";
94
96
  const moduleCode = `
95
- import {render} from '@lit-labs/ssr';
96
- ${litImport}
97
+ ${runtimeImport}
97
98
  ${code.server}
98
99
  export function contentFn(data, layout) {
99
100
  data._clientCode = \`${code.client
@@ -117,12 +118,11 @@ export function contentFn(data, layout) {
117
118
  */
118
119
  async function makeJsFile(serverCode, clientCode, markdown, headlines) {
119
120
  const normalizedServerCode = normalizeLayoutExportBindings(serverCode);
120
- const litImport = hasTopLevelHtmlBinding(normalizedServerCode)
121
- ? ''
122
- : "import { html } from 'lit'";
121
+ const runtimeImport = hasTopLevelHtmlBinding(normalizedServerCode)
122
+ ? "import { render } from '@rocket/js/ssr.js';"
123
+ : "import { html, render } from '@rocket/js/ssr.js';";
123
124
  return `
124
- import {render} from '@lit-labs/ssr';
125
- ${litImport}
125
+ ${runtimeImport}
126
126
  ${normalizedServerCode}
127
127
  export function contentFn(data, defaultLayout) {
128
128
  let renderLayout = defaultLayout;