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 +2 -2
- package/bin/webim-plugin.js +44 -15
- package/package.json +1 -1
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 ->
|
|
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": "
|
|
70
|
+
"out": "build/plugin.js",
|
|
71
71
|
"api": "https://your-webim/api",
|
|
72
72
|
"tenant": "your-tenant-slug"
|
|
73
73
|
}
|
package/bin/webim-plugin.js
CHANGED
|
@@ -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
|
|
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
|
|
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": "
|
|
40
|
-
"api": "
|
|
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: '
|
|
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 ->
|
|
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 \`
|
|
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
|
|
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 ->
|
|
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: '
|
|
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 ?? '
|
|
491
|
-
api: config.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