writr 6.0.0 → 6.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 CHANGED
@@ -22,6 +22,7 @@
22
22
  * Github Flavor Markdown (remark-gfm).
23
23
  * Emoji Support (remark-emoji).
24
24
  * MDX Support (remark-mdx).
25
+ * Raw HTML Passthrough (rehype-raw).
25
26
  * Built in Hooks for adding code to render pipeline.
26
27
  * AI-powered metadata generation, SEO, and translation via the [Vercel AI SDK](https://sdk.vercel.ai).
27
28
 
@@ -118,6 +119,7 @@ const writrOptions = {
118
119
  gfm: true,
119
120
  math: true,
120
121
  mdx: true,
122
+ rawHtml: false,
121
123
  caching: true,
122
124
  }
123
125
  };
@@ -142,6 +144,7 @@ const writrOptions = {
142
144
  gfm: true,
143
145
  math: true,
144
146
  mdx: true,
147
+ rawHtml: false,
145
148
  caching: true,
146
149
  }
147
150
  };
@@ -190,11 +193,16 @@ Accessing the default options for this instance of Writr. Here is the default se
190
193
  gfm: true,
191
194
  math: true,
192
195
  mdx: false,
196
+ rawHtml: false,
193
197
  caching: true,
194
198
  }
195
199
  }
196
200
  ```
197
201
 
202
+ By default, raw HTML in markdown (such as `<iframe>`, `<video>`, or `<div>` tags) is stripped during rendering. Set `rawHtml: true` to preserve raw HTML elements and their attributes in the rendered output. This is useful for embedding videos, widgets, or custom HTML in your markdown content.
203
+
204
+ **Note:** Setting `mdx: true` also enables raw HTML passthrough as part of the MDX specification. The `rawHtml` option is for enabling raw HTML in standard markdown without using MDX.
205
+
198
206
  ## `.frontmatter`
199
207
 
200
208
  Accessing the frontmatter for this instance of Writr. This is a `Record<string, any>` and can be set via the `.content` property.
@@ -921,14 +929,13 @@ Generate SEO metadata using `writr.ai.getSEO()`. By default all fields are gener
921
929
  ```typescript
922
930
  const seo = await writr.ai.getSEO();
923
931
  console.log(seo.slug); // "getting-started-with-writr"
924
- console.log(seo.canonical); // "https://example.com/getting-started-with-writr"
925
932
  console.log(seo.openGraph?.title); // "Getting Started with Writr"
926
933
 
927
934
  // Generate only a slug
928
935
  const seo = await writr.ai.getSEO({ slug: true });
929
936
  ```
930
937
 
931
- **Available fields:** `slug`, `canonical`, `openGraph` (includes `title`, `description`, `image`).
938
+ **Available fields:** `slug`, `openGraph` (includes `title`, `description`, `image`).
932
939
 
933
940
  ## Translation
934
941
 
package/dist/writr.d.ts CHANGED
@@ -26,6 +26,7 @@ type WritrOptions = {
26
26
  * @property {boolean} [gfm] - Github flavor markdown (default: true)
27
27
  * @property {boolean} [math] - Math support (default: true)
28
28
  * @property {boolean} [mdx] - MDX support (default: false)
29
+ * @property {boolean} [rawHtml] - Raw HTML passthrough (default: false)
29
30
  * @property {boolean} [caching] - Caching (default: true)
30
31
  */
31
32
  type RenderOptions = {
@@ -36,6 +37,7 @@ type RenderOptions = {
36
37
  gfm?: boolean;
37
38
  math?: boolean;
38
39
  mdx?: boolean;
40
+ rawHtml?: boolean;
39
41
  caching?: boolean;
40
42
  };
41
43
  /**
@@ -116,10 +118,6 @@ type WritrSEO = {
116
118
  * A URL-safe identifier for the document.
117
119
  */
118
120
  slug?: string;
119
- /**
120
- * The preferred canonical URL for the document.
121
- */
122
- canonical?: string;
123
121
  /**
124
122
  * Open Graph metadata used by social platforms.
125
123
  */
@@ -240,10 +238,6 @@ type WritrGetSEOOptions = {
240
238
  * Generate a URL-safe slug.
241
239
  */
242
240
  slug?: boolean;
243
- /**
244
- * Generate a canonical URL value.
245
- */
246
- canonical?: boolean;
247
241
  /**
248
242
  * Generate Open Graph metadata for the document.
249
243
  */
package/dist/writr.js CHANGED
@@ -6,6 +6,7 @@ import parse from "html-react-parser";
6
6
  import * as yaml from "js-yaml";
7
7
  import rehypeHighlight from "rehype-highlight";
8
8
  import rehypeKatex from "rehype-katex";
9
+ import rehypeRaw from "rehype-raw";
9
10
  import rehypeSlug from "rehype-slug";
10
11
  import rehypeStringify from "rehype-stringify";
11
12
  import remarkEmoji from "remark-emoji";
@@ -332,7 +333,7 @@ ${this.writr.content}`
332
333
  );
333
334
  }
334
335
  resolveSEOFields(options) {
335
- const allFields = ["slug", "canonical", "openGraph"];
336
+ const allFields = ["slug", "openGraph"];
336
337
  if (!options) {
337
338
  return allFields;
338
339
  }
@@ -420,12 +421,6 @@ ${this.writr.content}`
420
421
  z.string().describe("A URL-safe identifier for the document")
421
422
  ]);
422
423
  }
423
- if (fieldSet.has("canonical")) {
424
- entries.push([
425
- "canonical",
426
- z.string().describe("The preferred canonical URL for the document")
427
- ]);
428
- }
429
424
  if (fieldSet.has("openGraph")) {
430
425
  entries.push([
431
426
  "openGraph",
@@ -467,6 +462,7 @@ var Writr = class extends Hookified {
467
462
  gfm: true,
468
463
  math: true,
469
464
  mdx: false,
465
+ rawHtml: false,
470
466
  caching: true
471
467
  }
472
468
  };
@@ -948,7 +944,23 @@ ${yamlString}---
948
944
  if (options.emoji) {
949
945
  processor.use(remarkEmoji);
950
946
  }
951
- processor.use(remarkRehype);
947
+ if (options.mdx) {
948
+ processor.use(remarkMDX);
949
+ }
950
+ const rehypeOptions = {};
951
+ if (options.rawHtml) {
952
+ rehypeOptions.allowDangerousHtml = true;
953
+ }
954
+ if (options.mdx) {
955
+ rehypeOptions.handlers = {
956
+ mdxJsxFlowElement: mdxJsxHandler,
957
+ mdxJsxTextElement: mdxJsxHandler
958
+ };
959
+ }
960
+ processor.use(remarkRehype, rehypeOptions);
961
+ if (options.rawHtml) {
962
+ processor.use(rehypeRaw);
963
+ }
952
964
  if (options.slug) {
953
965
  processor.use(rehypeSlug);
954
966
  }
@@ -958,9 +970,6 @@ ${yamlString}---
958
970
  if (options.math) {
959
971
  processor.use(remarkMath).use(rehypeKatex);
960
972
  }
961
- if (options.mdx) {
962
- processor.use(remarkMDX);
963
- }
964
973
  processor.use(rehypeStringify);
965
974
  return processor;
966
975
  }
@@ -986,12 +995,33 @@ ${yamlString}---
986
995
  if (options.mdx !== void 0) {
987
996
  current.mdx = options.mdx;
988
997
  }
998
+ if (options.rawHtml !== void 0) {
999
+ current.rawHtml = options.rawHtml;
1000
+ }
989
1001
  if (options.caching !== void 0) {
990
1002
  current.caching = options.caching;
991
1003
  }
992
1004
  return current;
993
1005
  }
994
1006
  };
1007
+ function mdxJsxHandler(state, node) {
1008
+ const properties = {};
1009
+ for (const attr of node.attributes) {
1010
+ if (attr.type === "mdxJsxAttribute") {
1011
+ if (attr.value === null) {
1012
+ properties[attr.name] = true;
1013
+ } else if (typeof attr.value === "string") {
1014
+ properties[attr.name] = attr.value;
1015
+ }
1016
+ }
1017
+ }
1018
+ return {
1019
+ type: "element",
1020
+ tagName: node.name ?? "div",
1021
+ properties,
1022
+ children: state.all(node)
1023
+ };
1024
+ }
995
1025
  export {
996
1026
  Writr,
997
1027
  WritrAI,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "writr",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "description": "Markdown Rendering Simplified",
5
5
  "type": "module",
6
6
  "main": "./dist/writr.js",
@@ -58,6 +58,7 @@
58
58
  "react": "^19.2.4",
59
59
  "rehype-highlight": "^7.0.2",
60
60
  "rehype-katex": "^7.0.1",
61
+ "rehype-raw": "^7.0.0",
61
62
  "rehype-slug": "^6.0.0",
62
63
  "rehype-stringify": "^10.0.1",
63
64
  "remark-emoji": "^5.0.2",