{"_id":"@macaly/static-tagger","_rev":"4-0d14e00e9b6ba7b1858e5a88d3b617bb","name":"@macaly/static-tagger","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@macaly/static-tagger","version":"0.1.0","keywords":["vite","vite-plugin","jsx","tsx","react","ssr","ssg","source-location","click-to-source","debugging","typescript","babel"],"author":{"url":"https://macaly.com","name":"Macaly","email":"hi@macaly.com"},"license":"MIT","_id":"@macaly/static-tagger@0.1.0","maintainers":[{"name":"thyrst","email":"thyrst@seznam.cz"}],"homepage":"https://github.com/langtail/macaly-static-tagger#readme","bugs":{"url":"https://github.com/langtail/macaly-static-tagger/issues"},"dist":{"shasum":"9df8467bf2488e49c8aa9df41fe805b6c43db9a8","tarball":"https://registry.npmjs.org/@macaly/static-tagger/-/static-tagger-0.1.0.tgz","fileCount":21,"integrity":"sha512-xRgoyLYFjHZuBw8IWEd0U3VvdH9XhoM1HeoPccqful9dsAANdEWUYPcwjPwNe/MG27N+9Ai+PzVeXkYZU3RCAQ==","signatures":[{"sig":"MEUCIQDJGZe/N9debpw7vb/7mKKl4zFaeDPwyDbWaso1bUVJwQIgK6E7q6JuwCwXjB/almadV4BmpBIkTev4pIhhdUWcslg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27602},"main":"dist/index.js","type":"module","_from":"file:macaly-static-tagger-0.1.0.tgz","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"rimraf dist","format":"prettier --write \"src/**/*.{ts,tsx}\"","lint:fix":"eslint src --ext .ts,.tsx --fix","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"tsc -p tsconfig.build.json --watch","format:check":"prettier --check \"src/**/*.{ts,tsx}\"","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"thyrst","email":"thyrst@seznam.cz"},"_resolved":"/private/var/folders/zp/cxy7nltn4653ty7cc5dvtljm0000gn/T/42c90353467138cd690f7d1fcc6828f1/macaly-static-tagger-0.1.0.tgz","_integrity":"sha512-xRgoyLYFjHZuBw8IWEd0U3VvdH9XhoM1HeoPccqful9dsAANdEWUYPcwjPwNe/MG27N+9Ai+PzVeXkYZU3RCAQ==","repository":{"url":"git+https://github.com/langtail/macaly-static-tagger.git","type":"git"},"_npmVersion":"11.12.1","description":"Vite plugin that injects source-location data attributes onto JSX elements at build time, so production HTML/JS carries data-macaly-loc / data-macaly-name pointing back at the original source coordinate.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"magic-string":"^0.30.0","@babel/parser":"^7.24.0","estree-walker":"^3.0.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.0.0 || ^6.0.0 || ^7.0.0","eslint":"^8.57.0","rimraf":"^5.0.5","vitest":"^4.0.17","prettier":"^3.2.5","typescript":"^5.4.2","@types/node":"^20.11.30","@babel/types":"^7.24.0","@types/estree":"^1.0.5","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","@typescript-eslint/parser":"^7.3.1","@typescript-eslint/eslint-plugin":"^7.3.1"},"peerDependencies":{"vite":"^5.0.0 || ^6.0.0 || ^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/static-tagger_0.1.0_1778147197586_0.6548021310822505","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@macaly/static-tagger","version":"0.1.1","keywords":["vite","vite-plugin","jsx","tsx","react","ssr","ssg","source-location","click-to-source","debugging","typescript","babel"],"author":{"url":"https://macaly.com","name":"Macaly","email":"hi@macaly.com"},"license":"MIT","_id":"@macaly/static-tagger@0.1.1","maintainers":[{"name":"thyrst","email":"thyrst@seznam.cz"}],"homepage":"https://github.com/langtail/macaly-static-tagger#readme","bugs":{"url":"https://github.com/langtail/macaly-static-tagger/issues"},"dist":{"shasum":"9a733b672e47d0923aa673bc6999c6d88a5585a7","tarball":"https://registry.npmjs.org/@macaly/static-tagger/-/static-tagger-0.1.1.tgz","fileCount":21,"integrity":"sha512-/4Usd5FDAliKTVHWzYWLLLq47g+Q2abARLd5d9iP1ORArIab2I2OX8fCMZtHKvqCnQAns94IHyWcg2lWWRd0zA==","signatures":[{"sig":"MEUCIQDr4MfoZM9spaZzbCB+azLkLqCtTe9TkhTMHWyCvX4yfgIgMFu/2mjNR9WD7e4JI1HKZJuwafXoRJZNH2ujWXLkHO8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27908},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":"^18.0.0 || ^20.19.0 || >=22.12.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"d27d600554be7fa39633381d1ae3a178de9e867a","scripts":{"lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"tsc -p tsconfig.build.json","clean":"rimraf dist","format":"prettier --write \"src/**/*.{ts,tsx}\"","prepack":"npm run build","lint:fix":"eslint src --ext .ts,.tsx --fix","test:watch":"vitest","type-check":"tsc --noEmit","build:watch":"tsc -p tsconfig.build.json --watch","format:check":"prettier --check \"src/**/*.{ts,tsx}\"","test:coverage":"vitest run --coverage","prepublishOnly":"npm run clean && npm run build && npm run test && npm run lint"},"_npmUser":{"name":"thyrst","email":"thyrst@seznam.cz"},"repository":{"url":"git+https://github.com/langtail/macaly-static-tagger.git","type":"git"},"_npmVersion":"11.12.1","description":"Vite plugin that injects source-location data attributes onto JSX elements at build time, so production HTML/JS carries data-macaly-loc / data-macaly-name pointing back at the original source coordinate.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"magic-string":"^0.30.0","@babel/parser":"^7.24.0","estree-walker":"^3.0.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531","devDependencies":{"vite":"^8.1.5","eslint":"^8.57.0","rimraf":"^5.0.5","vitest":"^4.0.17","prettier":"^3.2.5","typescript":"^5.4.2","@types/node":"^20.11.30","@babel/types":"^7.24.0","@types/estree":"^1.0.5","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.3","@typescript-eslint/parser":"^7.3.1","@typescript-eslint/eslint-plugin":"^7.3.1"},"peerDependencies":{"vite":"^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/static-tagger_0.1.1_1784238667783_0.8988175384819859","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-05-07T09:46:37.471Z","modified":"2026-08-06T10:59:33.262Z","0.1.0":"2026-05-07T09:46:37.748Z","0.1.1":"2026-07-16T21:51:07.914Z"},"bugs":{"url":"https://github.com/langtail/macaly-static-tagger/issues"},"author":{"url":"https://macaly.com","name":"Macaly","email":"hi@macaly.com"},"license":"MIT","homepage":"https://github.com/langtail/macaly-static-tagger#readme","keywords":["vite","vite-plugin","jsx","tsx","react","ssr","ssg","source-location","click-to-source","debugging","typescript","babel"],"repository":{"url":"git+https://github.com/langtail/macaly-static-tagger.git","type":"git"},"description":"Vite plugin that injects source-location data attributes onto JSX elements at build time, so production HTML/JS carries data-macaly-loc / data-macaly-name pointing back at the original source coordinate.","maintainers":[{"email":"thyrst@seznam.cz","name":"thyrst"},{"email":"rychlis@rychlis.cz","name":"rychlis"},{"email":"tomasjohanovsky@macaly.com","name":"johanovskyt"}],"readme":"# @macaly/static-tagger\n\nVite plugin. Rewrites `.jsx` / `.tsx` source so every JSX element gains two static attributes:\n\n- `data-macaly-loc=\"<relative/path.tsx>:<line>:<col>\"` — points back at the source coordinate where the element was authored.\n- `data-macaly-name=\"<TagName>\"` — `div`, `Button`, `MyLib.Card`, …\n\nThe rewrite happens before JSX is lowered to `_jsx()` / `React.createElement()`, so the attributes survive into the bundled JS as ordinary string props on regular HTML elements. They land in:\n\n- the **production DOM** for SPA builds (after React mounts client-side);\n- the **prerendered HTML** for SSG/SSR builds (TanStack Start, Vike, Astro React islands, Remix/React Router SSR, etc.) — visible without JS.\n\nIntended use: click an element in the browser → jump to the exact source line in your editor. This package only writes the attributes; a separate runtime/extension reads them.\n\nVite-only. Build-time only. No webpack, no Turbopack, no dev-server tagging.\n\n## Installation\n\n```bash\nnpm install --save-dev @macaly/static-tagger\n# or: pnpm add -D @macaly/static-tagger\n```\n\n## Usage\n\n```ts\n// vite.config.ts\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\nimport { macalyTagger } from '@macaly/static-tagger';\n\nexport default defineConfig({\n  plugins: [\n    macalyTagger({\n      // ignorePackages: ['@react-three/fiber', '@react-three/drei'],\n      // disableSourceMaps: false,\n      // debug: false,\n    }),\n    react(),\n  ],\n});\n```\n\n`macalyTagger()` must come **before** `@vitejs/plugin-react`. The plugin sets `enforce: 'pre'` so Vite always runs it before non-pre plugins, but keeping it first in the array is the obvious form.\n\n## How it works\n\n```\nyour src/Foo.tsx                            <Foo data-macaly-loc=... data-macaly-name=...>\n   ↓                                                     ↑\n[macalyTagger plugin]   parse → walk AST → magic-string  │\n   ↓ injects 2 string attrs onto each JSXOpeningElement  │\n                                                         │\n[@vitejs/plugin-react]  JSX → _jsx(\"Foo\", { ... })       │\n   ↓ attrs become regular string-valued object props     │\n                                                         │\n[esbuild / rollup]      bundle, tree-shake, minify       │\n   ↓                                                     │\ndist/assets/*.js        contains data-macaly-loc=\"…\"  ───┘\n   ↓\nSPA: browser loads → React mounts → DOM has the attrs\nSSG/SSR: prerender writes them straight into dist/**/*.html\n```\n\nMechanics:\n\n1. **`enforce: 'pre'`** — Vite's transform pipeline runs `pre` plugins before user plugins. `@vitejs/plugin-react` is a user plugin, so we get the file while `JSXOpeningElement` nodes still exist. After plugin-react has run, JSX is lowered to `_jsx(...)` calls and there is nothing tag-shaped left to rewrite.\n2. **`apply: 'build'`** — only runs during `vite build`. The dev server is left untouched. (Dev-mode tagging is out of scope.)\n3. **AST rewrite, not codegen** — parses with `@babel/parser` (`jsx`+`typescript` plugins), walks with `estree-walker`, splices two attributes after the tag name with `magic-string`. The rest of the source is byte-identical, including indentation, comments, and trailing commas. A high-resolution sourcemap is returned alongside the code.\n4. **What ends up in the bundle** — for a host element:\n   ```jsx\n   <button onClick={...}>Click</button>\n   ```\n   the plugin produces:\n   ```jsx\n   <button data-macaly-loc=\"src/App.tsx:42:8\" data-macaly-name=\"button\" onClick={...}>Click</button>\n   ```\n   plugin-react/esbuild lowers that to:\n   ```js\n   _jsx(\"button\", { \"data-macaly-loc\": \"src/App.tsx:42:8\", \"data-macaly-name\": \"button\", onClick: ..., children: \"Click\" })\n   ```\n   At render time React forwards both `data-*` props to the DOM, exactly as it would for any other prop.\n5. **Skipped automatically** — virtual modules (ids starting with `\\0`), files outside `.jsx`/`.tsx`, anything under `node_modules`, React Fragments, lowercase non-HTML/SVG tags (custom-renderer elements like R3F's `<mesh>`, `<boxGeometry>`), and any element already carrying `data-macaly-loc`. Components imported from packages listed in `ignorePackages` are also skipped — see below.\n\n### SPA vs SSG/SSR\n\nPlugin behavior is identical. The difference is *where the attributes become visible*:\n\n- **SPA** (`vite build` with default `index.html`): `dist/index.html` is an empty shell. Attributes appear in the DOM only after React mounts. View via DevTools → Elements.\n- **SSG / SSR** (TanStack Start, Vike, Astro React islands, Remix/React Router SSR, etc.): the prerenderer runs your components on the server, React's HTML serializer emits the `data-macaly-*` attributes into the markup, and they sit directly in the static `.html` output — visible without JavaScript.\n\nNo configuration changes between the two modes.\n\n## Options\n\n```ts\nmacalyTagger({\n  debug: false,             // verbose console logging\n  disableSourceMaps: false, // skip generating the high-res sourcemap\n  ignorePackages: [],       // see \"Custom renderers\" section\n});\n```\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `debug` | `boolean` | `false` | Log each file processed and each tag decision. |\n| `disableSourceMaps` | `boolean` | `false` | Don't return a sourcemap from the transform. |\n| `ignorePackages` | `string[]` | `[]` | Don't tag components imported from these packages. |\n\n## Programmatic API\n\n```ts\nimport { transformJSX } from '@macaly/static-tagger';\n\nconst result = transformJSX(sourceCode, '/abs/path/src/App.tsx', '/abs/path', {\n  ignorePackages: ['@react-three/fiber'],\n});\n// result === null  → file skipped or no taggable JSX\n// result === { code, map }\n```\n\n`transformJSX` is the framework-agnostic core; the Vite plugin is a thin shell around it.\n\n## Example\n\nInput:\n\n```tsx\nexport default function TestComponent() {\n  return (\n    <div className=\"container\">\n      <h1>Hello Macaly!</h1>\n      <button onClick={() => console.log('clicked')}>Click me</button>\n      <MyLib.SpecialButton />\n    </div>\n  );\n}\n```\n\nAfter build, in the rendered DOM (or prerendered HTML):\n\n```html\n<div data-macaly-loc=\"components/TestComponent.tsx:3:4\" data-macaly-name=\"div\" class=\"container\">\n  <h1 data-macaly-loc=\"components/TestComponent.tsx:4:6\" data-macaly-name=\"h1\">Hello Macaly!</h1>\n  <button data-macaly-loc=\"components/TestComponent.tsx:5:6\" data-macaly-name=\"button\">Click me</button>\n  <!-- MyLib.SpecialButton renders whatever it renders, with data-macaly-* forwarded onto its root -->\n</div>\n```\n\n## Custom renderers (React Three Fiber, etc.)\n\nRenderers that map JSX onto non-DOM hosts (R3F's `<mesh>`, `<boxGeometry>`, …) cannot accept `data-*` props. Two layers of filtering keep them clean:\n\n1. **Heuristic** — lowercase tag names that aren't standard HTML/SVG are never tagged. R3F's `<mesh>`, `<boxGeometry>`, `<meshStandardMaterial>`, `<ambientLight>`, etc. fall out automatically.\n2. **`ignorePackages`** — for capitalized React components from these renderers (e.g. `<Canvas>` from `@react-three/fiber`, `<OrbitControls>` from `@react-three/drei`), list the package and the plugin skips every component imported from it.\n\n```ts\nmacalyTagger({\n  ignorePackages: [\n    '@react-three/fiber',\n    '@react-three/drei',\n    '@react-three/postprocessing',\n    'three',\n  ],\n});\n```\n\n```jsx\nimport { Canvas } from '@react-three/fiber';            // Canvas → skipped\nimport { OrbitControls, Html } from '@react-three/drei'; // skipped\nimport * as Fiber from '@react-three/fiber';            // Fiber.* → skipped\n\nfunction Scene() {\n  return (\n    <div>                    {/* tagged */}\n      <Canvas>               {/* skipped (imported from ignored pkg) */}\n        <OrbitControls />    {/* skipped */}\n        <Html>               {/* skipped */}\n          <span>Label</span> {/* tagged (HTML element) */}\n        </Html>\n        <mesh>               {/* skipped (lowercase non-HTML) */}\n          <boxGeometry />    {/* skipped */}\n        </mesh>\n      </Canvas>\n    </div>\n  );\n}\n```\n\nAll three import styles are handled:\n\n- `import { Canvas } from '...'` (named) → `Canvas` is skipped.\n- `import Drei from '...'` (default) → `Drei.*` is skipped.\n- `import * as Fiber from '...'` (namespace) → `Fiber.*` is skipped.\n\n## Troubleshooting\n\n**No `data-macaly-*` in the DOM.** Confirm `macalyTagger()` is listed *before* `@vitejs/plugin-react`. If plugin-react sees the file first, JSX has already been lowered and there's nothing to rewrite.\n\n**Plugin doesn't run during `vite dev`.** By design — `apply: 'build'`. Tagging is a build-time-only feature.\n\n**`Element type is invalid` from a custom renderer.** That renderer doesn't accept `data-*` props. Add its package to `ignorePackages`.\n\n**Loud logging?** Set `debug: true`.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","readmeFilename":"README.md"}