@airdraft/plugin-seo 0.1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@airdraft/plugin-seo` will be documented here.
4
+
5
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
@@ -0,0 +1,3 @@
1
+ export { withSeo } from './withSeo.js';
2
+ export type { WithSeoOptions } from './withSeo.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { withSeo } from './withSeo.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,30 @@
1
+ import type { Plugin } from '@airdraft/core';
2
+ export interface WithSeoOptions {
3
+ /**
4
+ * Collection names to inject SEO fields into.
5
+ * Omit to apply to all collections.
6
+ */
7
+ collections?: string[];
8
+ }
9
+ /**
10
+ * Injects a pre-defined `seo` object field into the specified collections
11
+ * (or all collections if none are specified).
12
+ *
13
+ * Added fields:
14
+ * - `seo.title` — Meta / OG title
15
+ * - `seo.description` — Meta description
16
+ * - `seo.image` — Open Graph image URL
17
+ * - `seo.noIndex` — Opt out of indexing (default: false)
18
+ *
19
+ * ```ts
20
+ * import { withSeo } from '@airdraft/plugin-seo'
21
+ *
22
+ * plugins: [
23
+ * withSeo({ collections: ['posts', 'pages'] }),
24
+ * // or to apply to all:
25
+ * withSeo(),
26
+ * ]
27
+ * ```
28
+ */
29
+ export declare function withSeo(options?: WithSeoOptions): Plugin;
30
+ //# sourceMappingURL=withSeo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withSeo.d.ts","sourceRoot":"","sources":["../src/withSeo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAa,MAAM,gBAAgB,CAAA;AAMvD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAsBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,MAAM,CA2B5D"}
@@ -0,0 +1,63 @@
1
+ // ---------------------------------------------------------------------------
2
+ // SEO field schema
3
+ // ---------------------------------------------------------------------------
4
+ /** The `seo` object field injected by this plugin. */
5
+ const SEO_FIELD = {
6
+ type: 'object',
7
+ label: 'SEO',
8
+ fields: {
9
+ title: { type: 'string', label: 'Meta title' },
10
+ description: { type: 'text', label: 'Meta description' },
11
+ image: { type: 'image', label: 'OG image' },
12
+ noIndex: { type: 'boolean', label: 'No index', default: false },
13
+ },
14
+ };
15
+ // ---------------------------------------------------------------------------
16
+ // withSeo
17
+ // ---------------------------------------------------------------------------
18
+ /**
19
+ * Injects a pre-defined `seo` object field into the specified collections
20
+ * (or all collections if none are specified).
21
+ *
22
+ * Added fields:
23
+ * - `seo.title` — Meta / OG title
24
+ * - `seo.description` — Meta description
25
+ * - `seo.image` — Open Graph image URL
26
+ * - `seo.noIndex` — Opt out of indexing (default: false)
27
+ *
28
+ * ```ts
29
+ * import { withSeo } from '@airdraft/plugin-seo'
30
+ *
31
+ * plugins: [
32
+ * withSeo({ collections: ['posts', 'pages'] }),
33
+ * // or to apply to all:
34
+ * withSeo(),
35
+ * ]
36
+ * ```
37
+ */
38
+ export function withSeo(options = {}) {
39
+ return {
40
+ name: 'seo',
41
+ schema(schema) {
42
+ const updatedCollections = { ...schema.collections };
43
+ for (const [name, col] of Object.entries(schema.collections)) {
44
+ // Skip if a target list is given and this collection isn't in it
45
+ // (explicitly empty array = no collections; omitting = all collections)
46
+ if (options.collections !== undefined && !options.collections.includes(name))
47
+ continue;
48
+ // Skip if this collection already has a `seo` field
49
+ if ('seo' in col.fields)
50
+ continue;
51
+ updatedCollections[name] = {
52
+ ...col,
53
+ fields: {
54
+ ...col.fields,
55
+ seo: SEO_FIELD,
56
+ },
57
+ };
58
+ }
59
+ return { ...schema, collections: updatedCollections };
60
+ },
61
+ };
62
+ }
63
+ //# sourceMappingURL=withSeo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withSeo.js","sourceRoot":"","sources":["../src/withSeo.ts"],"names":[],"mappings":"AAcA,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,sDAAsD;AACtD,MAAM,SAAS,GAAG;IAChB,IAAI,EAAE,QAAiB;IACvB,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE;QACN,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,KAAK,EAAE,YAAY,EAAE;QACvD,WAAW,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,KAAK,EAAE,kBAAkB,EAAE;QACjE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAgB,EAAE,KAAK,EAAE,UAAU,EAAE;QACpD,OAAO,EAAE,EAAE,IAAI,EAAE,SAAkB,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE;KACzE;CACF,CAAA;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,OAAO,CAAC,UAA0B,EAAE;IAClD,OAAO;QACL,IAAI,EAAE,KAAK;QAEX,MAAM,CAAC,MAAiB;YACtB,MAAM,kBAAkB,GAAG,EAAE,GAAG,MAAM,CAAC,WAAW,EAAE,CAAA;YAEpD,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC7D,iEAAiE;gBACjE,wEAAwE;gBACxE,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,SAAQ;gBAEtF,oDAAoD;gBACpD,IAAI,KAAK,IAAI,GAAG,CAAC,MAAM;oBAAE,SAAQ;gBAEjC,kBAAkB,CAAC,IAAI,CAAC,GAAG;oBACzB,GAAG,GAAG;oBACN,MAAM,EAAE;wBACN,GAAG,GAAG,CAAC,MAAM;wBACb,GAAG,EAAE,SAAS;qBACf;iBACF,CAAA;YACH,CAAC;YAED,OAAO,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAA;QACvD,CAAC;KACF,CAAA;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@airdraft/plugin-seo",
3
+ "version": "0.1.0",
4
+ "description": "Airdraft SEO plugin — meta fields, OG, sitemap generation",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": ["dist", "README.md", "CHANGELOG.md"],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "clean": "rm -rf dist",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest",
21
+ "typecheck": "tsc --noEmit",
22
+ "prepublishOnly": "npm run build",
23
+ "release": "standard-version",
24
+ "release:patch": "standard-version --release-as patch",
25
+ "release:minor": "standard-version --release-as minor",
26
+ "release:major": "standard-version --release-as major"
27
+ },
28
+ "publishConfig": { "access": "public" },
29
+ "license": "MIT",
30
+ "devDependencies": {
31
+ "@types/node": "^20.0.0",
32
+ "standard-version": "^9.5.0",
33
+ "tsx": "^4.7.0",
34
+ "typescript": "^5.4.0",
35
+ "vitest": "^1.5.0"
36
+ },
37
+ "dependencies": {
38
+ "@airdraft/core": "*"
39
+ },
40
+ "engines": { "node": ">=18.0.0" }
41
+ }