@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.
Files changed (61) hide show
  1. package/README.md +118 -2
  2. package/dist/blog.css +227 -0
  3. package/dist/chunks/BlogEditor-VF3UAJB6.js +2527 -0
  4. package/dist/chunks/chunk-3GCZFCUK.js +51 -0
  5. package/dist/chunks/chunk-3WRTL63O.js +106 -0
  6. package/dist/chunks/chunk-AEQDRBA3.js +128 -0
  7. package/dist/chunks/chunk-AJVVTSKZ.js +90 -0
  8. package/dist/chunks/chunk-EICE5ONB.js +197 -0
  9. package/dist/chunks/chunk-HWR3R5MU.js +48 -0
  10. package/dist/chunks/chunk-QX6276YA.js +0 -0
  11. package/dist/chunks/chunk-TYX2HJZC.js +68 -0
  12. package/dist/chunks/chunk-UA243KAQ.js +104 -0
  13. package/dist/chunks/chunk-WJVZD4UI.js +114 -0
  14. package/dist/chunks/chunk-XLJBCIXI.js +93 -0
  15. package/dist/cli.js +440 -0
  16. package/dist/content-source.d.ts +31 -0
  17. package/dist/editor/BlogEditor.d.ts +37 -0
  18. package/dist/editor/BlogEditorMount.d.ts +64 -0
  19. package/dist/editor/DocumentActions.d.ts +39 -0
  20. package/dist/editor/EditDesignLink.d.ts +30 -0
  21. package/dist/editor/NewPostForm.d.ts +10 -0
  22. package/dist/editor/SlashMenu.d.ts +5 -0
  23. package/dist/editor/Toolbar.d.ts +39 -0
  24. package/dist/editor/blocks.d.ts +5 -0
  25. package/dist/editor/client.d.ts +88 -0
  26. package/dist/editor/client.js +6 -0
  27. package/dist/editor/component-node.d.ts +14 -0
  28. package/dist/editor/config.d.ts +24 -0
  29. package/dist/editor/document.d.ts +47 -0
  30. package/dist/editor/extensions.d.ts +19 -0
  31. package/dist/editor/header.d.ts +20 -0
  32. package/dist/editor/index.d.ts +11 -0
  33. package/dist/editor/index.js +209 -0
  34. package/dist/editor/paste-guard.d.ts +14 -0
  35. package/dist/editor/primitives.d.ts +17 -0
  36. package/dist/editor/props-form.d.ts +17 -0
  37. package/dist/editor/serialize.d.ts +34 -0
  38. package/dist/editor/slash-command.d.ts +21 -0
  39. package/dist/feed.d.ts +4 -0
  40. package/dist/index.d.ts +8 -0
  41. package/dist/index.js +72 -0
  42. package/dist/next/app.d.ts +34 -0
  43. package/dist/next/config.d.ts +44 -0
  44. package/dist/next/index.d.ts +2 -0
  45. package/dist/next/index.js +94 -0
  46. package/dist/next/pages.d.ts +33 -0
  47. package/dist/next/pages.js +167 -0
  48. package/dist/next/routes.d.ts +14 -0
  49. package/dist/next/routes.js +37 -0
  50. package/dist/next/views.d.ts +18 -0
  51. package/dist/react/components.d.ts +18 -0
  52. package/dist/react/index.d.ts +2 -0
  53. package/dist/react/index.js +15 -0
  54. package/dist/react/render.d.ts +7 -0
  55. package/dist/registry.d.ts +95 -0
  56. package/dist/sanitize.d.ts +33 -0
  57. package/dist/schema.d.ts +24 -0
  58. package/dist/seo.d.ts +63 -0
  59. package/dist/sitemap.d.ts +4 -0
  60. package/dist/xml.d.ts +1 -0
  61. 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;
@@ -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
+ };
@@ -0,0 +1,4 @@
1
+ import type { PostSummary } from "./content-source.js";
2
+ import { type BlogSite } from "./seo.js";
3
+ /** A sitemap of the blog index and every post; `posts` are newest first. */
4
+ export declare function sitemapXml(site: BlogSite, posts: PostSummary[]): string;
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.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
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
+ }