@analogjs/platform 3.0.0-alpha.98 → 3.0.0-beta.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.
Files changed (144) hide show
  1. package/migrations/migrate-setup-testbed-browser-mode/migrate-setup-testbed-browser-mode.js +8 -6
  2. package/migrations/migrate-setup-testbed-browser-mode/migrate-setup-testbed-browser-mode.js.map +1 -1
  3. package/migrations/migrate-to-separated-plugins/migrate-to-separated-plugins.js.map +1 -1
  4. package/migrations/migrate-vitest-builder-aliases/migrate-vitest-builder-aliases.js.map +1 -1
  5. package/migrations/utils/source-edits.js.map +1 -1
  6. package/package.json +2 -2
  7. package/src/lib/analog-integration-plugin.js.map +1 -1
  8. package/src/lib/clear-client-page-endpoint.js.map +1 -1
  9. package/src/lib/content/marked/index.js.map +1 -1
  10. package/src/lib/content/marked/marked-content-highlighter.js.map +1 -1
  11. package/src/lib/content/marked/marked-setup.service.js.map +1 -1
  12. package/src/lib/content/prism/angular.js.map +1 -1
  13. package/src/lib/content/prism/index.js +1 -1
  14. package/src/lib/content/prism/index.js.map +1 -1
  15. package/src/lib/content/prism/prism-highlighter.js.map +1 -1
  16. package/src/lib/content/shiki/index.js +6 -4
  17. package/src/lib/content/shiki/index.js.map +1 -1
  18. package/src/lib/content/shiki/shiki-highlighter.js.map +1 -1
  19. package/src/lib/content/utils/escape-html.js.map +1 -1
  20. package/src/lib/content-plugin.js +18 -16
  21. package/src/lib/content-plugin.js.map +1 -1
  22. package/src/lib/deps-plugin.js.map +1 -1
  23. package/src/lib/discover-library-routes.js.map +1 -1
  24. package/src/lib/inject-server-fn-ids.js.map +1 -1
  25. package/src/lib/nitro/analog-nitro-plugin.js +8 -4
  26. package/src/lib/nitro/analog-nitro-plugin.js.map +1 -1
  27. package/src/lib/nitro/angular-linker-plugin.js +2 -1
  28. package/src/lib/nitro/angular-linker-plugin.js.map +1 -1
  29. package/src/lib/nitro/build-sitemap.js.map +1 -1
  30. package/src/lib/nitro/debug.js +8 -4
  31. package/src/lib/nitro/debug.js.map +1 -1
  32. package/src/lib/nitro/get-content-files.js +2 -1
  33. package/src/lib/nitro/get-content-files.js.map +1 -1
  34. package/src/lib/nitro/get-page-handlers.js +2 -1
  35. package/src/lib/nitro/get-page-handlers.js.map +1 -1
  36. package/src/lib/nitro/get-server-fn-handlers.js.map +1 -1
  37. package/src/lib/nitro/i18n-prerender.js +1 -1
  38. package/src/lib/nitro/i18n-prerender.js.map +1 -1
  39. package/src/lib/nitro/page-endpoints-plugin.js.map +1 -1
  40. package/src/lib/nitro/post-rendering-hook.js.map +1 -1
  41. package/src/lib/nitro/server-fn-endpoints.js +1 -1
  42. package/src/lib/nitro/server-fn-endpoints.js.map +1 -1
  43. package/src/lib/nx-plugin/_virtual/_rolldown/runtime.js +1 -1
  44. package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/camelCase.js.map +1 -1
  45. package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/capitalize.js.map +1 -1
  46. package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/words.js +1 -0
  47. package/src/lib/nx-plugin/node_modules/.pnpm/es-toolkit@1.45.1/node_modules/es-toolkit/dist/string/words.js.map +1 -1
  48. package/src/lib/nx-plugin/src/executors/vite-dev-server/compat.js +0 -1
  49. package/src/lib/nx-plugin/src/executors/vite-dev-server/compat.js.map +1 -1
  50. package/src/lib/nx-plugin/src/executors/vite-dev-server/vite-dev-server.impl.js +0 -1
  51. package/src/lib/nx-plugin/src/executors/vite-dev-server/vite-dev-server.impl.js.map +1 -1
  52. package/src/lib/nx-plugin/src/generators/app/compat.js +0 -1
  53. package/src/lib/nx-plugin/src/generators/app/compat.js.map +1 -1
  54. package/src/lib/nx-plugin/src/generators/app/generator.js +0 -1
  55. package/src/lib/nx-plugin/src/generators/app/generator.js.map +1 -1
  56. package/src/lib/nx-plugin/src/generators/app/lib/add-agent-context.js +0 -1
  57. package/src/lib/nx-plugin/src/generators/app/lib/add-agent-context.js.map +1 -1
  58. package/src/lib/nx-plugin/src/generators/app/lib/add-analog-project-config.js +48 -47
  59. package/src/lib/nx-plugin/src/generators/app/lib/add-analog-project-config.js.map +1 -1
  60. package/src/lib/nx-plugin/src/generators/app/lib/add-angular-app.js +0 -1
  61. package/src/lib/nx-plugin/src/generators/app/lib/add-angular-app.js.map +1 -1
  62. package/src/lib/nx-plugin/src/generators/app/lib/add-files.js +0 -1
  63. package/src/lib/nx-plugin/src/generators/app/lib/add-files.js.map +1 -1
  64. package/src/lib/nx-plugin/src/generators/app/lib/add-home-page.js +0 -1
  65. package/src/lib/nx-plugin/src/generators/app/lib/add-home-page.js.map +1 -1
  66. package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-config.js +1 -1
  67. package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-config.js.map +1 -1
  68. package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.js +0 -1
  69. package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.js.map +1 -1
  70. package/src/lib/nx-plugin/src/generators/app/lib/cleanup-files.js.map +1 -1
  71. package/src/lib/nx-plugin/src/generators/app/lib/update-index-html.js +0 -1
  72. package/src/lib/nx-plugin/src/generators/app/lib/update-index-html.js.map +1 -1
  73. package/src/lib/nx-plugin/src/generators/app/versions/minimum-supported-versions.js +0 -1
  74. package/src/lib/nx-plugin/src/generators/app/versions/minimum-supported-versions.js.map +1 -1
  75. package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.js +5 -5
  76. package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.js.map +1 -1
  77. package/src/lib/nx-plugin/src/generators/app/versions/versions.d.ts +4 -0
  78. package/src/lib/nx-plugin/src/generators/app/versions/versions.js +12 -0
  79. package/src/lib/nx-plugin/src/generators/app/versions/versions.js.map +1 -0
  80. package/src/lib/nx-plugin/src/generators/init/compat.js +0 -1
  81. package/src/lib/nx-plugin/src/generators/init/compat.js.map +1 -1
  82. package/src/lib/nx-plugin/src/generators/init/generator.js +0 -1
  83. package/src/lib/nx-plugin/src/generators/init/generator.js.map +1 -1
  84. package/src/lib/nx-plugin/src/generators/init/lib/add-analog-dependencies.js +0 -1
  85. package/src/lib/nx-plugin/src/generators/init/lib/add-analog-dependencies.js.map +1 -1
  86. package/src/lib/nx-plugin/src/generators/init/lib/update-app-tsconfig.js +0 -1
  87. package/src/lib/nx-plugin/src/generators/init/lib/update-app-tsconfig.js.map +1 -1
  88. package/src/lib/nx-plugin/src/generators/init/lib/update-build-target.js +0 -1
  89. package/src/lib/nx-plugin/src/generators/init/lib/update-build-target.js.map +1 -1
  90. package/src/lib/nx-plugin/src/generators/init/lib/update-git-ignore.js.map +1 -1
  91. package/src/lib/nx-plugin/src/generators/init/lib/update-index-html.js +0 -1
  92. package/src/lib/nx-plugin/src/generators/init/lib/update-index-html.js.map +1 -1
  93. package/src/lib/nx-plugin/src/generators/init/lib/update-main.js +0 -1
  94. package/src/lib/nx-plugin/src/generators/init/lib/update-main.js.map +1 -1
  95. package/src/lib/nx-plugin/src/generators/init/lib/update-package-json.js +2 -2
  96. package/src/lib/nx-plugin/src/generators/init/lib/update-package-json.js.map +1 -1
  97. package/src/lib/nx-plugin/src/generators/init/lib/update-serve-target.js +0 -1
  98. package/src/lib/nx-plugin/src/generators/init/lib/update-serve-target.js.map +1 -1
  99. package/src/lib/nx-plugin/src/generators/init/lib/update-test-target.js +0 -1
  100. package/src/lib/nx-plugin/src/generators/init/lib/update-test-target.js.map +1 -1
  101. package/src/lib/nx-plugin/src/generators/init/lib/update-test-tsconfig.js +0 -1
  102. package/src/lib/nx-plugin/src/generators/init/lib/update-test-tsconfig.js.map +1 -1
  103. package/src/lib/nx-plugin/src/generators/page/compat.js +0 -1
  104. package/src/lib/nx-plugin/src/generators/page/compat.js.map +1 -1
  105. package/src/lib/nx-plugin/src/generators/page/generator.js +2 -2
  106. package/src/lib/nx-plugin/src/generators/page/generator.js.map +1 -1
  107. package/src/lib/nx-plugin/src/generators/preset/generator.js +0 -1
  108. package/src/lib/nx-plugin/src/generators/preset/generator.js.map +1 -1
  109. package/src/lib/nx-plugin/src/utils/version-utils.js +0 -1
  110. package/src/lib/nx-plugin/src/utils/version-utils.js.map +1 -1
  111. package/src/lib/nx-plugin/src/utils/versions/dependencies.js +8 -9
  112. package/src/lib/nx-plugin/src/utils/versions/dependencies.js.map +1 -1
  113. package/src/lib/nx-plugin/src/utils/versions/dev-dependencies.js +13 -13
  114. package/src/lib/nx-plugin/src/utils/versions/dev-dependencies.js.map +1 -1
  115. package/src/lib/nx-plugin/src/utils/versions/versions.d.ts +15 -0
  116. package/src/lib/nx-plugin/src/utils/versions/versions.js +34 -0
  117. package/src/lib/nx-plugin/src/utils/versions/versions.js.map +1 -0
  118. package/src/lib/platform-plugin.js.map +1 -1
  119. package/src/lib/route-file-discovery.js.map +1 -1
  120. package/src/lib/route-idiom-diagnostics.js +3 -13
  121. package/src/lib/route-idiom-diagnostics.js.map +1 -1
  122. package/src/lib/route-manifest.js +1 -1
  123. package/src/lib/route-manifest.js.map +1 -1
  124. package/src/lib/router-plugin.js +18 -2
  125. package/src/lib/router-plugin.js.map +1 -1
  126. package/src/lib/server-fn-client-transform.js.map +1 -1
  127. package/src/lib/server-fn-id.js.map +1 -1
  128. package/src/lib/ssr/defer-streaming-plugin.js.map +1 -1
  129. package/src/lib/ssr/inject-html-plugin.js.map +1 -1
  130. package/src/lib/ssr/ssr-build-plugin.js.map +1 -1
  131. package/src/lib/typed-routes-plugin.js.map +1 -1
  132. package/src/lib/utils/debug-harness.js.map +1 -1
  133. package/src/lib/utils/debug-log-file.js +2 -1
  134. package/src/lib/utils/debug-log-file.js.map +1 -1
  135. package/src/lib/utils/debug.js +7 -4
  136. package/src/lib/utils/debug.js.map +1 -1
  137. package/src/lib/utils/rolldown.js.map +1 -1
  138. package/src/server-mode-plugin.js.map +1 -1
  139. package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.d.ts +0 -28
  140. package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.js +0 -12
  141. package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.js.map +0 -1
  142. package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.d.ts +0 -15
  143. package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.js +0 -34
  144. package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.js.map +0 -1
@@ -43,12 +43,14 @@ function migrateSetupTestBedSource(filePath, source) {
43
43
  const browserMode = options.properties[index];
44
44
  const hasTeardown = options.properties.some((property) => getPropertyName(property) === "teardown");
45
45
  const value = browserMode && ts.isPropertyAssignment(browserMode) ? browserMode.initializer : browserMode && ts.isShorthandPropertyAssignment(browserMode) ? browserMode.name : void 0;
46
- if (browserMode && value) if (hasTeardown || value.kind === ts.SyntaxKind.FalseKeyword) edits.push(removeProperty(options, index, sourceFile));
47
- else edits.push({
48
- start: browserMode.getStart(sourceFile),
49
- end: browserMode.end,
50
- text: toTeardown(value, sourceFile)
51
- });
46
+ if (browserMode && value) {
47
+ if (hasTeardown || value.kind === ts.SyntaxKind.FalseKeyword) edits.push(removeProperty(options, index, sourceFile));
48
+ else edits.push({
49
+ start: browserMode.getStart(sourceFile),
50
+ end: browserMode.end,
51
+ text: toTeardown(value, sourceFile)
52
+ });
53
+ }
52
54
  }
53
55
  ts.forEachChild(node, visit);
54
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-setup-testbed-browser-mode.js","names":[],"sources":["../../../migrations/migrate-setup-testbed-browser-mode/migrate-setup-testbed-browser-mode.ts"],"sourcesContent":["import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\n\nimport {\n applyEdits,\n rewriteSourceFiles,\n type Edit,\n} from '../utils/source-edits';\n\nconst SETUP_TESTBED_PKG = '@analogjs/vitest-angular/setup-testbed';\nconst MIGRATION_DOC_URL =\n 'https://analogjs.org/docs/guides/migrating-v2-to-v3#the-setuptestbed-browsermode-option-was-removed';\n\nfunction getPropertyName(\n property: ts.ObjectLiteralElementLike,\n): string | undefined {\n return property.name && ts.isIdentifier(property.name)\n ? property.name.text\n : undefined;\n}\n\nfunction toTeardown(value: ts.Expression, sourceFile: ts.SourceFile): string {\n if (value.kind === ts.SyntaxKind.TrueKeyword) {\n return 'teardown: { destroyAfterEach: false }';\n }\n return `teardown: { destroyAfterEach: !(${value.getText(sourceFile)}) }`;\n}\n\nfunction removeProperty(\n object: ts.ObjectLiteralExpression,\n index: number,\n sourceFile: ts.SourceFile,\n): Edit {\n const properties = object.properties;\n if (properties.length === 1) {\n return { start: object.getStart(sourceFile), end: object.end, text: '' };\n }\n if (index < properties.length - 1) {\n return {\n start: properties[index].getStart(sourceFile),\n end: properties[index + 1].getStart(sourceFile),\n text: '',\n };\n }\n return {\n start: properties[index - 1].end,\n end: properties[index].end,\n text: '',\n };\n}\n\n/**\n * Replaces `setupTestBed({ browserMode })` with the equivalent\n * `teardown.destroyAfterEach` option.\n */\nexport function migrateSetupTestBedSource(\n filePath: string,\n source: string,\n): string | null {\n if (!source.includes('browserMode')) return null;\n\n const sourceFile = ts.createSourceFile(\n filePath,\n source,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n const edits: Edit[] = [];\n\n function visit(node: ts.Node): void {\n if (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'setupTestBed' &&\n node.arguments[0] &&\n ts.isObjectLiteralExpression(node.arguments[0])\n ) {\n const options = node.arguments[0];\n const index = options.properties.findIndex(\n (property) => getPropertyName(property) === 'browserMode',\n );\n const browserMode = options.properties[index];\n const hasTeardown = options.properties.some(\n (property) => getPropertyName(property) === 'teardown',\n );\n\n const value =\n browserMode && ts.isPropertyAssignment(browserMode)\n ? browserMode.initializer\n : browserMode && ts.isShorthandPropertyAssignment(browserMode)\n ? browserMode.name\n : undefined;\n if (browserMode && value) {\n if (hasTeardown || value.kind === ts.SyntaxKind.FalseKeyword) {\n edits.push(removeProperty(options, index, sourceFile));\n } else {\n edits.push({\n start: browserMode.getStart(sourceFile),\n end: browserMode.end,\n text: toTeardown(value, sourceFile),\n });\n }\n }\n }\n ts.forEachChild(node, visit);\n }\n visit(sourceFile);\n\n return edits.length > 0 ? applyEdits(source, edits) : null;\n}\n\nexport default function migrateSetupTestBedBrowserMode(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const rewritten = rewriteSourceFiles(\n tree,\n SETUP_TESTBED_PKG,\n migrateSetupTestBedSource,\n );\n if (rewritten.length > 0) {\n context.logger.info(\n `Replaced setupTestBed({ browserMode }) with teardown.destroyAfterEach in:\\n${rewritten\n .map((file) => ` - ${file}`)\n .join('\\n')}\\nSee ${MIGRATION_DOC_URL}`,\n );\n }\n return tree;\n };\n}\n"],"mappings":";;;AASA,IAAM,oBAAoB;AAC1B,IAAM,oBACJ;AAEF,SAAS,gBACP,UACoB;AACpB,QAAO,SAAS,QAAQ,GAAG,aAAa,SAAS,KAAK,GAClD,SAAS,KAAK,OACd,KAAA;;AAGN,SAAS,WAAW,OAAsB,YAAmC;AAC3E,KAAI,MAAM,SAAS,GAAG,WAAW,YAC/B,QAAO;AAET,QAAO,mCAAmC,MAAM,QAAQ,WAAW,CAAC;;AAGtE,SAAS,eACP,QACA,OACA,YACM;CACN,MAAM,aAAa,OAAO;AAC1B,KAAI,WAAW,WAAW,EACxB,QAAO;EAAE,OAAO,OAAO,SAAS,WAAW;EAAE,KAAK,OAAO;EAAK,MAAM;EAAI;AAE1E,KAAI,QAAQ,WAAW,SAAS,EAC9B,QAAO;EACL,OAAO,WAAW,OAAO,SAAS,WAAW;EAC7C,KAAK,WAAW,QAAQ,GAAG,SAAS,WAAW;EAC/C,MAAM;EACP;AAEH,QAAO;EACL,OAAO,WAAW,QAAQ,GAAG;EAC7B,KAAK,WAAW,OAAO;EACvB,MAAM;EACP;;;;;;AAOH,SAAgB,0BACd,UACA,QACe;AACf,KAAI,CAAC,OAAO,SAAS,cAAc,CAAE,QAAO;CAE5C,MAAM,aAAa,GAAG,iBACpB,UACA,QACA,GAAG,aAAa,QAChB,MACA,GAAG,WAAW,GACf;CACD,MAAM,QAAgB,EAAE;CAExB,SAAS,MAAM,MAAqB;AAClC,MACE,GAAG,iBAAiB,KAAK,IACzB,GAAG,aAAa,KAAK,WAAW,IAChC,KAAK,WAAW,SAAS,kBACzB,KAAK,UAAU,MACf,GAAG,0BAA0B,KAAK,UAAU,GAAG,EAC/C;GACA,MAAM,UAAU,KAAK,UAAU;GAC/B,MAAM,QAAQ,QAAQ,WAAW,WAC9B,aAAa,gBAAgB,SAAS,KAAK,cAC7C;GACD,MAAM,cAAc,QAAQ,WAAW;GACvC,MAAM,cAAc,QAAQ,WAAW,MACpC,aAAa,gBAAgB,SAAS,KAAK,WAC7C;GAED,MAAM,QACJ,eAAe,GAAG,qBAAqB,YAAY,GAC/C,YAAY,cACZ,eAAe,GAAG,8BAA8B,YAAY,GAC1D,YAAY,OACZ,KAAA;AACR,OAAI,eAAe,MACjB,KAAI,eAAe,MAAM,SAAS,GAAG,WAAW,aAC9C,OAAM,KAAK,eAAe,SAAS,OAAO,WAAW,CAAC;OAEtD,OAAM,KAAK;IACT,OAAO,YAAY,SAAS,WAAW;IACvC,KAAK,YAAY;IACjB,MAAM,WAAW,OAAO,WAAW;IACpC,CAAC;;AAIR,KAAG,aAAa,MAAM,MAAM;;AAE9B,OAAM,WAAW;AAEjB,QAAO,MAAM,SAAS,IAAI,WAAW,QAAQ,MAAM,GAAG;;AAGxD,SAAwB,iCAAuC;AAC7D,SAAQ,MAAY,YAA8B;EAChD,MAAM,YAAY,mBAChB,MACA,mBACA,0BACD;AACD,MAAI,UAAU,SAAS,EACrB,SAAQ,OAAO,KACb,8EAA8E,UAC3E,KAAK,SAAS,OAAO,OAAO,CAC5B,KAAK,KAAK,CAAC,QAAQ,oBACvB;AAEH,SAAO"}
1
+ {"version":3,"file":"migrate-setup-testbed-browser-mode.js","names":[],"sources":["../../../migrations/migrate-setup-testbed-browser-mode/migrate-setup-testbed-browser-mode.ts"],"sourcesContent":["import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\nimport * as ts from 'typescript';\n\nimport {\n applyEdits,\n rewriteSourceFiles,\n type Edit,\n} from '../utils/source-edits';\n\nconst SETUP_TESTBED_PKG = '@analogjs/vitest-angular/setup-testbed';\nconst MIGRATION_DOC_URL =\n 'https://analogjs.org/docs/guides/migrating-v2-to-v3#the-setuptestbed-browsermode-option-was-removed';\n\nfunction getPropertyName(\n property: ts.ObjectLiteralElementLike,\n): string | undefined {\n return property.name && ts.isIdentifier(property.name)\n ? property.name.text\n : undefined;\n}\n\nfunction toTeardown(value: ts.Expression, sourceFile: ts.SourceFile): string {\n if (value.kind === ts.SyntaxKind.TrueKeyword) {\n return 'teardown: { destroyAfterEach: false }';\n }\n return `teardown: { destroyAfterEach: !(${value.getText(sourceFile)}) }`;\n}\n\nfunction removeProperty(\n object: ts.ObjectLiteralExpression,\n index: number,\n sourceFile: ts.SourceFile,\n): Edit {\n const properties = object.properties;\n if (properties.length === 1) {\n return { start: object.getStart(sourceFile), end: object.end, text: '' };\n }\n if (index < properties.length - 1) {\n return {\n start: properties[index].getStart(sourceFile),\n end: properties[index + 1].getStart(sourceFile),\n text: '',\n };\n }\n return {\n start: properties[index - 1].end,\n end: properties[index].end,\n text: '',\n };\n}\n\n/**\n * Replaces `setupTestBed({ browserMode })` with the equivalent\n * `teardown.destroyAfterEach` option.\n */\nexport function migrateSetupTestBedSource(\n filePath: string,\n source: string,\n): string | null {\n if (!source.includes('browserMode')) return null;\n\n const sourceFile = ts.createSourceFile(\n filePath,\n source,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n const edits: Edit[] = [];\n\n function visit(node: ts.Node): void {\n if (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'setupTestBed' &&\n node.arguments[0] &&\n ts.isObjectLiteralExpression(node.arguments[0])\n ) {\n const options = node.arguments[0];\n const index = options.properties.findIndex(\n (property) => getPropertyName(property) === 'browserMode',\n );\n const browserMode = options.properties[index];\n const hasTeardown = options.properties.some(\n (property) => getPropertyName(property) === 'teardown',\n );\n\n const value =\n browserMode && ts.isPropertyAssignment(browserMode)\n ? browserMode.initializer\n : browserMode && ts.isShorthandPropertyAssignment(browserMode)\n ? browserMode.name\n : undefined;\n if (browserMode && value) {\n if (hasTeardown || value.kind === ts.SyntaxKind.FalseKeyword) {\n edits.push(removeProperty(options, index, sourceFile));\n } else {\n edits.push({\n start: browserMode.getStart(sourceFile),\n end: browserMode.end,\n text: toTeardown(value, sourceFile),\n });\n }\n }\n }\n ts.forEachChild(node, visit);\n }\n visit(sourceFile);\n\n return edits.length > 0 ? applyEdits(source, edits) : null;\n}\n\nexport default function migrateSetupTestBedBrowserMode(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const rewritten = rewriteSourceFiles(\n tree,\n SETUP_TESTBED_PKG,\n migrateSetupTestBedSource,\n );\n if (rewritten.length > 0) {\n context.logger.info(\n `Replaced setupTestBed({ browserMode }) with teardown.destroyAfterEach in:\\n${rewritten\n .map((file) => ` - ${file}`)\n .join('\\n')}\\nSee ${MIGRATION_DOC_URL}`,\n );\n }\n return tree;\n };\n}\n"],"mappings":";;;AASA,IAAM,oBAAoB;AAC1B,IAAM,oBACJ;AAEF,SAAS,gBACP,UACoB;CACpB,OAAO,SAAS,QAAQ,GAAG,aAAa,SAAS,IAAI,IACjD,SAAS,KAAK,OACd,KAAA;AACN;AAEA,SAAS,WAAW,OAAsB,YAAmC;CAC3E,IAAI,MAAM,SAAS,GAAG,WAAW,aAC/B,OAAO;CAET,OAAO,mCAAmC,MAAM,QAAQ,UAAU,EAAE;AACtE;AAEA,SAAS,eACP,QACA,OACA,YACM;CACN,MAAM,aAAa,OAAO;CAC1B,IAAI,WAAW,WAAW,GACxB,OAAO;EAAE,OAAO,OAAO,SAAS,UAAU;EAAG,KAAK,OAAO;EAAK,MAAM;CAAG;CAEzE,IAAI,QAAQ,WAAW,SAAS,GAC9B,OAAO;EACL,OAAO,WAAW,MAAM,CAAC,SAAS,UAAU;EAC5C,KAAK,WAAW,QAAQ,EAAE,CAAC,SAAS,UAAU;EAC9C,MAAM;CACR;CAEF,OAAO;EACL,OAAO,WAAW,QAAQ,EAAE,CAAC;EAC7B,KAAK,WAAW,MAAM,CAAC;EACvB,MAAM;CACR;AACF;;;;;AAMA,SAAgB,0BACd,UACA,QACe;CACf,IAAI,CAAC,OAAO,SAAS,aAAa,GAAG,OAAO;CAE5C,MAAM,aAAa,GAAG,iBACpB,UACA,QACA,GAAG,aAAa,QAChB,MACA,GAAG,WAAW,EAChB;CACA,MAAM,QAAgB,CAAC;CAEvB,SAAS,MAAM,MAAqB;EAClC,IACE,GAAG,iBAAiB,IAAI,KACxB,GAAG,aAAa,KAAK,UAAU,KAC/B,KAAK,WAAW,SAAS,kBACzB,KAAK,UAAU,MACf,GAAG,0BAA0B,KAAK,UAAU,EAAE,GAC9C;GACA,MAAM,UAAU,KAAK,UAAU;GAC/B,MAAM,QAAQ,QAAQ,WAAW,WAC9B,aAAa,gBAAgB,QAAQ,MAAM,aAC9C;GACA,MAAM,cAAc,QAAQ,WAAW;GACvC,MAAM,cAAc,QAAQ,WAAW,MACpC,aAAa,gBAAgB,QAAQ,MAAM,UAC9C;GAEA,MAAM,QACJ,eAAe,GAAG,qBAAqB,WAAW,IAC9C,YAAY,cACZ,eAAe,GAAG,8BAA8B,WAAW,IACzD,YAAY,OACZ,KAAA;GACR,IAAI,eAAe,OAAO;IACxB,IAAI,eAAe,MAAM,SAAS,GAAG,WAAW,cAC9C,MAAM,KAAK,eAAe,SAAS,OAAO,UAAU,CAAC;SAErD,MAAM,KAAK;KACT,OAAO,YAAY,SAAS,UAAU;KACtC,KAAK,YAAY;KACjB,MAAM,WAAW,OAAO,UAAU;IACpC,CAAC;GAEL;EACF;EACA,GAAG,aAAa,MAAM,KAAK;CAC7B;CACA,MAAM,UAAU;CAEhB,OAAO,MAAM,SAAS,IAAI,WAAW,QAAQ,KAAK,IAAI;AACxD;AAEA,SAAwB,iCAAuC;CAC7D,QAAQ,MAAY,YAA8B;EAChD,MAAM,YAAY,mBAChB,MACA,mBACA,yBACF;EACA,IAAI,UAAU,SAAS,GACrB,QAAQ,OAAO,KACb,8EAA8E,UAC3E,KAAK,SAAS,OAAO,MAAM,CAAC,CAC5B,KAAK,IAAI,EAAE,QAAQ,mBACxB;EAEF,OAAO;CACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-to-separated-plugins.js","names":[],"sources":["../../../migrations/migrate-to-separated-plugins/migrate-to-separated-plugins.ts"],"sourcesContent":["import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\n// The explicit file path resolves when this runs as native ESM.\nimport { NodePackageInstallTask } from '@angular-devkit/schematics/tasks/index.js';\nimport * as ts from 'typescript';\n\nimport { applyEdits, type Edit } from '../utils/source-edits';\n\nconst ANALOG_PLATFORM_IMPORT = `from '@analogjs/platform'`;\nconst ANGULAR_PLUGIN_IMPORT = `from '@analogjs/vite-plugin-angular'`;\nconst NITRO_IMPORTS = [\n `from '@analogjs/vite-plugin-nitro'`,\n `from 'nitro/vite'`,\n];\nconst ANGULAR_PLUGIN_PKG = '@analogjs/vite-plugin-angular';\nconst NITRO_PLUGIN_PKG = '@analogjs/vite-plugin-nitro';\nconst MIGRATION_DOC_URL =\n 'https://analogjs.org/docs/guides/migrating-v2-to-v3#analog-angular-and-nitro-are-now-separate-plugins';\n\nconst VITE_CONFIG_EXTENSIONS = ['.ts', '.mts', '.js', '.mjs'];\n\nfunction isViteConfig(filePath: string): boolean {\n const file = filePath.slice(filePath.lastIndexOf('/') + 1);\n if (!file.startsWith('vite.config.')) {\n return false;\n }\n return VITE_CONFIG_EXTENSIONS.some((ext) => file.endsWith(ext));\n}\n\nfunction usesLegacyPluginShape(source: string): boolean {\n if (!source.includes(ANALOG_PLATFORM_IMPORT)) {\n return false;\n }\n if (\n source.includes(ANGULAR_PLUGIN_IMPORT) &&\n NITRO_IMPORTS.some((nitroImport) => source.includes(nitroImport))\n ) {\n return false;\n }\n return /\\banalog\\s*\\(/.test(source);\n}\n\nfunction readPackageJson(\n tree: Tree,\n): { raw: string; pkg: Record<string, unknown> } | null {\n const content = tree.read('/package.json');\n if (!content) return null;\n const raw = content.toString('utf-8');\n try {\n return { raw, pkg: JSON.parse(raw) };\n } catch {\n return null;\n }\n}\n\nfunction getDepVersion(\n pkg: Record<string, unknown>,\n name: string,\n): string | undefined {\n const dev =\n (pkg['devDependencies'] as Record<string, string> | undefined) ?? {};\n const reg = (pkg['dependencies'] as Record<string, string> | undefined) ?? {};\n return dev[name] ?? reg[name];\n}\n\nfunction addDependencies(tree: Tree, context: SchematicContext): boolean {\n const info = readPackageJson(tree);\n if (!info) return false;\n\n const { pkg, raw } = info;\n const devDeps = {\n ...((pkg['devDependencies'] as Record<string, string> | undefined) ?? {}),\n };\n let changed = false;\n\n // Match the @analogjs/platform pin so the plugins stay aligned with the\n // rest of the Analog packages already in this workspace.\n const platformVersion = getDepVersion(pkg, '@analogjs/platform') ?? '*';\n const missingPlugins = [ANGULAR_PLUGIN_PKG, NITRO_PLUGIN_PKG].filter(\n (name) =>\n !getDepVersion(pkg, name) &&\n // Apps already on Nitro v3 keep `nitro()` from `nitro/vite`.\n !(name === NITRO_PLUGIN_PKG && getDepVersion(pkg, 'nitro')),\n );\n for (const name of missingPlugins) {\n devDeps[name] = platformVersion;\n changed = true;\n context.logger.info(\n `Added '${name}': '${platformVersion}' to devDependencies.`,\n );\n }\n\n if (!changed) return false;\n\n pkg['devDependencies'] = devDeps;\n const trailingNewline = raw.endsWith('\\n') ? '\\n' : '';\n tree.overwrite(\n '/package.json',\n JSON.stringify(pkg, null, 2) + trailingNewline,\n );\n context.addTask(new NodePackageInstallTask());\n return true;\n}\n\ninterface TransformResult {\n source: string;\n movedVite: boolean;\n movedNitro: boolean;\n}\n\nfunction getLineIndent(source: string, pos: number): string {\n let lineStart = pos;\n while (lineStart > 0 && source[lineStart - 1] !== '\\n') {\n lineStart--;\n }\n let indent = '';\n for (let i = lineStart; i < source.length; i++) {\n const ch = source[i];\n if (ch === ' ' || ch === '\\t') indent += ch;\n else break;\n }\n return indent;\n}\n\n/**\n * Tries to lift `vite: {...}` and `nitro: {...}` properties off the\n * single `analog(...)` call into companion `angular(...)` / `nitro(...)`\n * calls. Returns the rewritten source on success, or null if the file\n * doesn't match the supported pattern (we then fall back to logging\n * instructions rather than risking a corrupted file).\n *\n * Supported pattern: exactly one `analog(...)` call whose argument is\n * an object literal. Properties named `vite` and `nitro` are recognized;\n * everything else stays on `analog`.\n */\nfunction tryTransformViteConfig(\n filePath: string,\n source: string,\n): TransformResult | null {\n let sourceFile: ts.SourceFile;\n try {\n sourceFile = ts.createSourceFile(\n filePath,\n source,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n } catch {\n return null;\n }\n\n let analogImportEnd = -1;\n let angularImported = false;\n let nitroImported = false;\n const analogCalls: ts.CallExpression[] = [];\n\n function visit(node: ts.Node): void {\n if (ts.isImportDeclaration(node)) {\n const ml = node.moduleSpecifier;\n if (ts.isStringLiteral(ml)) {\n if (ml.text === '@analogjs/platform') {\n analogImportEnd = node.end;\n } else if (ml.text === '@analogjs/vite-plugin-angular') {\n angularImported = true;\n } else if (\n ml.text === '@analogjs/vite-plugin-nitro' ||\n ml.text === 'nitro/vite'\n ) {\n nitroImported = true;\n }\n }\n } else if (ts.isCallExpression(node)) {\n if (\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'analog'\n ) {\n analogCalls.push(node);\n }\n }\n ts.forEachChild(node, visit);\n }\n visit(sourceFile);\n\n if (analogImportEnd === -1) return null;\n if (analogCalls.length !== 1) return null;\n\n const analogCall = analogCalls[0];\n const callStart = analogCall.getStart(sourceFile);\n const callEnd = analogCall.getEnd();\n\n let viteValueText: string | null = null;\n let nitroValueText: string | null = null;\n let remainingPropsText: string | null = null;\n\n const arg = analogCall.arguments[0];\n if (arg && ts.isObjectLiteralExpression(arg)) {\n const remaining: ts.ObjectLiteralElementLike[] = [];\n for (const prop of arg.properties) {\n if (\n ts.isPropertyAssignment(prop) &&\n ts.isIdentifier(prop.name) &&\n (prop.name.text === 'vite' || prop.name.text === 'nitro')\n ) {\n const value = prop.initializer;\n const text = source.slice(value.getStart(sourceFile), value.getEnd());\n if (prop.name.text === 'vite') viteValueText = text;\n else nitroValueText = text;\n } else {\n remaining.push(prop);\n }\n }\n\n if (remaining.length > 0) {\n // Reconstruct the analog object literal from the remaining props,\n // preserving their original source text (comments, spacing).\n const propTexts = remaining.map((p) =>\n source.slice(p.getStart(sourceFile), p.getEnd()),\n );\n const objStart = arg.getStart(sourceFile);\n const indent = getLineIndent(source, objStart);\n const propIndent = indent + ' ';\n remainingPropsText = `{\\n${propTexts.map((t) => `${propIndent}${t}`).join(',\\n')},\\n${indent}}`;\n }\n } else if (arg !== undefined) {\n // analog(otherExpression) — can't statically split a variable or call\n // expression. Fall back to logging instructions.\n return null;\n }\n // analog() with no argument falls through to the rewrite below; we just\n // emit `analog(), angular(), nitro()` to scaffold the new plugin chain.\n\n const indent = getLineIndent(source, callStart);\n const newAnalogCall = remainingPropsText\n ? `analog(${remainingPropsText})`\n : `analog()`;\n const parts: string[] = [newAnalogCall];\n if (viteValueText !== null) parts.push(`angular(${viteValueText})`);\n else parts.push('angular()');\n if (nitroValueText !== null) parts.push(`nitro(${nitroValueText})`);\n else parts.push('nitro()');\n const replacement = parts.join(`,\\n${indent}`);\n\n const edits: Edit[] = [{ start: callStart, end: callEnd, text: replacement }];\n\n const importsToAdd: string[] = [];\n if (!angularImported) {\n importsToAdd.push(`import angular from '@analogjs/vite-plugin-angular';`);\n }\n if (!nitroImported) {\n importsToAdd.push(`import nitro from '@analogjs/vite-plugin-nitro';`);\n }\n if (importsToAdd.length > 0) {\n edits.push({\n start: analogImportEnd,\n end: analogImportEnd,\n text: `\\n${importsToAdd.join('\\n')}`,\n });\n }\n\n const rewritten = applyEdits(source, edits);\n\n return {\n source: rewritten,\n movedVite: viteValueText !== null,\n movedNitro: nitroValueText !== null,\n };\n}\n\nexport default function migrateToSeparatedPlugins(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const filesUsingLegacyShape: string[] = [];\n const rewrittenFiles: string[] = [];\n const unhandledFiles: string[] = [];\n\n tree.visit((filePath) => {\n if (filePath.includes('/node_modules/')) return;\n if (!isViteConfig(filePath)) return;\n\n const content = tree.read(filePath);\n if (!content) return;\n\n const source = content.toString('utf-8');\n if (!usesLegacyPluginShape(source)) return;\n\n filesUsingLegacyShape.push(filePath);\n\n const transformed = tryTransformViteConfig(filePath, source);\n if (transformed) {\n tree.overwrite(filePath, transformed.source);\n rewrittenFiles.push(filePath);\n } else {\n unhandledFiles.push(filePath);\n }\n });\n\n if (filesUsingLegacyShape.length === 0) {\n return tree;\n }\n\n if (rewrittenFiles.length > 0) {\n context.logger.info(\n `Rewrote ${rewrittenFiles.length} vite.config file(s) to the separated \\`analog() + angular() + nitro()\\` shape:`,\n );\n for (const file of rewrittenFiles) {\n context.logger.info(` - ${file}`);\n }\n context.logger.info(\n `Review the result — only \\`vite\\` and \\`nitro\\` were moved automatically. Other angular-passthrough options (\\`liveReload\\`, \\`fastCompile\\`, \\`fileReplacements\\`, etc.) still need to be relocated by hand.\\nSee ${MIGRATION_DOC_URL}`,\n );\n }\n\n if (unhandledFiles.length > 0) {\n context.logger.info(\n `Could not safely rewrite ${unhandledFiles.length} vite.config file(s); migrate them by hand:`,\n );\n for (const file of unhandledFiles) {\n context.logger.info(` - ${file}`);\n }\n context.logger.info(\n `Split \\`analog()\\` into \\`analog() + angular() + nitro()\\` and move each option to its owning plugin.\\nSee ${MIGRATION_DOC_URL}`,\n );\n }\n\n addDependencies(tree, context);\n\n return tree;\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"migrate-to-separated-plugins.js","names":[],"sources":["../../../migrations/migrate-to-separated-plugins/migrate-to-separated-plugins.ts"],"sourcesContent":["import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\n// The explicit file path resolves when this runs as native ESM.\nimport { NodePackageInstallTask } from '@angular-devkit/schematics/tasks/index.js';\nimport * as ts from 'typescript';\n\nimport { applyEdits, type Edit } from '../utils/source-edits';\n\nconst ANALOG_PLATFORM_IMPORT = `from '@analogjs/platform'`;\nconst ANGULAR_PLUGIN_IMPORT = `from '@analogjs/vite-plugin-angular'`;\nconst NITRO_IMPORTS = [\n `from '@analogjs/vite-plugin-nitro'`,\n `from 'nitro/vite'`,\n];\nconst ANGULAR_PLUGIN_PKG = '@analogjs/vite-plugin-angular';\nconst NITRO_PLUGIN_PKG = '@analogjs/vite-plugin-nitro';\nconst MIGRATION_DOC_URL =\n 'https://analogjs.org/docs/guides/migrating-v2-to-v3#analog-angular-and-nitro-are-now-separate-plugins';\n\nconst VITE_CONFIG_EXTENSIONS = ['.ts', '.mts', '.js', '.mjs'];\n\nfunction isViteConfig(filePath: string): boolean {\n const file = filePath.slice(filePath.lastIndexOf('/') + 1);\n if (!file.startsWith('vite.config.')) {\n return false;\n }\n return VITE_CONFIG_EXTENSIONS.some((ext) => file.endsWith(ext));\n}\n\nfunction usesLegacyPluginShape(source: string): boolean {\n if (!source.includes(ANALOG_PLATFORM_IMPORT)) {\n return false;\n }\n if (\n source.includes(ANGULAR_PLUGIN_IMPORT) &&\n NITRO_IMPORTS.some((nitroImport) => source.includes(nitroImport))\n ) {\n return false;\n }\n return /\\banalog\\s*\\(/.test(source);\n}\n\nfunction readPackageJson(\n tree: Tree,\n): { raw: string; pkg: Record<string, unknown> } | null {\n const content = tree.read('/package.json');\n if (!content) return null;\n const raw = content.toString('utf-8');\n try {\n return { raw, pkg: JSON.parse(raw) };\n } catch {\n return null;\n }\n}\n\nfunction getDepVersion(\n pkg: Record<string, unknown>,\n name: string,\n): string | undefined {\n const dev =\n (pkg['devDependencies'] as Record<string, string> | undefined) ?? {};\n const reg = (pkg['dependencies'] as Record<string, string> | undefined) ?? {};\n return dev[name] ?? reg[name];\n}\n\nfunction addDependencies(tree: Tree, context: SchematicContext): boolean {\n const info = readPackageJson(tree);\n if (!info) return false;\n\n const { pkg, raw } = info;\n const devDeps = {\n ...((pkg['devDependencies'] as Record<string, string> | undefined) ?? {}),\n };\n let changed = false;\n\n // Match the @analogjs/platform pin so the plugins stay aligned with the\n // rest of the Analog packages already in this workspace.\n const platformVersion = getDepVersion(pkg, '@analogjs/platform') ?? '*';\n const missingPlugins = [ANGULAR_PLUGIN_PKG, NITRO_PLUGIN_PKG].filter(\n (name) =>\n !getDepVersion(pkg, name) &&\n // Apps already on Nitro v3 keep `nitro()` from `nitro/vite`.\n !(name === NITRO_PLUGIN_PKG && getDepVersion(pkg, 'nitro')),\n );\n for (const name of missingPlugins) {\n devDeps[name] = platformVersion;\n changed = true;\n context.logger.info(\n `Added '${name}': '${platformVersion}' to devDependencies.`,\n );\n }\n\n if (!changed) return false;\n\n pkg['devDependencies'] = devDeps;\n const trailingNewline = raw.endsWith('\\n') ? '\\n' : '';\n tree.overwrite(\n '/package.json',\n JSON.stringify(pkg, null, 2) + trailingNewline,\n );\n context.addTask(new NodePackageInstallTask());\n return true;\n}\n\ninterface TransformResult {\n source: string;\n movedVite: boolean;\n movedNitro: boolean;\n}\n\nfunction getLineIndent(source: string, pos: number): string {\n let lineStart = pos;\n while (lineStart > 0 && source[lineStart - 1] !== '\\n') {\n lineStart--;\n }\n let indent = '';\n for (let i = lineStart; i < source.length; i++) {\n const ch = source[i];\n if (ch === ' ' || ch === '\\t') indent += ch;\n else break;\n }\n return indent;\n}\n\n/**\n * Tries to lift `vite: {...}` and `nitro: {...}` properties off the\n * single `analog(...)` call into companion `angular(...)` / `nitro(...)`\n * calls. Returns the rewritten source on success, or null if the file\n * doesn't match the supported pattern (we then fall back to logging\n * instructions rather than risking a corrupted file).\n *\n * Supported pattern: exactly one `analog(...)` call whose argument is\n * an object literal. Properties named `vite` and `nitro` are recognized;\n * everything else stays on `analog`.\n */\nfunction tryTransformViteConfig(\n filePath: string,\n source: string,\n): TransformResult | null {\n let sourceFile: ts.SourceFile;\n try {\n sourceFile = ts.createSourceFile(\n filePath,\n source,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n } catch {\n return null;\n }\n\n let analogImportEnd = -1;\n let angularImported = false;\n let nitroImported = false;\n const analogCalls: ts.CallExpression[] = [];\n\n function visit(node: ts.Node): void {\n if (ts.isImportDeclaration(node)) {\n const ml = node.moduleSpecifier;\n if (ts.isStringLiteral(ml)) {\n if (ml.text === '@analogjs/platform') {\n analogImportEnd = node.end;\n } else if (ml.text === '@analogjs/vite-plugin-angular') {\n angularImported = true;\n } else if (\n ml.text === '@analogjs/vite-plugin-nitro' ||\n ml.text === 'nitro/vite'\n ) {\n nitroImported = true;\n }\n }\n } else if (ts.isCallExpression(node)) {\n if (\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'analog'\n ) {\n analogCalls.push(node);\n }\n }\n ts.forEachChild(node, visit);\n }\n visit(sourceFile);\n\n if (analogImportEnd === -1) return null;\n if (analogCalls.length !== 1) return null;\n\n const analogCall = analogCalls[0];\n const callStart = analogCall.getStart(sourceFile);\n const callEnd = analogCall.getEnd();\n\n let viteValueText: string | null = null;\n let nitroValueText: string | null = null;\n let remainingPropsText: string | null = null;\n\n const arg = analogCall.arguments[0];\n if (arg && ts.isObjectLiteralExpression(arg)) {\n const remaining: ts.ObjectLiteralElementLike[] = [];\n for (const prop of arg.properties) {\n if (\n ts.isPropertyAssignment(prop) &&\n ts.isIdentifier(prop.name) &&\n (prop.name.text === 'vite' || prop.name.text === 'nitro')\n ) {\n const value = prop.initializer;\n const text = source.slice(value.getStart(sourceFile), value.getEnd());\n if (prop.name.text === 'vite') viteValueText = text;\n else nitroValueText = text;\n } else {\n remaining.push(prop);\n }\n }\n\n if (remaining.length > 0) {\n // Reconstruct the analog object literal from the remaining props,\n // preserving their original source text (comments, spacing).\n const propTexts = remaining.map((p) =>\n source.slice(p.getStart(sourceFile), p.getEnd()),\n );\n const objStart = arg.getStart(sourceFile);\n const indent = getLineIndent(source, objStart);\n const propIndent = indent + ' ';\n remainingPropsText = `{\\n${propTexts.map((t) => `${propIndent}${t}`).join(',\\n')},\\n${indent}}`;\n }\n } else if (arg !== undefined) {\n // analog(otherExpression) — can't statically split a variable or call\n // expression. Fall back to logging instructions.\n return null;\n }\n // analog() with no argument falls through to the rewrite below; we just\n // emit `analog(), angular(), nitro()` to scaffold the new plugin chain.\n\n const indent = getLineIndent(source, callStart);\n const newAnalogCall = remainingPropsText\n ? `analog(${remainingPropsText})`\n : `analog()`;\n const parts: string[] = [newAnalogCall];\n if (viteValueText !== null) parts.push(`angular(${viteValueText})`);\n else parts.push('angular()');\n if (nitroValueText !== null) parts.push(`nitro(${nitroValueText})`);\n else parts.push('nitro()');\n const replacement = parts.join(`,\\n${indent}`);\n\n const edits: Edit[] = [{ start: callStart, end: callEnd, text: replacement }];\n\n const importsToAdd: string[] = [];\n if (!angularImported) {\n importsToAdd.push(`import angular from '@analogjs/vite-plugin-angular';`);\n }\n if (!nitroImported) {\n importsToAdd.push(`import nitro from '@analogjs/vite-plugin-nitro';`);\n }\n if (importsToAdd.length > 0) {\n edits.push({\n start: analogImportEnd,\n end: analogImportEnd,\n text: `\\n${importsToAdd.join('\\n')}`,\n });\n }\n\n const rewritten = applyEdits(source, edits);\n\n return {\n source: rewritten,\n movedVite: viteValueText !== null,\n movedNitro: nitroValueText !== null,\n };\n}\n\nexport default function migrateToSeparatedPlugins(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const filesUsingLegacyShape: string[] = [];\n const rewrittenFiles: string[] = [];\n const unhandledFiles: string[] = [];\n\n tree.visit((filePath) => {\n if (filePath.includes('/node_modules/')) return;\n if (!isViteConfig(filePath)) return;\n\n const content = tree.read(filePath);\n if (!content) return;\n\n const source = content.toString('utf-8');\n if (!usesLegacyPluginShape(source)) return;\n\n filesUsingLegacyShape.push(filePath);\n\n const transformed = tryTransformViteConfig(filePath, source);\n if (transformed) {\n tree.overwrite(filePath, transformed.source);\n rewrittenFiles.push(filePath);\n } else {\n unhandledFiles.push(filePath);\n }\n });\n\n if (filesUsingLegacyShape.length === 0) {\n return tree;\n }\n\n if (rewrittenFiles.length > 0) {\n context.logger.info(\n `Rewrote ${rewrittenFiles.length} vite.config file(s) to the separated \\`analog() + angular() + nitro()\\` shape:`,\n );\n for (const file of rewrittenFiles) {\n context.logger.info(` - ${file}`);\n }\n context.logger.info(\n `Review the result — only \\`vite\\` and \\`nitro\\` were moved automatically. Other angular-passthrough options (\\`liveReload\\`, \\`fastCompile\\`, \\`fileReplacements\\`, etc.) still need to be relocated by hand.\\nSee ${MIGRATION_DOC_URL}`,\n );\n }\n\n if (unhandledFiles.length > 0) {\n context.logger.info(\n `Could not safely rewrite ${unhandledFiles.length} vite.config file(s); migrate them by hand:`,\n );\n for (const file of unhandledFiles) {\n context.logger.info(` - ${file}`);\n }\n context.logger.info(\n `Split \\`analog()\\` into \\`analog() + angular() + nitro()\\` and move each option to its owning plugin.\\nSee ${MIGRATION_DOC_URL}`,\n );\n }\n\n addDependencies(tree, context);\n\n return tree;\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-vitest-builder-aliases.js","names":[],"sources":["../../../migrations/migrate-vitest-builder-aliases/migrate-vitest-builder-aliases.ts"],"sourcesContent":["import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\n// The explicit file path resolves when this runs as native ESM.\nimport { NodePackageInstallTask } from '@angular-devkit/schematics/tasks/index.js';\n\nconst VITEST_BUILDER = '@analogjs/vitest-angular:test';\nconst VITEST_ANGULAR_PKG = '@analogjs/vitest-angular';\nconst REMOVED_ALIASES = [\n '@analogjs/vite-plugin-angular:vitest',\n '@analogjs/platform:vitest',\n '@analogjs/storybook-angular:test-storybook',\n];\nconst WORKSPACE_FILES = [\n 'angular.json',\n 'workspace.json',\n 'project.json',\n 'nx.json',\n 'package.json',\n];\n\nfunction isWorkspaceFile(filePath: string): boolean {\n const file = filePath.slice(filePath.lastIndexOf('/') + 1);\n return WORKSPACE_FILES.includes(file);\n}\n\nfunction addVitestAngular(tree: Tree, context: SchematicContext): void {\n const raw = tree.read('/package.json')?.toString('utf-8');\n if (!raw) return;\n\n const pkg = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n if (\n pkg.dependencies?.[VITEST_ANGULAR_PKG] ||\n pkg.devDependencies?.[VITEST_ANGULAR_PKG]\n ) {\n return;\n }\n\n const version =\n pkg.devDependencies?.['@analogjs/platform'] ??\n pkg.dependencies?.['@analogjs/platform'] ??\n '*';\n pkg.devDependencies = {\n ...pkg.devDependencies,\n [VITEST_ANGULAR_PKG]: version,\n };\n const trailingNewline = raw.endsWith('\\n') ? '\\n' : '';\n tree.overwrite(\n '/package.json',\n JSON.stringify(pkg, null, 2) + trailingNewline,\n );\n context.addTask(new NodePackageInstallTask());\n}\n\n/**\n * Points targets that use the removed Vitest builder/executor aliases at\n * `@analogjs/vitest-angular:test`.\n */\nexport default function migrateVitestBuilderAliases(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const rewritten: string[] = [];\n tree.visit((filePath) => {\n if (filePath.includes('/node_modules/')) return;\n if (!isWorkspaceFile(filePath)) return;\n\n const source = tree.read(filePath)?.toString('utf-8');\n if (!source) return;\n\n const result = REMOVED_ALIASES.reduce(\n (content, alias) =>\n content.replaceAll(`\"${alias}\"`, `\"${VITEST_BUILDER}\"`),\n source,\n );\n if (result !== source) {\n tree.overwrite(filePath, result);\n rewritten.push(filePath);\n }\n });\n\n if (rewritten.length === 0) {\n return tree;\n }\n\n context.logger.info(\n `Replaced removed Vitest builder aliases with ${VITEST_BUILDER} in:\\n${rewritten\n .map((file) => ` - ${file}`)\n .join('\\n')}`,\n );\n addVitestAngular(tree, context);\n return tree;\n };\n}\n"],"mappings":";;AAIA,IAAM,iBAAiB;AACvB,IAAM,qBAAqB;AAC3B,IAAM,kBAAkB;CACtB;CACA;CACA;CACD;AACD,IAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACD;AAED,SAAS,gBAAgB,UAA2B;CAClD,MAAM,OAAO,SAAS,MAAM,SAAS,YAAY,IAAI,GAAG,EAAE;AAC1D,QAAO,gBAAgB,SAAS,KAAK;;AAGvC,SAAS,iBAAiB,MAAY,SAAiC;CACrE,MAAM,MAAM,KAAK,KAAK,gBAAgB,EAAE,SAAS,QAAQ;AACzD,KAAI,CAAC,IAAK;CAEV,MAAM,MAAM,KAAK,MAAM,IAAI;AAI3B,KACE,IAAI,eAAe,uBACnB,IAAI,kBAAkB,oBAEtB;CAGF,MAAM,UACJ,IAAI,kBAAkB,yBACtB,IAAI,eAAe,yBACnB;AACF,KAAI,kBAAkB;EACpB,GAAG,IAAI;GACN,qBAAqB;EACvB;CACD,MAAM,kBAAkB,IAAI,SAAS,KAAK,GAAG,OAAO;AACpD,MAAK,UACH,iBACA,KAAK,UAAU,KAAK,MAAM,EAAE,GAAG,gBAChC;AACD,SAAQ,QAAQ,IAAI,wBAAwB,CAAC;;;;;;AAO/C,SAAwB,8BAAoC;AAC1D,SAAQ,MAAY,YAA8B;EAChD,MAAM,YAAsB,EAAE;AAC9B,OAAK,OAAO,aAAa;AACvB,OAAI,SAAS,SAAS,iBAAiB,CAAE;AACzC,OAAI,CAAC,gBAAgB,SAAS,CAAE;GAEhC,MAAM,SAAS,KAAK,KAAK,SAAS,EAAE,SAAS,QAAQ;AACrD,OAAI,CAAC,OAAQ;GAEb,MAAM,SAAS,gBAAgB,QAC5B,SAAS,UACR,QAAQ,WAAW,IAAI,MAAM,IAAI,IAAI,eAAe,GAAG,EACzD,OACD;AACD,OAAI,WAAW,QAAQ;AACrB,SAAK,UAAU,UAAU,OAAO;AAChC,cAAU,KAAK,SAAS;;IAE1B;AAEF,MAAI,UAAU,WAAW,EACvB,QAAO;AAGT,UAAQ,OAAO,KACb,gDAAgD,eAAe,QAAQ,UACpE,KAAK,SAAS,OAAO,OAAO,CAC5B,KAAK,KAAK,GACd;AACD,mBAAiB,MAAM,QAAQ;AAC/B,SAAO"}
1
+ {"version":3,"file":"migrate-vitest-builder-aliases.js","names":[],"sources":["../../../migrations/migrate-vitest-builder-aliases/migrate-vitest-builder-aliases.ts"],"sourcesContent":["import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';\n// The explicit file path resolves when this runs as native ESM.\nimport { NodePackageInstallTask } from '@angular-devkit/schematics/tasks/index.js';\n\nconst VITEST_BUILDER = '@analogjs/vitest-angular:test';\nconst VITEST_ANGULAR_PKG = '@analogjs/vitest-angular';\nconst REMOVED_ALIASES = [\n '@analogjs/vite-plugin-angular:vitest',\n '@analogjs/platform:vitest',\n '@analogjs/storybook-angular:test-storybook',\n];\nconst WORKSPACE_FILES = [\n 'angular.json',\n 'workspace.json',\n 'project.json',\n 'nx.json',\n 'package.json',\n];\n\nfunction isWorkspaceFile(filePath: string): boolean {\n const file = filePath.slice(filePath.lastIndexOf('/') + 1);\n return WORKSPACE_FILES.includes(file);\n}\n\nfunction addVitestAngular(tree: Tree, context: SchematicContext): void {\n const raw = tree.read('/package.json')?.toString('utf-8');\n if (!raw) return;\n\n const pkg = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n if (\n pkg.dependencies?.[VITEST_ANGULAR_PKG] ||\n pkg.devDependencies?.[VITEST_ANGULAR_PKG]\n ) {\n return;\n }\n\n const version =\n pkg.devDependencies?.['@analogjs/platform'] ??\n pkg.dependencies?.['@analogjs/platform'] ??\n '*';\n pkg.devDependencies = {\n ...pkg.devDependencies,\n [VITEST_ANGULAR_PKG]: version,\n };\n const trailingNewline = raw.endsWith('\\n') ? '\\n' : '';\n tree.overwrite(\n '/package.json',\n JSON.stringify(pkg, null, 2) + trailingNewline,\n );\n context.addTask(new NodePackageInstallTask());\n}\n\n/**\n * Points targets that use the removed Vitest builder/executor aliases at\n * `@analogjs/vitest-angular:test`.\n */\nexport default function migrateVitestBuilderAliases(): Rule {\n return (tree: Tree, context: SchematicContext) => {\n const rewritten: string[] = [];\n tree.visit((filePath) => {\n if (filePath.includes('/node_modules/')) return;\n if (!isWorkspaceFile(filePath)) return;\n\n const source = tree.read(filePath)?.toString('utf-8');\n if (!source) return;\n\n const result = REMOVED_ALIASES.reduce(\n (content, alias) =>\n content.replaceAll(`\"${alias}\"`, `\"${VITEST_BUILDER}\"`),\n source,\n );\n if (result !== source) {\n tree.overwrite(filePath, result);\n rewritten.push(filePath);\n }\n });\n\n if (rewritten.length === 0) {\n return tree;\n }\n\n context.logger.info(\n `Replaced removed Vitest builder aliases with ${VITEST_BUILDER} in:\\n${rewritten\n .map((file) => ` - ${file}`)\n .join('\\n')}`,\n );\n addVitestAngular(tree, context);\n return tree;\n };\n}\n"],"mappings":";;AAIA,IAAM,iBAAiB;AACvB,IAAM,qBAAqB;AAC3B,IAAM,kBAAkB;CACtB;CACA;CACA;AACF;AACA,IAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,gBAAgB,UAA2B;CAClD,MAAM,OAAO,SAAS,MAAM,SAAS,YAAY,GAAG,IAAI,CAAC;CACzD,OAAO,gBAAgB,SAAS,IAAI;AACtC;AAEA,SAAS,iBAAiB,MAAY,SAAiC;CACrE,MAAM,MAAM,KAAK,KAAK,eAAe,CAAC,EAAE,SAAS,OAAO;CACxD,IAAI,CAAC,KAAK;CAEV,MAAM,MAAM,KAAK,MAAM,GAAG;CAI1B,IACE,IAAI,eAAe,uBACnB,IAAI,kBAAkB,qBAEtB;CAGF,MAAM,UACJ,IAAI,kBAAkB,yBACtB,IAAI,eAAe,yBACnB;CACF,IAAI,kBAAkB;EACpB,GAAG,IAAI;GACN,qBAAqB;CACxB;CACA,MAAM,kBAAkB,IAAI,SAAS,IAAI,IAAI,OAAO;CACpD,KAAK,UACH,iBACA,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,eACjC;CACA,QAAQ,QAAQ,IAAI,uBAAuB,CAAC;AAC9C;;;;;AAMA,SAAwB,8BAAoC;CAC1D,QAAQ,MAAY,YAA8B;EAChD,MAAM,YAAsB,CAAC;EAC7B,KAAK,OAAO,aAAa;GACvB,IAAI,SAAS,SAAS,gBAAgB,GAAG;GACzC,IAAI,CAAC,gBAAgB,QAAQ,GAAG;GAEhC,MAAM,SAAS,KAAK,KAAK,QAAQ,CAAC,EAAE,SAAS,OAAO;GACpD,IAAI,CAAC,QAAQ;GAEb,MAAM,SAAS,gBAAgB,QAC5B,SAAS,UACR,QAAQ,WAAW,IAAI,MAAM,IAAI,IAAI,eAAe,EAAE,GACxD,MACF;GACA,IAAI,WAAW,QAAQ;IACrB,KAAK,UAAU,UAAU,MAAM;IAC/B,UAAU,KAAK,QAAQ;GACzB;EACF,CAAC;EAED,IAAI,UAAU,WAAW,GACvB,OAAO;EAGT,QAAQ,OAAO,KACb,gDAAgD,eAAe,QAAQ,UACpE,KAAK,SAAS,OAAO,MAAM,CAAC,CAC5B,KAAK,IAAI,GACd;EACA,iBAAiB,MAAM,OAAO;EAC9B,OAAO;CACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"source-edits.js","names":[],"sources":["../../../migrations/utils/source-edits.ts"],"sourcesContent":["import type { Tree } from '@angular-devkit/schematics';\n\nexport interface Edit {\n start: number;\n end: number;\n text: string;\n}\n\nexport function applyEdits(source: string, edits: Edit[]): string {\n // Apply right-to-left so earlier offsets stay valid.\n const sorted = [...edits].sort((a, b) => b.start - a.start);\n let result = source;\n for (const edit of sorted) {\n result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);\n }\n return result;\n}\n\nconst SOURCE_EXTENSIONS = ['.ts', '.mts', '.cts', '.tsx'];\n\n/** Rewrites workspace TypeScript sources that contain `marker`. */\nexport function rewriteSourceFiles(\n tree: Tree,\n marker: string,\n rewrite: (filePath: string, source: string) => string | null,\n): string[] {\n const rewritten: string[] = [];\n tree.visit((filePath) => {\n if (filePath.includes('/node_modules/')) return;\n if (!SOURCE_EXTENSIONS.some((ext) => filePath.endsWith(ext))) return;\n\n const source = tree.read(filePath)?.toString('utf-8');\n if (!source?.includes(marker)) return;\n\n const result = rewrite(filePath, source);\n if (result !== null && result !== source) {\n tree.overwrite(filePath, result);\n rewritten.push(filePath);\n }\n });\n return rewritten;\n}\n"],"mappings":";AAQA,SAAgB,WAAW,QAAgB,OAAuB;CAEhE,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;CAC3D,IAAI,SAAS;AACb,MAAK,MAAM,QAAQ,OACjB,UAAS,OAAO,MAAM,GAAG,KAAK,MAAM,GAAG,KAAK,OAAO,OAAO,MAAM,KAAK,IAAI;AAE3E,QAAO;;AAGT,IAAM,oBAAoB;CAAC;CAAO;CAAQ;CAAQ;CAAO;;AAGzD,SAAgB,mBACd,MACA,QACA,SACU;CACV,MAAM,YAAsB,EAAE;AAC9B,MAAK,OAAO,aAAa;AACvB,MAAI,SAAS,SAAS,iBAAiB,CAAE;AACzC,MAAI,CAAC,kBAAkB,MAAM,QAAQ,SAAS,SAAS,IAAI,CAAC,CAAE;EAE9D,MAAM,SAAS,KAAK,KAAK,SAAS,EAAE,SAAS,QAAQ;AACrD,MAAI,CAAC,QAAQ,SAAS,OAAO,CAAE;EAE/B,MAAM,SAAS,QAAQ,UAAU,OAAO;AACxC,MAAI,WAAW,QAAQ,WAAW,QAAQ;AACxC,QAAK,UAAU,UAAU,OAAO;AAChC,aAAU,KAAK,SAAS;;GAE1B;AACF,QAAO"}
1
+ {"version":3,"file":"source-edits.js","names":[],"sources":["../../../migrations/utils/source-edits.ts"],"sourcesContent":["import type { Tree } from '@angular-devkit/schematics';\n\nexport interface Edit {\n start: number;\n end: number;\n text: string;\n}\n\nexport function applyEdits(source: string, edits: Edit[]): string {\n // Apply right-to-left so earlier offsets stay valid.\n const sorted = [...edits].sort((a, b) => b.start - a.start);\n let result = source;\n for (const edit of sorted) {\n result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);\n }\n return result;\n}\n\nconst SOURCE_EXTENSIONS = ['.ts', '.mts', '.cts', '.tsx'];\n\n/** Rewrites workspace TypeScript sources that contain `marker`. */\nexport function rewriteSourceFiles(\n tree: Tree,\n marker: string,\n rewrite: (filePath: string, source: string) => string | null,\n): string[] {\n const rewritten: string[] = [];\n tree.visit((filePath) => {\n if (filePath.includes('/node_modules/')) return;\n if (!SOURCE_EXTENSIONS.some((ext) => filePath.endsWith(ext))) return;\n\n const source = tree.read(filePath)?.toString('utf-8');\n if (!source?.includes(marker)) return;\n\n const result = rewrite(filePath, source);\n if (result !== null && result !== source) {\n tree.overwrite(filePath, result);\n rewritten.push(filePath);\n }\n });\n return rewritten;\n}\n"],"mappings":";AAQA,SAAgB,WAAW,QAAgB,OAAuB;CAEhE,MAAM,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;CAC1D,IAAI,SAAS;CACb,KAAK,MAAM,QAAQ,QACjB,SAAS,OAAO,MAAM,GAAG,KAAK,KAAK,IAAI,KAAK,OAAO,OAAO,MAAM,KAAK,GAAG;CAE1E,OAAO;AACT;AAEA,IAAM,oBAAoB;CAAC;CAAO;CAAQ;CAAQ;AAAM;;AAGxD,SAAgB,mBACd,MACA,QACA,SACU;CACV,MAAM,YAAsB,CAAC;CAC7B,KAAK,OAAO,aAAa;EACvB,IAAI,SAAS,SAAS,gBAAgB,GAAG;EACzC,IAAI,CAAC,kBAAkB,MAAM,QAAQ,SAAS,SAAS,GAAG,CAAC,GAAG;EAE9D,MAAM,SAAS,KAAK,KAAK,QAAQ,CAAC,EAAE,SAAS,OAAO;EACpD,IAAI,CAAC,QAAQ,SAAS,MAAM,GAAG;EAE/B,MAAM,SAAS,QAAQ,UAAU,MAAM;EACvC,IAAI,WAAW,QAAQ,WAAW,QAAQ;GACxC,KAAK,UAAU,UAAU,MAAM;GAC/B,UAAU,KAAK,QAAQ;EACzB;CACF,CAAC;CACD,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@analogjs/platform",
3
- "version": "3.0.0-alpha.98",
3
+ "version": "3.0.0-beta.1",
4
4
  "description": "The fullstack meta-framework for Angular",
5
5
  "type": "module",
6
6
  "author": "Brandon Roberts <robertsbt@gmail.com>",
@@ -31,7 +31,7 @@
31
31
  "url": "https://github.com/sponsors/brandonroberts"
32
32
  },
33
33
  "dependencies": {
34
- "@analogjs/vite-plugin-angular": "3.0.0-alpha.98",
34
+ "@analogjs/vite-plugin-angular": "3.0.0-beta.1",
35
35
  "es-toolkit": "^1.45.1",
36
36
  "front-matter": "^4.0.2",
37
37
  "magic-string": "^0.30.21",
@@ -1 +1 @@
1
- {"version":3,"file":"analog-integration-plugin.js","names":[],"sources":["../../../src/lib/analog-integration-plugin.ts"],"sourcesContent":["import type { AnalogIntegrationPlugin } from '@analogjs/vite-plugin-angular';\n\nimport { pageGlobs } from './discover-library-routes.js';\nimport type { Options } from './options.js';\n\n/**\n * The platform's `analog.setup()` hook into `@analogjs/vite-plugin-angular`.\n * Keeps Angular away from the platform's content modules and registers\n * `additionalPagesDirs` so workspace library pages compile without a matching\n * `include` on `angular()`.\n */\nexport function analogIntegrationPlugin(\n options?: Options,\n): AnalogIntegrationPlugin {\n const pagesDirs = options?.additionalPagesDirs ?? [];\n\n return {\n name: 'analogjs-platform-angular-integration',\n analog: {\n setup(ctx) {\n // Content files are imported with `?analog-content-*` markers and\n // served by the content plugin, never compiled by Angular.\n ctx.registerTransformFilter(\n (_code, id) => !(id.includes('?') && id.includes('analog-content-')),\n );\n if (pagesDirs.length) {\n ctx.addInclude(pageGlobs(pagesDirs));\n }\n },\n },\n };\n}\n"],"mappings":";;;;;;;;AAWA,SAAgB,wBACd,SACyB;CACzB,MAAM,YAAY,SAAS,uBAAuB,EAAE;AAEpD,QAAO;EACL,MAAM;EACN,QAAQ,EACN,MAAM,KAAK;AAGT,OAAI,yBACD,OAAO,OAAO,EAAE,GAAG,SAAS,IAAI,IAAI,GAAG,SAAS,kBAAkB,EACpE;AACD,OAAI,UAAU,OACZ,KAAI,WAAW,UAAU,UAAU,CAAC;KAGzC;EACF"}
1
+ {"version":3,"file":"analog-integration-plugin.js","names":[],"sources":["../../../src/lib/analog-integration-plugin.ts"],"sourcesContent":["import type { AnalogIntegrationPlugin } from '@analogjs/vite-plugin-angular';\n\nimport { pageGlobs } from './discover-library-routes.js';\nimport type { Options } from './options.js';\n\n/**\n * The platform's `analog.setup()` hook into `@analogjs/vite-plugin-angular`.\n * Keeps Angular away from the platform's content modules and registers\n * `additionalPagesDirs` so workspace library pages compile without a matching\n * `include` on `angular()`.\n */\nexport function analogIntegrationPlugin(\n options?: Options,\n): AnalogIntegrationPlugin {\n const pagesDirs = options?.additionalPagesDirs ?? [];\n\n return {\n name: 'analogjs-platform-angular-integration',\n analog: {\n setup(ctx) {\n // Content files are imported with `?analog-content-*` markers and\n // served by the content plugin, never compiled by Angular.\n ctx.registerTransformFilter(\n (_code, id) => !(id.includes('?') && id.includes('analog-content-')),\n );\n if (pagesDirs.length) {\n ctx.addInclude(pageGlobs(pagesDirs));\n }\n },\n },\n };\n}\n"],"mappings":";;;;;;;;AAWA,SAAgB,wBACd,SACyB;CACzB,MAAM,YAAY,SAAS,uBAAuB,CAAC;CAEnD,OAAO;EACL,MAAM;EACN,QAAQ,EACN,MAAM,KAAK;GAGT,IAAI,yBACD,OAAO,OAAO,EAAE,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,iBAAiB,EACpE;GACA,IAAI,UAAU,QACZ,IAAI,WAAW,UAAU,SAAS,CAAC;EAEvC,EACF;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"clear-client-page-endpoint.js","names":[],"sources":["../../../src/lib/clear-client-page-endpoint.ts"],"sourcesContent":["import { Plugin, normalizePath } from 'vite';\nimport { injectServerFnIds } from './inject-server-fn-ids.js';\nimport { serverFnFileId } from './server-fn-id.js';\n\nimport { scrubServerFnModule } from './server-fn-client-transform.js';\n\nexport function clearClientPageEndpointsPlugin(): Plugin {\n let projectRoot = process.cwd();\n let isBuild = true;\n\n return {\n name: 'analogjs-platform-clear-client-page-endpoint',\n // After Angular compilation, which re-emits `.server.ts` files from its own\n // program and would otherwise drop this transform's output.\n enforce: 'post',\n config() {\n return {\n build: {\n rollupOptions: {\n onwarn(warning) {\n if (\n warning.message.includes('empty chunk') &&\n warning.message.endsWith('.server')\n ) {\n return;\n }\n },\n },\n },\n };\n },\n configResolved(config) {\n projectRoot = config.root;\n isBuild = config.command === 'build';\n },\n transform(code, id, options) {\n if (!id.endsWith('.server.ts')) {\n return;\n }\n\n // Server-function ids are derived from the project-root-relative path so\n // the client proxy and the server registration always resolve to the same\n // opaque, collision-free route.\n const fileId = serverFnFileId(id, projectRoot);\n\n if (options?.ssr) {\n // SSR build keeps the real handlers but stamps the derived id into each\n // serverFn config so it registers under the route the client calls.\n const injected = injectServerFnIds(code, fileId);\n return injected ? { code: injected.code, map: null } : undefined;\n }\n\n // Client build: a `.server.ts` defining server functions is rewritten to\n // client-safe proxies (the `{ id, url, method }` refs the browser\n // dispatches through); handlers and server imports are dropped so they\n // tree-shake away.\n const scrubbed = scrubServerFnModule(code, fileId);\n if (scrubbed) {\n // An empty mapping, not `null`: a null map lets the original module —\n // handlers and all — survive in `sourcesContent` further down the\n // pipeline, which would ship the server code to the browser after the\n // scrub went to the trouble of removing it.\n return { code: scrubbed.code, map: { mappings: '' } };\n }\n\n // Page load/action endpoints carry no client-consumable exports. Only the\n // client build empties them; the dev server never pulls them into the\n // browser graph, and emptying them there would break the SSR request.\n if (isBuild && id.includes(normalizePath('src/app/pages'))) {\n return {\n code: 'export default undefined;',\n map: null,\n };\n }\n\n return;\n },\n };\n}\n"],"mappings":";;;;;AAMA,SAAgB,iCAAyC;CACvD,IAAI,cAAc,QAAQ,KAAK;CAC/B,IAAI,UAAU;AAEd,QAAO;EACL,MAAM;EAGN,SAAS;EACT,SAAS;AACP,UAAO,EACL,OAAO,EACL,eAAe,EACb,OAAO,SAAS;AACd,QACE,QAAQ,QAAQ,SAAS,cAAc,IACvC,QAAQ,QAAQ,SAAS,UAAU,CAEnC;MAGL,EACF,EACF;;EAEH,eAAe,QAAQ;AACrB,iBAAc,OAAO;AACrB,aAAU,OAAO,YAAY;;EAE/B,UAAU,MAAM,IAAI,SAAS;AAC3B,OAAI,CAAC,GAAG,SAAS,aAAa,CAC5B;GAMF,MAAM,SAAS,eAAe,IAAI,YAAY;AAE9C,OAAI,SAAS,KAAK;IAGhB,MAAM,WAAW,kBAAkB,MAAM,OAAO;AAChD,WAAO,WAAW;KAAE,MAAM,SAAS;KAAM,KAAK;KAAM,GAAG,KAAA;;GAOzD,MAAM,WAAW,oBAAoB,MAAM,OAAO;AAClD,OAAI,SAKF,QAAO;IAAE,MAAM,SAAS;IAAM,KAAK,EAAE,UAAU,IAAI;IAAE;AAMvD,OAAI,WAAW,GAAG,SAAS,cAAc,gBAAgB,CAAC,CACxD,QAAO;IACL,MAAM;IACN,KAAK;IACN;;EAKN"}
1
+ {"version":3,"file":"clear-client-page-endpoint.js","names":[],"sources":["../../../src/lib/clear-client-page-endpoint.ts"],"sourcesContent":["import { Plugin, normalizePath } from 'vite';\nimport { injectServerFnIds } from './inject-server-fn-ids.js';\nimport { serverFnFileId } from './server-fn-id.js';\n\nimport { scrubServerFnModule } from './server-fn-client-transform.js';\n\nexport function clearClientPageEndpointsPlugin(): Plugin {\n let projectRoot = process.cwd();\n let isBuild = true;\n\n return {\n name: 'analogjs-platform-clear-client-page-endpoint',\n // After Angular compilation, which re-emits `.server.ts` files from its own\n // program and would otherwise drop this transform's output.\n enforce: 'post',\n config() {\n return {\n build: {\n rollupOptions: {\n onwarn(warning) {\n if (\n warning.message.includes('empty chunk') &&\n warning.message.endsWith('.server')\n ) {\n return;\n }\n },\n },\n },\n };\n },\n configResolved(config) {\n projectRoot = config.root;\n isBuild = config.command === 'build';\n },\n transform(code, id, options) {\n if (!id.endsWith('.server.ts')) {\n return;\n }\n\n // Server-function ids are derived from the project-root-relative path so\n // the client proxy and the server registration always resolve to the same\n // opaque, collision-free route.\n const fileId = serverFnFileId(id, projectRoot);\n\n if (options?.ssr) {\n // SSR build keeps the real handlers but stamps the derived id into each\n // serverFn config so it registers under the route the client calls.\n const injected = injectServerFnIds(code, fileId);\n return injected ? { code: injected.code, map: null } : undefined;\n }\n\n // Client build: a `.server.ts` defining server functions is rewritten to\n // client-safe proxies (the `{ id, url, method }` refs the browser\n // dispatches through); handlers and server imports are dropped so they\n // tree-shake away.\n const scrubbed = scrubServerFnModule(code, fileId);\n if (scrubbed) {\n // An empty mapping, not `null`: a null map lets the original module —\n // handlers and all — survive in `sourcesContent` further down the\n // pipeline, which would ship the server code to the browser after the\n // scrub went to the trouble of removing it.\n return { code: scrubbed.code, map: { mappings: '' } };\n }\n\n // Page load/action endpoints carry no client-consumable exports. Only the\n // client build empties them; the dev server never pulls them into the\n // browser graph, and emptying them there would break the SSR request.\n if (isBuild && id.includes(normalizePath('src/app/pages'))) {\n return {\n code: 'export default undefined;',\n map: null,\n };\n }\n\n return;\n },\n };\n}\n"],"mappings":";;;;;AAMA,SAAgB,iCAAyC;CACvD,IAAI,cAAc,QAAQ,IAAI;CAC9B,IAAI,UAAU;CAEd,OAAO;EACL,MAAM;EAGN,SAAS;EACT,SAAS;GACP,OAAO,EACL,OAAO,EACL,eAAe,EACb,OAAO,SAAS;IACd,IACE,QAAQ,QAAQ,SAAS,aAAa,KACtC,QAAQ,QAAQ,SAAS,SAAS,GAElC;GAEJ,EACF,EACF,EACF;EACF;EACA,eAAe,QAAQ;GACrB,cAAc,OAAO;GACrB,UAAU,OAAO,YAAY;EAC/B;EACA,UAAU,MAAM,IAAI,SAAS;GAC3B,IAAI,CAAC,GAAG,SAAS,YAAY,GAC3B;GAMF,MAAM,SAAS,eAAe,IAAI,WAAW;GAE7C,IAAI,SAAS,KAAK;IAGhB,MAAM,WAAW,kBAAkB,MAAM,MAAM;IAC/C,OAAO,WAAW;KAAE,MAAM,SAAS;KAAM,KAAK;IAAK,IAAI,KAAA;GACzD;GAMA,MAAM,WAAW,oBAAoB,MAAM,MAAM;GACjD,IAAI,UAKF,OAAO;IAAE,MAAM,SAAS;IAAM,KAAK,EAAE,UAAU,GAAG;GAAE;GAMtD,IAAI,WAAW,GAAG,SAAS,cAAc,eAAe,CAAC,GACvD,OAAO;IACL,MAAM;IACN,KAAK;GACP;EAIJ;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/content/marked/index.ts"],"sourcesContent":["import { MarkedExtension } from 'marked';\nimport { MarkedSetupService } from './marked-setup.service.js';\nimport { MarkedContentHighlighter } from './marked-content-highlighter.js';\n\nexport type WithMarkedOptions = {\n mangle?: boolean;\n extensions?: MarkedExtension[];\n};\n\nlet markedSetupInstance: MarkedSetupService;\n\nexport function getMarkedSetup(\n options?: WithMarkedOptions,\n highlighter?: MarkedContentHighlighter,\n): MarkedSetupService {\n markedSetupInstance ??= new MarkedSetupService(options, highlighter);\n return markedSetupInstance;\n}\n"],"mappings":";;AASA,IAAI;AAEJ,SAAgB,eACd,SACA,aACoB;AACpB,yBAAwB,IAAI,mBAAmB,SAAS,YAAY;AACpE,QAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/content/marked/index.ts"],"sourcesContent":["import { MarkedExtension } from 'marked';\nimport { MarkedSetupService } from './marked-setup.service.js';\nimport { MarkedContentHighlighter } from './marked-content-highlighter.js';\n\nexport type WithMarkedOptions = {\n mangle?: boolean;\n extensions?: MarkedExtension[];\n};\n\nlet markedSetupInstance: MarkedSetupService;\n\nexport function getMarkedSetup(\n options?: WithMarkedOptions,\n highlighter?: MarkedContentHighlighter,\n): MarkedSetupService {\n markedSetupInstance ??= new MarkedSetupService(options, highlighter);\n return markedSetupInstance;\n}\n"],"mappings":";;AASA,IAAI;AAEJ,SAAgB,eACd,SACA,aACoB;CACpB,wBAAwB,IAAI,mBAAmB,SAAS,WAAW;CACnE,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"marked-content-highlighter.js","names":[],"sources":["../../../../../src/lib/content/marked/marked-content-highlighter.ts"],"sourcesContent":["export abstract class MarkedContentHighlighter {\n augmentCodeBlock?(code: string, lang: string): string;\n abstract getHighlightExtension(): import('marked').MarkedExtension;\n}\n"],"mappings":";AAAA,IAAsB,2BAAtB,MAA+C"}
1
+ {"version":3,"file":"marked-content-highlighter.js","names":[],"sources":["../../../../../src/lib/content/marked/marked-content-highlighter.ts"],"sourcesContent":["export abstract class MarkedContentHighlighter {\n augmentCodeBlock?(code: string, lang: string): string;\n abstract getHighlightExtension(): import('marked').MarkedExtension;\n}\n"],"mappings":";AAAA,IAAsB,2BAAtB,MAA+C,CAG/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"marked-setup.service.js","names":[],"sources":["../../../../../src/lib/content/marked/marked-setup.service.ts"],"sourcesContent":["import { marked, Parser, MarkedExtension } from 'marked';\nimport { gfmHeadingId } from 'marked-gfm-heading-id';\nimport { mangle } from 'marked-mangle';\n\nimport { MarkedContentHighlighter } from './marked-content-highlighter.js';\nimport { WithMarkedOptions } from './index.js';\nimport { escapeHtml, sanitizeLanguage } from '../utils/escape-html.js';\n\nexport class MarkedSetupService {\n private readonly marked: typeof marked;\n\n constructor(\n private readonly options?: WithMarkedOptions | undefined,\n private readonly highlighter?: MarkedContentHighlighter | undefined,\n ) {\n const analogMarkedExtension: MarkedExtension = {\n pedantic: false,\n gfm: true,\n breaks: false,\n renderer: {\n code({ text, lang }) {\n // Let's do a language based detection like on GitHub\n // So we can still have non-interpreted mermaid code\n const language = sanitizeLanguage(lang);\n if (language === 'mermaid') {\n return '<pre class=\"mermaid\">' + escapeHtml(text) + '</pre>';\n }\n\n if (!language) {\n return '<pre><code>' + escapeHtml(text) + '</code></pre>';\n }\n\n if (highlighter?.augmentCodeBlock) {\n return highlighter?.augmentCodeBlock(text, language);\n }\n\n return `<pre class=\"language-${language}\"><code class=\"language-${language}\">${escapeHtml(text)}</code></pre>`;\n },\n codespan({ text }) {\n return `<code>${escapeHtml(text)}</code>`;\n },\n paragraph({ tokens }) {\n const text = this.parser.parseInline(tokens);\n return `<p>${text}</p>`;\n },\n },\n };\n\n const extensions = [\n analogMarkedExtension,\n gfmHeadingId(),\n ...(options?.extensions || []),\n ];\n\n if (this.options?.mangle) {\n extensions.push(mangle());\n }\n\n if (this.highlighter) {\n extensions.push(this.highlighter.getHighlightExtension());\n }\n\n marked.use(...extensions);\n\n this.marked = marked;\n }\n\n getMarkedInstance(): typeof marked {\n return this.marked;\n }\n}\n"],"mappings":";;;;;AAQA,IAAa,qBAAb,MAAgC;CAG9B,YACE,SACA,aACA;AAFiB,OAAA,UAAA;AACA,OAAA,cAAA;EAmCjB,MAAM,aAAa;GAjC4B;IAC7C,UAAU;IACV,KAAK;IACL,QAAQ;IACR,UAAU;KACR,KAAK,EAAE,MAAM,QAAQ;MAGnB,MAAM,WAAW,iBAAiB,KAAK;AACvC,UAAI,aAAa,UACf,QAAO,4BAA0B,WAAW,KAAK,GAAG;AAGtD,UAAI,CAAC,SACH,QAAO,gBAAgB,WAAW,KAAK,GAAG;AAG5C,UAAI,aAAa,iBACf,QAAO,aAAa,iBAAiB,MAAM,SAAS;AAGtD,aAAO,wBAAwB,SAAS,0BAA0B,SAAS,IAAI,WAAW,KAAK,CAAC;;KAElG,SAAS,EAAE,QAAQ;AACjB,aAAO,SAAS,WAAW,KAAK,CAAC;;KAEnC,UAAU,EAAE,UAAU;AAEpB,aAAO,MADM,KAAK,OAAO,YAAY,OAAO,CAC1B;;KAErB;IACF;GAIC,cAAc;GACd,GAAI,SAAS,cAAc,EAAE;GAC9B;AAED,MAAI,KAAK,SAAS,OAChB,YAAW,KAAK,QAAQ,CAAC;AAG3B,MAAI,KAAK,YACP,YAAW,KAAK,KAAK,YAAY,uBAAuB,CAAC;AAG3D,SAAO,IAAI,GAAG,WAAW;AAEzB,OAAK,SAAS;;CAGhB,oBAAmC;AACjC,SAAO,KAAK"}
1
+ {"version":3,"file":"marked-setup.service.js","names":[],"sources":["../../../../../src/lib/content/marked/marked-setup.service.ts"],"sourcesContent":["import { marked, Parser, MarkedExtension } from 'marked';\nimport { gfmHeadingId } from 'marked-gfm-heading-id';\nimport { mangle } from 'marked-mangle';\n\nimport { MarkedContentHighlighter } from './marked-content-highlighter.js';\nimport { WithMarkedOptions } from './index.js';\nimport { escapeHtml, sanitizeLanguage } from '../utils/escape-html.js';\n\nexport class MarkedSetupService {\n private readonly marked: typeof marked;\n\n constructor(\n private readonly options?: WithMarkedOptions | undefined,\n private readonly highlighter?: MarkedContentHighlighter | undefined,\n ) {\n const analogMarkedExtension: MarkedExtension = {\n pedantic: false,\n gfm: true,\n breaks: false,\n renderer: {\n code({ text, lang }) {\n // Let's do a language based detection like on GitHub\n // So we can still have non-interpreted mermaid code\n const language = sanitizeLanguage(lang);\n if (language === 'mermaid') {\n return '<pre class=\"mermaid\">' + escapeHtml(text) + '</pre>';\n }\n\n if (!language) {\n return '<pre><code>' + escapeHtml(text) + '</code></pre>';\n }\n\n if (highlighter?.augmentCodeBlock) {\n return highlighter?.augmentCodeBlock(text, language);\n }\n\n return `<pre class=\"language-${language}\"><code class=\"language-${language}\">${escapeHtml(text)}</code></pre>`;\n },\n codespan({ text }) {\n return `<code>${escapeHtml(text)}</code>`;\n },\n paragraph({ tokens }) {\n const text = this.parser.parseInline(tokens);\n return `<p>${text}</p>`;\n },\n },\n };\n\n const extensions = [\n analogMarkedExtension,\n gfmHeadingId(),\n ...(options?.extensions || []),\n ];\n\n if (this.options?.mangle) {\n extensions.push(mangle());\n }\n\n if (this.highlighter) {\n extensions.push(this.highlighter.getHighlightExtension());\n }\n\n marked.use(...extensions);\n\n this.marked = marked;\n }\n\n getMarkedInstance(): typeof marked {\n return this.marked;\n }\n}\n"],"mappings":";;;;;AAQA,IAAa,qBAAb,MAAgC;CAG9B,YACE,SACA,aACA;EAFiB,KAAA,UAAA;EACA,KAAA,cAAA;EAmCjB,MAAM,aAAa;GACjB;IAjCA,UAAU;IACV,KAAK;IACL,QAAQ;IACR,UAAU;KACR,KAAK,EAAE,MAAM,QAAQ;MAGnB,MAAM,WAAW,iBAAiB,IAAI;MACtC,IAAI,aAAa,WACf,OAAO,4BAA0B,WAAW,IAAI,IAAI;MAGtD,IAAI,CAAC,UACH,OAAO,gBAAgB,WAAW,IAAI,IAAI;MAG5C,IAAI,aAAa,kBACf,OAAO,aAAa,iBAAiB,MAAM,QAAQ;MAGrD,OAAO,wBAAwB,SAAS,0BAA0B,SAAS,IAAI,WAAW,IAAI,EAAE;KAClG;KACA,SAAS,EAAE,QAAQ;MACjB,OAAO,SAAS,WAAW,IAAI,EAAE;KACnC;KACA,UAAU,EAAE,UAAU;MAEpB,OAAO,MADM,KAAK,OAAO,YAAY,MACxB,EAAK;KACpB;IACF;GAIA;GACA,aAAa;GACb,GAAI,SAAS,cAAc,CAAC;EAC9B;EAEA,IAAI,KAAK,SAAS,QAChB,WAAW,KAAK,OAAO,CAAC;EAG1B,IAAI,KAAK,aACP,WAAW,KAAK,KAAK,YAAY,sBAAsB,CAAC;EAG1D,OAAO,IAAI,GAAG,UAAU;EAExB,KAAK,SAAS;CAChB;CAEA,oBAAmC;EACjC,OAAO,KAAK;CACd;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"angular.js","names":[],"sources":["../../../../../src/lib/content/prism/angular.ts"],"sourcesContent":["import Prism from 'prismjs';\n\n(function () {\n if (typeof Prism === 'undefined') {\n return;\n }\n\n Prism.languages['angular'] = Prism.languages.extend('markup', {\n keyword:\n /(?:@if|@for|@switch|@defer|@loading|@error|@placeholder|prefetch)\\b/,\n operator: /\\b(?:on|when)\\b/,\n number: {\n pattern: /\\b(minimum|after)\\s+\\d+(?:s|ms|)/gi,\n lookbehind: true,\n },\n builtin: {\n pattern:\n /\\b(?:viewport|timer|minimum|after|hover|idle|immediate|interaction)/,\n },\n function:\n /#?(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*(?:\\.\\s*(?:apply|bind|call)\\s*)?\\()/,\n });\n\n Prism.languages['ng'] = Prism.languages['angular'];\n})();\n"],"mappings":";;CAEC,WAAY;AACX,KAAI,OAAO,UAAU,YACnB;AAGF,OAAM,UAAU,aAAa,MAAM,UAAU,OAAO,UAAU;EAC5D,SACE;EACF,UAAU;EACV,QAAQ;GACN,SAAS;GACT,YAAY;GACb;EACD,SAAS,EACP,SACE,uEACH;EACD,UACE;EACH,CAAC;AAEF,OAAM,UAAU,QAAQ,MAAM,UAAU;IACtC"}
1
+ {"version":3,"file":"angular.js","names":[],"sources":["../../../../../src/lib/content/prism/angular.ts"],"sourcesContent":["import Prism from 'prismjs';\n\n(function () {\n if (typeof Prism === 'undefined') {\n return;\n }\n\n Prism.languages['angular'] = Prism.languages.extend('markup', {\n keyword:\n /(?:@if|@for|@switch|@defer|@loading|@error|@placeholder|prefetch)\\b/,\n operator: /\\b(?:on|when)\\b/,\n number: {\n pattern: /\\b(minimum|after)\\s+\\d+(?:s|ms|)/gi,\n lookbehind: true,\n },\n builtin: {\n pattern:\n /\\b(?:viewport|timer|minimum|after|hover|idle|immediate|interaction)/,\n },\n function:\n /#?(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*(?=\\s*(?:\\.\\s*(?:apply|bind|call)\\s*)?\\()/,\n });\n\n Prism.languages['ng'] = Prism.languages['angular'];\n})();\n"],"mappings":";;CAEC,WAAY;CACX,IAAI,OAAO,UAAU,aACnB;CAGF,MAAM,UAAU,aAAa,MAAM,UAAU,OAAO,UAAU;EAC5D,SACE;EACF,UAAU;EACV,QAAQ;GACN,SAAS;GACT,YAAY;EACd;EACA,SAAS,EACP,SACE,sEACJ;EACA,UACE;CACJ,CAAC;CAED,MAAM,UAAU,QAAQ,MAAM,UAAU;AAC1C,EAAA,CAAG"}
@@ -6,6 +6,6 @@ function getPrismHighlighter() {
6
6
  return highlighterInstance;
7
7
  }
8
8
  //#endregion
9
- export { getPrismHighlighter };
9
+ export { PrismHighlighter, getPrismHighlighter };
10
10
 
11
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/content/prism/index.ts"],"sourcesContent":["import { PrismHighlighter } from './prism-highlighter.js';\n\nexport { PrismHighlighter };\n\nlet highlighterInstance: PrismHighlighter;\n\nexport function getPrismHighlighter(): PrismHighlighter {\n highlighterInstance ??= new PrismHighlighter();\n return highlighterInstance;\n}\n"],"mappings":";;AAIA,IAAI;AAEJ,SAAgB,sBAAwC;AACtD,yBAAwB,IAAI,kBAAkB;AAC9C,QAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/content/prism/index.ts"],"sourcesContent":["import { PrismHighlighter } from './prism-highlighter.js';\n\nexport { PrismHighlighter };\n\nlet highlighterInstance: PrismHighlighter;\n\nexport function getPrismHighlighter(): PrismHighlighter {\n highlighterInstance ??= new PrismHighlighter();\n return highlighterInstance;\n}\n"],"mappings":";;AAIA,IAAI;AAEJ,SAAgB,sBAAwC;CACtD,wBAAwB,IAAI,iBAAiB;CAC7C,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"prism-highlighter.js","names":[],"sources":["../../../../../src/lib/content/prism/prism-highlighter.ts"],"sourcesContent":["import { markedHighlight } from 'marked-highlight';\n\nimport 'prismjs';\nimport './angular.js';\n\nimport { MarkedContentHighlighter } from '../marked/marked-content-highlighter.js';\n\ndeclare const Prism: typeof import('prismjs');\n\nexport class PrismHighlighter extends MarkedContentHighlighter {\n override augmentCodeBlock(code: string, lang: string): string {\n const classes =\n lang.startsWith('diff') && Prism.languages['diff']\n ? `language-${lang} diff-highlight`\n : `language-${lang.replace('diff-', '')}`;\n return `<pre class=\"${classes}\"><code class=\"${classes}\">${code}</code></pre>`;\n }\n\n override getHighlightExtension(): import('marked').MarkedExtension {\n return markedHighlight({\n async: true,\n highlight: (code: string, lang: string) => {\n let diff = lang?.startsWith('diff-');\n lang = diff ? lang.replace('diff-', '') : lang || 'typescript';\n\n if (diff && !Prism.languages['diff']) {\n diff = false;\n console.warn(`Notice:\n ---------------------------------------------------------------------------------------\n The \\`diff\\` language and plugin are not available in the provided setup.\n\n To enable, add it to the \\`analog\\` plugin in your \\`vite.config.ts\\`:\n analog({\n content: {\n prismOptions: {\n additionalLangs: [\n 'prism-diff'\n ]\n }\n }\n })\n\n Add the plugin import to your \\`app.config.ts\\`\n import 'prismjs/plugins/diff-highlight/prism-diff-highlight.js';\n ---------------------------------------------------------------------------------------\n `);\n }\n\n if (!Prism.languages[lang]) {\n if (lang !== 'mermaid') {\n console.warn(`Notice:\n ---------------------------------------------------------------------------------------\n The requested language '${lang}' is not available in the provided setup.\n To enable, add it to the \\`analog\\` plugin in your \\`vite.config.ts\\`:\n analog({\n content: {\n prismOptions: {\n additionalLangs: [\n '${lang}',\n ]\n }\n }\n })\n ---------------------------------------------------------------------------------------\n `);\n }\n return code;\n }\n return Prism.highlight(\n code,\n diff ? Prism.languages['diff'] : Prism.languages[lang],\n lang,\n );\n },\n });\n }\n}\n"],"mappings":";;;;;AASA,IAAa,mBAAb,cAAsC,yBAAyB;CAC7D,iBAA0B,MAAc,MAAsB;EAC5D,MAAM,UACJ,KAAK,WAAW,OAAO,IAAI,MAAM,UAAU,UACvC,YAAY,KAAK,mBACjB,YAAY,KAAK,QAAQ,SAAS,GAAG;AAC3C,SAAO,eAAe,QAAQ,iBAAiB,QAAQ,IAAI,KAAK;;CAGlE,wBAAmE;AACjE,SAAO,gBAAgB;GACrB,OAAO;GACP,YAAY,MAAc,SAAiB;IACzC,IAAI,OAAO,MAAM,WAAW,QAAQ;AACpC,WAAO,OAAO,KAAK,QAAQ,SAAS,GAAG,GAAG,QAAQ;AAElD,QAAI,QAAQ,CAAC,MAAM,UAAU,SAAS;AACpC,YAAO;AACP,aAAQ,KAAK;;;;;;;;;;;;;;;;;;cAkBT;;AAGN,QAAI,CAAC,MAAM,UAAU,OAAO;AAC1B,SAAI,SAAS,UACX,SAAQ,KAAK;;8BAEK,KAAK;;;;;;iBAMlB,KAAK;;;;;;gBAMN;AAEN,YAAO;;AAET,WAAO,MAAM,UACX,MACA,OAAO,MAAM,UAAU,UAAU,MAAM,UAAU,OACjD,KACD;;GAEJ,CAAC"}
1
+ {"version":3,"file":"prism-highlighter.js","names":[],"sources":["../../../../../src/lib/content/prism/prism-highlighter.ts"],"sourcesContent":["import { markedHighlight } from 'marked-highlight';\n\nimport 'prismjs';\nimport './angular.js';\n\nimport { MarkedContentHighlighter } from '../marked/marked-content-highlighter.js';\n\ndeclare const Prism: typeof import('prismjs');\n\nexport class PrismHighlighter extends MarkedContentHighlighter {\n override augmentCodeBlock(code: string, lang: string): string {\n const classes =\n lang.startsWith('diff') && Prism.languages['diff']\n ? `language-${lang} diff-highlight`\n : `language-${lang.replace('diff-', '')}`;\n return `<pre class=\"${classes}\"><code class=\"${classes}\">${code}</code></pre>`;\n }\n\n override getHighlightExtension(): import('marked').MarkedExtension {\n return markedHighlight({\n async: true,\n highlight: (code: string, lang: string) => {\n let diff = lang?.startsWith('diff-');\n lang = diff ? lang.replace('diff-', '') : lang || 'typescript';\n\n if (diff && !Prism.languages['diff']) {\n diff = false;\n console.warn(`Notice:\n ---------------------------------------------------------------------------------------\n The \\`diff\\` language and plugin are not available in the provided setup.\n\n To enable, add it to the \\`analog\\` plugin in your \\`vite.config.ts\\`:\n analog({\n content: {\n prismOptions: {\n additionalLangs: [\n 'prism-diff'\n ]\n }\n }\n })\n\n Add the plugin import to your \\`app.config.ts\\`\n import 'prismjs/plugins/diff-highlight/prism-diff-highlight.js';\n ---------------------------------------------------------------------------------------\n `);\n }\n\n if (!Prism.languages[lang]) {\n if (lang !== 'mermaid') {\n console.warn(`Notice:\n ---------------------------------------------------------------------------------------\n The requested language '${lang}' is not available in the provided setup.\n To enable, add it to the \\`analog\\` plugin in your \\`vite.config.ts\\`:\n analog({\n content: {\n prismOptions: {\n additionalLangs: [\n '${lang}',\n ]\n }\n }\n })\n ---------------------------------------------------------------------------------------\n `);\n }\n return code;\n }\n return Prism.highlight(\n code,\n diff ? Prism.languages['diff'] : Prism.languages[lang],\n lang,\n );\n },\n });\n }\n}\n"],"mappings":";;;;;AASA,IAAa,mBAAb,cAAsC,yBAAyB;CAC7D,iBAA0B,MAAc,MAAsB;EAC5D,MAAM,UACJ,KAAK,WAAW,MAAM,KAAK,MAAM,UAAU,UACvC,YAAY,KAAK,mBACjB,YAAY,KAAK,QAAQ,SAAS,EAAE;EAC1C,OAAO,eAAe,QAAQ,iBAAiB,QAAQ,IAAI,KAAK;CAClE;CAEA,wBAAmE;EACjE,OAAO,gBAAgB;GACrB,OAAO;GACP,YAAY,MAAc,SAAiB;IACzC,IAAI,OAAO,MAAM,WAAW,OAAO;IACnC,OAAO,OAAO,KAAK,QAAQ,SAAS,EAAE,IAAI,QAAQ;IAElD,IAAI,QAAQ,CAAC,MAAM,UAAU,SAAS;KACpC,OAAO;KACP,QAAQ,KAAK;;;;;;;;;;;;;;;;;;aAkBV;IACL;IAEA,IAAI,CAAC,MAAM,UAAU,OAAO;KAC1B,IAAI,SAAS,WACX,QAAQ,KAAK;;8BAEK,KAAK;;;;;;iBAMlB,KAAK;;;;;;eAMP;KAEL,OAAO;IACT;IACA,OAAO,MAAM,UACX,MACA,OAAO,MAAM,UAAU,UAAU,MAAM,UAAU,OACjD,IACF;GACF;EACF,CAAC;CACH;AACF"}
@@ -6,9 +6,11 @@ function getShikiHighlighter({ highlighter = {}, highlight = {}, container = "%s
6
6
  const additionalLangs = highlighter.additionalLangs ?? [];
7
7
  const skipLangs = highlighter.skipLangs ?? [];
8
8
  const hasMermaidSupport = highlighter.langs?.includes("mermaid") || additionalLangs.includes("mermaid");
9
- if (!highlighter.themes) if (highlight.theme) highlighter.themes = [highlight.theme];
10
- else if (highlight.themes && typeof highlight.themes === "object") highlighter.themes = Object.values(highlight.themes);
11
- else highlighter.themes = defaultHighlighterOptions.themes;
9
+ if (!highlighter.themes) {
10
+ if (highlight.theme) highlighter.themes = [highlight.theme];
11
+ else if (highlight.themes && typeof highlight.themes === "object") highlighter.themes = Object.values(highlight.themes);
12
+ else highlighter.themes = defaultHighlighterOptions.themes;
13
+ }
12
14
  if (!highlighter.langs) highlighter.langs = [...defaultHighlighterOptions.langs];
13
15
  if (additionalLangs.length > 0) highlighter.langs.push(...additionalLangs);
14
16
  if (skipLangs.length > 0) highlighter.langs = highlighter.langs.filter((lang) => !skipLangs.includes(lang));
@@ -18,6 +20,6 @@ function getShikiHighlighter({ highlighter = {}, highlight = {}, container = "%s
18
20
  return highlighterInstance;
19
21
  }
20
22
  //#endregion
21
- export { getShikiHighlighter };
23
+ export { ShikiHighlighter, getShikiHighlighter };
22
24
 
23
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/content/shiki/index.ts"],"sourcesContent":["import { WithShikiHighlighterOptions } from './options.js';\nimport {\n defaultHighlighterOptions,\n ShikiHighlighter,\n ShikiHighlighterOptions,\n} from './shiki-highlighter.js';\n\nexport { ShikiHighlighter };\n\nlet highlighterInstance: ShikiHighlighter;\n\nexport function getShikiHighlighter({\n highlighter = {},\n highlight = {},\n container = '%s',\n}: WithShikiHighlighterOptions = {}): ShikiHighlighter {\n if (highlighterInstance) {\n return highlighterInstance;\n }\n\n const additionalLangs = highlighter.additionalLangs ?? [];\n const skipLangs = highlighter.skipLangs ?? [];\n const hasMermaidSupport =\n highlighter.langs?.includes('mermaid') ||\n additionalLangs.includes('mermaid');\n\n if (!highlighter.themes) {\n if (highlight.theme) {\n highlighter.themes = [highlight.theme];\n } else if (highlight.themes && typeof highlight.themes === 'object') {\n highlighter.themes = Object.values(highlight.themes) as string[];\n } else {\n highlighter.themes = defaultHighlighterOptions.themes;\n }\n }\n\n if (!highlighter.langs) {\n highlighter.langs = [...defaultHighlighterOptions.langs];\n }\n\n if (additionalLangs.length > 0) {\n highlighter.langs.push(...additionalLangs);\n }\n\n if (skipLangs.length > 0) {\n highlighter.langs = highlighter.langs.filter(\n (lang) => !skipLangs.includes(lang),\n );\n }\n\n delete highlighter.additionalLangs;\n delete highlighter.skipLangs;\n\n highlighterInstance = new ShikiHighlighter(\n highlighter as ShikiHighlighterOptions,\n highlight,\n container,\n hasMermaidSupport,\n skipLangs,\n );\n\n return highlighterInstance;\n}\n"],"mappings":";;AASA,IAAI;AAEJ,SAAgB,oBAAoB,EAClC,cAAc,EAAE,EAChB,YAAY,EAAE,EACd,YAAY,SACmB,EAAE,EAAoB;AACrD,KAAI,oBACF,QAAO;CAGT,MAAM,kBAAkB,YAAY,mBAAmB,EAAE;CACzD,MAAM,YAAY,YAAY,aAAa,EAAE;CAC7C,MAAM,oBACJ,YAAY,OAAO,SAAS,UAAU,IACtC,gBAAgB,SAAS,UAAU;AAErC,KAAI,CAAC,YAAY,OACf,KAAI,UAAU,MACZ,aAAY,SAAS,CAAC,UAAU,MAAM;UAC7B,UAAU,UAAU,OAAO,UAAU,WAAW,SACzD,aAAY,SAAS,OAAO,OAAO,UAAU,OAAO;KAEpD,aAAY,SAAS,0BAA0B;AAInD,KAAI,CAAC,YAAY,MACf,aAAY,QAAQ,CAAC,GAAG,0BAA0B,MAAM;AAG1D,KAAI,gBAAgB,SAAS,EAC3B,aAAY,MAAM,KAAK,GAAG,gBAAgB;AAG5C,KAAI,UAAU,SAAS,EACrB,aAAY,QAAQ,YAAY,MAAM,QACnC,SAAS,CAAC,UAAU,SAAS,KAAK,CACpC;AAGH,QAAO,YAAY;AACnB,QAAO,YAAY;AAEnB,uBAAsB,IAAI,iBACxB,aACA,WACA,WACA,mBACA,UACD;AAED,QAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/lib/content/shiki/index.ts"],"sourcesContent":["import { WithShikiHighlighterOptions } from './options.js';\nimport {\n defaultHighlighterOptions,\n ShikiHighlighter,\n ShikiHighlighterOptions,\n} from './shiki-highlighter.js';\n\nexport { ShikiHighlighter };\n\nlet highlighterInstance: ShikiHighlighter;\n\nexport function getShikiHighlighter({\n highlighter = {},\n highlight = {},\n container = '%s',\n}: WithShikiHighlighterOptions = {}): ShikiHighlighter {\n if (highlighterInstance) {\n return highlighterInstance;\n }\n\n const additionalLangs = highlighter.additionalLangs ?? [];\n const skipLangs = highlighter.skipLangs ?? [];\n const hasMermaidSupport =\n highlighter.langs?.includes('mermaid') ||\n additionalLangs.includes('mermaid');\n\n if (!highlighter.themes) {\n if (highlight.theme) {\n highlighter.themes = [highlight.theme];\n } else if (highlight.themes && typeof highlight.themes === 'object') {\n highlighter.themes = Object.values(highlight.themes) as string[];\n } else {\n highlighter.themes = defaultHighlighterOptions.themes;\n }\n }\n\n if (!highlighter.langs) {\n highlighter.langs = [...defaultHighlighterOptions.langs];\n }\n\n if (additionalLangs.length > 0) {\n highlighter.langs.push(...additionalLangs);\n }\n\n if (skipLangs.length > 0) {\n highlighter.langs = highlighter.langs.filter(\n (lang) => !skipLangs.includes(lang),\n );\n }\n\n delete highlighter.additionalLangs;\n delete highlighter.skipLangs;\n\n highlighterInstance = new ShikiHighlighter(\n highlighter as ShikiHighlighterOptions,\n highlight,\n container,\n hasMermaidSupport,\n skipLangs,\n );\n\n return highlighterInstance;\n}\n"],"mappings":";;AASA,IAAI;AAEJ,SAAgB,oBAAoB,EAClC,cAAc,CAAC,GACf,YAAY,CAAC,GACb,YAAY,SACmB,CAAC,GAAqB;CACrD,IAAI,qBACF,OAAO;CAGT,MAAM,kBAAkB,YAAY,mBAAmB,CAAC;CACxD,MAAM,YAAY,YAAY,aAAa,CAAC;CAC5C,MAAM,oBACJ,YAAY,OAAO,SAAS,SAAS,KACrC,gBAAgB,SAAS,SAAS;CAEpC,IAAI,CAAC,YAAY,QAAQ;EACvB,IAAI,UAAU,OACZ,YAAY,SAAS,CAAC,UAAU,KAAK;OAChC,IAAI,UAAU,UAAU,OAAO,UAAU,WAAW,UACzD,YAAY,SAAS,OAAO,OAAO,UAAU,MAAM;OAEnD,YAAY,SAAS,0BAA0B;CAEnD;CAEA,IAAI,CAAC,YAAY,OACf,YAAY,QAAQ,CAAC,GAAG,0BAA0B,KAAK;CAGzD,IAAI,gBAAgB,SAAS,GAC3B,YAAY,MAAM,KAAK,GAAG,eAAe;CAG3C,IAAI,UAAU,SAAS,GACrB,YAAY,QAAQ,YAAY,MAAM,QACnC,SAAS,CAAC,UAAU,SAAS,IAAI,CACpC;CAGF,OAAO,YAAY;CACnB,OAAO,YAAY;CAEnB,sBAAsB,IAAI,iBACxB,aACA,WACA,WACA,mBACA,SACF;CAEA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"shiki-highlighter.js","names":[],"sources":["../../../../../src/lib/content/shiki/shiki-highlighter.ts"],"sourcesContent":["import markedShiki from 'marked-shiki';\nimport {\n type BundledLanguage,\n type BundledTheme,\n type CodeOptionsMeta,\n type CodeOptionsMultipleThemes,\n type CodeOptionsSingleTheme,\n type CodeToHastOptionsCommon,\n createHighlighter,\n} from 'shiki';\n\nimport { MarkedContentHighlighter } from '../marked/marked-content-highlighter.js';\nimport { escapeHtml } from '../utils/escape-html.js';\n\nexport type ShikiHighlighterOptions = Parameters<typeof createHighlighter>[0];\nexport type ShikiHighlightOptions = Partial<\n Omit<CodeToHastOptionsCommon<BundledLanguage>, 'lang'>\n> &\n CodeOptionsMeta &\n Partial<CodeOptionsSingleTheme<BundledTheme>> &\n Partial<CodeOptionsMultipleThemes<BundledTheme>>;\n\nexport const defaultHighlighterOptions: {\n langs: string[];\n themes: string[];\n} = {\n langs: [\n 'json',\n 'ts',\n 'tsx',\n 'js',\n 'jsx',\n 'html',\n 'css',\n 'angular-html',\n 'angular-ts',\n ],\n themes: ['github-dark', 'github-light'],\n};\n\nexport class ShikiHighlighter extends MarkedContentHighlighter {\n private readonly highlighter: ReturnType<typeof createHighlighter>;\n\n constructor(\n private highlighterOptions: ShikiHighlighterOptions,\n private highlightOptions: ShikiHighlightOptions,\n private container: string,\n private hasLoadMermaid = false,\n private skipLangs: string[] = [],\n ) {\n super();\n this.highlighter = createHighlighter(this.highlighterOptions);\n }\n getHighlightExtension(): import('marked').MarkedExtension {\n return markedShiki({\n container: this.container,\n highlight: async (code, lang, props) => {\n if (this.hasLoadMermaid && lang === 'mermaid') {\n return `<pre class=\"mermaid\">${escapeHtml(code)}</pre>`;\n }\n\n if (this.skipLangs.includes(lang as string)) {\n const escapedCode = escapeHtml(code);\n\n return `<pre class=\"language-${lang}\"><code class=\"language-${lang}\">${escapedCode}</code></pre>`;\n }\n\n const { codeToHtml } = await this.highlighter;\n return codeToHtml(\n code,\n Object.assign(\n {\n lang,\n // required by `transformerMeta*`\n meta: { __raw: props.join(' ') },\n theme: 'github-dark',\n },\n this.highlightOptions,\n ),\n );\n },\n });\n }\n}\n"],"mappings":";;;;;AAsBA,IAAa,4BAGT;CACF,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CACD,QAAQ,CAAC,eAAe,eAAe;CACxC;AAED,IAAa,mBAAb,cAAsC,yBAAyB;CAG7D,YACE,oBACA,kBACA,WACA,iBAAyB,OACzB,YAA8B,EAAE,EAChC;AACA,SAAO;AANC,OAAA,qBAAA;AACA,OAAA,mBAAA;AACA,OAAA,YAAA;AACA,OAAA,iBAAA;AACA,OAAA,YAAA;AAGR,OAAK,cAAc,kBAAkB,KAAK,mBAAmB;;CAE/D,wBAA0D;AACxD,SAAO,YAAY;GACjB,WAAW,KAAK;GAChB,WAAW,OAAO,MAAM,MAAM,UAAU;AACtC,QAAI,KAAK,kBAAkB,SAAS,UAClC,QAAO,wBAAwB,WAAW,KAAK,CAAC;AAGlD,QAAI,KAAK,UAAU,SAAS,KAAe,CAGzC,QAAO,wBAAwB,KAAK,0BAA0B,KAAK,IAF/C,WAAW,KAAK,CAE+C;IAGrF,MAAM,EAAE,eAAe,MAAM,KAAK;AAClC,WAAO,WACL,MACA,OAAO,OACL;KACE;KAEA,MAAM,EAAE,OAAO,MAAM,KAAK,IAAI,EAAE;KAChC,OAAO;KACR,EACD,KAAK,iBACN,CACF;;GAEJ,CAAC"}
1
+ {"version":3,"file":"shiki-highlighter.js","names":[],"sources":["../../../../../src/lib/content/shiki/shiki-highlighter.ts"],"sourcesContent":["import markedShiki from 'marked-shiki';\nimport {\n type BundledLanguage,\n type BundledTheme,\n type CodeOptionsMeta,\n type CodeOptionsMultipleThemes,\n type CodeOptionsSingleTheme,\n type CodeToHastOptionsCommon,\n createHighlighter,\n} from 'shiki';\n\nimport { MarkedContentHighlighter } from '../marked/marked-content-highlighter.js';\nimport { escapeHtml } from '../utils/escape-html.js';\n\nexport type ShikiHighlighterOptions = Parameters<typeof createHighlighter>[0];\nexport type ShikiHighlightOptions = Partial<\n Omit<CodeToHastOptionsCommon<BundledLanguage>, 'lang'>\n> &\n CodeOptionsMeta &\n Partial<CodeOptionsSingleTheme<BundledTheme>> &\n Partial<CodeOptionsMultipleThemes<BundledTheme>>;\n\nexport const defaultHighlighterOptions: {\n langs: string[];\n themes: string[];\n} = {\n langs: [\n 'json',\n 'ts',\n 'tsx',\n 'js',\n 'jsx',\n 'html',\n 'css',\n 'angular-html',\n 'angular-ts',\n ],\n themes: ['github-dark', 'github-light'],\n};\n\nexport class ShikiHighlighter extends MarkedContentHighlighter {\n private readonly highlighter: ReturnType<typeof createHighlighter>;\n\n constructor(\n private highlighterOptions: ShikiHighlighterOptions,\n private highlightOptions: ShikiHighlightOptions,\n private container: string,\n private hasLoadMermaid = false,\n private skipLangs: string[] = [],\n ) {\n super();\n this.highlighter = createHighlighter(this.highlighterOptions);\n }\n getHighlightExtension(): import('marked').MarkedExtension {\n return markedShiki({\n container: this.container,\n highlight: async (code, lang, props) => {\n if (this.hasLoadMermaid && lang === 'mermaid') {\n return `<pre class=\"mermaid\">${escapeHtml(code)}</pre>`;\n }\n\n if (this.skipLangs.includes(lang as string)) {\n const escapedCode = escapeHtml(code);\n\n return `<pre class=\"language-${lang}\"><code class=\"language-${lang}\">${escapedCode}</code></pre>`;\n }\n\n const { codeToHtml } = await this.highlighter;\n return codeToHtml(\n code,\n Object.assign(\n {\n lang,\n // required by `transformerMeta*`\n meta: { __raw: props.join(' ') },\n theme: 'github-dark',\n },\n this.highlightOptions,\n ),\n );\n },\n });\n }\n}\n"],"mappings":";;;;;AAsBA,IAAa,4BAGT;CACF,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,QAAQ,CAAC,eAAe,cAAc;AACxC;AAEA,IAAa,mBAAb,cAAsC,yBAAyB;CAG7D,YACE,oBACA,kBACA,WACA,iBAAyB,OACzB,YAA8B,CAAC,GAC/B;EACA,MAAM;EANE,KAAA,qBAAA;EACA,KAAA,mBAAA;EACA,KAAA,YAAA;EACA,KAAA,iBAAA;EACA,KAAA,YAAA;EAGR,KAAK,cAAc,kBAAkB,KAAK,kBAAkB;CAC9D;CACA,wBAA0D;EACxD,OAAO,YAAY;GACjB,WAAW,KAAK;GAChB,WAAW,OAAO,MAAM,MAAM,UAAU;IACtC,IAAI,KAAK,kBAAkB,SAAS,WAClC,OAAO,wBAAwB,WAAW,IAAI,EAAE;IAGlD,IAAI,KAAK,UAAU,SAAS,IAAc,GAGxC,OAAO,wBAAwB,KAAK,0BAA0B,KAAK,IAF/C,WAAW,IAEwC,EAAY;IAGrF,MAAM,EAAE,eAAe,MAAM,KAAK;IAClC,OAAO,WACL,MACA,OAAO,OACL;KACE;KAEA,MAAM,EAAE,OAAO,MAAM,KAAK,GAAG,EAAE;KAC/B,OAAO;IACT,GACA,KAAK,gBACP,CACF;GACF;EACF,CAAC;CACH;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"escape-html.js","names":[],"sources":["../../../../../src/lib/content/utils/escape-html.ts"],"sourcesContent":["export function escapeHtml(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#39;');\n}\n\n/**\n * Reduces a fenced code-block info string to a safe language identifier so it\n * cannot break out of the `class=\"language-...\"` attribute it is interpolated\n * into.\n */\nexport function sanitizeLanguage(lang: string | undefined): string {\n return (lang ?? '').match(/^[a-zA-Z0-9-+#.]*/)?.[0] ?? '';\n}\n"],"mappings":";AAAA,SAAgB,WAAW,OAAuB;AAChD,QAAO,MACJ,WAAW,KAAK,QAAQ,CACxB,WAAW,KAAK,OAAO,CACvB,WAAW,KAAK,OAAO,CACvB,WAAW,MAAK,SAAS,CACzB,WAAW,KAAK,QAAQ;;;;;;;AAQ7B,SAAgB,iBAAiB,MAAkC;AACjE,SAAQ,QAAQ,IAAI,MAAM,oBAAoB,GAAG,MAAM"}
1
+ {"version":3,"file":"escape-html.js","names":[],"sources":["../../../../../src/lib/content/utils/escape-html.ts"],"sourcesContent":["export function escapeHtml(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#39;');\n}\n\n/**\n * Reduces a fenced code-block info string to a safe language identifier so it\n * cannot break out of the `class=\"language-...\"` attribute it is interpolated\n * into.\n */\nexport function sanitizeLanguage(lang: string | undefined): string {\n return (lang ?? '').match(/^[a-zA-Z0-9-+#.]*/)?.[0] ?? '';\n}\n"],"mappings":";AAAA,SAAgB,WAAW,OAAuB;CAChD,OAAO,MACJ,WAAW,KAAK,OAAO,CAAC,CACxB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,MAAK,QAAQ,CAAC,CACzB,WAAW,KAAK,OAAO;AAC5B;;;;;;AAOA,SAAgB,iBAAiB,MAAkC;CACjE,QAAQ,QAAQ,GAAA,CAAI,MAAM,mBAAmB,CAAC,GAAG,MAAM;AACzD"}
@@ -147,22 +147,24 @@ function contentPlugin({ highlighter, markedOptions, shikiOptions, prismOptions
147
147
  enforce: "post",
148
148
  async load(id) {
149
149
  if (!id.includes("analog-content-file=true")) return;
150
- if (!markedHighlighter) if (highlighter === "shiki") {
151
- const { getShikiHighlighter } = await import("./content/shiki/index.js");
152
- markedHighlighter = getShikiHighlighter(shikiOptions);
153
- } else {
154
- const { getPrismHighlighter } = await import("./content/prism/index.js");
155
- markedHighlighter = getPrismHighlighter();
156
- const langs = [
157
- "bash",
158
- "css",
159
- "javascript",
160
- "json",
161
- "markup",
162
- "typescript"
163
- ];
164
- if (Array.isArray(prismOptions?.additionalLangs) && prismOptions?.additionalLangs?.length > 0) langs.push(...prismOptions.additionalLangs);
165
- (await import("prismjs/components/index.js")).default(langs);
150
+ if (!markedHighlighter) {
151
+ if (highlighter === "shiki") {
152
+ const { getShikiHighlighter } = await import("./content/shiki/index.js");
153
+ markedHighlighter = getShikiHighlighter(shikiOptions);
154
+ } else {
155
+ const { getPrismHighlighter } = await import("./content/prism/index.js");
156
+ markedHighlighter = getPrismHighlighter();
157
+ const langs = [
158
+ "bash",
159
+ "css",
160
+ "javascript",
161
+ "json",
162
+ "markup",
163
+ "typescript"
164
+ ];
165
+ if (Array.isArray(prismOptions?.additionalLangs) && prismOptions?.additionalLangs?.length > 0) langs.push(...prismOptions.additionalLangs);
166
+ (await import("prismjs/components/index.js")).default(langs);
167
+ }
166
168
  }
167
169
  const fm = await import("front-matter");
168
170
  const { body, frontmatter } = (fm.default || fm)(readFileSync(id.split("?")[0], "utf8"));
@@ -1 +1 @@
1
- {"version":3,"file":"content-plugin.js","names":[],"sources":["../../../src/lib/content-plugin.ts"],"sourcesContent":["import * as vite from 'vite';\nimport { readFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport { globSync } from 'tinyglobby';\n\nimport type { WithShikiHighlighterOptions } from './content/shiki/options.js';\nimport type { MarkedContentHighlighter } from './content/marked/marked-content-highlighter.js';\nimport type { WithPrismHighlighterOptions } from './content/prism/options.js';\nimport type { WithMarkedOptions } from './content/marked/index.js';\nimport type { Options } from './options.js';\nimport { getBundleOptionsKey } from './utils/rolldown.js';\n\ninterface Content {\n code: string;\n attributes: string;\n}\n\nexport type ContentPluginOptions = {\n highlighter?: 'shiki' | 'prism';\n markedOptions?: WithMarkedOptions;\n shikiOptions?: WithShikiHighlighterOptions;\n prismOptions?: WithPrismHighlighterOptions;\n};\n\n/**\n * Content plugin that provides markdown and content file processing for Analog.\n *\n * IMPORTANT: This plugin uses tinyglobby for file discovery.\n * Key pitfall with { dot: true }:\n * - Returns relative paths from cwd (e.g., \"apps/blog-app/src/content/...\")\n * - These paths CANNOT be used directly in ES module imports\n * - Relative paths without ./ or ../ are treated as package names\n * - Must convert to absolute paths for imports to work correctly\n */\nexport function contentPlugin(\n {\n highlighter,\n markedOptions,\n shikiOptions,\n prismOptions,\n }: ContentPluginOptions = {},\n options?: Options,\n): vite.Plugin[] {\n const cache = new Map<string, Content>();\n // The content list placeholder can be transformed several times during serve.\n // Caching the discovered markdown paths keeps those repeat passes cheap.\n let contentFilesListCache: string[] | undefined;\n\n let markedHighlighter: MarkedContentHighlighter;\n const workspaceRoot = vite.normalizePath(\n options?.workspaceRoot ?? process.env['NX_WORKSPACE_ROOT'] ?? process.cwd(),\n );\n let config: vite.UserConfig;\n let root: string;\n // Keep discovery and invalidation aligned by deriving both from the same\n // normalized content roots. That way external content dirs participate in\n // cache busting exactly the same way they participate in glob discovery.\n // Initialized once in the `config` hook after `root` is resolved — all\n // inputs (`root`, `workspaceRoot`, `options`) are stable after that point.\n let contentRootDirs: string[];\n const normalizeContentDir = (dir: string) => {\n const normalized = vite.normalizePath(\n dir.startsWith('/')\n ? `${workspaceRoot}${dir}`\n : resolve(workspaceRoot, dir),\n );\n return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;\n };\n const initContentRootDirs = () => {\n contentRootDirs = [\n vite.normalizePath(`${root}/src/content`),\n ...(options?.additionalContentDirs || []).map(normalizeContentDir),\n ];\n };\n const discoverContentFilesList = () => {\n contentFilesListCache ??= globSync(\n contentRootDirs.map((dir) => `${dir}/**/*.md`),\n { dot: true },\n );\n\n return contentFilesListCache;\n };\n const resolveContentModulePath = (module: string) =>\n vite.normalizePath(\n module.startsWith('/') ? module : `${workspaceRoot}/${module}`,\n );\n const getContentModuleKey = (module: string) => {\n const absolutePath = resolveContentModulePath(module);\n const relativeToRoot = vite.normalizePath(relative(root, absolutePath));\n // `startsWith(root)` is not safe here because sibling directories such as\n // `/apps/my-app-tools` also start with `/apps/my-app`. A relative path only\n // represents in-app content when it stays within `root`.\n const isInApp =\n !relativeToRoot.startsWith('..') && !relativeToRoot.startsWith('/');\n\n // Both branches prepend `/` so generated keys are always absolute-\n // looking (`/src/content/...` for in-app, `/libs/shared/...` for\n // workspace-external). Downstream consumers like content-files-token\n // rely on the leading `/` for slug extraction regexes.\n return isInApp\n ? `/${relativeToRoot}`\n : `/${vite.normalizePath(relative(workspaceRoot, absolutePath))}`;\n };\n\n const contentDiscoveryPlugins: vite.Plugin[] = [\n {\n name: 'analog-content-glob-routes',\n config(_config) {\n config = _config;\n root = vite.normalizePath(\n resolve(workspaceRoot, config.root || '.') || '.',\n );\n initContentRootDirs();\n },\n // Vite 8 / Rolldown \"filtered transform\" — the `filter.code` string\n // tells the bundler to skip this handler entirely for modules whose\n // source does not contain the substring, avoiding unnecessary JS→Rust\n // round-trips. The inner `code.includes()` guard is kept for Vite 7\n // compat where filters are not evaluated by the bundler.\n transform: {\n filter: {\n code: 'ANALOG_CONTENT_FILE_LIST',\n },\n handler(code) {\n if (code.includes('ANALOG_CONTENT_FILE_LIST')) {\n const contentFilesList = discoverContentFilesList();\n\n const eagerImports: string[] = [];\n\n contentFilesList.forEach((module, index) => {\n // CRITICAL: tinyglobby returns relative paths like \"apps/blog-app/src/content/file.md\"\n // These MUST be converted to absolute paths for ES module imports\n // Otherwise Node.js treats \"apps\" as a package name and throws \"Cannot find package 'apps'\"\n const absolutePath = resolveContentModulePath(module);\n eagerImports.push(\n `import { default as analog_module_${index} } from \"${absolutePath}?analog-content-list=true\";`,\n );\n });\n\n // Match just the assignment (not the declaration) so the rewrite\n // works whether the source uses `const`, `let`, `var`, or\n // `export const` — including the post-Rolldown `var X = {};`\n // form — without destroying the declaration that keeps the\n // module binding exported.\n let result = code.replace(\n /ANALOG_CONTENT_FILE_LIST\\s*=\\s*\\{\\s*\\}/,\n `ANALOG_CONTENT_FILE_LIST = {${contentFilesList.map(\n (module, index) =>\n `\"${getContentModuleKey(module)}\": analog_module_${index}`,\n )}}`,\n );\n\n if (!code.includes('analog_module_')) {\n result = `${eagerImports.join('\\n')}\\n${result}`;\n }\n\n return {\n code: result,\n map: { mappings: '' },\n };\n }\n\n return;\n },\n },\n },\n {\n name: 'analogjs-invalidate-content-dirs',\n configureServer(server) {\n function invalidateContent(path: string) {\n const normalizedPath = vite.normalizePath(path);\n const isContentPath = contentRootDirs.some(\n (dir) =>\n normalizedPath === dir || normalizedPath.startsWith(`${dir}/`),\n );\n\n if (isContentPath) {\n // The file set only changes on add/remove because this watcher is\n // intentionally scoped to those events. Clear the list cache so the\n // next transform sees the updated directory contents.\n contentFilesListCache = undefined;\n server.moduleGraph.fileToModulesMap.forEach((mods) => {\n mods.forEach((mod) => {\n if (\n mod.id?.includes('analogjs') &&\n mod.id?.includes('content')\n ) {\n server.moduleGraph.invalidateModule(mod);\n\n mod.importers.forEach((imp) => {\n server.moduleGraph.invalidateModule(imp);\n });\n }\n });\n });\n\n server.ws.send('analog:debug-full-reload', {\n plugin: 'platform:content-plugin',\n reason: 'content-file-set-changed',\n path: normalizedPath,\n });\n server.ws.send({\n type: 'full-reload',\n });\n }\n }\n\n server.watcher.on('add', invalidateContent);\n server.watcher.on('unlink', invalidateContent);\n },\n },\n ];\n\n if (!highlighter) {\n return [\n {\n name: 'analogjs-external-content',\n config() {\n const bundleOptionsKey = getBundleOptionsKey();\n return {\n build: {\n [bundleOptionsKey]: {\n external: ['@analogjs/content'],\n },\n },\n };\n },\n },\n {\n name: 'analogjs-exclude-content-import',\n transform: {\n filter: {\n code: '@analogjs/content',\n },\n handler(code) {\n /**\n * Remove the package so it doesn't get\n * referenced when building for serverless\n * functions.\n */\n if (code.includes(`import('@analogjs/content')`)) {\n return {\n code: code.replace(\n `import('@analogjs/content')`,\n 'Promise.resolve({})',\n ),\n };\n }\n\n return;\n },\n },\n },\n ...contentDiscoveryPlugins,\n ];\n }\n\n return [\n {\n name: 'analogjs-content-frontmatter',\n // Filter by module ID so only `?analog-content-list=true` virtual\n // imports enter the handler. Returns `moduleSideEffects: false` so\n // Rolldown can tree-shake unused content list entries.\n transform: {\n filter: {\n id: /analog-content-list=true/,\n },\n async handler(code, id) {\n const cachedContent = cache.get(id);\n // There's no reason to run `readFileSync` and frontmatter parsing if the\n // `transform` hook is called with the same code. In such cases, we can simply\n // return the cached attributes, which is faster than repeatedly reading files\n // synchronously during the build process.\n if (cachedContent?.code === code) {\n return {\n code: `export default ${cachedContent.attributes}`,\n moduleSideEffects: false,\n };\n }\n\n const fm: any = await import('front-matter');\n // The `default` property will be available in CommonJS environment, for instance,\n // when running unit tests. It's safe to retrieve `default` first, since we still\n // fallback to the original implementation.\n const frontmatter = fm.default || fm;\n const fileContents = readFileSync(id.split('?')[0], 'utf8');\n const { attributes } = frontmatter(fileContents);\n const content = {\n code,\n attributes: JSON.stringify(attributes),\n };\n cache.set(id, content);\n\n return {\n code: `export default ${content.attributes}`,\n moduleSideEffects: false,\n };\n },\n },\n },\n {\n name: 'analogjs-content-file',\n enforce: 'post',\n async load(id) {\n if (!id.includes('analog-content-file=true')) {\n return;\n }\n\n if (!markedHighlighter) {\n if (highlighter === 'shiki') {\n const { getShikiHighlighter } =\n await import('./content/shiki/index.js');\n markedHighlighter = getShikiHighlighter(shikiOptions);\n } else {\n const { getPrismHighlighter } =\n await import('./content/prism/index.js');\n markedHighlighter = getPrismHighlighter();\n\n const langs = [\n 'bash',\n 'css',\n 'javascript',\n 'json',\n 'markup',\n 'typescript',\n ];\n\n if (\n Array.isArray(prismOptions?.additionalLangs) &&\n prismOptions?.additionalLangs?.length > 0\n ) {\n langs.push(...prismOptions.additionalLangs);\n }\n\n const loadLanguages = await import('prismjs/components/index.js');\n\n (\n loadLanguages as unknown as { default: (...args: any[]) => any }\n ).default(langs);\n }\n }\n\n const fm: any = await import('front-matter');\n // The `default` property will be available in CommonJS environment, for instance,\n // when running unit tests. It's safe to retrieve `default` first, since we still\n // fallback to the original implementation.\n const frontmatterFn = fm.default || fm;\n const fileContents = readFileSync(id.split('?')[0], 'utf8');\n const { body, frontmatter } = frontmatterFn(fileContents);\n\n // parse markdown and highlight\n const { getMarkedSetup } = await import('./content/marked/index.js');\n const markedSetupService = getMarkedSetup(\n { mangle: true, ...(markedOptions || {}) },\n markedHighlighter,\n );\n const mdContent = (await markedSetupService\n .getMarkedInstance()\n .parse(body)) as unknown as string;\n\n return `export default ${JSON.stringify(\n `---\\n${frontmatter}\\n---\\n\\n${mdContent}`,\n )}`;\n },\n },\n ...contentDiscoveryPlugins,\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"content-plugin.js","names":[],"sources":["../../../src/lib/content-plugin.ts"],"sourcesContent":["import * as vite from 'vite';\nimport { readFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport { globSync } from 'tinyglobby';\n\nimport type { WithShikiHighlighterOptions } from './content/shiki/options.js';\nimport type { MarkedContentHighlighter } from './content/marked/marked-content-highlighter.js';\nimport type { WithPrismHighlighterOptions } from './content/prism/options.js';\nimport type { WithMarkedOptions } from './content/marked/index.js';\nimport type { Options } from './options.js';\nimport { getBundleOptionsKey } from './utils/rolldown.js';\n\ninterface Content {\n code: string;\n attributes: string;\n}\n\nexport type ContentPluginOptions = {\n highlighter?: 'shiki' | 'prism';\n markedOptions?: WithMarkedOptions;\n shikiOptions?: WithShikiHighlighterOptions;\n prismOptions?: WithPrismHighlighterOptions;\n};\n\n/**\n * Content plugin that provides markdown and content file processing for Analog.\n *\n * IMPORTANT: This plugin uses tinyglobby for file discovery.\n * Key pitfall with { dot: true }:\n * - Returns relative paths from cwd (e.g., \"apps/blog-app/src/content/...\")\n * - These paths CANNOT be used directly in ES module imports\n * - Relative paths without ./ or ../ are treated as package names\n * - Must convert to absolute paths for imports to work correctly\n */\nexport function contentPlugin(\n {\n highlighter,\n markedOptions,\n shikiOptions,\n prismOptions,\n }: ContentPluginOptions = {},\n options?: Options,\n): vite.Plugin[] {\n const cache = new Map<string, Content>();\n // The content list placeholder can be transformed several times during serve.\n // Caching the discovered markdown paths keeps those repeat passes cheap.\n let contentFilesListCache: string[] | undefined;\n\n let markedHighlighter: MarkedContentHighlighter;\n const workspaceRoot = vite.normalizePath(\n options?.workspaceRoot ?? process.env['NX_WORKSPACE_ROOT'] ?? process.cwd(),\n );\n let config: vite.UserConfig;\n let root: string;\n // Keep discovery and invalidation aligned by deriving both from the same\n // normalized content roots. That way external content dirs participate in\n // cache busting exactly the same way they participate in glob discovery.\n // Initialized once in the `config` hook after `root` is resolved — all\n // inputs (`root`, `workspaceRoot`, `options`) are stable after that point.\n let contentRootDirs: string[];\n const normalizeContentDir = (dir: string) => {\n const normalized = vite.normalizePath(\n dir.startsWith('/')\n ? `${workspaceRoot}${dir}`\n : resolve(workspaceRoot, dir),\n );\n return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;\n };\n const initContentRootDirs = () => {\n contentRootDirs = [\n vite.normalizePath(`${root}/src/content`),\n ...(options?.additionalContentDirs || []).map(normalizeContentDir),\n ];\n };\n const discoverContentFilesList = () => {\n contentFilesListCache ??= globSync(\n contentRootDirs.map((dir) => `${dir}/**/*.md`),\n { dot: true },\n );\n\n return contentFilesListCache;\n };\n const resolveContentModulePath = (module: string) =>\n vite.normalizePath(\n module.startsWith('/') ? module : `${workspaceRoot}/${module}`,\n );\n const getContentModuleKey = (module: string) => {\n const absolutePath = resolveContentModulePath(module);\n const relativeToRoot = vite.normalizePath(relative(root, absolutePath));\n // `startsWith(root)` is not safe here because sibling directories such as\n // `/apps/my-app-tools` also start with `/apps/my-app`. A relative path only\n // represents in-app content when it stays within `root`.\n const isInApp =\n !relativeToRoot.startsWith('..') && !relativeToRoot.startsWith('/');\n\n // Both branches prepend `/` so generated keys are always absolute-\n // looking (`/src/content/...` for in-app, `/libs/shared/...` for\n // workspace-external). Downstream consumers like content-files-token\n // rely on the leading `/` for slug extraction regexes.\n return isInApp\n ? `/${relativeToRoot}`\n : `/${vite.normalizePath(relative(workspaceRoot, absolutePath))}`;\n };\n\n const contentDiscoveryPlugins: vite.Plugin[] = [\n {\n name: 'analog-content-glob-routes',\n config(_config) {\n config = _config;\n root = vite.normalizePath(\n resolve(workspaceRoot, config.root || '.') || '.',\n );\n initContentRootDirs();\n },\n // Vite 8 / Rolldown \"filtered transform\" — the `filter.code` string\n // tells the bundler to skip this handler entirely for modules whose\n // source does not contain the substring, avoiding unnecessary JS→Rust\n // round-trips. The inner `code.includes()` guard is kept for Vite 7\n // compat where filters are not evaluated by the bundler.\n transform: {\n filter: {\n code: 'ANALOG_CONTENT_FILE_LIST',\n },\n handler(code) {\n if (code.includes('ANALOG_CONTENT_FILE_LIST')) {\n const contentFilesList = discoverContentFilesList();\n\n const eagerImports: string[] = [];\n\n contentFilesList.forEach((module, index) => {\n // CRITICAL: tinyglobby returns relative paths like \"apps/blog-app/src/content/file.md\"\n // These MUST be converted to absolute paths for ES module imports\n // Otherwise Node.js treats \"apps\" as a package name and throws \"Cannot find package 'apps'\"\n const absolutePath = resolveContentModulePath(module);\n eagerImports.push(\n `import { default as analog_module_${index} } from \"${absolutePath}?analog-content-list=true\";`,\n );\n });\n\n // Match just the assignment (not the declaration) so the rewrite\n // works whether the source uses `const`, `let`, `var`, or\n // `export const` — including the post-Rolldown `var X = {};`\n // form — without destroying the declaration that keeps the\n // module binding exported.\n let result = code.replace(\n /ANALOG_CONTENT_FILE_LIST\\s*=\\s*\\{\\s*\\}/,\n `ANALOG_CONTENT_FILE_LIST = {${contentFilesList.map(\n (module, index) =>\n `\"${getContentModuleKey(module)}\": analog_module_${index}`,\n )}}`,\n );\n\n if (!code.includes('analog_module_')) {\n result = `${eagerImports.join('\\n')}\\n${result}`;\n }\n\n return {\n code: result,\n map: { mappings: '' },\n };\n }\n\n return;\n },\n },\n },\n {\n name: 'analogjs-invalidate-content-dirs',\n configureServer(server) {\n function invalidateContent(path: string) {\n const normalizedPath = vite.normalizePath(path);\n const isContentPath = contentRootDirs.some(\n (dir) =>\n normalizedPath === dir || normalizedPath.startsWith(`${dir}/`),\n );\n\n if (isContentPath) {\n // The file set only changes on add/remove because this watcher is\n // intentionally scoped to those events. Clear the list cache so the\n // next transform sees the updated directory contents.\n contentFilesListCache = undefined;\n server.moduleGraph.fileToModulesMap.forEach((mods) => {\n mods.forEach((mod) => {\n if (\n mod.id?.includes('analogjs') &&\n mod.id?.includes('content')\n ) {\n server.moduleGraph.invalidateModule(mod);\n\n mod.importers.forEach((imp) => {\n server.moduleGraph.invalidateModule(imp);\n });\n }\n });\n });\n\n server.ws.send('analog:debug-full-reload', {\n plugin: 'platform:content-plugin',\n reason: 'content-file-set-changed',\n path: normalizedPath,\n });\n server.ws.send({\n type: 'full-reload',\n });\n }\n }\n\n server.watcher.on('add', invalidateContent);\n server.watcher.on('unlink', invalidateContent);\n },\n },\n ];\n\n if (!highlighter) {\n return [\n {\n name: 'analogjs-external-content',\n config() {\n const bundleOptionsKey = getBundleOptionsKey();\n return {\n build: {\n [bundleOptionsKey]: {\n external: ['@analogjs/content'],\n },\n },\n };\n },\n },\n {\n name: 'analogjs-exclude-content-import',\n transform: {\n filter: {\n code: '@analogjs/content',\n },\n handler(code) {\n /**\n * Remove the package so it doesn't get\n * referenced when building for serverless\n * functions.\n */\n if (code.includes(`import('@analogjs/content')`)) {\n return {\n code: code.replace(\n `import('@analogjs/content')`,\n 'Promise.resolve({})',\n ),\n };\n }\n\n return;\n },\n },\n },\n ...contentDiscoveryPlugins,\n ];\n }\n\n return [\n {\n name: 'analogjs-content-frontmatter',\n // Filter by module ID so only `?analog-content-list=true` virtual\n // imports enter the handler. Returns `moduleSideEffects: false` so\n // Rolldown can tree-shake unused content list entries.\n transform: {\n filter: {\n id: /analog-content-list=true/,\n },\n async handler(code, id) {\n const cachedContent = cache.get(id);\n // There's no reason to run `readFileSync` and frontmatter parsing if the\n // `transform` hook is called with the same code. In such cases, we can simply\n // return the cached attributes, which is faster than repeatedly reading files\n // synchronously during the build process.\n if (cachedContent?.code === code) {\n return {\n code: `export default ${cachedContent.attributes}`,\n moduleSideEffects: false,\n };\n }\n\n const fm: any = await import('front-matter');\n // The `default` property will be available in CommonJS environment, for instance,\n // when running unit tests. It's safe to retrieve `default` first, since we still\n // fallback to the original implementation.\n const frontmatter = fm.default || fm;\n const fileContents = readFileSync(id.split('?')[0], 'utf8');\n const { attributes } = frontmatter(fileContents);\n const content = {\n code,\n attributes: JSON.stringify(attributes),\n };\n cache.set(id, content);\n\n return {\n code: `export default ${content.attributes}`,\n moduleSideEffects: false,\n };\n },\n },\n },\n {\n name: 'analogjs-content-file',\n enforce: 'post',\n async load(id) {\n if (!id.includes('analog-content-file=true')) {\n return;\n }\n\n if (!markedHighlighter) {\n if (highlighter === 'shiki') {\n const { getShikiHighlighter } =\n await import('./content/shiki/index.js');\n markedHighlighter = getShikiHighlighter(shikiOptions);\n } else {\n const { getPrismHighlighter } =\n await import('./content/prism/index.js');\n markedHighlighter = getPrismHighlighter();\n\n const langs = [\n 'bash',\n 'css',\n 'javascript',\n 'json',\n 'markup',\n 'typescript',\n ];\n\n if (\n Array.isArray(prismOptions?.additionalLangs) &&\n prismOptions?.additionalLangs?.length > 0\n ) {\n langs.push(...prismOptions.additionalLangs);\n }\n\n const loadLanguages = await import('prismjs/components/index.js');\n\n (\n loadLanguages as unknown as { default: (...args: any[]) => any }\n ).default(langs);\n }\n }\n\n const fm: any = await import('front-matter');\n // The `default` property will be available in CommonJS environment, for instance,\n // when running unit tests. It's safe to retrieve `default` first, since we still\n // fallback to the original implementation.\n const frontmatterFn = fm.default || fm;\n const fileContents = readFileSync(id.split('?')[0], 'utf8');\n const { body, frontmatter } = frontmatterFn(fileContents);\n\n // parse markdown and highlight\n const { getMarkedSetup } = await import('./content/marked/index.js');\n const markedSetupService = getMarkedSetup(\n { mangle: true, ...(markedOptions || {}) },\n markedHighlighter,\n );\n const mdContent = (await markedSetupService\n .getMarkedInstance()\n .parse(body)) as unknown as string;\n\n return `export default ${JSON.stringify(\n `---\\n${frontmatter}\\n---\\n\\n${mdContent}`,\n )}`;\n },\n },\n ...contentDiscoveryPlugins,\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkCA,SAAgB,cACd,EACE,aACA,eACA,cACA,iBACwB,CAAC,GAC3B,SACe;CACf,MAAM,wBAAQ,IAAI,IAAqB;CAGvC,IAAI;CAEJ,IAAI;CACJ,MAAM,gBAAgB,KAAK,cACzB,SAAS,iBAAiB,QAAQ,IAAI,wBAAwB,QAAQ,IAAI,CAC5E;CACA,IAAI;CACJ,IAAI;CAMJ,IAAI;CACJ,MAAM,uBAAuB,QAAgB;EAC3C,MAAM,aAAa,KAAK,cACtB,IAAI,WAAW,GAAG,IACd,GAAG,gBAAgB,QACnB,QAAQ,eAAe,GAAG,CAChC;EACA,OAAO,WAAW,SAAS,GAAG,IAAI,WAAW,MAAM,GAAG,EAAE,IAAI;CAC9D;CACA,MAAM,4BAA4B;EAChC,kBAAkB,CAChB,KAAK,cAAc,GAAG,KAAK,aAAa,GACxC,IAAI,SAAS,yBAAyB,CAAC,EAAA,CAAG,IAAI,mBAAmB,CACnE;CACF;CACA,MAAM,iCAAiC;EACrC,0BAA0B,SACxB,gBAAgB,KAAK,QAAQ,GAAG,IAAI,SAAS,GAC7C,EAAE,KAAK,KAAK,CACd;EAEA,OAAO;CACT;CACA,MAAM,4BAA4B,WAChC,KAAK,cACH,OAAO,WAAW,GAAG,IAAI,SAAS,GAAG,cAAc,GAAG,QACxD;CACF,MAAM,uBAAuB,WAAmB;EAC9C,MAAM,eAAe,yBAAyB,MAAM;EACpD,MAAM,iBAAiB,KAAK,cAAc,SAAS,MAAM,YAAY,CAAC;EAWtE,OANE,CAAC,eAAe,WAAW,IAAI,KAAK,CAAC,eAAe,WAAW,GAAG,IAOhE,IAAI,mBACJ,IAAI,KAAK,cAAc,SAAS,eAAe,YAAY,CAAC;CAClE;CAEA,MAAM,0BAAyC,CAC7C;EACE,MAAM;EACN,OAAO,SAAS;GACd,SAAS;GACT,OAAO,KAAK,cACV,QAAQ,eAAe,OAAO,QAAQ,GAAG,KAAK,GAChD;GACA,oBAAoB;EACtB;EAMA,WAAW;GACT,QAAQ,EACN,MAAM,2BACR;GACA,QAAQ,MAAM;IACZ,IAAI,KAAK,SAAS,0BAA0B,GAAG;KAC7C,MAAM,mBAAmB,yBAAyB;KAElD,MAAM,eAAyB,CAAC;KAEhC,iBAAiB,SAAS,QAAQ,UAAU;MAI1C,MAAM,eAAe,yBAAyB,MAAM;MACpD,aAAa,KACX,qCAAqC,MAAM,WAAW,aAAa,4BACrE;KACF,CAAC;KAOD,IAAI,SAAS,KAAK,QAChB,0CACA,+BAA+B,iBAAiB,KAC7C,QAAQ,UACP,IAAI,oBAAoB,MAAM,EAAE,mBAAmB,OACvD,EAAE,EACJ;KAEA,IAAI,CAAC,KAAK,SAAS,gBAAgB,GACjC,SAAS,GAAG,aAAa,KAAK,IAAI,EAAE,IAAI;KAG1C,OAAO;MACL,MAAM;MACN,KAAK,EAAE,UAAU,GAAG;KACtB;IACF;GAGF;EACF;CACF,GACA;EACE,MAAM;EACN,gBAAgB,QAAQ;GACtB,SAAS,kBAAkB,MAAc;IACvC,MAAM,iBAAiB,KAAK,cAAc,IAAI;IAM9C,IALsB,gBAAgB,MACnC,QACC,mBAAmB,OAAO,eAAe,WAAW,GAAG,IAAI,EAAE,CAG7D,GAAe;KAIjB,wBAAwB,KAAA;KACxB,OAAO,YAAY,iBAAiB,SAAS,SAAS;MACpD,KAAK,SAAS,QAAQ;OACpB,IACE,IAAI,IAAI,SAAS,UAAU,KAC3B,IAAI,IAAI,SAAS,SAAS,GAC1B;QACA,OAAO,YAAY,iBAAiB,GAAG;QAEvC,IAAI,UAAU,SAAS,QAAQ;SAC7B,OAAO,YAAY,iBAAiB,GAAG;QACzC,CAAC;OACH;MACF,CAAC;KACH,CAAC;KAED,OAAO,GAAG,KAAK,4BAA4B;MACzC,QAAQ;MACR,QAAQ;MACR,MAAM;KACR,CAAC;KACD,OAAO,GAAG,KAAK,EACb,MAAM,cACR,CAAC;IACH;GACF;GAEA,OAAO,QAAQ,GAAG,OAAO,iBAAiB;GAC1C,OAAO,QAAQ,GAAG,UAAU,iBAAiB;EAC/C;CACF,CACF;CAEA,IAAI,CAAC,aACH,OAAO;EACL;GACE,MAAM;GACN,SAAS;IAEP,OAAO,EACL,OAAO,GAFgB,oBAGpB,IAAmB,EAClB,UAAU,CAAC,mBAAmB,EAChC,EACF,EACF;GACF;EACF;EACA;GACE,MAAM;GACN,WAAW;IACT,QAAQ,EACN,MAAM,oBACR;IACA,QAAQ,MAAM;;;;;;KAMZ,IAAI,KAAK,SAAS,6BAA6B,GAC7C,OAAO,EACL,MAAM,KAAK,QACT,+BACA,qBACF,EACF;IAIJ;GACF;EACF;EACA,GAAG;CACL;CAGF,OAAO;EACL;GACE,MAAM;GAIN,WAAW;IACT,QAAQ,EACN,IAAI,2BACN;IACA,MAAM,QAAQ,MAAM,IAAI;KACtB,MAAM,gBAAgB,MAAM,IAAI,EAAE;KAKlC,IAAI,eAAe,SAAS,MAC1B,OAAO;MACL,MAAM,kBAAkB,cAAc;MACtC,mBAAmB;KACrB;KAGF,MAAM,KAAU,MAAM,OAAO;KAM7B,MAAM,EAAE,gBAFY,GAAG,WAAW,GAAA,CACb,aAAa,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,MACjB,CAAY;KAC/C,MAAM,UAAU;MACd;MACA,YAAY,KAAK,UAAU,UAAU;KACvC;KACA,MAAM,IAAI,IAAI,OAAO;KAErB,OAAO;MACL,MAAM,kBAAkB,QAAQ;MAChC,mBAAmB;KACrB;IACF;GACF;EACF;EACA;GACE,MAAM;GACN,SAAS;GACT,MAAM,KAAK,IAAI;IACb,IAAI,CAAC,GAAG,SAAS,0BAA0B,GACzC;IAGF,IAAI,CAAC,mBAAmB;KACtB,IAAI,gBAAgB,SAAS;MAC3B,MAAM,EAAE,wBACN,MAAM,OAAO;MACf,oBAAoB,oBAAoB,YAAY;KACtD,OAAO;MACL,MAAM,EAAE,wBACN,MAAM,OAAO;MACf,oBAAoB,oBAAoB;MAExC,MAAM,QAAQ;OACZ;OACA;OACA;OACA;OACA;OACA;MACF;MAEA,IACE,MAAM,QAAQ,cAAc,eAAe,KAC3C,cAAc,iBAAiB,SAAS,GAExC,MAAM,KAAK,GAAG,aAAa,eAAe;MAK5C,CAAA,MAF4B,OAAO,+BAAA,CAIjC,QAAQ,KAAK;KACjB;IACF;IAEA,MAAM,KAAU,MAAM,OAAO;IAM7B,MAAM,EAAE,MAAM,iBAFQ,GAAG,WAAW,GAAA,CACf,aAAa,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,MACR,CAAY;IAGxD,MAAM,EAAE,mBAAmB,MAAM,OAAO;IAKxC,MAAM,YAAa,MAJQ,eACzB;KAAE,QAAQ;KAAM,GAAI,iBAAiB,CAAC;IAAG,GACzC,iBAEuB,CAAA,CACtB,kBAAkB,CAAC,CACnB,MAAM,IAAI;IAEb,OAAO,kBAAkB,KAAK,UAC5B,QAAQ,YAAY,WAAW,WACjC;GACF;EACF;EACA,GAAG;CACL;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"deps-plugin.js","names":[],"sources":["../../../src/lib/deps-plugin.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { crawlFrameworkPkgs } from 'vitefu';\n\nimport { angularLinkerPlugin } from './nitro/angular-linker-plugin.js';\nimport { Options } from './options.js';\nimport { debugPlatform } from './utils/debug.js';\nimport { getJsTransformConfigKey, isRolldown } from './utils/rolldown.js';\n\nconst ANGULAR_LINKED_SSR_DEPS = [\n '@angular/compiler',\n '@angular/core',\n '@angular/platform-browser',\n '@angular/platform-server',\n];\n\nexport function depsPlugin(options?: Options): Plugin[] {\n const workspaceRoot =\n options?.workspaceRoot ?? process.env['NX_WORKSPACE_ROOT'] ?? process.cwd();\n\n return [\n {\n name: 'analogjs-deps-plugin',\n config() {\n // Skip Vite's built-in ts/js transform so `@analogjs/vite-plugin-angular`\n // (when the user includes it) owns Angular file compilation. Users who\n // run an alternative compiler or compile through Angular's own\n // compilation API can override this in their own Vite config.\n const transformConfig = { exclude: ['**/*.ts', '**/*.js'] };\n debugPlatform('deps transform config', {\n jsTransformKey: getJsTransformConfigKey(),\n transformExcluded: true,\n });\n\n return {\n [getJsTransformConfigKey()]: transformConfig,\n ssr: {\n noExternal: [\n '@analogjs/**',\n 'es-toolkit',\n 'firebase/**',\n 'firebase-admin/**',\n 'rxfire',\n '@ng-web-apis/**',\n '@taiga-ui/**',\n '@tanstack/angular-query-experimental',\n ],\n // The server pre-bundle is resolved separately from the client\n // one, so a secondary entry point left out of it loads its own\n // copy of `@angular/core`. `inject()` then runs against a runtime\n // with no active injection context and SSR fails with NG0203.\n // With Rolldown, the rest of Angular is pre-bundled too and the\n // partial-compilation packages are linked, so the server needs no JIT.\n optimizeDeps: {\n include: [\n ...(isRolldown() ? ANGULAR_LINKED_SSR_DEPS : []),\n '@angular/common',\n '@angular/common/http',\n '@angular/core/rxjs-interop',\n ],\n ...(isRolldown()\n ? { rolldownOptions: { plugins: [angularLinkerPlugin()] } }\n : {}),\n },\n },\n optimizeDeps: {\n include: [\n '@angular/common',\n '@angular/common/http',\n '@angular/core/rxjs-interop',\n 'front-matter',\n ],\n exclude: [\n '@angular/platform-server',\n '@analogjs/content',\n '@analogjs/router',\n '@nx/angular',\n '@nx/vite',\n '@nx/devkit',\n '@nx/js',\n '@nx/devkit',\n '@nx/cypress',\n '@nx/jest',\n '@nx/js',\n '@nx/eslint',\n '@nx/webpack',\n '@nx/web',\n '@nx/workspace',\n '@nx/eslint',\n '@nx/module-federation',\n '@nx/rspack',\n 'webpack',\n 'fsevents',\n 'nx',\n ],\n },\n };\n },\n },\n {\n name: 'analogjs-auto-discover-deps',\n async config(config, { command }) {\n const pkgConfig = await crawlFrameworkPkgs({\n root: workspaceRoot,\n isBuild: command === 'build',\n viteUserConfig: config,\n isSemiFrameworkPkgByJson(pkgJson) {\n return pkgJson['module'] && pkgJson['module'].includes('fesm');\n },\n });\n return pkgConfig;\n },\n },\n ];\n}\n"],"mappings":";;;;;AAQA,IAAM,0BAA0B;CAC9B;CACA;CACA;CACA;CACD;AAED,SAAgB,WAAW,SAA6B;CACtD,MAAM,gBACJ,SAAS,iBAAiB,QAAQ,IAAI,wBAAwB,QAAQ,KAAK;AAE7E,QAAO,CACL;EACE,MAAM;EACN,SAAS;GAKP,MAAM,kBAAkB,EAAE,SAAS,CAAC,WAAW,UAAU,EAAE;AAC3D,iBAAc,yBAAyB;IACrC,gBAAgB,yBAAyB;IACzC,mBAAmB;IACpB,CAAC;AAEF,UAAO;KACJ,yBAAyB,GAAG;IAC7B,KAAK;KACH,YAAY;MACV;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACD;KAOD,cAAc;MACZ,SAAS;OACP,GAAI,YAAY,GAAG,0BAA0B,EAAE;OAC/C;OACA;OACA;OACD;MACD,GAAI,YAAY,GACZ,EAAE,iBAAiB,EAAE,SAAS,CAAC,qBAAqB,CAAC,EAAE,EAAE,GACzD,EAAE;MACP;KACF;IACD,cAAc;KACZ,SAAS;MACP;MACA;MACA;MACA;MACD;KACD,SAAS;MACP;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACD;KACF;IACF;;EAEJ,EACD;EACE,MAAM;EACN,MAAM,OAAO,QAAQ,EAAE,WAAW;AAShC,UARkB,MAAM,mBAAmB;IACzC,MAAM;IACN,SAAS,YAAY;IACrB,gBAAgB;IAChB,yBAAyB,SAAS;AAChC,YAAO,QAAQ,aAAa,QAAQ,UAAU,SAAS,OAAO;;IAEjE,CAAC;;EAGL,CACF"}
1
+ {"version":3,"file":"deps-plugin.js","names":[],"sources":["../../../src/lib/deps-plugin.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { crawlFrameworkPkgs } from 'vitefu';\n\nimport { angularLinkerPlugin } from './nitro/angular-linker-plugin.js';\nimport { Options } from './options.js';\nimport { debugPlatform } from './utils/debug.js';\nimport { getJsTransformConfigKey, isRolldown } from './utils/rolldown.js';\n\nconst ANGULAR_LINKED_SSR_DEPS = [\n '@angular/compiler',\n '@angular/core',\n '@angular/platform-browser',\n '@angular/platform-server',\n];\n\nexport function depsPlugin(options?: Options): Plugin[] {\n const workspaceRoot =\n options?.workspaceRoot ?? process.env['NX_WORKSPACE_ROOT'] ?? process.cwd();\n\n return [\n {\n name: 'analogjs-deps-plugin',\n config() {\n // Skip Vite's built-in ts/js transform so `@analogjs/vite-plugin-angular`\n // (when the user includes it) owns Angular file compilation. Users who\n // run an alternative compiler or compile through Angular's own\n // compilation API can override this in their own Vite config.\n const transformConfig = { exclude: ['**/*.ts', '**/*.js'] };\n debugPlatform('deps transform config', {\n jsTransformKey: getJsTransformConfigKey(),\n transformExcluded: true,\n });\n\n return {\n [getJsTransformConfigKey()]: transformConfig,\n ssr: {\n noExternal: [\n '@analogjs/**',\n 'es-toolkit',\n 'firebase/**',\n 'firebase-admin/**',\n 'rxfire',\n '@ng-web-apis/**',\n '@taiga-ui/**',\n '@tanstack/angular-query-experimental',\n ],\n // The server pre-bundle is resolved separately from the client\n // one, so a secondary entry point left out of it loads its own\n // copy of `@angular/core`. `inject()` then runs against a runtime\n // with no active injection context and SSR fails with NG0203.\n // With Rolldown, the rest of Angular is pre-bundled too and the\n // partial-compilation packages are linked, so the server needs no JIT.\n optimizeDeps: {\n include: [\n ...(isRolldown() ? ANGULAR_LINKED_SSR_DEPS : []),\n '@angular/common',\n '@angular/common/http',\n '@angular/core/rxjs-interop',\n ],\n ...(isRolldown()\n ? { rolldownOptions: { plugins: [angularLinkerPlugin()] } }\n : {}),\n },\n },\n optimizeDeps: {\n include: [\n '@angular/common',\n '@angular/common/http',\n '@angular/core/rxjs-interop',\n 'front-matter',\n ],\n exclude: [\n '@angular/platform-server',\n '@analogjs/content',\n '@analogjs/router',\n '@nx/angular',\n '@nx/vite',\n '@nx/devkit',\n '@nx/js',\n '@nx/devkit',\n '@nx/cypress',\n '@nx/jest',\n '@nx/js',\n '@nx/eslint',\n '@nx/webpack',\n '@nx/web',\n '@nx/workspace',\n '@nx/eslint',\n '@nx/module-federation',\n '@nx/rspack',\n 'webpack',\n 'fsevents',\n 'nx',\n ],\n },\n };\n },\n },\n {\n name: 'analogjs-auto-discover-deps',\n async config(config, { command }) {\n const pkgConfig = await crawlFrameworkPkgs({\n root: workspaceRoot,\n isBuild: command === 'build',\n viteUserConfig: config,\n isSemiFrameworkPkgByJson(pkgJson) {\n return pkgJson['module'] && pkgJson['module'].includes('fesm');\n },\n });\n return pkgConfig;\n },\n },\n ];\n}\n"],"mappings":";;;;;AAQA,IAAM,0BAA0B;CAC9B;CACA;CACA;CACA;AACF;AAEA,SAAgB,WAAW,SAA6B;CACtD,MAAM,gBACJ,SAAS,iBAAiB,QAAQ,IAAI,wBAAwB,QAAQ,IAAI;CAE5E,OAAO,CACL;EACE,MAAM;EACN,SAAS;GAKP,MAAM,kBAAkB,EAAE,SAAS,CAAC,WAAW,SAAS,EAAE;GAC1D,cAAc,yBAAyB;IACrC,gBAAgB,wBAAwB;IACxC,mBAAmB;GACrB,CAAC;GAED,OAAO;KACJ,wBAAwB,IAAI;IAC7B,KAAK;KACH,YAAY;MACV;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;KAOA,cAAc;MACZ,SAAS;OACP,GAAI,WAAW,IAAI,0BAA0B,CAAC;OAC9C;OACA;OACA;MACF;MACA,GAAI,WAAW,IACX,EAAE,iBAAiB,EAAE,SAAS,CAAC,oBAAoB,CAAC,EAAE,EAAE,IACxD,CAAC;KACP;IACF;IACA,cAAc;KACZ,SAAS;MACP;MACA;MACA;MACA;KACF;KACA,SAAS;MACP;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACF;IACF;GACF;EACF;CACF,GACA;EACE,MAAM;EACN,MAAM,OAAO,QAAQ,EAAE,WAAW;GAShC,OAAO,MARiB,mBAAmB;IACzC,MAAM;IACN,SAAS,YAAY;IACrB,gBAAgB;IAChB,yBAAyB,SAAS;KAChC,OAAO,QAAQ,aAAa,QAAQ,SAAS,CAAC,SAAS,MAAM;IAC/D;GACF,CAAC;EAEH;CACF,CACF;AACF"}