@dualmark/astro 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +88 -0
  3. package/dist/endpoints/collection.cjs +24 -0
  4. package/dist/endpoints/collection.cjs.map +1 -0
  5. package/dist/endpoints/collection.d.cts +27 -0
  6. package/dist/endpoints/collection.d.ts +27 -0
  7. package/dist/endpoints/collection.js +22 -0
  8. package/dist/endpoints/collection.js.map +1 -0
  9. package/dist/endpoints/listing.cjs +34 -0
  10. package/dist/endpoints/listing.cjs.map +1 -0
  11. package/dist/endpoints/listing.d.cts +20 -0
  12. package/dist/endpoints/listing.d.ts +20 -0
  13. package/dist/endpoints/listing.js +32 -0
  14. package/dist/endpoints/listing.js.map +1 -0
  15. package/dist/endpoints/llms-txt.cjs +23 -0
  16. package/dist/endpoints/llms-txt.cjs.map +1 -0
  17. package/dist/endpoints/llms-txt.d.cts +12 -0
  18. package/dist/endpoints/llms-txt.d.ts +12 -0
  19. package/dist/endpoints/llms-txt.js +21 -0
  20. package/dist/endpoints/llms-txt.js.map +1 -0
  21. package/dist/endpoints/parameterized.cjs +18 -0
  22. package/dist/endpoints/parameterized.cjs.map +1 -0
  23. package/dist/endpoints/parameterized.d.cts +25 -0
  24. package/dist/endpoints/parameterized.d.ts +25 -0
  25. package/dist/endpoints/parameterized.js +16 -0
  26. package/dist/endpoints/parameterized.js.map +1 -0
  27. package/dist/endpoints/static.cjs +17 -0
  28. package/dist/endpoints/static.cjs.map +1 -0
  29. package/dist/endpoints/static.d.cts +11 -0
  30. package/dist/endpoints/static.d.ts +11 -0
  31. package/dist/endpoints/static.js +15 -0
  32. package/dist/endpoints/static.js.map +1 -0
  33. package/dist/index.cjs +316 -0
  34. package/dist/index.cjs.map +1 -0
  35. package/dist/index.d.cts +54 -0
  36. package/dist/index.d.ts +54 -0
  37. package/dist/index.js +307 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/middleware.cjs +22 -0
  40. package/dist/middleware.cjs.map +1 -0
  41. package/dist/middleware.d.cts +9 -0
  42. package/dist/middleware.d.ts +9 -0
  43. package/dist/middleware.js +19 -0
  44. package/dist/middleware.js.map +1 -0
  45. package/dist/types-BPk2cf2p.d.cts +64 -0
  46. package/dist/types-BPk2cf2p.d.ts +64 -0
  47. package/dist/virtual.cjs +10 -0
  48. package/dist/virtual.cjs.map +1 -0
  49. package/dist/virtual.d.cts +7 -0
  50. package/dist/virtual.d.ts +7 -0
  51. package/dist/virtual.js +8 -0
  52. package/dist/virtual.js.map +1 -0
  53. package/package.json +102 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dodo Payments
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # @dualmark/astro
2
+
3
+ Astro integration for the Dualmark AEO framework.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun add @dualmark/astro @dualmark/core @dualmark/converters
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ // astro.config.mjs
15
+ import { defineConfig } from "astro/config";
16
+ import dualmark from "@dualmark/astro";
17
+
18
+ export default defineConfig({
19
+ site: "https://example.com",
20
+ integrations: [
21
+ dualmark({
22
+ siteUrl: "https://example.com",
23
+
24
+ collections: {
25
+ blog: {
26
+ converter: "blog",
27
+ route: "blog",
28
+ slugStrategy: "catch-all",
29
+ },
30
+ glossary: {
31
+ converter: "glossary",
32
+ slugStrategy: "single",
33
+ },
34
+ },
35
+
36
+ staticPages: [
37
+ { pattern: "/", render: () => "# Home\n\nWelcome to Acme." },
38
+ { pattern: "/about", render: () => "# About\n\nAcme builds widgets." },
39
+ ],
40
+
41
+ parameterizedRoutes: [
42
+ {
43
+ pattern: "/blog/category/[category]",
44
+ getStaticPaths: async () => [{ params: { category: "engineering" } }],
45
+ render: ({ params }) => `# ${params.category} posts`,
46
+ },
47
+ ],
48
+
49
+ llmsTxt: {
50
+ enabled: true,
51
+ brandName: "Acme",
52
+ description: "Widgets for everyone.",
53
+ sections: [
54
+ {
55
+ title: "Products",
56
+ links: [{ title: "Widget", href: "https://example.com/widget" }],
57
+ },
58
+ ],
59
+ },
60
+
61
+ middleware: { injectLinkHeader: true },
62
+ }),
63
+ ],
64
+ });
65
+ ```
66
+
67
+ ## What it does
68
+
69
+ - Generates `.md` endpoints for every configured collection (`/blog/[...slug].md`, `/blog.md`)
70
+ - Generates `.md` endpoints for every configured static page (`/index.md`, `/about.md`)
71
+ - Generates `.md` endpoints for every parameterized route (`/blog/category/[category].md`)
72
+ - Generates `/llms.txt` from config
73
+ - Injects an Astro middleware that adds `Link rel="alternate" type="text/markdown"` to every HTML response
74
+ - Validates config (throws `DualmarkConfigError` with helpful messages on misconfiguration)
75
+
76
+ ## Built-in converter names
77
+
78
+ `blog`, `case-study`, `changelog`, `compare`, `docs`, `feature`, `glossary`, `legal`, `pricing`, `pseo`, `tool`, `video`
79
+
80
+ Pass any string from this list as `converter`, or pass a function (currently not serializable into generated routes — coming in v0.2).
81
+
82
+ ## Where the generated files live
83
+
84
+ `node_modules/.dualmark-generated/` — regenerated on every Astro build. You don't need to commit anything.
85
+
86
+ ## License
87
+
88
+ MIT
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ var core = require('@dualmark/core');
4
+
5
+ // src/endpoints/collection.ts
6
+ function makeCollectionDetailEndpoint(args) {
7
+ return {
8
+ async getStaticPaths() {
9
+ const entries = await args.getCollection(args.collectionName, args.filter);
10
+ return entries.map((entry) => ({
11
+ params: { slug: entry.id },
12
+ props: { entry }
13
+ }));
14
+ },
15
+ GET(ctx) {
16
+ const md = args.converter(ctx.props.entry);
17
+ return core.markdownResponse(md, args.responseOptions);
18
+ }
19
+ };
20
+ }
21
+
22
+ exports.makeCollectionDetailEndpoint = makeCollectionDetailEndpoint;
23
+ //# sourceMappingURL=collection.cjs.map
24
+ //# sourceMappingURL=collection.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/collection.ts"],"names":["markdownResponse"],"mappings":";;;;;AAcO,SAAS,6BACd,IAAA,EAIA;AACA,EAAA,OAAO;AAAA,IACL,MAAM,cAAA,GAAiB;AACrB,MAAA,MAAM,UAAU,MAAM,IAAA,CAAK,cAAc,IAAA,CAAK,cAAA,EAAgB,KAAK,MAAM,CAAA;AACzE,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,QAC7B,MAAA,EAAQ,EAAE,IAAA,EAAM,KAAA,CAAM,EAAA,EAAG;AAAA,QACzB,KAAA,EAAO,EAAE,KAAA;AAAM,OACjB,CAAE,CAAA;AAAA,IACJ,CAAA;AAAA,IACA,IAAI,GAAA,EAAK;AACP,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,MAAM,KAAK,CAAA;AACzC,MAAA,OAAOA,qBAAA,CAAiB,EAAA,EAAI,IAAA,CAAK,eAAe,CAAA;AAAA,IAClD;AAAA,GACF;AACF","file":"collection.cjs","sourcesContent":["import { markdownResponse, type MarkdownResponseOptions } from \"@dualmark/core\";\nimport type { Converter, CollectionEntry } from \"@dualmark/converters\";\n\nexport interface CollectionEndpointArgs<TEntry extends CollectionEntry<unknown>> {\n collectionName: string;\n converter: Converter<TEntry>;\n getCollection: (\n name: string,\n filter?: (entry: TEntry) => boolean,\n ) => Promise<TEntry[]>;\n filter?: (entry: TEntry) => boolean;\n responseOptions?: MarkdownResponseOptions;\n}\n\nexport function makeCollectionDetailEndpoint<TEntry extends CollectionEntry<unknown>>(\n args: CollectionEndpointArgs<TEntry>,\n): {\n getStaticPaths: () => Promise<Array<{ params: { slug: string }; props: { entry: TEntry } }>>;\n GET: (ctx: { props: { entry: TEntry } }) => Response;\n} {\n return {\n async getStaticPaths() {\n const entries = await args.getCollection(args.collectionName, args.filter);\n return entries.map((entry) => ({\n params: { slug: entry.id },\n props: { entry },\n }));\n },\n GET(ctx) {\n const md = args.converter(ctx.props.entry);\n return markdownResponse(md, args.responseOptions);\n },\n };\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import { MarkdownResponseOptions } from '@dualmark/core';
2
+ import { CollectionEntry, Converter } from '@dualmark/converters';
3
+
4
+ interface CollectionEndpointArgs<TEntry extends CollectionEntry<unknown>> {
5
+ collectionName: string;
6
+ converter: Converter<TEntry>;
7
+ getCollection: (name: string, filter?: (entry: TEntry) => boolean) => Promise<TEntry[]>;
8
+ filter?: (entry: TEntry) => boolean;
9
+ responseOptions?: MarkdownResponseOptions;
10
+ }
11
+ declare function makeCollectionDetailEndpoint<TEntry extends CollectionEntry<unknown>>(args: CollectionEndpointArgs<TEntry>): {
12
+ getStaticPaths: () => Promise<Array<{
13
+ params: {
14
+ slug: string;
15
+ };
16
+ props: {
17
+ entry: TEntry;
18
+ };
19
+ }>>;
20
+ GET: (ctx: {
21
+ props: {
22
+ entry: TEntry;
23
+ };
24
+ }) => Response;
25
+ };
26
+
27
+ export { type CollectionEndpointArgs, makeCollectionDetailEndpoint };
@@ -0,0 +1,27 @@
1
+ import { MarkdownResponseOptions } from '@dualmark/core';
2
+ import { CollectionEntry, Converter } from '@dualmark/converters';
3
+
4
+ interface CollectionEndpointArgs<TEntry extends CollectionEntry<unknown>> {
5
+ collectionName: string;
6
+ converter: Converter<TEntry>;
7
+ getCollection: (name: string, filter?: (entry: TEntry) => boolean) => Promise<TEntry[]>;
8
+ filter?: (entry: TEntry) => boolean;
9
+ responseOptions?: MarkdownResponseOptions;
10
+ }
11
+ declare function makeCollectionDetailEndpoint<TEntry extends CollectionEntry<unknown>>(args: CollectionEndpointArgs<TEntry>): {
12
+ getStaticPaths: () => Promise<Array<{
13
+ params: {
14
+ slug: string;
15
+ };
16
+ props: {
17
+ entry: TEntry;
18
+ };
19
+ }>>;
20
+ GET: (ctx: {
21
+ props: {
22
+ entry: TEntry;
23
+ };
24
+ }) => Response;
25
+ };
26
+
27
+ export { type CollectionEndpointArgs, makeCollectionDetailEndpoint };
@@ -0,0 +1,22 @@
1
+ import { markdownResponse } from '@dualmark/core';
2
+
3
+ // src/endpoints/collection.ts
4
+ function makeCollectionDetailEndpoint(args) {
5
+ return {
6
+ async getStaticPaths() {
7
+ const entries = await args.getCollection(args.collectionName, args.filter);
8
+ return entries.map((entry) => ({
9
+ params: { slug: entry.id },
10
+ props: { entry }
11
+ }));
12
+ },
13
+ GET(ctx) {
14
+ const md = args.converter(ctx.props.entry);
15
+ return markdownResponse(md, args.responseOptions);
16
+ }
17
+ };
18
+ }
19
+
20
+ export { makeCollectionDetailEndpoint };
21
+ //# sourceMappingURL=collection.js.map
22
+ //# sourceMappingURL=collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/collection.ts"],"names":[],"mappings":";;;AAcO,SAAS,6BACd,IAAA,EAIA;AACA,EAAA,OAAO;AAAA,IACL,MAAM,cAAA,GAAiB;AACrB,MAAA,MAAM,UAAU,MAAM,IAAA,CAAK,cAAc,IAAA,CAAK,cAAA,EAAgB,KAAK,MAAM,CAAA;AACzE,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,QAC7B,MAAA,EAAQ,EAAE,IAAA,EAAM,KAAA,CAAM,EAAA,EAAG;AAAA,QACzB,KAAA,EAAO,EAAE,KAAA;AAAM,OACjB,CAAE,CAAA;AAAA,IACJ,CAAA;AAAA,IACA,IAAI,GAAA,EAAK;AACP,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,MAAM,KAAK,CAAA;AACzC,MAAA,OAAO,gBAAA,CAAiB,EAAA,EAAI,IAAA,CAAK,eAAe,CAAA;AAAA,IAClD;AAAA,GACF;AACF","file":"collection.js","sourcesContent":["import { markdownResponse, type MarkdownResponseOptions } from \"@dualmark/core\";\nimport type { Converter, CollectionEntry } from \"@dualmark/converters\";\n\nexport interface CollectionEndpointArgs<TEntry extends CollectionEntry<unknown>> {\n collectionName: string;\n converter: Converter<TEntry>;\n getCollection: (\n name: string,\n filter?: (entry: TEntry) => boolean,\n ) => Promise<TEntry[]>;\n filter?: (entry: TEntry) => boolean;\n responseOptions?: MarkdownResponseOptions;\n}\n\nexport function makeCollectionDetailEndpoint<TEntry extends CollectionEntry<unknown>>(\n args: CollectionEndpointArgs<TEntry>,\n): {\n getStaticPaths: () => Promise<Array<{ params: { slug: string }; props: { entry: TEntry } }>>;\n GET: (ctx: { props: { entry: TEntry } }) => Response;\n} {\n return {\n async getStaticPaths() {\n const entries = await args.getCollection(args.collectionName, args.filter);\n return entries.map((entry) => ({\n params: { slug: entry.id },\n props: { entry },\n }));\n },\n GET(ctx) {\n const md = args.converter(ctx.props.entry);\n return markdownResponse(md, args.responseOptions);\n },\n };\n}\n"]}
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ var core = require('@dualmark/core');
4
+
5
+ // src/endpoints/listing.ts
6
+ function makeListingEndpoint(args) {
7
+ return {
8
+ async GET() {
9
+ let entries = await args.getCollection(args.collectionName, args.filter);
10
+ if (args.sort) entries = [...entries].sort(args.sort);
11
+ const items = entries.map(
12
+ args.itemMapper ?? ((entry) => {
13
+ const data = entry.data;
14
+ return {
15
+ title: data.title ?? entry.id,
16
+ href: `${args.basePath}/${entry.id}`,
17
+ description: data.description
18
+ };
19
+ })
20
+ );
21
+ const md = core.listingToMarkdown({
22
+ title: args.title,
23
+ description: args.description,
24
+ url: `${args.siteUrl}${args.basePath}`,
25
+ items
26
+ });
27
+ return core.markdownResponse(md, args.responseOptions);
28
+ }
29
+ };
30
+ }
31
+
32
+ exports.makeListingEndpoint = makeListingEndpoint;
33
+ //# sourceMappingURL=listing.cjs.map
34
+ //# sourceMappingURL=listing.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/listing.ts"],"names":["listingToMarkdown","markdownResponse"],"mappings":";;;;;AAwBO,SAAS,oBACd,IAAA,EACkC;AAClC,EAAA,OAAO;AAAA,IACL,MAAM,GAAA,GAAM;AACV,MAAA,IAAI,UAAU,MAAM,IAAA,CAAK,cAAc,IAAA,CAAK,cAAA,EAAgB,KAAK,MAAM,CAAA;AACvE,MAAA,IAAI,IAAA,CAAK,MAAM,OAAA,GAAU,CAAC,GAAG,OAAO,CAAA,CAAE,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AACpD,MAAA,MAAM,QAAuB,OAAA,CAAQ,GAAA;AAAA,QACnC,IAAA,CAAK,UAAA,KACF,CAAC,KAAA,KAAU;AACV,UAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,UAAA,OAAO;AAAA,YACL,KAAA,EAAO,IAAA,CAAK,KAAA,IAAS,KAAA,CAAM,EAAA;AAAA,YAC3B,MAAM,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA,CAAA,EAAI,MAAM,EAAE,CAAA,CAAA;AAAA,YAClC,aAAa,IAAA,CAAK;AAAA,WACpB;AAAA,QACF,CAAA;AAAA,OACJ;AACA,MAAA,MAAM,KAAKA,sBAAA,CAAkB;AAAA,QAC3B,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,aAAa,IAAA,CAAK,WAAA;AAAA,QAClB,KAAK,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,EAAG,KAAK,QAAQ,CAAA,CAAA;AAAA,QACpC;AAAA,OACD,CAAA;AACD,MAAA,OAAOC,qBAAA,CAAiB,EAAA,EAAI,IAAA,CAAK,eAAe,CAAA;AAAA,IAClD;AAAA,GACF;AACF","file":"listing.cjs","sourcesContent":["import {\n markdownResponse,\n listingToMarkdown,\n type MarkdownResponseOptions,\n type ListingItem,\n} from \"@dualmark/core\";\nimport type { CollectionEntry } from \"@dualmark/converters\";\n\nexport interface ListingEndpointArgs<TEntry extends CollectionEntry<unknown>> {\n collectionName: string;\n siteUrl: string;\n basePath: string;\n title: string;\n description: string;\n getCollection: (\n name: string,\n filter?: (entry: TEntry) => boolean,\n ) => Promise<TEntry[]>;\n filter?: (entry: TEntry) => boolean;\n sort?: (a: TEntry, b: TEntry) => number;\n itemMapper?: (entry: TEntry) => ListingItem;\n responseOptions?: MarkdownResponseOptions;\n}\n\nexport function makeListingEndpoint<TEntry extends CollectionEntry<unknown>>(\n args: ListingEndpointArgs<TEntry>,\n): { GET: () => Promise<Response> } {\n return {\n async GET() {\n let entries = await args.getCollection(args.collectionName, args.filter);\n if (args.sort) entries = [...entries].sort(args.sort);\n const items: ListingItem[] = entries.map(\n args.itemMapper ??\n ((entry) => {\n const data = entry.data as { title?: string; description?: string };\n return {\n title: data.title ?? entry.id,\n href: `${args.basePath}/${entry.id}`,\n description: data.description,\n };\n }),\n );\n const md = listingToMarkdown({\n title: args.title,\n description: args.description,\n url: `${args.siteUrl}${args.basePath}`,\n items,\n });\n return markdownResponse(md, args.responseOptions);\n },\n };\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import { ListingItem, MarkdownResponseOptions } from '@dualmark/core';
2
+ import { CollectionEntry } from '@dualmark/converters';
3
+
4
+ interface ListingEndpointArgs<TEntry extends CollectionEntry<unknown>> {
5
+ collectionName: string;
6
+ siteUrl: string;
7
+ basePath: string;
8
+ title: string;
9
+ description: string;
10
+ getCollection: (name: string, filter?: (entry: TEntry) => boolean) => Promise<TEntry[]>;
11
+ filter?: (entry: TEntry) => boolean;
12
+ sort?: (a: TEntry, b: TEntry) => number;
13
+ itemMapper?: (entry: TEntry) => ListingItem;
14
+ responseOptions?: MarkdownResponseOptions;
15
+ }
16
+ declare function makeListingEndpoint<TEntry extends CollectionEntry<unknown>>(args: ListingEndpointArgs<TEntry>): {
17
+ GET: () => Promise<Response>;
18
+ };
19
+
20
+ export { type ListingEndpointArgs, makeListingEndpoint };
@@ -0,0 +1,20 @@
1
+ import { ListingItem, MarkdownResponseOptions } from '@dualmark/core';
2
+ import { CollectionEntry } from '@dualmark/converters';
3
+
4
+ interface ListingEndpointArgs<TEntry extends CollectionEntry<unknown>> {
5
+ collectionName: string;
6
+ siteUrl: string;
7
+ basePath: string;
8
+ title: string;
9
+ description: string;
10
+ getCollection: (name: string, filter?: (entry: TEntry) => boolean) => Promise<TEntry[]>;
11
+ filter?: (entry: TEntry) => boolean;
12
+ sort?: (a: TEntry, b: TEntry) => number;
13
+ itemMapper?: (entry: TEntry) => ListingItem;
14
+ responseOptions?: MarkdownResponseOptions;
15
+ }
16
+ declare function makeListingEndpoint<TEntry extends CollectionEntry<unknown>>(args: ListingEndpointArgs<TEntry>): {
17
+ GET: () => Promise<Response>;
18
+ };
19
+
20
+ export { type ListingEndpointArgs, makeListingEndpoint };
@@ -0,0 +1,32 @@
1
+ import { listingToMarkdown, markdownResponse } from '@dualmark/core';
2
+
3
+ // src/endpoints/listing.ts
4
+ function makeListingEndpoint(args) {
5
+ return {
6
+ async GET() {
7
+ let entries = await args.getCollection(args.collectionName, args.filter);
8
+ if (args.sort) entries = [...entries].sort(args.sort);
9
+ const items = entries.map(
10
+ args.itemMapper ?? ((entry) => {
11
+ const data = entry.data;
12
+ return {
13
+ title: data.title ?? entry.id,
14
+ href: `${args.basePath}/${entry.id}`,
15
+ description: data.description
16
+ };
17
+ })
18
+ );
19
+ const md = listingToMarkdown({
20
+ title: args.title,
21
+ description: args.description,
22
+ url: `${args.siteUrl}${args.basePath}`,
23
+ items
24
+ });
25
+ return markdownResponse(md, args.responseOptions);
26
+ }
27
+ };
28
+ }
29
+
30
+ export { makeListingEndpoint };
31
+ //# sourceMappingURL=listing.js.map
32
+ //# sourceMappingURL=listing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/listing.ts"],"names":[],"mappings":";;;AAwBO,SAAS,oBACd,IAAA,EACkC;AAClC,EAAA,OAAO;AAAA,IACL,MAAM,GAAA,GAAM;AACV,MAAA,IAAI,UAAU,MAAM,IAAA,CAAK,cAAc,IAAA,CAAK,cAAA,EAAgB,KAAK,MAAM,CAAA;AACvE,MAAA,IAAI,IAAA,CAAK,MAAM,OAAA,GAAU,CAAC,GAAG,OAAO,CAAA,CAAE,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AACpD,MAAA,MAAM,QAAuB,OAAA,CAAQ,GAAA;AAAA,QACnC,IAAA,CAAK,UAAA,KACF,CAAC,KAAA,KAAU;AACV,UAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,UAAA,OAAO;AAAA,YACL,KAAA,EAAO,IAAA,CAAK,KAAA,IAAS,KAAA,CAAM,EAAA;AAAA,YAC3B,MAAM,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA,CAAA,EAAI,MAAM,EAAE,CAAA,CAAA;AAAA,YAClC,aAAa,IAAA,CAAK;AAAA,WACpB;AAAA,QACF,CAAA;AAAA,OACJ;AACA,MAAA,MAAM,KAAK,iBAAA,CAAkB;AAAA,QAC3B,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,aAAa,IAAA,CAAK,WAAA;AAAA,QAClB,KAAK,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,EAAG,KAAK,QAAQ,CAAA,CAAA;AAAA,QACpC;AAAA,OACD,CAAA;AACD,MAAA,OAAO,gBAAA,CAAiB,EAAA,EAAI,IAAA,CAAK,eAAe,CAAA;AAAA,IAClD;AAAA,GACF;AACF","file":"listing.js","sourcesContent":["import {\n markdownResponse,\n listingToMarkdown,\n type MarkdownResponseOptions,\n type ListingItem,\n} from \"@dualmark/core\";\nimport type { CollectionEntry } from \"@dualmark/converters\";\n\nexport interface ListingEndpointArgs<TEntry extends CollectionEntry<unknown>> {\n collectionName: string;\n siteUrl: string;\n basePath: string;\n title: string;\n description: string;\n getCollection: (\n name: string,\n filter?: (entry: TEntry) => boolean,\n ) => Promise<TEntry[]>;\n filter?: (entry: TEntry) => boolean;\n sort?: (a: TEntry, b: TEntry) => number;\n itemMapper?: (entry: TEntry) => ListingItem;\n responseOptions?: MarkdownResponseOptions;\n}\n\nexport function makeListingEndpoint<TEntry extends CollectionEntry<unknown>>(\n args: ListingEndpointArgs<TEntry>,\n): { GET: () => Promise<Response> } {\n return {\n async GET() {\n let entries = await args.getCollection(args.collectionName, args.filter);\n if (args.sort) entries = [...entries].sort(args.sort);\n const items: ListingItem[] = entries.map(\n args.itemMapper ??\n ((entry) => {\n const data = entry.data as { title?: string; description?: string };\n return {\n title: data.title ?? entry.id,\n href: `${args.basePath}/${entry.id}`,\n description: data.description,\n };\n }),\n );\n const md = listingToMarkdown({\n title: args.title,\n description: args.description,\n url: `${args.siteUrl}${args.basePath}`,\n items,\n });\n return markdownResponse(md, args.responseOptions);\n },\n };\n}\n"]}
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ var core = require('@dualmark/core');
4
+
5
+ // src/endpoints/llms-txt.ts
6
+ function makeLlmsTxtEndpoint(args) {
7
+ return {
8
+ GET() {
9
+ const body = core.renderLlmsTxt(args);
10
+ return new Response(body, {
11
+ headers: {
12
+ "Content-Type": "text/plain; charset=utf-8",
13
+ "X-Robots-Tag": "noindex",
14
+ "Cache-Control": "public, max-age=3600"
15
+ }
16
+ });
17
+ }
18
+ };
19
+ }
20
+
21
+ exports.makeLlmsTxtEndpoint = makeLlmsTxtEndpoint;
22
+ //# sourceMappingURL=llms-txt.cjs.map
23
+ //# sourceMappingURL=llms-txt.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/llms-txt.ts"],"names":["renderLlmsTxt"],"mappings":";;;;;AAQO,SAAS,oBAAoB,IAAA,EAElC;AACA,EAAA,OAAO;AAAA,IACL,GAAA,GAAM;AACJ,MAAA,MAAM,IAAA,GAAOA,mBAAc,IAAI,CAAA;AAC/B,MAAA,OAAO,IAAI,SAAS,IAAA,EAAM;AAAA,QACxB,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,2BAAA;AAAA,UAChB,cAAA,EAAgB,SAAA;AAAA,UAChB,eAAA,EAAiB;AAAA;AACnB,OACD,CAAA;AAAA,IACH;AAAA,GACF;AACF","file":"llms-txt.cjs","sourcesContent":["import { renderLlmsTxt, type LlmsTxtSection } from \"@dualmark/core\";\n\nexport interface LlmsTxtEndpointArgs {\n brandName: string;\n description?: string;\n sections: LlmsTxtSection[];\n}\n\nexport function makeLlmsTxtEndpoint(args: LlmsTxtEndpointArgs): {\n GET: () => Response;\n} {\n return {\n GET() {\n const body = renderLlmsTxt(args);\n return new Response(body, {\n headers: {\n \"Content-Type\": \"text/plain; charset=utf-8\",\n \"X-Robots-Tag\": \"noindex\",\n \"Cache-Control\": \"public, max-age=3600\",\n },\n });\n },\n };\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { LlmsTxtSection } from '@dualmark/core';
2
+
3
+ interface LlmsTxtEndpointArgs {
4
+ brandName: string;
5
+ description?: string;
6
+ sections: LlmsTxtSection[];
7
+ }
8
+ declare function makeLlmsTxtEndpoint(args: LlmsTxtEndpointArgs): {
9
+ GET: () => Response;
10
+ };
11
+
12
+ export { type LlmsTxtEndpointArgs, makeLlmsTxtEndpoint };
@@ -0,0 +1,12 @@
1
+ import { LlmsTxtSection } from '@dualmark/core';
2
+
3
+ interface LlmsTxtEndpointArgs {
4
+ brandName: string;
5
+ description?: string;
6
+ sections: LlmsTxtSection[];
7
+ }
8
+ declare function makeLlmsTxtEndpoint(args: LlmsTxtEndpointArgs): {
9
+ GET: () => Response;
10
+ };
11
+
12
+ export { type LlmsTxtEndpointArgs, makeLlmsTxtEndpoint };
@@ -0,0 +1,21 @@
1
+ import { renderLlmsTxt } from '@dualmark/core';
2
+
3
+ // src/endpoints/llms-txt.ts
4
+ function makeLlmsTxtEndpoint(args) {
5
+ return {
6
+ GET() {
7
+ const body = renderLlmsTxt(args);
8
+ return new Response(body, {
9
+ headers: {
10
+ "Content-Type": "text/plain; charset=utf-8",
11
+ "X-Robots-Tag": "noindex",
12
+ "Cache-Control": "public, max-age=3600"
13
+ }
14
+ });
15
+ }
16
+ };
17
+ }
18
+
19
+ export { makeLlmsTxtEndpoint };
20
+ //# sourceMappingURL=llms-txt.js.map
21
+ //# sourceMappingURL=llms-txt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/llms-txt.ts"],"names":[],"mappings":";;;AAQO,SAAS,oBAAoB,IAAA,EAElC;AACA,EAAA,OAAO;AAAA,IACL,GAAA,GAAM;AACJ,MAAA,MAAM,IAAA,GAAO,cAAc,IAAI,CAAA;AAC/B,MAAA,OAAO,IAAI,SAAS,IAAA,EAAM;AAAA,QACxB,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,2BAAA;AAAA,UAChB,cAAA,EAAgB,SAAA;AAAA,UAChB,eAAA,EAAiB;AAAA;AACnB,OACD,CAAA;AAAA,IACH;AAAA,GACF;AACF","file":"llms-txt.js","sourcesContent":["import { renderLlmsTxt, type LlmsTxtSection } from \"@dualmark/core\";\n\nexport interface LlmsTxtEndpointArgs {\n brandName: string;\n description?: string;\n sections: LlmsTxtSection[];\n}\n\nexport function makeLlmsTxtEndpoint(args: LlmsTxtEndpointArgs): {\n GET: () => Response;\n} {\n return {\n GET() {\n const body = renderLlmsTxt(args);\n return new Response(body, {\n headers: {\n \"Content-Type\": \"text/plain; charset=utf-8\",\n \"X-Robots-Tag\": \"noindex\",\n \"Cache-Control\": \"public, max-age=3600\",\n },\n });\n },\n };\n}\n"]}
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var core = require('@dualmark/core');
4
+
5
+ // src/endpoints/parameterized.ts
6
+ function makeParameterizedEndpoint(args) {
7
+ return {
8
+ getStaticPaths: args.getStaticPaths,
9
+ async GET(ctx) {
10
+ const body = await args.render({ params: ctx.params });
11
+ return core.markdownResponse(body, args.responseOptions);
12
+ }
13
+ };
14
+ }
15
+
16
+ exports.makeParameterizedEndpoint = makeParameterizedEndpoint;
17
+ //# sourceMappingURL=parameterized.cjs.map
18
+ //# sourceMappingURL=parameterized.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/parameterized.ts"],"names":["markdownResponse"],"mappings":";;;;;AAUO,SAAS,0BAA0B,IAAA,EAKxC;AACA,EAAA,OAAO;AAAA,IACL,gBAAgB,IAAA,CAAK,cAAA;AAAA,IACrB,MAAM,IAAI,GAAA,EAAK;AACb,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,EAAE,MAAA,EAAQ,GAAA,CAAI,QAAQ,CAAA;AACrD,MAAA,OAAOA,qBAAA,CAAiB,IAAA,EAAM,IAAA,CAAK,eAAe,CAAA;AAAA,IACpD;AAAA,GACF;AACF","file":"parameterized.cjs","sourcesContent":["import { markdownResponse, type MarkdownResponseOptions } from \"@dualmark/core\";\n\nexport interface ParameterizedEndpointArgs {\n getStaticPaths: () =>\n | Promise<Array<{ params: Record<string, string> }>>\n | Array<{ params: Record<string, string> }>;\n render: (args: { params: Record<string, string> }) => string | Promise<string>;\n responseOptions?: MarkdownResponseOptions;\n}\n\nexport function makeParameterizedEndpoint(args: ParameterizedEndpointArgs): {\n getStaticPaths: () =>\n | Promise<Array<{ params: Record<string, string> }>>\n | Array<{ params: Record<string, string> }>;\n GET: (ctx: { params: Record<string, string> }) => Promise<Response>;\n} {\n return {\n getStaticPaths: args.getStaticPaths,\n async GET(ctx) {\n const body = await args.render({ params: ctx.params });\n return markdownResponse(body, args.responseOptions);\n },\n };\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import { MarkdownResponseOptions } from '@dualmark/core';
2
+
3
+ interface ParameterizedEndpointArgs {
4
+ getStaticPaths: () => Promise<Array<{
5
+ params: Record<string, string>;
6
+ }>> | Array<{
7
+ params: Record<string, string>;
8
+ }>;
9
+ render: (args: {
10
+ params: Record<string, string>;
11
+ }) => string | Promise<string>;
12
+ responseOptions?: MarkdownResponseOptions;
13
+ }
14
+ declare function makeParameterizedEndpoint(args: ParameterizedEndpointArgs): {
15
+ getStaticPaths: () => Promise<Array<{
16
+ params: Record<string, string>;
17
+ }>> | Array<{
18
+ params: Record<string, string>;
19
+ }>;
20
+ GET: (ctx: {
21
+ params: Record<string, string>;
22
+ }) => Promise<Response>;
23
+ };
24
+
25
+ export { type ParameterizedEndpointArgs, makeParameterizedEndpoint };
@@ -0,0 +1,25 @@
1
+ import { MarkdownResponseOptions } from '@dualmark/core';
2
+
3
+ interface ParameterizedEndpointArgs {
4
+ getStaticPaths: () => Promise<Array<{
5
+ params: Record<string, string>;
6
+ }>> | Array<{
7
+ params: Record<string, string>;
8
+ }>;
9
+ render: (args: {
10
+ params: Record<string, string>;
11
+ }) => string | Promise<string>;
12
+ responseOptions?: MarkdownResponseOptions;
13
+ }
14
+ declare function makeParameterizedEndpoint(args: ParameterizedEndpointArgs): {
15
+ getStaticPaths: () => Promise<Array<{
16
+ params: Record<string, string>;
17
+ }>> | Array<{
18
+ params: Record<string, string>;
19
+ }>;
20
+ GET: (ctx: {
21
+ params: Record<string, string>;
22
+ }) => Promise<Response>;
23
+ };
24
+
25
+ export { type ParameterizedEndpointArgs, makeParameterizedEndpoint };
@@ -0,0 +1,16 @@
1
+ import { markdownResponse } from '@dualmark/core';
2
+
3
+ // src/endpoints/parameterized.ts
4
+ function makeParameterizedEndpoint(args) {
5
+ return {
6
+ getStaticPaths: args.getStaticPaths,
7
+ async GET(ctx) {
8
+ const body = await args.render({ params: ctx.params });
9
+ return markdownResponse(body, args.responseOptions);
10
+ }
11
+ };
12
+ }
13
+
14
+ export { makeParameterizedEndpoint };
15
+ //# sourceMappingURL=parameterized.js.map
16
+ //# sourceMappingURL=parameterized.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/parameterized.ts"],"names":[],"mappings":";;;AAUO,SAAS,0BAA0B,IAAA,EAKxC;AACA,EAAA,OAAO;AAAA,IACL,gBAAgB,IAAA,CAAK,cAAA;AAAA,IACrB,MAAM,IAAI,GAAA,EAAK;AACb,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,EAAE,MAAA,EAAQ,GAAA,CAAI,QAAQ,CAAA;AACrD,MAAA,OAAO,gBAAA,CAAiB,IAAA,EAAM,IAAA,CAAK,eAAe,CAAA;AAAA,IACpD;AAAA,GACF;AACF","file":"parameterized.js","sourcesContent":["import { markdownResponse, type MarkdownResponseOptions } from \"@dualmark/core\";\n\nexport interface ParameterizedEndpointArgs {\n getStaticPaths: () =>\n | Promise<Array<{ params: Record<string, string> }>>\n | Array<{ params: Record<string, string> }>;\n render: (args: { params: Record<string, string> }) => string | Promise<string>;\n responseOptions?: MarkdownResponseOptions;\n}\n\nexport function makeParameterizedEndpoint(args: ParameterizedEndpointArgs): {\n getStaticPaths: () =>\n | Promise<Array<{ params: Record<string, string> }>>\n | Array<{ params: Record<string, string> }>;\n GET: (ctx: { params: Record<string, string> }) => Promise<Response>;\n} {\n return {\n getStaticPaths: args.getStaticPaths,\n async GET(ctx) {\n const body = await args.render({ params: ctx.params });\n return markdownResponse(body, args.responseOptions);\n },\n };\n}\n"]}
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ var core = require('@dualmark/core');
4
+
5
+ // src/endpoints/static.ts
6
+ function makeStaticEndpoint(args) {
7
+ return {
8
+ async GET() {
9
+ const body = await args.render();
10
+ return core.markdownResponse(body, args.responseOptions);
11
+ }
12
+ };
13
+ }
14
+
15
+ exports.makeStaticEndpoint = makeStaticEndpoint;
16
+ //# sourceMappingURL=static.cjs.map
17
+ //# sourceMappingURL=static.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/static.ts"],"names":["markdownResponse"],"mappings":";;;;;AAOO,SAAS,mBAAmB,IAAA,EAEjC;AACA,EAAA,OAAO;AAAA,IACL,MAAM,GAAA,GAAM;AACV,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,EAAO;AAC/B,MAAA,OAAOA,qBAAA,CAAiB,IAAA,EAAM,IAAA,CAAK,eAAe,CAAA;AAAA,IACpD;AAAA,GACF;AACF","file":"static.cjs","sourcesContent":["import { markdownResponse, type MarkdownResponseOptions } from \"@dualmark/core\";\n\nexport interface StaticEndpointArgs {\n render: () => string | Promise<string>;\n responseOptions?: MarkdownResponseOptions;\n}\n\nexport function makeStaticEndpoint(args: StaticEndpointArgs): {\n GET: () => Promise<Response>;\n} {\n return {\n async GET() {\n const body = await args.render();\n return markdownResponse(body, args.responseOptions);\n },\n };\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { MarkdownResponseOptions } from '@dualmark/core';
2
+
3
+ interface StaticEndpointArgs {
4
+ render: () => string | Promise<string>;
5
+ responseOptions?: MarkdownResponseOptions;
6
+ }
7
+ declare function makeStaticEndpoint(args: StaticEndpointArgs): {
8
+ GET: () => Promise<Response>;
9
+ };
10
+
11
+ export { type StaticEndpointArgs, makeStaticEndpoint };
@@ -0,0 +1,11 @@
1
+ import { MarkdownResponseOptions } from '@dualmark/core';
2
+
3
+ interface StaticEndpointArgs {
4
+ render: () => string | Promise<string>;
5
+ responseOptions?: MarkdownResponseOptions;
6
+ }
7
+ declare function makeStaticEndpoint(args: StaticEndpointArgs): {
8
+ GET: () => Promise<Response>;
9
+ };
10
+
11
+ export { type StaticEndpointArgs, makeStaticEndpoint };
@@ -0,0 +1,15 @@
1
+ import { markdownResponse } from '@dualmark/core';
2
+
3
+ // src/endpoints/static.ts
4
+ function makeStaticEndpoint(args) {
5
+ return {
6
+ async GET() {
7
+ const body = await args.render();
8
+ return markdownResponse(body, args.responseOptions);
9
+ }
10
+ };
11
+ }
12
+
13
+ export { makeStaticEndpoint };
14
+ //# sourceMappingURL=static.js.map
15
+ //# sourceMappingURL=static.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/static.ts"],"names":[],"mappings":";;;AAOO,SAAS,mBAAmB,IAAA,EAEjC;AACA,EAAA,OAAO;AAAA,IACL,MAAM,GAAA,GAAM;AACV,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,EAAO;AAC/B,MAAA,OAAO,gBAAA,CAAiB,IAAA,EAAM,IAAA,CAAK,eAAe,CAAA;AAAA,IACpD;AAAA,GACF;AACF","file":"static.js","sourcesContent":["import { markdownResponse, type MarkdownResponseOptions } from \"@dualmark/core\";\n\nexport interface StaticEndpointArgs {\n render: () => string | Promise<string>;\n responseOptions?: MarkdownResponseOptions;\n}\n\nexport function makeStaticEndpoint(args: StaticEndpointArgs): {\n GET: () => Promise<Response>;\n} {\n return {\n async GET() {\n const body = await args.render();\n return markdownResponse(body, args.responseOptions);\n },\n };\n}\n"]}