@prudentbird/voxx-core 1.0.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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  4. package/dist/config.cjs +151 -0
  5. package/dist/config.cjs.map +1 -0
  6. package/dist/config.d.cts +122 -0
  7. package/dist/config.d.cts.map +1 -0
  8. package/dist/config.d.mts +122 -0
  9. package/dist/config.d.mts.map +1 -0
  10. package/dist/config.mjs +149 -0
  11. package/dist/config.mjs.map +1 -0
  12. package/dist/content.cjs +147 -0
  13. package/dist/content.cjs.map +1 -0
  14. package/dist/content.d.cts +41 -0
  15. package/dist/content.d.cts.map +1 -0
  16. package/dist/content.d.mts +41 -0
  17. package/dist/content.d.mts.map +1 -0
  18. package/dist/content.mjs +145 -0
  19. package/dist/content.mjs.map +1 -0
  20. package/dist/dev.cjs +82 -0
  21. package/dist/dev.cjs.map +1 -0
  22. package/dist/dev.d.cts +24 -0
  23. package/dist/dev.d.cts.map +1 -0
  24. package/dist/dev.d.mts +24 -0
  25. package/dist/dev.d.mts.map +1 -0
  26. package/dist/dev.mjs +82 -0
  27. package/dist/dev.mjs.map +1 -0
  28. package/dist/effect.cjs +23 -0
  29. package/dist/effect.d.cts +8 -0
  30. package/dist/effect.d.mts +8 -0
  31. package/dist/effect.mjs +8 -0
  32. package/dist/errors.cjs +20 -0
  33. package/dist/errors.cjs.map +1 -0
  34. package/dist/errors.d.cts +45 -0
  35. package/dist/errors.d.cts.map +1 -0
  36. package/dist/errors.d.mts +45 -0
  37. package/dist/errors.d.mts.map +1 -0
  38. package/dist/errors.mjs +16 -0
  39. package/dist/errors.mjs.map +1 -0
  40. package/dist/feeds.cjs +97 -0
  41. package/dist/feeds.cjs.map +1 -0
  42. package/dist/feeds.d.cts +49 -0
  43. package/dist/feeds.d.cts.map +1 -0
  44. package/dist/feeds.d.mts +49 -0
  45. package/dist/feeds.d.mts.map +1 -0
  46. package/dist/feeds.mjs +94 -0
  47. package/dist/feeds.mjs.map +1 -0
  48. package/dist/frontmatter.cjs +22 -0
  49. package/dist/frontmatter.cjs.map +1 -0
  50. package/dist/frontmatter.d.cts +30 -0
  51. package/dist/frontmatter.d.cts.map +1 -0
  52. package/dist/frontmatter.d.mts +30 -0
  53. package/dist/frontmatter.d.mts.map +1 -0
  54. package/dist/frontmatter.mjs +20 -0
  55. package/dist/frontmatter.mjs.map +1 -0
  56. package/dist/index.cjs +90 -0
  57. package/dist/index.cjs.map +1 -0
  58. package/dist/index.d.cts +50 -0
  59. package/dist/index.d.cts.map +1 -0
  60. package/dist/index.d.mts +50 -0
  61. package/dist/index.d.mts.map +1 -0
  62. package/dist/index.mjs +59 -0
  63. package/dist/index.mjs.map +1 -0
  64. package/dist/llms.cjs +81 -0
  65. package/dist/llms.cjs.map +1 -0
  66. package/dist/llms.d.cts +43 -0
  67. package/dist/llms.d.cts.map +1 -0
  68. package/dist/llms.d.mts +43 -0
  69. package/dist/llms.d.mts.map +1 -0
  70. package/dist/llms.mjs +78 -0
  71. package/dist/llms.mjs.map +1 -0
  72. package/dist/nav.cjs +50 -0
  73. package/dist/nav.cjs.map +1 -0
  74. package/dist/nav.d.cts +16 -0
  75. package/dist/nav.d.cts.map +1 -0
  76. package/dist/nav.d.mts +16 -0
  77. package/dist/nav.d.mts.map +1 -0
  78. package/dist/nav.mjs +50 -0
  79. package/dist/nav.mjs.map +1 -0
  80. package/dist/render.cjs +152 -0
  81. package/dist/render.cjs.map +1 -0
  82. package/dist/render.d.cts +29 -0
  83. package/dist/render.d.cts.map +1 -0
  84. package/dist/render.d.mts +29 -0
  85. package/dist/render.d.mts.map +1 -0
  86. package/dist/render.mjs +143 -0
  87. package/dist/render.mjs.map +1 -0
  88. package/dist/schema.cjs +78 -0
  89. package/dist/schema.cjs.map +1 -0
  90. package/dist/schema.d.cts +93 -0
  91. package/dist/schema.d.cts.map +1 -0
  92. package/dist/schema.d.mts +93 -0
  93. package/dist/schema.d.mts.map +1 -0
  94. package/dist/schema.mjs +77 -0
  95. package/dist/schema.mjs.map +1 -0
  96. package/dist/seo.cjs +77 -0
  97. package/dist/seo.cjs.map +1 -0
  98. package/dist/seo.d.cts +15 -0
  99. package/dist/seo.d.cts.map +1 -0
  100. package/dist/seo.d.mts +15 -0
  101. package/dist/seo.d.mts.map +1 -0
  102. package/dist/seo.mjs +77 -0
  103. package/dist/seo.mjs.map +1 -0
  104. package/dist/types.cjs +45 -0
  105. package/dist/types.cjs.map +1 -0
  106. package/dist/types.d.cts +138 -0
  107. package/dist/types.d.cts.map +1 -0
  108. package/dist/types.d.mts +138 -0
  109. package/dist/types.d.mts.map +1 -0
  110. package/dist/types.mjs +45 -0
  111. package/dist/types.mjs.map +1 -0
  112. package/dist/util.cjs +185 -0
  113. package/dist/util.cjs.map +1 -0
  114. package/dist/util.d.cts +98 -0
  115. package/dist/util.d.cts.map +1 -0
  116. package/dist/util.d.mts +98 -0
  117. package/dist/util.d.mts.map +1 -0
  118. package/dist/util.mjs +171 -0
  119. package/dist/util.mjs.map +1 -0
  120. package/package.json +106 -0
  121. package/theme/demo-globals.css +61 -0
  122. package/theme/voxx.css +915 -0
  123. package/voxx.schema.json +186 -0
@@ -0,0 +1,78 @@
1
+ let effect = require("effect");
2
+ //#region src/schema.ts
3
+ const DateLike = effect.Schema.transform(effect.Schema.Union(effect.Schema.String, effect.Schema.DateFromSelf), effect.Schema.String, {
4
+ strict: false,
5
+ decode: (value) => value instanceof Date ? value.toISOString() : value,
6
+ encode: (value) => value
7
+ });
8
+ const optionalString = effect.Schema.optionalWith(effect.Schema.String, { nullable: true });
9
+ const Frontmatter = effect.Schema.Struct({
10
+ title: effect.Schema.String,
11
+ description: optionalString,
12
+ date: effect.Schema.optionalWith(DateLike, { nullable: true }),
13
+ updated: effect.Schema.optionalWith(DateLike, { nullable: true }),
14
+ slug: optionalString,
15
+ tags: effect.Schema.optionalWith(effect.Schema.Array(effect.Schema.String), {
16
+ default: () => [],
17
+ nullable: true
18
+ }),
19
+ category: optionalString,
20
+ order: effect.Schema.optionalWith(effect.Schema.Number, { nullable: true }),
21
+ version: optionalString,
22
+ draft: effect.Schema.optionalWith(effect.Schema.Boolean, {
23
+ default: () => false,
24
+ nullable: true
25
+ }),
26
+ image: optionalString,
27
+ author: optionalString,
28
+ excerpt: optionalString
29
+ });
30
+ const ConfigInput = effect.Schema.Struct({
31
+ site: effect.Schema.Struct({
32
+ title: effect.Schema.String,
33
+ description: effect.Schema.optional(effect.Schema.String),
34
+ url: effect.Schema.String,
35
+ author: effect.Schema.optional(effect.Schema.Struct({
36
+ name: effect.Schema.String,
37
+ url: effect.Schema.optional(effect.Schema.String)
38
+ })),
39
+ locale: effect.Schema.optional(effect.Schema.String)
40
+ }),
41
+ content: effect.Schema.optional(effect.Schema.Struct({
42
+ type: effect.Schema.optional(effect.Schema.Literal("blog", "docs", "changelog")),
43
+ dir: effect.Schema.optional(effect.Schema.String),
44
+ basePath: effect.Schema.optional(effect.Schema.String),
45
+ drafts: effect.Schema.optional(effect.Schema.Boolean)
46
+ })),
47
+ collections: effect.Schema.optional(effect.Schema.Array(effect.Schema.Struct({
48
+ name: effect.Schema.optional(effect.Schema.String),
49
+ type: effect.Schema.optional(effect.Schema.Literal("blog", "docs", "changelog")),
50
+ dir: effect.Schema.optional(effect.Schema.String),
51
+ basePath: effect.Schema.optional(effect.Schema.String),
52
+ drafts: effect.Schema.optional(effect.Schema.Boolean)
53
+ }))),
54
+ theme: effect.Schema.optional(effect.Schema.Struct({
55
+ preset: effect.Schema.optional(effect.Schema.Literal("shadcn")),
56
+ css: effect.Schema.optional(effect.Schema.NullOr(effect.Schema.String)),
57
+ codeTheme: effect.Schema.optional(effect.Schema.String)
58
+ })),
59
+ features: effect.Schema.optional(effect.Schema.Struct({
60
+ toc: effect.Schema.optional(effect.Schema.Boolean),
61
+ rss: effect.Schema.optional(effect.Schema.Boolean),
62
+ sitemap: effect.Schema.optional(effect.Schema.Boolean),
63
+ llmsTxt: effect.Schema.optional(effect.Schema.Boolean),
64
+ tags: effect.Schema.optional(effect.Schema.Boolean),
65
+ readingTime: effect.Schema.optional(effect.Schema.Boolean)
66
+ })),
67
+ seo: effect.Schema.optional(effect.Schema.Struct({
68
+ openGraph: effect.Schema.optional(effect.Schema.Boolean),
69
+ twitter: effect.Schema.optional(effect.Schema.NullOr(effect.Schema.String)),
70
+ jsonLd: effect.Schema.optional(effect.Schema.Boolean),
71
+ defaultImage: effect.Schema.optional(effect.Schema.NullOr(effect.Schema.String))
72
+ }))
73
+ });
74
+ //#endregion
75
+ exports.ConfigInput = ConfigInput;
76
+ exports.Frontmatter = Frontmatter;
77
+
78
+ //# sourceMappingURL=schema.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.cjs","names":["Schema"],"sources":["../src/schema.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nconst DateLike = Schema.transform(\n Schema.Union(Schema.String, Schema.DateFromSelf),\n Schema.String,\n {\n strict: false,\n decode: (value) => (value instanceof Date ? value.toISOString() : value),\n encode: (value) => value,\n },\n);\n\nconst optionalString = Schema.optionalWith(Schema.String, { nullable: true });\n\nexport const Frontmatter = Schema.Struct({\n title: Schema.String,\n description: optionalString,\n date: Schema.optionalWith(DateLike, { nullable: true }),\n updated: Schema.optionalWith(DateLike, { nullable: true }),\n slug: optionalString,\n tags: Schema.optionalWith(Schema.Array(Schema.String), {\n default: () => [],\n nullable: true,\n }),\n category: optionalString,\n order: Schema.optionalWith(Schema.Number, { nullable: true }),\n version: optionalString,\n draft: Schema.optionalWith(Schema.Boolean, {\n default: () => false,\n nullable: true,\n }),\n image: optionalString,\n author: optionalString,\n excerpt: optionalString,\n});\n\nexport type FrontmatterData = typeof Frontmatter.Type;\n\nexport const ConfigInput = Schema.Struct({\n site: Schema.Struct({\n title: Schema.String,\n description: Schema.optional(Schema.String),\n url: Schema.String,\n author: Schema.optional(\n Schema.Struct({\n name: Schema.String,\n url: Schema.optional(Schema.String),\n }),\n ),\n locale: Schema.optional(Schema.String),\n }),\n content: Schema.optional(\n Schema.Struct({\n type: Schema.optional(Schema.Literal(\"blog\", \"docs\", \"changelog\")),\n dir: Schema.optional(Schema.String),\n basePath: Schema.optional(Schema.String),\n drafts: Schema.optional(Schema.Boolean),\n }),\n ),\n\n collections: Schema.optional(\n Schema.Array(\n Schema.Struct({\n name: Schema.optional(Schema.String),\n type: Schema.optional(Schema.Literal(\"blog\", \"docs\", \"changelog\")),\n dir: Schema.optional(Schema.String),\n basePath: Schema.optional(Schema.String),\n drafts: Schema.optional(Schema.Boolean),\n }),\n ),\n ),\n theme: Schema.optional(\n Schema.Struct({\n preset: Schema.optional(Schema.Literal(\"shadcn\")),\n css: Schema.optional(Schema.NullOr(Schema.String)),\n codeTheme: Schema.optional(Schema.String),\n }),\n ),\n features: Schema.optional(\n Schema.Struct({\n toc: Schema.optional(Schema.Boolean),\n rss: Schema.optional(Schema.Boolean),\n sitemap: Schema.optional(Schema.Boolean),\n llmsTxt: Schema.optional(Schema.Boolean),\n tags: Schema.optional(Schema.Boolean),\n readingTime: Schema.optional(Schema.Boolean),\n }),\n ),\n seo: Schema.optional(\n Schema.Struct({\n openGraph: Schema.optional(Schema.Boolean),\n twitter: Schema.optional(Schema.NullOr(Schema.String)),\n jsonLd: Schema.optional(Schema.Boolean),\n defaultImage: Schema.optional(Schema.NullOr(Schema.String)),\n }),\n ),\n});\n\nexport type VoxxConfigInput = typeof ConfigInput.Type;\n"],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import { Schema } from "effect";
2
+
3
+ //#region src/schema.d.ts
4
+ declare const Frontmatter: Schema.Struct<{
5
+ title: typeof Schema.String;
6
+ description: Schema.optionalWith<typeof Schema.String, {
7
+ nullable: true;
8
+ }>;
9
+ date: Schema.optionalWith<Schema.transform<Schema.Union<[typeof Schema.String, typeof Schema.DateFromSelf]>, typeof Schema.String>, {
10
+ nullable: true;
11
+ }>;
12
+ updated: Schema.optionalWith<Schema.transform<Schema.Union<[typeof Schema.String, typeof Schema.DateFromSelf]>, typeof Schema.String>, {
13
+ nullable: true;
14
+ }>;
15
+ slug: Schema.optionalWith<typeof Schema.String, {
16
+ nullable: true;
17
+ }>;
18
+ tags: Schema.optionalWith<Schema.Array$<typeof Schema.String>, {
19
+ default: () => never[];
20
+ nullable: true;
21
+ }>;
22
+ category: Schema.optionalWith<typeof Schema.String, {
23
+ nullable: true;
24
+ }>;
25
+ order: Schema.optionalWith<typeof Schema.Number, {
26
+ nullable: true;
27
+ }>;
28
+ version: Schema.optionalWith<typeof Schema.String, {
29
+ nullable: true;
30
+ }>;
31
+ draft: Schema.optionalWith<typeof Schema.Boolean, {
32
+ default: () => false;
33
+ nullable: true;
34
+ }>;
35
+ image: Schema.optionalWith<typeof Schema.String, {
36
+ nullable: true;
37
+ }>;
38
+ author: Schema.optionalWith<typeof Schema.String, {
39
+ nullable: true;
40
+ }>;
41
+ excerpt: Schema.optionalWith<typeof Schema.String, {
42
+ nullable: true;
43
+ }>;
44
+ }>;
45
+ type FrontmatterData = typeof Frontmatter.Type;
46
+ declare const ConfigInput: Schema.Struct<{
47
+ site: Schema.Struct<{
48
+ title: typeof Schema.String;
49
+ description: Schema.optional<typeof Schema.String>;
50
+ url: typeof Schema.String;
51
+ author: Schema.optional<Schema.Struct<{
52
+ name: typeof Schema.String;
53
+ url: Schema.optional<typeof Schema.String>;
54
+ }>>;
55
+ locale: Schema.optional<typeof Schema.String>;
56
+ }>;
57
+ content: Schema.optional<Schema.Struct<{
58
+ type: Schema.optional<Schema.Literal<["blog", "docs", "changelog"]>>;
59
+ dir: Schema.optional<typeof Schema.String>;
60
+ basePath: Schema.optional<typeof Schema.String>;
61
+ drafts: Schema.optional<typeof Schema.Boolean>;
62
+ }>>;
63
+ collections: Schema.optional<Schema.Array$<Schema.Struct<{
64
+ name: Schema.optional<typeof Schema.String>;
65
+ type: Schema.optional<Schema.Literal<["blog", "docs", "changelog"]>>;
66
+ dir: Schema.optional<typeof Schema.String>;
67
+ basePath: Schema.optional<typeof Schema.String>;
68
+ drafts: Schema.optional<typeof Schema.Boolean>;
69
+ }>>>;
70
+ theme: Schema.optional<Schema.Struct<{
71
+ preset: Schema.optional<Schema.Literal<["shadcn"]>>;
72
+ css: Schema.optional<Schema.NullOr<typeof Schema.String>>;
73
+ codeTheme: Schema.optional<typeof Schema.String>;
74
+ }>>;
75
+ features: Schema.optional<Schema.Struct<{
76
+ toc: Schema.optional<typeof Schema.Boolean>;
77
+ rss: Schema.optional<typeof Schema.Boolean>;
78
+ sitemap: Schema.optional<typeof Schema.Boolean>;
79
+ llmsTxt: Schema.optional<typeof Schema.Boolean>;
80
+ tags: Schema.optional<typeof Schema.Boolean>;
81
+ readingTime: Schema.optional<typeof Schema.Boolean>;
82
+ }>>;
83
+ seo: Schema.optional<Schema.Struct<{
84
+ openGraph: Schema.optional<typeof Schema.Boolean>;
85
+ twitter: Schema.optional<Schema.NullOr<typeof Schema.String>>;
86
+ jsonLd: Schema.optional<typeof Schema.Boolean>;
87
+ defaultImage: Schema.optional<Schema.NullOr<typeof Schema.String>>;
88
+ }>>;
89
+ }>;
90
+ type VoxxConfigInput = typeof ConfigInput.Type;
91
+ //#endregion
92
+ export { ConfigInput, Frontmatter, FrontmatterData, VoxxConfigInput };
93
+ //# sourceMappingURL=schema.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.cts","names":[],"sources":["../src/schema.ts"],"mappings":";;;cAca,WAAA,EAAW,MAAA,CAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsBZ,eAAA,UAAyB,WAAA,CAAY,IAAI;AAAA,cAExC,WAAA,EAAW,MAAA,CAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4DZ,eAAA,UAAyB,WAAA,CAAY,IAAI"}
@@ -0,0 +1,93 @@
1
+ import { Schema } from "effect";
2
+
3
+ //#region src/schema.d.ts
4
+ declare const Frontmatter: Schema.Struct<{
5
+ title: typeof Schema.String;
6
+ description: Schema.optionalWith<typeof Schema.String, {
7
+ nullable: true;
8
+ }>;
9
+ date: Schema.optionalWith<Schema.transform<Schema.Union<[typeof Schema.String, typeof Schema.DateFromSelf]>, typeof Schema.String>, {
10
+ nullable: true;
11
+ }>;
12
+ updated: Schema.optionalWith<Schema.transform<Schema.Union<[typeof Schema.String, typeof Schema.DateFromSelf]>, typeof Schema.String>, {
13
+ nullable: true;
14
+ }>;
15
+ slug: Schema.optionalWith<typeof Schema.String, {
16
+ nullable: true;
17
+ }>;
18
+ tags: Schema.optionalWith<Schema.Array$<typeof Schema.String>, {
19
+ default: () => never[];
20
+ nullable: true;
21
+ }>;
22
+ category: Schema.optionalWith<typeof Schema.String, {
23
+ nullable: true;
24
+ }>;
25
+ order: Schema.optionalWith<typeof Schema.Number, {
26
+ nullable: true;
27
+ }>;
28
+ version: Schema.optionalWith<typeof Schema.String, {
29
+ nullable: true;
30
+ }>;
31
+ draft: Schema.optionalWith<typeof Schema.Boolean, {
32
+ default: () => false;
33
+ nullable: true;
34
+ }>;
35
+ image: Schema.optionalWith<typeof Schema.String, {
36
+ nullable: true;
37
+ }>;
38
+ author: Schema.optionalWith<typeof Schema.String, {
39
+ nullable: true;
40
+ }>;
41
+ excerpt: Schema.optionalWith<typeof Schema.String, {
42
+ nullable: true;
43
+ }>;
44
+ }>;
45
+ type FrontmatterData = typeof Frontmatter.Type;
46
+ declare const ConfigInput: Schema.Struct<{
47
+ site: Schema.Struct<{
48
+ title: typeof Schema.String;
49
+ description: Schema.optional<typeof Schema.String>;
50
+ url: typeof Schema.String;
51
+ author: Schema.optional<Schema.Struct<{
52
+ name: typeof Schema.String;
53
+ url: Schema.optional<typeof Schema.String>;
54
+ }>>;
55
+ locale: Schema.optional<typeof Schema.String>;
56
+ }>;
57
+ content: Schema.optional<Schema.Struct<{
58
+ type: Schema.optional<Schema.Literal<["blog", "docs", "changelog"]>>;
59
+ dir: Schema.optional<typeof Schema.String>;
60
+ basePath: Schema.optional<typeof Schema.String>;
61
+ drafts: Schema.optional<typeof Schema.Boolean>;
62
+ }>>;
63
+ collections: Schema.optional<Schema.Array$<Schema.Struct<{
64
+ name: Schema.optional<typeof Schema.String>;
65
+ type: Schema.optional<Schema.Literal<["blog", "docs", "changelog"]>>;
66
+ dir: Schema.optional<typeof Schema.String>;
67
+ basePath: Schema.optional<typeof Schema.String>;
68
+ drafts: Schema.optional<typeof Schema.Boolean>;
69
+ }>>>;
70
+ theme: Schema.optional<Schema.Struct<{
71
+ preset: Schema.optional<Schema.Literal<["shadcn"]>>;
72
+ css: Schema.optional<Schema.NullOr<typeof Schema.String>>;
73
+ codeTheme: Schema.optional<typeof Schema.String>;
74
+ }>>;
75
+ features: Schema.optional<Schema.Struct<{
76
+ toc: Schema.optional<typeof Schema.Boolean>;
77
+ rss: Schema.optional<typeof Schema.Boolean>;
78
+ sitemap: Schema.optional<typeof Schema.Boolean>;
79
+ llmsTxt: Schema.optional<typeof Schema.Boolean>;
80
+ tags: Schema.optional<typeof Schema.Boolean>;
81
+ readingTime: Schema.optional<typeof Schema.Boolean>;
82
+ }>>;
83
+ seo: Schema.optional<Schema.Struct<{
84
+ openGraph: Schema.optional<typeof Schema.Boolean>;
85
+ twitter: Schema.optional<Schema.NullOr<typeof Schema.String>>;
86
+ jsonLd: Schema.optional<typeof Schema.Boolean>;
87
+ defaultImage: Schema.optional<Schema.NullOr<typeof Schema.String>>;
88
+ }>>;
89
+ }>;
90
+ type VoxxConfigInput = typeof ConfigInput.Type;
91
+ //#endregion
92
+ export { ConfigInput, Frontmatter, FrontmatterData, VoxxConfigInput };
93
+ //# sourceMappingURL=schema.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.mts","names":[],"sources":["../src/schema.ts"],"mappings":";;;cAca,WAAA,EAAW,MAAA,CAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsBZ,eAAA,UAAyB,WAAA,CAAY,IAAI;AAAA,cAExC,WAAA,EAAW,MAAA,CAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4DZ,eAAA,UAAyB,WAAA,CAAY,IAAI"}
@@ -0,0 +1,77 @@
1
+ import { Schema } from "effect";
2
+ //#region src/schema.ts
3
+ const DateLike = Schema.transform(Schema.Union(Schema.String, Schema.DateFromSelf), Schema.String, {
4
+ strict: false,
5
+ decode: (value) => value instanceof Date ? value.toISOString() : value,
6
+ encode: (value) => value
7
+ });
8
+ const optionalString = Schema.optionalWith(Schema.String, { nullable: true });
9
+ const Frontmatter = Schema.Struct({
10
+ title: Schema.String,
11
+ description: optionalString,
12
+ date: Schema.optionalWith(DateLike, { nullable: true }),
13
+ updated: Schema.optionalWith(DateLike, { nullable: true }),
14
+ slug: optionalString,
15
+ tags: Schema.optionalWith(Schema.Array(Schema.String), {
16
+ default: () => [],
17
+ nullable: true
18
+ }),
19
+ category: optionalString,
20
+ order: Schema.optionalWith(Schema.Number, { nullable: true }),
21
+ version: optionalString,
22
+ draft: Schema.optionalWith(Schema.Boolean, {
23
+ default: () => false,
24
+ nullable: true
25
+ }),
26
+ image: optionalString,
27
+ author: optionalString,
28
+ excerpt: optionalString
29
+ });
30
+ const ConfigInput = Schema.Struct({
31
+ site: Schema.Struct({
32
+ title: Schema.String,
33
+ description: Schema.optional(Schema.String),
34
+ url: Schema.String,
35
+ author: Schema.optional(Schema.Struct({
36
+ name: Schema.String,
37
+ url: Schema.optional(Schema.String)
38
+ })),
39
+ locale: Schema.optional(Schema.String)
40
+ }),
41
+ content: Schema.optional(Schema.Struct({
42
+ type: Schema.optional(Schema.Literal("blog", "docs", "changelog")),
43
+ dir: Schema.optional(Schema.String),
44
+ basePath: Schema.optional(Schema.String),
45
+ drafts: Schema.optional(Schema.Boolean)
46
+ })),
47
+ collections: Schema.optional(Schema.Array(Schema.Struct({
48
+ name: Schema.optional(Schema.String),
49
+ type: Schema.optional(Schema.Literal("blog", "docs", "changelog")),
50
+ dir: Schema.optional(Schema.String),
51
+ basePath: Schema.optional(Schema.String),
52
+ drafts: Schema.optional(Schema.Boolean)
53
+ }))),
54
+ theme: Schema.optional(Schema.Struct({
55
+ preset: Schema.optional(Schema.Literal("shadcn")),
56
+ css: Schema.optional(Schema.NullOr(Schema.String)),
57
+ codeTheme: Schema.optional(Schema.String)
58
+ })),
59
+ features: Schema.optional(Schema.Struct({
60
+ toc: Schema.optional(Schema.Boolean),
61
+ rss: Schema.optional(Schema.Boolean),
62
+ sitemap: Schema.optional(Schema.Boolean),
63
+ llmsTxt: Schema.optional(Schema.Boolean),
64
+ tags: Schema.optional(Schema.Boolean),
65
+ readingTime: Schema.optional(Schema.Boolean)
66
+ })),
67
+ seo: Schema.optional(Schema.Struct({
68
+ openGraph: Schema.optional(Schema.Boolean),
69
+ twitter: Schema.optional(Schema.NullOr(Schema.String)),
70
+ jsonLd: Schema.optional(Schema.Boolean),
71
+ defaultImage: Schema.optional(Schema.NullOr(Schema.String))
72
+ }))
73
+ });
74
+ //#endregion
75
+ export { ConfigInput, Frontmatter };
76
+
77
+ //# sourceMappingURL=schema.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.mjs","names":[],"sources":["../src/schema.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nconst DateLike = Schema.transform(\n Schema.Union(Schema.String, Schema.DateFromSelf),\n Schema.String,\n {\n strict: false,\n decode: (value) => (value instanceof Date ? value.toISOString() : value),\n encode: (value) => value,\n },\n);\n\nconst optionalString = Schema.optionalWith(Schema.String, { nullable: true });\n\nexport const Frontmatter = Schema.Struct({\n title: Schema.String,\n description: optionalString,\n date: Schema.optionalWith(DateLike, { nullable: true }),\n updated: Schema.optionalWith(DateLike, { nullable: true }),\n slug: optionalString,\n tags: Schema.optionalWith(Schema.Array(Schema.String), {\n default: () => [],\n nullable: true,\n }),\n category: optionalString,\n order: Schema.optionalWith(Schema.Number, { nullable: true }),\n version: optionalString,\n draft: Schema.optionalWith(Schema.Boolean, {\n default: () => false,\n nullable: true,\n }),\n image: optionalString,\n author: optionalString,\n excerpt: optionalString,\n});\n\nexport type FrontmatterData = typeof Frontmatter.Type;\n\nexport const ConfigInput = Schema.Struct({\n site: Schema.Struct({\n title: Schema.String,\n description: Schema.optional(Schema.String),\n url: Schema.String,\n author: Schema.optional(\n Schema.Struct({\n name: Schema.String,\n url: Schema.optional(Schema.String),\n }),\n ),\n locale: Schema.optional(Schema.String),\n }),\n content: Schema.optional(\n Schema.Struct({\n type: Schema.optional(Schema.Literal(\"blog\", \"docs\", \"changelog\")),\n dir: Schema.optional(Schema.String),\n basePath: Schema.optional(Schema.String),\n drafts: Schema.optional(Schema.Boolean),\n }),\n ),\n\n collections: Schema.optional(\n Schema.Array(\n Schema.Struct({\n name: Schema.optional(Schema.String),\n type: Schema.optional(Schema.Literal(\"blog\", \"docs\", \"changelog\")),\n dir: Schema.optional(Schema.String),\n basePath: Schema.optional(Schema.String),\n drafts: Schema.optional(Schema.Boolean),\n }),\n ),\n ),\n theme: Schema.optional(\n Schema.Struct({\n preset: Schema.optional(Schema.Literal(\"shadcn\")),\n css: Schema.optional(Schema.NullOr(Schema.String)),\n codeTheme: Schema.optional(Schema.String),\n }),\n ),\n features: Schema.optional(\n Schema.Struct({\n toc: Schema.optional(Schema.Boolean),\n rss: Schema.optional(Schema.Boolean),\n sitemap: Schema.optional(Schema.Boolean),\n llmsTxt: Schema.optional(Schema.Boolean),\n tags: Schema.optional(Schema.Boolean),\n readingTime: Schema.optional(Schema.Boolean),\n }),\n ),\n seo: Schema.optional(\n Schema.Struct({\n openGraph: Schema.optional(Schema.Boolean),\n twitter: Schema.optional(Schema.NullOr(Schema.String)),\n jsonLd: Schema.optional(Schema.Boolean),\n defaultImage: Schema.optional(Schema.NullOr(Schema.String)),\n }),\n ),\n});\n\nexport type VoxxConfigInput = typeof ConfigInput.Type;\n"],"mappings":";;AAEA,MAAM,WAAW,OAAO,UACtB,OAAO,MAAM,OAAO,QAAQ,OAAO,YAAY,GAC/C,OAAO,QACP;CACE,QAAQ;CACR,SAAS,UAAW,iBAAiB,OAAO,MAAM,YAAY,IAAI;CAClE,SAAS,UAAU;AACrB,CACF;AAEA,MAAM,iBAAiB,OAAO,aAAa,OAAO,QAAQ,EAAE,UAAU,KAAK,CAAC;AAE5E,MAAa,cAAc,OAAO,OAAO;CACvC,OAAO,OAAO;CACd,aAAa;CACb,MAAM,OAAO,aAAa,UAAU,EAAE,UAAU,KAAK,CAAC;CACtD,SAAS,OAAO,aAAa,UAAU,EAAE,UAAU,KAAK,CAAC;CACzD,MAAM;CACN,MAAM,OAAO,aAAa,OAAO,MAAM,OAAO,MAAM,GAAG;EACrD,eAAe,CAAC;EAChB,UAAU;CACZ,CAAC;CACD,UAAU;CACV,OAAO,OAAO,aAAa,OAAO,QAAQ,EAAE,UAAU,KAAK,CAAC;CAC5D,SAAS;CACT,OAAO,OAAO,aAAa,OAAO,SAAS;EACzC,eAAe;EACf,UAAU;CACZ,CAAC;CACD,OAAO;CACP,QAAQ;CACR,SAAS;AACX,CAAC;AAID,MAAa,cAAc,OAAO,OAAO;CACvC,MAAM,OAAO,OAAO;EAClB,OAAO,OAAO;EACd,aAAa,OAAO,SAAS,OAAO,MAAM;EAC1C,KAAK,OAAO;EACZ,QAAQ,OAAO,SACb,OAAO,OAAO;GACZ,MAAM,OAAO;GACb,KAAK,OAAO,SAAS,OAAO,MAAM;EACpC,CAAC,CACH;EACA,QAAQ,OAAO,SAAS,OAAO,MAAM;CACvC,CAAC;CACD,SAAS,OAAO,SACd,OAAO,OAAO;EACZ,MAAM,OAAO,SAAS,OAAO,QAAQ,QAAQ,QAAQ,WAAW,CAAC;EACjE,KAAK,OAAO,SAAS,OAAO,MAAM;EAClC,UAAU,OAAO,SAAS,OAAO,MAAM;EACvC,QAAQ,OAAO,SAAS,OAAO,OAAO;CACxC,CAAC,CACH;CAEA,aAAa,OAAO,SAClB,OAAO,MACL,OAAO,OAAO;EACZ,MAAM,OAAO,SAAS,OAAO,MAAM;EACnC,MAAM,OAAO,SAAS,OAAO,QAAQ,QAAQ,QAAQ,WAAW,CAAC;EACjE,KAAK,OAAO,SAAS,OAAO,MAAM;EAClC,UAAU,OAAO,SAAS,OAAO,MAAM;EACvC,QAAQ,OAAO,SAAS,OAAO,OAAO;CACxC,CAAC,CACH,CACF;CACA,OAAO,OAAO,SACZ,OAAO,OAAO;EACZ,QAAQ,OAAO,SAAS,OAAO,QAAQ,QAAQ,CAAC;EAChD,KAAK,OAAO,SAAS,OAAO,OAAO,OAAO,MAAM,CAAC;EACjD,WAAW,OAAO,SAAS,OAAO,MAAM;CAC1C,CAAC,CACH;CACA,UAAU,OAAO,SACf,OAAO,OAAO;EACZ,KAAK,OAAO,SAAS,OAAO,OAAO;EACnC,KAAK,OAAO,SAAS,OAAO,OAAO;EACnC,SAAS,OAAO,SAAS,OAAO,OAAO;EACvC,SAAS,OAAO,SAAS,OAAO,OAAO;EACvC,MAAM,OAAO,SAAS,OAAO,OAAO;EACpC,aAAa,OAAO,SAAS,OAAO,OAAO;CAC7C,CAAC,CACH;CACA,KAAK,OAAO,SACV,OAAO,OAAO;EACZ,WAAW,OAAO,SAAS,OAAO,OAAO;EACzC,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,MAAM,CAAC;EACrD,QAAQ,OAAO,SAAS,OAAO,OAAO;EACtC,cAAc,OAAO,SAAS,OAAO,OAAO,OAAO,MAAM,CAAC;CAC5D,CAAC,CACH;AACF,CAAC"}
package/dist/seo.cjs ADDED
@@ -0,0 +1,77 @@
1
+ const require_util = require("./util.cjs");
2
+ //#region src/seo.ts
3
+ const JSON_LD_TYPE = {
4
+ blog: "BlogPosting",
5
+ docs: "TechArticle",
6
+ changelog: "Article"
7
+ };
8
+ /**
9
+ * Builds the full SEO payload for a post — canonical URL, Open Graph,
10
+ * Twitter card, and JSON-LD — based on the active config flags.
11
+ *
12
+ * @param post - The rendered post to generate metadata for.
13
+ * @param config - Resolved Voxx config.
14
+ * @returns `SeoData` ready to be spread into `<head>` metadata.
15
+ */
16
+ function buildSeo(post, config) {
17
+ const canonical = require_util.absoluteUrl(config.site.url, post.url);
18
+ const description = post.description ?? post.excerpt;
19
+ const imgSrc = post.image ?? config.seo.defaultImage ?? void 0;
20
+ const images = imgSrc ? [require_util.absoluteUrl(config.site.url, imgSrc)] : [];
21
+ const authors = post.author ? [post.author] : config.site.author ? [config.site.author.name] : [];
22
+ const tags = config.features.tags ? post.tags : [];
23
+ const seo = {
24
+ title: post.title,
25
+ description,
26
+ canonical
27
+ };
28
+ if (config.seo.openGraph) seo.openGraph = {
29
+ title: post.title,
30
+ description,
31
+ url: canonical,
32
+ type: "article",
33
+ siteName: config.site.title,
34
+ locale: config.site.locale,
35
+ images,
36
+ publishedTime: post.date,
37
+ modifiedTime: post.updated,
38
+ authors,
39
+ tags
40
+ };
41
+ if (config.seo.openGraph || config.seo.twitter) seo.twitter = {
42
+ card: "summary_large_image",
43
+ site: config.seo.twitter ?? void 0,
44
+ creator: config.seo.twitter ?? void 0,
45
+ title: post.title,
46
+ description,
47
+ images
48
+ };
49
+ if (config.seo.jsonLd) seo.jsonLd = {
50
+ "@context": "https://schema.org",
51
+ "@type": JSON_LD_TYPE[config.content.type],
52
+ headline: post.title,
53
+ description,
54
+ datePublished: post.date,
55
+ dateModified: post.updated ?? post.date,
56
+ ...images.length ? { image: images } : {},
57
+ author: {
58
+ "@type": "Person",
59
+ name: authors[0] ?? config.site.title,
60
+ ...config.site.author?.url ? { url: config.site.author.url } : {}
61
+ },
62
+ ...tags.length ? { keywords: tags.join(", ") } : {},
63
+ mainEntityOfPage: {
64
+ "@type": "WebPage",
65
+ "@id": canonical
66
+ },
67
+ ...config.site.title ? { publisher: {
68
+ "@type": "Organization",
69
+ name: config.site.title
70
+ } } : {}
71
+ };
72
+ return seo;
73
+ }
74
+ //#endregion
75
+ exports.buildSeo = buildSeo;
76
+
77
+ //# sourceMappingURL=seo.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.cjs","names":["absoluteUrl"],"sources":["../src/seo.ts"],"sourcesContent":["import { absoluteUrl } from \"./util\";\nimport type { ContentType, Post, SeoData, VoxxConfig } from \"./types\";\n\nconst JSON_LD_TYPE: Record<ContentType, string> = {\n blog: \"BlogPosting\",\n docs: \"TechArticle\",\n changelog: \"Article\",\n};\n\n/**\n * Builds the full SEO payload for a post — canonical URL, Open Graph,\n * Twitter card, and JSON-LD — based on the active config flags.\n *\n * @param post - The rendered post to generate metadata for.\n * @param config - Resolved Voxx config.\n * @returns `SeoData` ready to be spread into `<head>` metadata.\n */\nexport function buildSeo(post: Post, config: VoxxConfig): SeoData {\n const canonical = absoluteUrl(config.site.url, post.url);\n const description = post.description ?? post.excerpt;\n const imgSrc = post.image ?? config.seo.defaultImage ?? undefined;\n const images = imgSrc ? [absoluteUrl(config.site.url, imgSrc)] : [];\n const authors = post.author\n ? [post.author]\n : config.site.author\n ? [config.site.author.name]\n : [];\n\n const tags = config.features.tags ? post.tags : [];\n\n const seo: SeoData = { title: post.title, description, canonical };\n\n if (config.seo.openGraph) {\n seo.openGraph = {\n title: post.title,\n description,\n url: canonical,\n type: \"article\",\n siteName: config.site.title,\n locale: config.site.locale,\n images,\n publishedTime: post.date,\n modifiedTime: post.updated,\n authors,\n tags,\n };\n }\n\n if (config.seo.openGraph || config.seo.twitter) {\n seo.twitter = {\n card: \"summary_large_image\",\n site: config.seo.twitter ?? undefined,\n creator: config.seo.twitter ?? undefined,\n title: post.title,\n description,\n images,\n };\n }\n\n if (config.seo.jsonLd) {\n seo.jsonLd = {\n \"@context\": \"https://schema.org\",\n \"@type\": JSON_LD_TYPE[config.content.type],\n headline: post.title,\n description,\n datePublished: post.date,\n dateModified: post.updated ?? post.date,\n ...(images.length ? { image: images } : {}),\n author: {\n \"@type\": \"Person\",\n name: authors[0] ?? config.site.title,\n ...(config.site.author?.url ? { url: config.site.author.url } : {}),\n },\n ...(tags.length ? { keywords: tags.join(\", \") } : {}),\n mainEntityOfPage: { \"@type\": \"WebPage\", \"@id\": canonical },\n ...(config.site.title\n ? { publisher: { \"@type\": \"Organization\", name: config.site.title } }\n : {}),\n };\n }\n\n return seo;\n}\n"],"mappings":";;AAGA,MAAM,eAA4C;CAChD,MAAM;CACN,MAAM;CACN,WAAW;AACb;;;;;;;;;AAUA,SAAgB,SAAS,MAAY,QAA6B;CAChE,MAAM,YAAYA,aAAAA,YAAY,OAAO,KAAK,KAAK,KAAK,GAAG;CACvD,MAAM,cAAc,KAAK,eAAe,KAAK;CAC7C,MAAM,SAAS,KAAK,SAAS,OAAO,IAAI,gBAAgB,KAAA;CACxD,MAAM,SAAS,SAAS,CAACA,aAAAA,YAAY,OAAO,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC;CAClE,MAAM,UAAU,KAAK,SACjB,CAAC,KAAK,MAAM,IACZ,OAAO,KAAK,SACV,CAAC,OAAO,KAAK,OAAO,IAAI,IACxB,CAAC;CAEP,MAAM,OAAO,OAAO,SAAS,OAAO,KAAK,OAAO,CAAC;CAEjD,MAAM,MAAe;EAAE,OAAO,KAAK;EAAO;EAAa;CAAU;CAEjE,IAAI,OAAO,IAAI,WACb,IAAI,YAAY;EACd,OAAO,KAAK;EACZ;EACA,KAAK;EACL,MAAM;EACN,UAAU,OAAO,KAAK;EACtB,QAAQ,OAAO,KAAK;EACpB;EACA,eAAe,KAAK;EACpB,cAAc,KAAK;EACnB;EACA;CACF;CAGF,IAAI,OAAO,IAAI,aAAa,OAAO,IAAI,SACrC,IAAI,UAAU;EACZ,MAAM;EACN,MAAM,OAAO,IAAI,WAAW,KAAA;EAC5B,SAAS,OAAO,IAAI,WAAW,KAAA;EAC/B,OAAO,KAAK;EACZ;EACA;CACF;CAGF,IAAI,OAAO,IAAI,QACb,IAAI,SAAS;EACX,YAAY;EACZ,SAAS,aAAa,OAAO,QAAQ;EACrC,UAAU,KAAK;EACf;EACA,eAAe,KAAK;EACpB,cAAc,KAAK,WAAW,KAAK;EACnC,GAAI,OAAO,SAAS,EAAE,OAAO,OAAO,IAAI,CAAC;EACzC,QAAQ;GACN,SAAS;GACT,MAAM,QAAQ,MAAM,OAAO,KAAK;GAChC,GAAI,OAAO,KAAK,QAAQ,MAAM,EAAE,KAAK,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC;EACnE;EACA,GAAI,KAAK,SAAS,EAAE,UAAU,KAAK,KAAK,IAAI,EAAE,IAAI,CAAC;EACnD,kBAAkB;GAAE,SAAS;GAAW,OAAO;EAAU;EACzD,GAAI,OAAO,KAAK,QACZ,EAAE,WAAW;GAAE,SAAS;GAAgB,MAAM,OAAO,KAAK;EAAM,EAAE,IAClE,CAAC;CACP;CAGF,OAAO;AACT"}
package/dist/seo.d.cts ADDED
@@ -0,0 +1,15 @@
1
+ import { Post, SeoData, VoxxConfig } from "./types.cjs";
2
+
3
+ //#region src/seo.d.ts
4
+ /**
5
+ * Builds the full SEO payload for a post — canonical URL, Open Graph,
6
+ * Twitter card, and JSON-LD — based on the active config flags.
7
+ *
8
+ * @param post - The rendered post to generate metadata for.
9
+ * @param config - Resolved Voxx config.
10
+ * @returns `SeoData` ready to be spread into `<head>` metadata.
11
+ */
12
+ declare function buildSeo(post: Post, config: VoxxConfig): SeoData;
13
+ //#endregion
14
+ export { buildSeo };
15
+ //# sourceMappingURL=seo.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.d.cts","names":[],"sources":["../src/seo.ts"],"mappings":";;;;;AAiBA;;;;;;iBAAgB,QAAA,CAAS,IAAA,EAAM,IAAA,EAAM,MAAA,EAAQ,UAAA,GAAa,OAAA"}
package/dist/seo.d.mts ADDED
@@ -0,0 +1,15 @@
1
+ import { Post, SeoData, VoxxConfig } from "./types.mjs";
2
+
3
+ //#region src/seo.d.ts
4
+ /**
5
+ * Builds the full SEO payload for a post — canonical URL, Open Graph,
6
+ * Twitter card, and JSON-LD — based on the active config flags.
7
+ *
8
+ * @param post - The rendered post to generate metadata for.
9
+ * @param config - Resolved Voxx config.
10
+ * @returns `SeoData` ready to be spread into `<head>` metadata.
11
+ */
12
+ declare function buildSeo(post: Post, config: VoxxConfig): SeoData;
13
+ //#endregion
14
+ export { buildSeo };
15
+ //# sourceMappingURL=seo.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.d.mts","names":[],"sources":["../src/seo.ts"],"mappings":";;;;;AAiBA;;;;;;iBAAgB,QAAA,CAAS,IAAA,EAAM,IAAA,EAAM,MAAA,EAAQ,UAAA,GAAa,OAAA"}
package/dist/seo.mjs ADDED
@@ -0,0 +1,77 @@
1
+ import { absoluteUrl } from "./util.mjs";
2
+ //#region src/seo.ts
3
+ const JSON_LD_TYPE = {
4
+ blog: "BlogPosting",
5
+ docs: "TechArticle",
6
+ changelog: "Article"
7
+ };
8
+ /**
9
+ * Builds the full SEO payload for a post — canonical URL, Open Graph,
10
+ * Twitter card, and JSON-LD — based on the active config flags.
11
+ *
12
+ * @param post - The rendered post to generate metadata for.
13
+ * @param config - Resolved Voxx config.
14
+ * @returns `SeoData` ready to be spread into `<head>` metadata.
15
+ */
16
+ function buildSeo(post, config) {
17
+ const canonical = absoluteUrl(config.site.url, post.url);
18
+ const description = post.description ?? post.excerpt;
19
+ const imgSrc = post.image ?? config.seo.defaultImage ?? void 0;
20
+ const images = imgSrc ? [absoluteUrl(config.site.url, imgSrc)] : [];
21
+ const authors = post.author ? [post.author] : config.site.author ? [config.site.author.name] : [];
22
+ const tags = config.features.tags ? post.tags : [];
23
+ const seo = {
24
+ title: post.title,
25
+ description,
26
+ canonical
27
+ };
28
+ if (config.seo.openGraph) seo.openGraph = {
29
+ title: post.title,
30
+ description,
31
+ url: canonical,
32
+ type: "article",
33
+ siteName: config.site.title,
34
+ locale: config.site.locale,
35
+ images,
36
+ publishedTime: post.date,
37
+ modifiedTime: post.updated,
38
+ authors,
39
+ tags
40
+ };
41
+ if (config.seo.openGraph || config.seo.twitter) seo.twitter = {
42
+ card: "summary_large_image",
43
+ site: config.seo.twitter ?? void 0,
44
+ creator: config.seo.twitter ?? void 0,
45
+ title: post.title,
46
+ description,
47
+ images
48
+ };
49
+ if (config.seo.jsonLd) seo.jsonLd = {
50
+ "@context": "https://schema.org",
51
+ "@type": JSON_LD_TYPE[config.content.type],
52
+ headline: post.title,
53
+ description,
54
+ datePublished: post.date,
55
+ dateModified: post.updated ?? post.date,
56
+ ...images.length ? { image: images } : {},
57
+ author: {
58
+ "@type": "Person",
59
+ name: authors[0] ?? config.site.title,
60
+ ...config.site.author?.url ? { url: config.site.author.url } : {}
61
+ },
62
+ ...tags.length ? { keywords: tags.join(", ") } : {},
63
+ mainEntityOfPage: {
64
+ "@type": "WebPage",
65
+ "@id": canonical
66
+ },
67
+ ...config.site.title ? { publisher: {
68
+ "@type": "Organization",
69
+ name: config.site.title
70
+ } } : {}
71
+ };
72
+ return seo;
73
+ }
74
+ //#endregion
75
+ export { buildSeo };
76
+
77
+ //# sourceMappingURL=seo.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.mjs","names":[],"sources":["../src/seo.ts"],"sourcesContent":["import { absoluteUrl } from \"./util\";\nimport type { ContentType, Post, SeoData, VoxxConfig } from \"./types\";\n\nconst JSON_LD_TYPE: Record<ContentType, string> = {\n blog: \"BlogPosting\",\n docs: \"TechArticle\",\n changelog: \"Article\",\n};\n\n/**\n * Builds the full SEO payload for a post — canonical URL, Open Graph,\n * Twitter card, and JSON-LD — based on the active config flags.\n *\n * @param post - The rendered post to generate metadata for.\n * @param config - Resolved Voxx config.\n * @returns `SeoData` ready to be spread into `<head>` metadata.\n */\nexport function buildSeo(post: Post, config: VoxxConfig): SeoData {\n const canonical = absoluteUrl(config.site.url, post.url);\n const description = post.description ?? post.excerpt;\n const imgSrc = post.image ?? config.seo.defaultImage ?? undefined;\n const images = imgSrc ? [absoluteUrl(config.site.url, imgSrc)] : [];\n const authors = post.author\n ? [post.author]\n : config.site.author\n ? [config.site.author.name]\n : [];\n\n const tags = config.features.tags ? post.tags : [];\n\n const seo: SeoData = { title: post.title, description, canonical };\n\n if (config.seo.openGraph) {\n seo.openGraph = {\n title: post.title,\n description,\n url: canonical,\n type: \"article\",\n siteName: config.site.title,\n locale: config.site.locale,\n images,\n publishedTime: post.date,\n modifiedTime: post.updated,\n authors,\n tags,\n };\n }\n\n if (config.seo.openGraph || config.seo.twitter) {\n seo.twitter = {\n card: \"summary_large_image\",\n site: config.seo.twitter ?? undefined,\n creator: config.seo.twitter ?? undefined,\n title: post.title,\n description,\n images,\n };\n }\n\n if (config.seo.jsonLd) {\n seo.jsonLd = {\n \"@context\": \"https://schema.org\",\n \"@type\": JSON_LD_TYPE[config.content.type],\n headline: post.title,\n description,\n datePublished: post.date,\n dateModified: post.updated ?? post.date,\n ...(images.length ? { image: images } : {}),\n author: {\n \"@type\": \"Person\",\n name: authors[0] ?? config.site.title,\n ...(config.site.author?.url ? { url: config.site.author.url } : {}),\n },\n ...(tags.length ? { keywords: tags.join(\", \") } : {}),\n mainEntityOfPage: { \"@type\": \"WebPage\", \"@id\": canonical },\n ...(config.site.title\n ? { publisher: { \"@type\": \"Organization\", name: config.site.title } }\n : {}),\n };\n }\n\n return seo;\n}\n"],"mappings":";;AAGA,MAAM,eAA4C;CAChD,MAAM;CACN,MAAM;CACN,WAAW;AACb;;;;;;;;;AAUA,SAAgB,SAAS,MAAY,QAA6B;CAChE,MAAM,YAAY,YAAY,OAAO,KAAK,KAAK,KAAK,GAAG;CACvD,MAAM,cAAc,KAAK,eAAe,KAAK;CAC7C,MAAM,SAAS,KAAK,SAAS,OAAO,IAAI,gBAAgB,KAAA;CACxD,MAAM,SAAS,SAAS,CAAC,YAAY,OAAO,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC;CAClE,MAAM,UAAU,KAAK,SACjB,CAAC,KAAK,MAAM,IACZ,OAAO,KAAK,SACV,CAAC,OAAO,KAAK,OAAO,IAAI,IACxB,CAAC;CAEP,MAAM,OAAO,OAAO,SAAS,OAAO,KAAK,OAAO,CAAC;CAEjD,MAAM,MAAe;EAAE,OAAO,KAAK;EAAO;EAAa;CAAU;CAEjE,IAAI,OAAO,IAAI,WACb,IAAI,YAAY;EACd,OAAO,KAAK;EACZ;EACA,KAAK;EACL,MAAM;EACN,UAAU,OAAO,KAAK;EACtB,QAAQ,OAAO,KAAK;EACpB;EACA,eAAe,KAAK;EACpB,cAAc,KAAK;EACnB;EACA;CACF;CAGF,IAAI,OAAO,IAAI,aAAa,OAAO,IAAI,SACrC,IAAI,UAAU;EACZ,MAAM;EACN,MAAM,OAAO,IAAI,WAAW,KAAA;EAC5B,SAAS,OAAO,IAAI,WAAW,KAAA;EAC/B,OAAO,KAAK;EACZ;EACA;CACF;CAGF,IAAI,OAAO,IAAI,QACb,IAAI,SAAS;EACX,YAAY;EACZ,SAAS,aAAa,OAAO,QAAQ;EACrC,UAAU,KAAK;EACf;EACA,eAAe,KAAK;EACpB,cAAc,KAAK,WAAW,KAAK;EACnC,GAAI,OAAO,SAAS,EAAE,OAAO,OAAO,IAAI,CAAC;EACzC,QAAQ;GACN,SAAS;GACT,MAAM,QAAQ,MAAM,OAAO,KAAK;GAChC,GAAI,OAAO,KAAK,QAAQ,MAAM,EAAE,KAAK,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC;EACnE;EACA,GAAI,KAAK,SAAS,EAAE,UAAU,KAAK,KAAK,IAAI,EAAE,IAAI,CAAC;EACnD,kBAAkB;GAAE,SAAS;GAAW,OAAO;EAAU;EACzD,GAAI,OAAO,KAAK,QACZ,EAAE,WAAW;GAAE,SAAS;GAAgB,MAAM,OAAO,KAAK;EAAM,EAAE,IAClE,CAAC;CACP;CAGF,OAAO;AACT"}
package/dist/types.cjs ADDED
@@ -0,0 +1,45 @@
1
+ //#region src/types.ts
2
+ const DEFAULT_CONFIG = {
3
+ site: {
4
+ title: "Blog",
5
+ description: "",
6
+ url: "",
7
+ locale: "en-US"
8
+ },
9
+ content: {
10
+ type: "blog",
11
+ dir: "content/blog",
12
+ basePath: "/blog",
13
+ drafts: false
14
+ },
15
+ collections: [{
16
+ name: "blog",
17
+ type: "blog",
18
+ dir: "content/blog",
19
+ basePath: "/blog",
20
+ drafts: false
21
+ }],
22
+ theme: {
23
+ preset: "shadcn",
24
+ css: null,
25
+ codeTheme: "github-light github-dark"
26
+ },
27
+ features: {
28
+ toc: true,
29
+ rss: true,
30
+ sitemap: true,
31
+ llmsTxt: true,
32
+ tags: true,
33
+ readingTime: true
34
+ },
35
+ seo: {
36
+ openGraph: true,
37
+ twitter: null,
38
+ jsonLd: true,
39
+ defaultImage: null
40
+ }
41
+ };
42
+ //#endregion
43
+ exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
44
+
45
+ //# sourceMappingURL=types.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["/** Author metadata attached to a site or post. */\nexport interface VoxxAuthor {\n name: string;\n url?: string;\n}\n\n/** The rendering mode for a content collection. */\nexport type ContentType = \"blog\" | \"docs\" | \"changelog\";\n\n/** A resolved content collection with all defaults applied. */\nexport interface CollectionConfig {\n name: string;\n type: ContentType;\n /** Filesystem path to the content directory. */\n dir: string;\n /** URL prefix for all posts in this collection. */\n basePath: string;\n /** Whether draft posts are included by default. */\n drafts: boolean;\n}\n\n/** Resolved Voxx configuration merged from `voxx.json` and defaults. */\nexport interface VoxxConfig {\n site: {\n title: string;\n description: string;\n /** Canonical origin, e.g. `https://example.com`. */\n url: string;\n author?: VoxxAuthor;\n /** BCP 47 locale tag, e.g. `en-US`. */\n locale: string;\n };\n /** Primary content collection (mirrors `collections[0]`). */\n content: {\n type: ContentType;\n dir: string;\n basePath: string;\n drafts: boolean;\n };\n collections: CollectionConfig[];\n theme: {\n preset: \"shadcn\";\n /** Path to a custom CSS file, or `null` to use the preset default. */\n css: string | null;\n /** One or two Shiki theme names separated by a space (light dark). */\n codeTheme: string;\n };\n features: {\n toc: boolean;\n rss: boolean;\n sitemap: boolean;\n llmsTxt: boolean;\n tags: boolean;\n readingTime: boolean;\n };\n seo: {\n openGraph: boolean;\n /** Twitter/X handle including `@`, or `null` to omit. */\n twitter: string | null;\n jsonLd: boolean;\n /** Fallback OG image path relative to the site root. */\n defaultImage: string | null;\n };\n}\n\n/** A single entry in a page's table of contents. */\nexport interface TocItem {\n id: string;\n text: string;\n /** Heading level — `2` for `h2`, `3` for `h3`. */\n depth: number;\n}\n\n/** A fully processed content post ready to render. */\nexport interface Post {\n /** Final path segment(s), e.g. `[\"getting-started\", \"install\"]`. */\n slug: string;\n path: string[];\n /** Absolute URL path, e.g. `/blog/my-post`. */\n url: string;\n title: string;\n description?: string;\n /** ISO 8601 publish date. */\n date: string;\n /** ISO 8601 last-modified date. */\n updated?: string;\n tags: string[];\n category?: string;\n /** Sort order within the parent directory (docs only). */\n order?: number;\n /** Semver string extracted from the filename or frontmatter (changelog only). */\n version?: string;\n draft: boolean;\n image?: string;\n author?: string;\n /** Plain-text excerpt derived from the first 180 characters of content. */\n excerpt: string;\n readingTimeMinutes: number;\n /** Rendered HTML string. */\n html: string;\n toc: TocItem[];\n /** Raw Markdown source. */\n content: string;\n}\n\n/** A node in the sidebar navigation tree. */\nexport interface NavNode {\n title: string;\n /** Present on leaf nodes; absent on category nodes. */\n url?: string;\n children: NavNode[];\n}\n\n/** Open Graph article metadata. */\nexport interface OpenGraphData {\n title: string;\n description: string;\n url: string;\n type: \"article\";\n siteName: string;\n locale: string;\n images: string[];\n publishedTime?: string;\n modifiedTime?: string;\n authors: string[];\n tags: string[];\n}\n\n/** Twitter card metadata. */\nexport interface TwitterData {\n card: \"summary_large_image\";\n site?: string;\n creator?: string;\n title: string;\n description: string;\n images: string[];\n}\n\n/** Aggregated SEO metadata for a single page. */\nexport interface SeoData {\n title: string;\n description: string;\n canonical: string;\n openGraph?: OpenGraphData;\n twitter?: TwitterData;\n /** JSON-LD structured data object — serialize with `serializeJsonLd`. */\n jsonLd?: Record<string, unknown>;\n}\n\nexport const DEFAULT_CONFIG: VoxxConfig = {\n site: {\n title: \"Blog\",\n description: \"\",\n url: \"\",\n locale: \"en-US\",\n },\n content: {\n type: \"blog\",\n dir: \"content/blog\",\n basePath: \"/blog\",\n drafts: false,\n },\n collections: [\n {\n name: \"blog\",\n type: \"blog\",\n dir: \"content/blog\",\n basePath: \"/blog\",\n drafts: false,\n },\n ],\n theme: {\n preset: \"shadcn\",\n css: null,\n codeTheme: \"github-light github-dark\",\n },\n features: {\n toc: true,\n rss: true,\n sitemap: true,\n llmsTxt: true,\n tags: true,\n readingTime: true,\n },\n seo: {\n openGraph: true,\n twitter: null,\n jsonLd: true,\n defaultImage: null,\n },\n};\n"],"mappings":";AAqJA,MAAa,iBAA6B;CACxC,MAAM;EACJ,OAAO;EACP,aAAa;EACb,KAAK;EACL,QAAQ;CACV;CACA,SAAS;EACP,MAAM;EACN,KAAK;EACL,UAAU;EACV,QAAQ;CACV;CACA,aAAa,CACX;EACE,MAAM;EACN,MAAM;EACN,KAAK;EACL,UAAU;EACV,QAAQ;CACV,CACF;CACA,OAAO;EACL,QAAQ;EACR,KAAK;EACL,WAAW;CACb;CACA,UAAU;EACR,KAAK;EACL,KAAK;EACL,SAAS;EACT,SAAS;EACT,MAAM;EACN,aAAa;CACf;CACA,KAAK;EACH,WAAW;EACX,SAAS;EACT,QAAQ;EACR,cAAc;CAChB;AACF"}