{"_id":"@abeyjs/compiler","_rev":"3-ed99d93d97d59b0b8d3242532a421475","name":"@abeyjs/compiler","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@abeyjs/compiler","version":"0.1.0","license":"MIT","_id":"@abeyjs/compiler@0.1.0","maintainers":[{"name":"abeyjs","email":"abeyjs98@gmail.com"}],"dist":{"shasum":"b7f1ca77b299e2affd33759d883b702543d0c19f","tarball":"https://registry.npmjs.org/@abeyjs/compiler/-/compiler-0.1.0.tgz","fileCount":22,"integrity":"sha512-jjTI5IQ1JUrojhEMHImR2N8L4iOFsq54xcTkSF8CpakIuYUNg1QfbEfgTp2CcLuc24OLtQCF9mVmrf8bCG6j5Q==","signatures":[{"sig":"MEUCIBc2wbgNFFXzdqKTXNaz4BtZBf6i7W6fNlqE69ORtsarAiEAnidTnIZ2GBwr/KtchGNUO3jcvhYwvtI1wsoV1VrFKg8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":273398},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"24fe5ea792f5be4e8facf7c820025f89265c1467","scripts":{"build":"tsc -p tsconfig.json"},"_npmUser":{"name":"abeyjs","email":"abeyjs98@gmail.com"},"_npmVersion":"10.8.2","description":"Turns AbeyJs markup files into **plain TypeScript modules** the bundler can import. Pair it with Vite via `abeyVitePlugin()` so `*.view.html` and `*.abey` behave like first-class sources instead of static HTML entrypoints.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"parse5":"^7.2.0","esbuild":"^0.25.0","magic-string":"^0.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.4.2","typescript":"^5.7.3"},"_npmOperationalInternal":{"tmp":"tmp/compiler_0.1.0_1777684973244_0.9938140544617811","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@abeyjs/compiler","version":"0.1.1","license":"MIT","_id":"@abeyjs/compiler@0.1.1","maintainers":[{"name":"abeyjs","email":"abeyjs98@gmail.com"}],"dist":{"shasum":"675b5159c65f82d524c0d7ba2039281b1c77fe4f","tarball":"https://registry.npmjs.org/@abeyjs/compiler/-/compiler-0.1.1.tgz","fileCount":22,"integrity":"sha512-IL0aYDYy+UZ5ogHE4LY+QDeX7uJyxwQGtx6SflTIZFZuc4EjKKxYTgmfmr2BzDztR56Wmx3WZ1vzpW3LKKnnqg==","signatures":[{"sig":"MEQCIFbV0vzefI0+rN9dLOxkTiPGF6Oyv+MccZXGK4h73jUEAiB2f8cEg7kQpSL1/asIg8IkwIYwJ73ZsMPNZdQptjfuQg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":285168},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"8e89473e70d292931fe54ab9e184c613a03528d3","scripts":{"build":"tsc -p tsconfig.json"},"_npmUser":{"name":"abeyjs","email":"abeyjs98@gmail.com"},"_npmVersion":"10.8.2","description":"Turns AbeyJs markup files into **plain TypeScript modules** the bundler can import. Pair it with Vite via `abeyVitePlugin()` so `*.view.html` and `*.abey` behave like first-class sources instead of static HTML entrypoints.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"parse5":"^7.2.0","esbuild":"^0.25.0","magic-string":"^0.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.4.2","typescript":"^5.7.3"},"_npmOperationalInternal":{"tmp":"tmp/compiler_0.1.1_1777734080693_0.385409307172367","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@abeyjs/compiler","version":"0.1.2","license":"MIT","publishConfig":{"access":"public"},"type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.json"},"dependencies":{"magic-string":"^0.30.0","esbuild":"^0.25.0","parse5":"^7.2.0"},"devDependencies":{"typescript":"^5.7.3","vite":"^6.4.2"},"_id":"@abeyjs/compiler@0.1.2","gitHead":"8e89473e70d292931fe54ab9e184c613a03528d3","description":"Turns AbeyJs markup files into **plain TypeScript modules** the bundler can import. Pair it with Vite via `abeyVitePlugin()` so `*.view.html` and `*.abey` behave like first-class sources instead of static HTML entrypoints.","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-ZalXVKMes/5M69LgezsUshvVKMYmbcE91AL8QDtpW3YTBmtEp293F2wSM8czbg5cScs4xXwAg/klXr5FpxXYSQ==","shasum":"2f38e1641db36745d48e7b4b79513ce8615027f8","tarball":"https://registry.npmjs.org/@abeyjs/compiler/-/compiler-0.1.2.tgz","fileCount":8,"unpackedSize":91274,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFqKdhw+wv8taTEKaAcQG/0yH0Aho5q84EcskG5iMqESAiBXWE8mfcAElSC8YaBJLlo/zN2WZ3bwACXdfMOp87UaVw=="}]},"_npmUser":{"name":"abeyjs","email":"abeyjs98@gmail.com"},"directories":{},"maintainers":[{"name":"abeyjs","email":"abeyjs98@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/compiler_0.1.2_1777736113187_0.731956576127684"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-02T01:22:53.141Z","modified":"2026-05-02T15:35:13.468Z","0.1.0":"2026-05-02T01:22:53.437Z","0.1.1":"2026-05-02T15:01:20.849Z","0.1.2":"2026-05-02T15:35:13.377Z"},"license":"MIT","description":"Turns AbeyJs markup files into **plain TypeScript modules** the bundler can import. Pair it with Vite via `abeyVitePlugin()` so `*.view.html` and `*.abey` behave like first-class sources instead of static HTML entrypoints.","maintainers":[{"name":"abeyjs","email":"abeyjs98@gmail.com"}],"readme":"# `@abeyjs/compiler`\r\n\r\nTurns AbeyJs markup files into **plain TypeScript modules** the bundler can import. Pair it with Vite via `abeyVitePlugin()` so `*.view.html` and `*.abey` behave like first-class sources instead of static HTML entrypoints.\r\n\r\n---\r\n\r\n## Compilation pipeline (`compileAbeyToTs`)\r\n\r\nThe public function walks the source in a **fixed order** (see `compileAbeyToTs` in `src/abey-compile.ts`). Skipping or reordering passes would break markers such as `data-abey-select-items` vs generic `[prop]` handling.\r\n\r\n| Step | What runs | Why it matters |\r\n|------|-----------|----------------|\r\n| 1 | `splitFrontmatter` | Optional `---` … `---` block; body becomes the template string. |\r\n| 2 | `parseComponentMeta` | Reads `@Component({ selector, styles, state?, aot? })`. Missing `aot` defaults to **`true`**; set `aot: false` to force the `innerHTML` mount path. |\r\n| 3 | `preprocessSugar` | `*if` / `*for` / `@switch` lowering before structural extraction. |\r\n| 4 | `extractAttrMixedInterpolation` | Mixed `href=\"/u/{{ id }}\"` style attributes. |\r\n| 5 | `extractAttrHoles` | Exact `attr=\"{{ expr }}\"`. |\r\n| 6 | `extractSelectItemsDirectives` | **Before** bracket extraction: `<select [items]>` expansion. |\r\n| 7 | `extractBracketBindings` | `[prop]`, `(event)`, `[(model)]`, class/style maps, etc. |\r\n| 8 | `extractIfBlocks` / `extractForBlocks` | `@if` / `@else if` / `@else`, `@for`; nested `@for` under `@if` is merged for render ordering. |\r\n| 9 | `extractHoles` | Text `{{ }}` and `{expr}` only. |\r\n| 10 | Emit | `template`, `compiledTemplate`, `mount`, helpers; optional AOT factory when eligible; optional `AbeyComponent` class. |\r\n\r\n**Render ordering:** `@if` / `@for` blocks are sorted **outer → inner** (higher block index first) so a parent branch does not wipe nested DOM when toggling.\r\n\r\n**AOT:** When `aot` is true and the compiled HTML contains **no** `template data-abey-if` / `template data-abey-for`, `buildAotFactory` emits imperative `createElement` code. Otherwise `mount` falls back to parsing `compiledTemplate` even if `aot` was left at default.\r\n\r\n---\r\n\r\n## Vite hook (`abeyVitePlugin`)\r\n\r\n- Runs **`enforce: \"pre\"`** so templates compile before the rest of the pipeline.\r\n- Resolves `.view.html` / `.abey` imports to **virtual modules** so Vite’s dependency scan does not treat them as multi-page HTML entries.\r\n- Feeds the generated TS through **esbuild** with `experimentalDecorators` enabled—frontmatter-generated classes may emit `@AbeyComponent`.\r\n- Reads optional **`abey.json`** beside the Vite root (see below).\r\n- Hot updates currently **full-reload** the dev server (granular HMR is future work).\r\n\r\n### Virtual module IDs\r\n\r\nResolved ids look like:\r\n\r\n`virtual:abeyjs-abey:` + **base64url** of the absolute file path (UTF-8, `+` → `-`, `/` → `_`, padding `=` stripped).\r\n\r\nThe plugin maps these back to disk in `load` and compiles with `compileAbeyToTs`.\r\n\r\n### `abey.json` (optional)\r\n\r\nPlace next to Vite **`root`** (often the app folder that contains `vite.config.*`).\r\n\r\nMinimal shape:\r\n\r\n```json\r\n{\r\n  \"styles\": [\"./src/styles/global.css\", \"./src/styles/theme.css\"]\r\n}\r\n```\r\n\r\n- Each string is a path **relative to `abey.json`** (or resolvable from the project); the plugin generates a small module that **imports** them so Vite processes URLs and HMR.\r\n- Global styles: add `import \"/abey-styles.js\"` in `main.ts` (resolved by the Abey Vite plugin from `abey.json`); do not rely on an HTML-injected script — it is not emitted on `vite build` and causes a blank app / *Invalid or unexpected token* when the browser loads a 404 HTML page as JS.\r\n- `@AbeyComponent` in `*.ts`: enable `\"experimentalDecorators\": true` in `tsconfig.json`, or use `abeyVitePlugin()` — it merges that flag into Vite’s `esbuild` options. If decorators are not lowered, emitted JS still contains `@` and a lazy route’s dynamic `import()` fails with *Invalid or unexpected token*.\r\n\r\n---\r\n\r\n## What a compiled module exports\r\n\r\n| Symbol | Purpose |\r\n|--------|---------|\r\n| `template` | Original markup (escaped string). Feed `@AbeyComponent({ template })` when the runtime binder should keep raw bindings alive. |\r\n| `compiledTemplate` | Transformed HTML with `data-abey-*` markers, `<template data-abey-if/for>`, etc.—what the non-AOT `mount()` path expects. |\r\n| `mount(outlet, ctx)` | Binds the compiled template to a DOM node, returns `{ render, dispose }`. |\r\n| Optional custom element class | When frontmatter includes a `@Component({ selector, styles, state? })` block, the compiler emits an `AbeyComponentElement` subclass wired to `mount`. |\r\n\r\nFrontmatter is optional YAML-style `---` … `---`; everything after the second delimiter is template body.\r\n\r\n---\r\n\r\n## Syntax surface (current compiler)\r\n\r\n**Structural**\r\n\r\n- `@if (expr) { ... }` with `@else if` / `@else`.\r\n- `@for (item of listExpr) { ... }` (optional `track` clause ignored in MVP).\r\n- `@switch` rewritten to an `@if` ladder during preprocess.\r\n\r\n**Sugar**\r\n\r\n- `*if=\"expr\"` / `*for=\"item of expr\"` on elements unwrap into the block forms above.\r\n\r\n**Text**\r\n\r\n- `{{ expr }}` mustache holes in text nodes.\r\n- `{expr}` single-brace holes (same insertion mechanism, lighter syntax).\r\n\r\n**Attributes**\r\n\r\n- Exact attribute binding `attr=\"{{ expr }}\"`.\r\n- Mixed attribute strings like `href=\"/u/{{ id }}\"`.\r\n- Bracket bindings: `[prop]`, `[attr.name]`, `[class.foo]`, `[style.prop]` / `[style.prop.px]`, `(event)=\"handler($event)\"`, `[(model)]` with element-aware two-way sugar.\r\n- `<select [items] [value] [name]>` helper expands into option rendering logic.\r\n\r\n**Limits (today)**\r\n\r\n- Expressions are **not** type-checked at compile time.\r\n- Parser passes are MVP: avoid exotic nesting the tests do not cover yet.\r\n\r\n---\r\n\r\n## TypeScript: typing template imports\r\n\r\nVite resolves templates to JS modules. Add a **declaration** in your app (path is up to you; many projects use `src/vite-env.d.ts`):\r\n\r\n```ts\r\n/** Matches the `ctx` object your screen passes into `mount` (narrow per view in your app if you want). */\r\ntype AbeyViewCtx = Record<string, unknown>;\r\n\r\ndeclare module \"*.view.html\" {\r\n  export const template: string;\r\n  export const compiledTemplate: string;\r\n  export function mount(\r\n    outlet: HTMLElement,\r\n    ctx: AbeyViewCtx\r\n  ): { render: () => void; dispose: () => void };\r\n}\r\n\r\ndeclare module \"*.abey\" {\r\n  export const template: string;\r\n  export const compiledTemplate: string;\r\n  export function mount(\r\n    outlet: HTMLElement,\r\n    ctx: AbeyViewCtx\r\n  ): { render: () => void; dispose: () => void };\r\n}\r\n```\r\n\r\nEmitted modules type `mount` as `ctx: Ctx` but **`Ctx` is not exported** by `@abeyjs/view`; use `AbeyViewCtx` (or replace with your own domain type). Custom elements from `@Component` add named class exports—extend the `declare module` when you import those symbols.\r\n\r\n---\r\n\r\n## Programmatic API\r\n\r\n```ts\r\nimport { compileAbeyToTs } from \"@abeyjs/compiler\";\r\n\r\nconst { code } = compileAbeyToTs(source, \"/abs/path/to/screen.view.html\");\r\n```\r\n\r\n`code` is ready to hand to esbuild/TypeScript the same way the Vite plugin does.\r\n\r\n---\r\n\r\n## Troubleshooting\r\n\r\n| Symptom | Likely cause |\r\n|---------|----------------|\r\n| Vite / esbuild errors mentioning `html:virtual:` or dependency scan on `.view.html` | Ensure `abeyVitePlugin()` is registered and runs **`pre`** (do not strip `enforce`). The plugin disables automatic optimize-deps discovery for this reason. |\r\n| `[value]` on `<select>` behaves like a generic property | `<select [items]>` **must** be processed before `[prop]`; that order is enforced in the compiler—if you fork passes, preserve it. |\r\n| `@else if` branch never shows | Nested DOM + TreeWalker ordering is sensitive; upstream tests cover supported patterns—avoid replacing nodes while iterating in custom runtime code. |\r\n| Expected AOT (`createElement`) but got `innerHTML` path | AOT is skipped when `@if` / `@for` remain in compiled HTML (`buildAotFactory` returns `null`). |\r\n| Styles from `abey.json` missing | Confirm `abey.json` sits at Vite **root**, paths are correct, and the dev `index.html` is transformed (plugin hook runs). |\r\n\r\n---\r\n\r\n## Dependencies\r\n\r\n`parse5` for HTML-ish transforms, `magic-string` / `esbuild` helpers inside the implementation. Consumers typically add `@abeyjs/view` because generated components import `AbeyComponentElement`.\r\n\r\n---\r\n\r\n## Build\r\n\r\n```bash\r\nnpm run build -w @abeyjs/compiler\r\n```\r\n","readmeFilename":"README.md"}