denoland / deno-gfm

Server-side GitHub Flavored Markdown rendering for Deno
https://jsr.io/@deno/gfm
MIT License
226 stars 37 forks source link

Allow custom HTML #105

Closed ooker777 closed 4 months ago

ooker777 commented 9 months ago

I would like this code to render my custom marker. I don't want to style everything in the style.css.

import { CSS, render } from "https://deno.land/x/gfm/mod.ts";

const body = render(`# Hello, world!
<ul style="list-style-type: '&#x1F514; ';">
    <li>item</li>
    <li>item</li>
    <li>item</li>
</ul>

- Normal list
- Normal list
- Normal list
`);

export default function a() {
    return <main dangerouslySetInnerHTML={{ __html: body }}>
    {body}
    </main>
} 
deer commented 9 months ago

Again it would be great if you could provide more details. In this particular case about the current output and the expected output.

Although to keep things short, I guess you want to do something like this:

  const body = render(
    `# Hello, world!
<ul style="list-style-type: '&#x1F514; ';">
    <li>item</li>
    <li>item</li>
    <li>item</li>
</ul>

- Normal list
- Normal list
- Normal list
`,
    { allowedAttributes: { ul: ["style"] } },
  );
deer commented 9 months ago

Please close this if using allowedAttributes solves your problem.

ooker777 commented 9 months ago

It looks promising, but not working on my machine. The full code:

import { render } from "https://deno.land/x/gfm/mod.ts";

const body = render(
  `# Hello, world!
<ul style="list-style-type: '&#x1F514; ';">
  <li>item</li>
  <li>item</li>
  <li>item</li>
</ul>

- Normal list
- Normal list
- Normal list
`,
  { allowedAttributes: { ul: ["style"] } },
);

export default function a() {
  return <main dangerouslySetInnerHTML={{ __html: body }}>
  {body}
  </main>
} 

There is an error at allowedAttributes: Object literal may only specify known properties, and 'allowedAttributes' does not exist in type 'RenderOptions'.deno-ts(2353)

deer commented 9 months ago

It's always a good idea to be explicit about versions. You likely have an old version cached. Try specifying the version like this: https://deno.land/x/gfm@0.6.0/mod.ts

ooker777 commented 9 months ago

I see. I thought that if you don't specify the version, the runtime will check if the cache is already in the latest version or not. I also notice that the allowedAttributes option is only introduced at 0.6.0. However the release note doesn't note this. Is this normal?

deer commented 9 months ago

Blindly using the latest version can be, at worst, a huge security vulnerability and, slightly less bad, can sometimes cause your code to break. I can't really imagine a case where always using the latest is desired.

As for the caching issue, I guess if you had reran your code with -r it would have reloaded the dependencies.

For the release notes, most projects just take a list of all the PRs that have been merged. You can see I'm there:

feat: custom tags and attributes by @deer in #95

What more are you expecting?

ooker777 commented 9 months ago

I see. Thanks for your help

ooker777 commented 4 months ago

I import "@deno/gfm": "jsr:@deno/gfm@^0.8.2" in the import map and use this code in routes/index.tsx:

import { render } from "@deno/gfm";

const markdown = `
# Markdown
<div style="color:red">red</div>
<button>
  button
</button>
`;

const html = render(markdown, {
  baseUrl: "https://example.com",
  allowedAttributes: { div: ["style"] },
  allowedTags : ['div', 'button'] 
});

export default function Test() {
  return (
    <div
      dangerouslySetInnerHTML={{ __html: render(html) }}
    />
  );
}

The red text isn't red and the button isn't a button. Do you have any idea?

deer commented 4 months ago

Your example isn't immediately runnable. Are you using fresh? Here's what I did to get something working, by using the test framework in this repo:

diff --git a/test/test_utils.ts b/test/test_utils.ts
index 2aa8e42..8095367 100644
--- a/test/test_utils.ts
+++ b/test/test_utils.ts
@@ -9,7 +9,7 @@ type TestCase = {
   renderOptions?: RenderOptions;
 };

-export type TestCases = "basicMarkdownTable" | "footnotes";
+export type TestCases = "basicMarkdownTable" | "footnotes" | "105";

 export const testCases: Record<TestCases, TestCase> = {
   "basicMarkdownTable": {
@@ -24,6 +24,18 @@ export const testCases: Record<TestCases, TestCase> = {
   "footnotes": {
     markdown: Deno.readTextFileSync("./test/fixtures/footnote.md"),
   },
+  "105": {
+    markdown: `# Markdown
+<div style="color:red">red</div>
+<button>
+  button
+</button>`,
+    renderOptions: {
+      baseUrl: "https://example.com",
+      allowedAttributes: { div: ["style"] },
+      allowedTags: ["div", "button"],
+    },
+  },
 };

and then I run deno task server to launch the test server. Going to http://localhost:8000/105 shows me some red text and a button.

ooker777 commented 4 months ago

Yes I'm using Fresh. Just install the latest instance. Using the test framework of the repo I also get the color as well. Any idea?

deer commented 4 months ago

I looked at your code more closely. Why are you calling the render function twice? You have:

export default function Test() {
  return (
    <div
      dangerouslySetInnerHTML={{ __html: render(html) }}
    />
  );
}

but it works when I change it to:

export default function Test() {
  return (
    <div
      dangerouslySetInnerHTML={{ __html: html }}
    />
  );
}
ooker777 commented 4 months ago

I'm embarrassed. Thanks for your time.