webim-plugin 1.1.0 → 1.2.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.
package/README.md CHANGED
@@ -32,7 +32,7 @@ Requires Node 18+.
32
32
  ```bash
33
33
  webim-plugin init my-widget # scaffold: webim-plugin.json, src/, README
34
34
  cd my-widget
35
- webim-plugin build # esbuild -> dist/plugin.js + validation
35
+ webim-plugin build # esbuild -> build/plugin.js + validation
36
36
  webim-plugin push # build, sign in, merge into builder_plugins
37
37
  webim-plugin dev # watch src/, rebuild + push on every change
38
38
  ```
@@ -67,7 +67,7 @@ needed).
67
67
  ```json
68
68
  {
69
69
  "entry": "src/index.js",
70
- "out": "dist/plugin.js",
70
+ "out": "build/plugin.js",
71
71
  "api": "https://your-webim/api",
72
72
  "tenant": "your-tenant-slug"
73
73
  }
@@ -3,7 +3,7 @@
3
3
  // webim-plugin — the Web-IM builder plugin CLI.
4
4
  //
5
5
  // webim-plugin init [dir] scaffold a plugin project
6
- // webim-plugin build bundle src/ into dist/plugin.js and validate it
6
+ // webim-plugin build bundle src/ into build/plugin.js and validate it
7
7
  // webim-plugin push build + upload to the tenant's builder_plugins
8
8
  // webim-plugin dev watch src/, rebuild and push on every change
9
9
  //
@@ -31,13 +31,13 @@ Commands:
31
31
  wrap [dir] convert an EXISTING project: add config, an adapter entry
32
32
  (Shadow-DOM boilerplate, React-aware) and WEBIM_PLUGIN.md —
33
33
  the plugin contract written as rules for AI assistants
34
- build bundle the entry into dist/plugin.js and validate it
34
+ build bundle the entry into build/plugin.js and validate it
35
35
  push build, then upload to the tenant's builder_plugins setting
36
36
  dev watch the source; rebuild and push on every change
37
37
 
38
38
  Config (webim-plugin.json):
39
- { "entry": "src/index.js", "out": "dist/plugin.js",
40
- "api": "http://localhost:4100/api", "tenant": "root" }
39
+ { "entry": "src/index.js", "out": "build/plugin.js",
40
+ "api": "https://webim.app/api", "tenant": "root" }
41
41
 
42
42
  Auth (push/dev): WEBIM_TOKEN, or WEBIM_EMAIL + WEBIM_PASSWORD.`;
43
43
 
@@ -45,7 +45,7 @@ Auth (push/dev): WEBIM_TOKEN, or WEBIM_EMAIL + WEBIM_PASSWORD.`;
45
45
  // scaffolding
46
46
 
47
47
  const TEMPLATE_CONFIG = (name) => `${JSON.stringify(
48
- { entry: 'src/index.js', out: 'dist/plugin.js', api: 'http://localhost:4100/api', tenant: 'root' },
48
+ { entry: 'src/index.js', out: 'build/plugin.js', api: 'https://webim.app/api', tenant: 'root' },
49
49
  null,
50
50
  2
51
51
  )}\n`;
@@ -106,7 +106,7 @@ A Web-IM builder plugin. Develop:
106
106
 
107
107
  \`\`\`bash
108
108
  npm install
109
- npx webim-plugin build # bundle + validate -> dist/plugin.js
109
+ npx webim-plugin build # bundle + validate -> build/plugin.js
110
110
  npx webim-plugin push # upload to the tenant in webim-plugin.json
111
111
  npx webim-plugin dev # watch + rebuild + push
112
112
  \`\`\`
@@ -172,7 +172,7 @@ const TEMPLATE_GUIDE = (id, name, entry) => `# Web-IM plugin rules — ${name}
172
172
 
173
173
  Directives for AI assistants (and humans) working on the Web-IM builder
174
174
  plugin in this project. Follow every MUST. The plugin entry is \`${entry}\`;
175
- \`npx webim-plugin build\` bundles it to \`dist/plugin.js\` and validates it.
175
+ \`npx webim-plugin build\` bundles it to \`build/plugin.js\` and validates it.
176
176
 
177
177
  ## The contract
178
178
 
@@ -206,7 +206,9 @@ must have a default in \`props\`.
206
206
 
207
207
  - Everything must land in ONE ES module — \`push\` uploads only the built JS.
208
208
  - \`import\` of \`.css\`/\`.html\` files yields the file content as a STRING
209
- (inject a \`<style>\` tag / parse markup yourself at mount time).
209
+ (inject a \`<style>\` tag / parse markup yourself at mount time). In \`.css\`
210
+ imports the CLI rewrites \`:root\` to \`:host\` — inside a shadow root
211
+ \`:root\` matches nothing, \`:host\` is its exact analogue.
210
212
  - Images and fonts (\`.svg .png .jpg .jpeg .gif .webp .woff .woff2\`) import
211
213
  as \`data:\` URLs.
212
214
  - After bundling, the CLI IMPORTS the bundle in Node.js to validate it.
@@ -226,7 +228,8 @@ must have a default in \`props\`.
226
228
  \`document.head\` (deduplicate first) — \`@font-face\` is inert inside a
227
229
  shadow root.
228
230
  3. If reusing an app's page-level stylesheet, rescope it to a wrapper div
229
- inside the shadow: \`body\`/\`html\`/\`:root\` selectors → the wrapper class,
231
+ inside the shadow: \`body\`/\`html\` selectors → the wrapper class
232
+ (\`:root\` is rewritten to \`:host\` by the build automatically),
230
233
  \`position: fixed\` → \`absolute\`, \`100vw/100vh\` → \`100%\`. Give the
231
234
  wrapper \`position: relative; overflow: hidden\`.
232
235
  4. The same block can be mounted MULTIPLE times on one page: no module-level
@@ -258,7 +261,7 @@ must have a default in \`props\`.
258
261
  ## Ship
259
262
 
260
263
  \`\`\`bash
261
- npx webim-plugin build # bundle + validate -> dist/plugin.js
264
+ npx webim-plugin build # bundle + validate -> build/plugin.js
262
265
  npx webim-plugin push # upload to the tenant in webim-plugin.json
263
266
  npx webim-plugin dev # watch + rebuild + push
264
267
  \`\`\`
@@ -445,7 +448,7 @@ async function wrap(dirArg) {
445
448
 
446
449
  await mkdir(path.dirname(entryFile), { recursive: true });
447
450
  await writeFile(path.join(dir, CONFIG_FILE), `${JSON.stringify(
448
- { entry, out: 'dist/plugin.js', api: 'http://localhost:4100/api', tenant: 'root' },
451
+ { entry, out: 'build/plugin.js', api: 'https://webim.app/api', tenant: 'root' },
449
452
  null,
450
453
  2
451
454
  )}\n`);
@@ -487,8 +490,8 @@ async function loadConfig() {
487
490
 
488
491
  return {
489
492
  entry: config.entry ?? 'src/index.js',
490
- out: config.out ?? 'dist/plugin.js',
491
- api: config.api ?? 'http://localhost:4100/api',
493
+ out: config.out ?? 'build/plugin.js',
494
+ api: config.api ?? 'https://webim.app/api',
492
495
  tenant: config.tenant ?? ''
493
496
  };
494
497
  }
@@ -497,7 +500,6 @@ async function loadConfig() {
497
500
  // and HTML come in as strings (inject a <style> / parse markup at mount),
498
501
  // images and fonts as data: URLs.
499
502
  const LOADERS = {
500
- '.css': 'text',
501
503
  '.html': 'text',
502
504
  '.svg': 'dataurl',
503
505
  '.png': 'dataurl',
@@ -509,6 +511,31 @@ const LOADERS = {
509
511
  '.woff2': 'dataurl'
510
512
  };
511
513
 
514
+ // .css imports are strings too, but rescoped first: plugins render inside a
515
+ // Shadow DOM, where `:root` matches nothing — its analogue is `:host`, so the
516
+ // rewrite is always safe (same specificity, same "tree root" meaning).
517
+ // `html`/`body` selectors CAN'T be rewritten automatically — the wrapper
518
+ // class they should target is the plugin's own choice — so they only warn.
519
+ const warnedCssFiles = new Set();
520
+ const cssRescopePlugin = {
521
+ name: 'css-rescope',
522
+ setup(build) {
523
+ build.onLoad({ filter: /\.css$/ }, async (args) => {
524
+ const css = await readFile(args.path, 'utf8');
525
+
526
+ if (!warnedCssFiles.has(args.path) && /(^|[\s,}])(html|body)\s*[,{[.:>#]/m.test(css)) {
527
+ warnedCssFiles.add(args.path);
528
+ console.warn(
529
+ `Warning: ${path.relative(process.cwd(), args.path)} styles html/body — those selectors match nothing ` +
530
+ 'inside the shadow root; rescope them to a wrapper class (see WEBIM_PLUGIN.md, Rendering rules).'
531
+ );
532
+ }
533
+
534
+ return { contents: css.replace(/:root\b/g, ':host'), loader: 'text' };
535
+ });
536
+ }
537
+ };
538
+
512
539
  async function bundle(config) {
513
540
  const esbuild = await import('esbuild');
514
541
  const result = await esbuild.build({
@@ -523,7 +550,8 @@ async function bundle(config) {
523
550
  // Modern JSX runtime (React 17+/Vite default): .jsx/.tsx files work
524
551
  // without a manual `import React` in every file.
525
552
  jsx: 'automatic',
526
- loader: LOADERS
553
+ loader: LOADERS,
554
+ plugins: [cssRescopePlugin]
527
555
  });
528
556
 
529
557
  if (result.errors.length) throw new Error(result.errors.map((e) => e.text).join('\n'));
@@ -684,6 +712,7 @@ async function dev() {
684
712
  jsx: 'automatic',
685
713
  loader: LOADERS,
686
714
  plugins: [
715
+ cssRescopePlugin,
687
716
  {
688
717
  name: 'webim-push',
689
718
  setup(buildHook) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webim-plugin",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "CLI for Web-IM builder plugins — scaffold, bundle TS/JSX into the single-module standard, validate, and push to a tenant",
5
5
  "license": "MIT",
6
6
  "author": "Orhan POLAT",