@codepress/blog 0.0.0-stage → 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/README.md +118 -2
- package/dist/blog.css +227 -0
- package/dist/chunks/BlogEditor-VF3UAJB6.js +2527 -0
- package/dist/chunks/chunk-3GCZFCUK.js +51 -0
- package/dist/chunks/chunk-3WRTL63O.js +106 -0
- package/dist/chunks/chunk-AEQDRBA3.js +128 -0
- package/dist/chunks/chunk-AJVVTSKZ.js +90 -0
- package/dist/chunks/chunk-EICE5ONB.js +197 -0
- package/dist/chunks/chunk-HWR3R5MU.js +48 -0
- package/dist/chunks/chunk-QX6276YA.js +0 -0
- package/dist/chunks/chunk-TYX2HJZC.js +68 -0
- package/dist/chunks/chunk-UA243KAQ.js +104 -0
- package/dist/chunks/chunk-WJVZD4UI.js +114 -0
- package/dist/chunks/chunk-XLJBCIXI.js +93 -0
- package/dist/cli.js +440 -0
- package/dist/content-source.d.ts +31 -0
- package/dist/editor/BlogEditor.d.ts +37 -0
- package/dist/editor/BlogEditorMount.d.ts +64 -0
- package/dist/editor/DocumentActions.d.ts +39 -0
- package/dist/editor/EditDesignLink.d.ts +30 -0
- package/dist/editor/NewPostForm.d.ts +10 -0
- package/dist/editor/SlashMenu.d.ts +5 -0
- package/dist/editor/Toolbar.d.ts +39 -0
- package/dist/editor/blocks.d.ts +5 -0
- package/dist/editor/client.d.ts +88 -0
- package/dist/editor/client.js +6 -0
- package/dist/editor/component-node.d.ts +14 -0
- package/dist/editor/config.d.ts +24 -0
- package/dist/editor/document.d.ts +47 -0
- package/dist/editor/extensions.d.ts +19 -0
- package/dist/editor/header.d.ts +20 -0
- package/dist/editor/index.d.ts +11 -0
- package/dist/editor/index.js +209 -0
- package/dist/editor/paste-guard.d.ts +14 -0
- package/dist/editor/primitives.d.ts +17 -0
- package/dist/editor/props-form.d.ts +17 -0
- package/dist/editor/serialize.d.ts +34 -0
- package/dist/editor/slash-command.d.ts +21 -0
- package/dist/feed.d.ts +4 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +72 -0
- package/dist/next/app.d.ts +34 -0
- package/dist/next/config.d.ts +44 -0
- package/dist/next/index.d.ts +2 -0
- package/dist/next/index.js +94 -0
- package/dist/next/pages.d.ts +33 -0
- package/dist/next/pages.js +167 -0
- package/dist/next/routes.d.ts +14 -0
- package/dist/next/routes.js +37 -0
- package/dist/next/views.d.ts +18 -0
- package/dist/react/components.d.ts +18 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +15 -0
- package/dist/react/render.d.ts +7 -0
- package/dist/registry.d.ts +95 -0
- package/dist/sanitize.d.ts +33 -0
- package/dist/schema.d.ts +24 -0
- package/dist/seo.d.ts +63 -0
- package/dist/sitemap.d.ts +4 -0
- package/dist/xml.d.ts +1 -0
- package/package.json +92 -4
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ChildNode } from "domhandler";
|
|
2
|
+
/**
|
|
3
|
+
* An isomorphic allowlist sanitizer derived from the registry.
|
|
4
|
+
*
|
|
5
|
+
* This is the boundary between authored content and the page: the renderer
|
|
6
|
+
* always runs it, so a post that was never sanitized upstream still cannot put
|
|
7
|
+
* a script, an event handler or a `javascript:` URL on the page. It works on
|
|
8
|
+
* the parsed tree rather than on strings, so there is no regex over markup to
|
|
9
|
+
* get wrong.
|
|
10
|
+
*/
|
|
11
|
+
export interface SanitizeIssue {
|
|
12
|
+
kind: "element" | "attribute" | "url" | "props";
|
|
13
|
+
tag: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SanitizeResult {
|
|
18
|
+
nodes: ChildNode[];
|
|
19
|
+
issues: SanitizeIssue[];
|
|
20
|
+
}
|
|
21
|
+
/** Elements dropped together with everything inside them. */
|
|
22
|
+
export declare const DROP_WITH_CONTENT: Set<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns the URL when it is safe to emit, otherwise null. Only the schemes in
|
|
25
|
+
* the registry pass; site-relative paths (`/x`, `#x`) are allowed, but not
|
|
26
|
+
* protocol-relative ones (`//host`, `/\host`), which browsers resolve to
|
|
27
|
+
* another origin. Any whitespace or control character rejects the value:
|
|
28
|
+
* browsers strip them inside a scheme, so `java\tscript:` must not slip by.
|
|
29
|
+
*/
|
|
30
|
+
export declare function sanitizeUrl(value: string): string | null;
|
|
31
|
+
/** Parses `html` and returns the sanitized tree plus what was removed. */
|
|
32
|
+
export declare function sanitizeNodes(html: string): SanitizeResult;
|
|
33
|
+
export declare function sanitizeHtml(html: string): string;
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ComponentContent } from "./registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Version of the `content-schema.json` shape. Bump only when a key or its
|
|
4
|
+
* meaning changes; adding an element or component does not change it.
|
|
5
|
+
*/
|
|
6
|
+
export declare const schemaVersion = 1;
|
|
7
|
+
export interface ContentSchema {
|
|
8
|
+
version: number;
|
|
9
|
+
elements: Record<string, {
|
|
10
|
+
attributes: string[];
|
|
11
|
+
urlAttributes?: string[];
|
|
12
|
+
}>;
|
|
13
|
+
components: Record<string, {
|
|
14
|
+
attributes: string[];
|
|
15
|
+
content: ComponentContent;
|
|
16
|
+
props: Record<string, unknown>;
|
|
17
|
+
}>;
|
|
18
|
+
urlSchemes: string[];
|
|
19
|
+
/** Site-relative URLs (`/x`, `#x`) are allowed wherever a URL is. */
|
|
20
|
+
relativeUrls: boolean;
|
|
21
|
+
meta: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
/** Builds the contract a site serves at `<blog>/_schema.json` from the registry. */
|
|
24
|
+
export declare function buildContentSchema(): ContentSchema;
|
package/dist/seo.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { PostMeta } from "./registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Where a blog lives and who publishes it. Canonical URLs, structured data,
|
|
4
|
+
* the feed and the sitemap are all built from this, never from the request, so
|
|
5
|
+
* a blog mounted at `https://acme.com/blog` or `https://blog.acme.com` names
|
|
6
|
+
* itself correctly.
|
|
7
|
+
*/
|
|
8
|
+
export interface BlogSite {
|
|
9
|
+
/** Absolute URL of the blog index, for example `https://acme.com/blog`. */
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
/** The publisher's name: default author, breadcrumb root, JSON-LD publisher. */
|
|
12
|
+
name: string;
|
|
13
|
+
/** The publisher's home page. Defaults to the origin of `baseUrl`. */
|
|
14
|
+
homeUrl?: string;
|
|
15
|
+
/** The feed's channel title, for example `Acme Blog`. */
|
|
16
|
+
title: string;
|
|
17
|
+
/** The feed's channel description. */
|
|
18
|
+
description: string;
|
|
19
|
+
/** Absolute URL of the image for posts without an `ogImage`. */
|
|
20
|
+
defaultImage: string;
|
|
21
|
+
/** The feed's language. Defaults to `en`. */
|
|
22
|
+
language?: string;
|
|
23
|
+
}
|
|
24
|
+
/** The blog index URL, without a trailing slash. */
|
|
25
|
+
export declare function blogUrl(site: BlogSite): string;
|
|
26
|
+
export declare function postUrl(site: BlogSite, slug: string): string;
|
|
27
|
+
export declare function feedUrl(site: BlogSite): string;
|
|
28
|
+
export declare function homeUrl(site: BlogSite): string;
|
|
29
|
+
/** Escapes `<` so authored text can never close the JSON-LD script tag. */
|
|
30
|
+
export declare function jsonLd(value: unknown): string;
|
|
31
|
+
/** A post's `ogImage` as an absolute URL; site-relative paths use the blog's origin. */
|
|
32
|
+
export declare function absoluteImage(site: BlogSite, ogImage: string | undefined): string;
|
|
33
|
+
export declare function blogPostingJsonLd(site: BlogSite, slug: string, meta: PostMeta): {
|
|
34
|
+
keywords?: string | undefined;
|
|
35
|
+
"@context": string;
|
|
36
|
+
"@type": string;
|
|
37
|
+
headline: string;
|
|
38
|
+
description: string;
|
|
39
|
+
url: string;
|
|
40
|
+
mainEntityOfPage: string;
|
|
41
|
+
datePublished: string;
|
|
42
|
+
dateModified: string;
|
|
43
|
+
image: string;
|
|
44
|
+
author: {
|
|
45
|
+
"@type": string;
|
|
46
|
+
name: string;
|
|
47
|
+
}[];
|
|
48
|
+
publisher: {
|
|
49
|
+
"@type": string;
|
|
50
|
+
name: string;
|
|
51
|
+
url: string;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export declare function breadcrumbJsonLd(site: BlogSite, slug: string, title: string): {
|
|
55
|
+
"@context": string;
|
|
56
|
+
"@type": string;
|
|
57
|
+
itemListElement: {
|
|
58
|
+
"@type": string;
|
|
59
|
+
position: number;
|
|
60
|
+
name: string;
|
|
61
|
+
item: string;
|
|
62
|
+
}[];
|
|
63
|
+
};
|
package/dist/xml.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function escapeXml(value: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,94 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codepress/blog",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Render a CodePress blog: registry, sanitizer, schema, SEO, feed, sitemap, content source and React renderer.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"*.css"
|
|
8
|
+
],
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./react": {
|
|
15
|
+
"types": "./dist/react/index.d.ts",
|
|
16
|
+
"default": "./dist/react/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./next": {
|
|
19
|
+
"types": "./dist/next/index.d.ts",
|
|
20
|
+
"default": "./dist/next/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./next/pages": {
|
|
23
|
+
"types": "./dist/next/pages.d.ts",
|
|
24
|
+
"default": "./dist/next/pages.js"
|
|
25
|
+
},
|
|
26
|
+
"./next/routes": {
|
|
27
|
+
"types": "./dist/next/routes.d.ts",
|
|
28
|
+
"default": "./dist/next/routes.js"
|
|
29
|
+
},
|
|
30
|
+
"./editor": {
|
|
31
|
+
"types": "./dist/editor/index.d.ts",
|
|
32
|
+
"default": "./dist/editor/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./editor/client": {
|
|
35
|
+
"types": "./dist/editor/client.d.ts",
|
|
36
|
+
"default": "./dist/editor/client.js"
|
|
37
|
+
},
|
|
38
|
+
"./blog.css": "./dist/blog.css"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
45
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
46
|
+
"dom-serializer": "^3.1.1",
|
|
47
|
+
"domhandler": "^6.0.1",
|
|
48
|
+
"html-react-parser": "^6.1.8",
|
|
49
|
+
"htmlparser2": "^12.0.0",
|
|
50
|
+
"lucide-react": "^0.541.0",
|
|
51
|
+
"tailwind-merge": "^3.5.0",
|
|
52
|
+
"zod": "^4.3.6"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"@tiptap/extension-image": "3.24.0",
|
|
56
|
+
"@tiptap/extension-unique-id": "3.24.0",
|
|
57
|
+
"@tiptap/pm": "3.24.0",
|
|
58
|
+
"@tiptap/react": "3.24.0",
|
|
59
|
+
"@tiptap/starter-kit": "3.24.0",
|
|
60
|
+
"@tiptap/suggestion": "3.24.0",
|
|
61
|
+
"next": ">=15.0.0",
|
|
62
|
+
"react": "^19.0.0",
|
|
63
|
+
"react-dom": "^19.0.0"
|
|
64
|
+
},
|
|
65
|
+
"peerDependenciesMeta": {
|
|
66
|
+
"@tiptap/extension-image": {
|
|
67
|
+
"optional": true
|
|
68
|
+
},
|
|
69
|
+
"@tiptap/extension-unique-id": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"@tiptap/pm": {
|
|
73
|
+
"optional": true
|
|
74
|
+
},
|
|
75
|
+
"@tiptap/react": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"@tiptap/starter-kit": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"@tiptap/suggestion": {
|
|
82
|
+
"optional": true
|
|
83
|
+
},
|
|
84
|
+
"next": {
|
|
85
|
+
"optional": true
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"bin": {
|
|
89
|
+
"codepress-blog": "./dist/cli.js"
|
|
90
|
+
},
|
|
91
|
+
"files": [
|
|
92
|
+
"dist"
|
|
93
|
+
]
|
|
94
|
+
}
|