Git Product home page Git Product logo

svelte-exmarkdown's People

Contributors

agarwalpragy avatar dciug avatar github-actions[bot] avatar jacokok avatar renovate[bot] avatar ssssota avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

svelte-exmarkdown's Issues

Warnings in SvelteKit

I think they just need a default value, but my console.log goes crazy. All I did is import the Markdown component:

warnings

J

Raw HTML rendered as text

The problem

According to the original Markdown spec, the CommonMark spec and the GitHub Flavored Markdown spec, HTML blocks are specified as valid Markdown. However, attempting to use HTML in Markdown with svelte-exmarkdown, it will get rendered as text instead:

Input:

# Hello
<div>hello</div>

Output:

<h1>Hello</h1>
&lt;div&gt;hello&lt;/div&gt;

I understand that this might the be intended output for some use cases – for example if the Markdown source is to be specified by the user, this approach is the absolutely safest way to avoid XSS. However, there are situations where one might want to allow a subset of HTML, or even all HTML, if the Markdown source is trusted.

Detailed investigation

Logging the AST in each stage reveals that the parsed Markdown tree:

{
  type: "root",
  children: [
    {
      type: "heading",
      depth: 1,
      children: [{ type: "text", value: "Hello" }],
    },
    {
      type: "html",
      value: "<div>hello</div>",
    },
  ],
}

... gets turned to the following HTML AST:

{
  type: "root",
  children: [
    {
      type: "element",
      tagName: "h1",
      children: [{ type: "text", value: "Hello" }],
    },
    {
      type: "raw",
      value: "<div>hello</div>",
    },
  ],
}

I don't understand how exactly the renderer decides to render type: "raw" as a text node, but somehow it does.

Non-solution

Note, however, that this can't be solved by adding a rendering rule that would output {@html value}, because the raw HTML may contain unmatched tags. For example, consider this Markdown snippet:

<div>

# Hello
</div>

In the unified pipeline, it will get turned to the following HAST:

{
  type: "root",
  children: [
    { type: "raw", value: "<div>" },
    {
      type: "element",
      tagName: "h1",
      children: [{ type: "text", value: "Hello" }],
    },
    { type: "raw", value: "</div>" },
  ],
}

Attempting to render this HAST using the {@html ...} directive would output the following result:

<div></div>
<h1>Hello</h1>
<div></div>

(see for example this demonstration), rather than the intended tree:

<div>
  <h1>Hello</h1>
</div>

Walkaround

Since the AST can contain effectively unparsed tokens, the most straightforward and robust solution seems to be to stringify and re-parse it. This is an example of a svelte-exmarkdown plugin that does just that:

import type { Plugin } from 'svelte-exmarkdown';
import { unified } from 'unified';
import { toHtml } from 'hast-util-to-html';
import rehypeParse from 'rehype-parse';

export const rawHtml: Plugin = {
	rehypePlugin: () => (node) => {
		const str = toHtml(node, { allowDangerousHtml: true });
		console.log(str);
		return unified().use(rehypeParse, { fragment: true }).parse(str);
	},
};

A serious problem with this approach is that it cannot distinguish harmless HTML from a XSS attempt, so it's only ever useful if one has absolute control over the Markdown source. A somewhat less serious problem is the loss of the AST's metadata (eg. the position props).

Warnings in SvelteKit, part 2

First up: thanks for a wonderful library! It looks exactly like what I needed.

Issue description

When starting to use it I do immediately notice an issue (running v1.1.7). It seems to be a follow-up to #17 where related warnings showed up in the browser console.

That issue was resolved and I indeed don't see the warnings in my browser. However, they've been replaced by new warnings when building a SvelteKit (TypeScript based) project now. In fact they are the same warnings that were also present in the GitHub Actions output for the commit that fixed the browser warnings.

Repro

Run npm create svelte@latest . in your test folder and choose these options:

Welcome to SvelteKit!

√ Where should we create your project?
  (leave blank to use current directory) ...
√ Which Svelte app template? » Skeleton project
√ Add type checking with TypeScript? » Yes, using TypeScript syntax
√ Add ESLint for code linting? ... No / Yes
√ Add Prettier for code formatting? ... No / Yes
√ Add Playwright for browser testing? ... No / Yes
√ Add Vitest for unit testing? ... No / Yes

Then run npm i -D svelte-exmarkdown (it gave me 1.1.7), and change the +page.svelte that was generated into:

<script>
	import Markdown from 'svelte-exmarkdown';
	let md = '# Hello world!';
</script>

<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>

<textarea bind:value={md} />
<Markdown {md} />

And run npm run dev -- --open.

Output

The actual resulting output on the console includes:

18:13:31 [vite-plugin-svelte] ssr compile in progress ...
18:13:31 [vite-plugin-svelte] ssr compile done.
package                         files     time    avg
svelte-exmarkdown-issue-repro       9   80.3ms  8.9ms
18:13:33 [vite-plugin-svelte] prebundle libraries done.
package                         files     time     avg
svelte-exmarkdown-issue-repro       5   80.9ms  16.2ms
18:13:33 [vite] ✨ new dependencies optimized: svelte-exmarkdown
18:13:33 [vite] ✨ optimized dependencies changed. reloading
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/Renderer.svelte:5:11 Renderer has unused export property 'type'. If it is for external reference only, please consider using `export const type`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/Renderer.svelte:6:11 Renderer has unused export property 'position'. If it is for external reference only, please consider using `export const position`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/Text.svelte:2:11 Text has unused export property 'type'. If it is for external reference only, please consider using `export const type`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/Text.svelte:3:11 Text has unused export property 'position'. If it is for external reference only, please consider using `export const position`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/Text.svelte:4:11 Text has unused export property '__index'. If it is for external reference only, please consider using `export const __index`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/Children.svelte:3:11 Children has unused export property 'type'. If it is for external reference only, please consider using `export const type`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/Children.svelte:4:11 Children has unused export property 'position'. If it is for external reference only, please consider using `export const position`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/Children.svelte:5:11 Children has unused export property '__index'. If it is for external reference only, please consider using `export const __index`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/html/Default.svelte:5:11 Default has unused export property 'type'. If it is for external reference only, please consider using `export const type`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/html/Default.svelte:6:11 Default has unused export property 'position'. If it is for external reference only, please consider using `export const position`
18:13:34 [vite-plugin-svelte] /node_modules/svelte-exmarkdown/renderer/html/Default.svelte:7:11 Default has unused export property '__index'. If it is for external reference only, please consider using `export const __index`
18:13:34 [vite-plugin-svelte] ssr compile done.
package                         files     time    avg
svelte-exmarkdown-issue-repro       8   32.6ms  4.1ms

The expected output would not include the warnings.

Workaround

For the moment I've added this to my svelte.config.js export default config object:

  // Workaround for: https://github.com/ssssota/svelte-exmarkdown/issues/23
  onwarn: (warning, handler) => {
    if (warning?.filename?.includes('svelte-exmarkdown') && warning?.code === 'unused-export-let') {
      return;
    }
    handler(warning);
  },

Just to suppress the warning for the time being.

Finally

The library otherwise seems to work just fine, at first glance. They're just warnings, after all.

Thank you for considering. If I can assist any further: let me know!

How does it sanitize the output

I think I'm going to give this package a try and am looking at the source code. Could you point out to me how it sanitizes the output?

help: Pass options to plugin

How do you pass options to plugins ?

I tried to add remark-behead. But I need to give it some options like {depth:2}. How is it acheived ?

import behead from 'remark-behead';
const beheadPlugin = { remarkPlugin: behead };

<Markdown plugins={[beheadPlugin]} md={...} />

Cannot `parse` without `parser`

Hi, I notice this error during server side rendering, with version 3.0.1:

Cannot `parse` without `parser`

Which seems to be an error throw by unified, and I can find their test case here:

https://github.com/unifiedjs/unified/blob/67949bb47abe4da52a20f1472ef9b0a9f0a6d123/test/parse.js#L16C9-L16C40

And this is how I am using the markdown component. I created a wrapper like this:

<script
  context="module"
  lang="ts">
  // @ts-expect-error no type available for this package yet, it is possible this will break in the future
  import removeComments from "remark-remove-comments";
  import Markdown from "svelte-exmarkdown";
  import { gfmPlugin } from "svelte-exmarkdown/gfm";
</script>

<script lang="ts">
  export let md: string;
</script>

<Markdown
  {md}
  plugins={[
    gfmPlugin(),
    {
      remarkPlugin: [removeComments]
    },
    {
      renderer: {
        strong: "b"
      }
    }
  ]}
/>

And then use it like this:

<Markdown md={"Hello world"} />

For now I have mitigated the issue using app/environment, and only render this component in client side. This avoided the issue, but this is not ideal for SEO

    import { browser } from '$app/environment'
   // …
               {#if typeof data.product.description === "string" && browser}
                <Markdown md={data.product.description} />
            {/if}

Also downgrading to 3.0.0 does not have this error

Package breaks apps deployed to Cloudflare Pages

Hi, @ssssota

Great work on svelte-exmarkdown. Thank you.

As I was trying to use it for my use case, I ran into some challenges, some highlighted in #113, but so far, the most pressing is the fact that when using this package in the Cloudflare Pages environment, they break, for reasons, more or less, related to how CF doesn't support a true node runtime - or so I hear.

These are the errors output in the console.

20:14:27.378 | ✘ [ERROR] Could not resolve "node:process"
-- | --
20:14:27.379 |  
20:14:27.379 | .svelte-kit/output/server/entries/pages/_page.svelte.js:3:17:
20:14:27.380 | 3 │ import proc from "node:process";
20:14:27.380 |~~~~~~~~~~~~~~
20:14:27.381 |  
20:14:27.381 | The package "node:process" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
20:14:27.381 |  
20:14:27.381 | ✘ [ERROR] Could not resolve "node:path"
20:14:27.381 |  
20:14:27.382 | .svelte-kit/output/server/entries/pages/_page.svelte.js:4:17:
20:14:27.382 | 4 │ import path from "node:path";
20:14:27.382 | ╵                  ~~~~~~~~~~~
20:14:27.382 |  
20:14:27.382 | The package "node:path" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
20:14:27.382 |  
20:14:27.382 | ✘ [ERROR] Could not resolve "node:url"
20:14:27.383 |  
20:14:27.383 | .svelte-kit/output/server/entries/pages/_page.svelte.js:5:30:
20:14:27.383 | 5 │ import { fileURLToPath } from "node:url";
20:14:27.383 |~~~~~~~~~~
20:14:27.383 |  
20:14:27.383 | The package "node:url" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
20:14:27.383 |  
20:14:27.384 | error during build:
20:14:27.384 | Error: Build failed with 3 errors:
20:14:27.384 | .svelte-kit/output/server/entries/pages/_page.svelte.js:3:17: ERROR: Could not resolve "node:process"
20:14:27.384 | .svelte-kit/output/server/entries/pages/_page.svelte.js:4:17: ERROR: Could not resolve "node:path"
20:14:27.385 | .svelte-kit/output/server/entries/pages/_page.svelte.js:5:30: ERROR: Could not resolve "node:url"

Are you aware of a project that used this package running on Cloudflare?

If not, is there a fix for people who use Cloudflare for hosting/deployments?

Thank you for the consideration.

How to make a custom tokenizer?

Hi! This package works great but I'm having trouble figuring out how to customise the rendering when a special character is detected, eg. If "%%%" is detected in the markdown string, I would like to swap that part of the string with a custom svelte component. 🤞Is that possible?

By chance is there an example? I was unable to find more info online about this especially with this package..

I'm on Sveltkit 1.22, with Typescript and Tailwind CSS.

Adding custom components

Hey, I have a question, because I tried to implement it, but I can't figure it out. Is there any way, to add custom components to the svelte-exmarkdown?

Lets imagine we have h1 text called "Test". You would type it normally as

# Test

But is there a way to f.e add a button below, that acts like a svelte component, from the text itself?
For example

# Test
<CustomButton/>

(So the user can type this and server can import these components if necessary)

Not parsing anchor links

For some reason, svelte-exmarkdown is not parsing my tags, it only renders their content

<script>
  import Markdown from 'svelte-exmarkdown'

  async function fetchTerms() {
    const termsMarkdown = await fetch(`privacy_policy.md`)
    const text = await termsMarkdown.text()

    return text
  }
</script>

{#await fetchTerms()}
  <p>Caricamento privacy policy in corso...</p>
{:then source}
  <h1 class="mb-9 whitespace-nowrap text-blue-400">Informativa Privacy</h1>
  <div class="prose pb-9">
    <Markdown md={source} />
  </div>
{/await}

ERR_REQUIRE_ESM error on netlify

現時点で最新のsveltekitのバージョンで本サンプルを作成してnetlifyにデプロイすると下記エラーになってしまいます。

500
require() of ES Module /var/task/node_modules/remark-parse/index.js from /var/task/.netlify/server/entries/pages/index.svelte.js not supported.
Instead change the require of index.js in /var/task/.netlify/server/entries/pages/index.svelte.js to a dynamic import() which is available in all CommonJS modules.
Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/node_modules/remark-parse/index.js from /var/task/.netlify/server/entries/pages/index.svelte.js not supported.
Instead change the require of index.js in /var/task/.netlify/server/entries/pages/index.svelte.js to a dynamic import() which is available in all CommonJS modules.

Any idea why this is happening?

Working good, using two plugins, one for code blocks and one for tables and I'm seeing a lot of warnings in console:
image

Any idea how this could happen?

How to add Mermaid and Math plugins?

Firstly I want to say thank you for making this!

I've been building a small interface for your renderer using skeleton for fun.
markdown

The trouble I've been having is adding in more complicated remark/rehype plugins like Mermaid and Math. Is there an example of how to accomplish this or is it not currently possible?

Thank you for your time.

Supporting a subset of markdown syntax?

Hi! I would like to support a subset of markdown syntax: Only bold, cursive, strikethrough and automatic links (so https://google.com becomes https://google.com). I don't understand how I can do that with this package.

I found the documentation for writing custom elements here: https://ssssota.github.io/svelte-exmarkdown/docs/03-override-component.

However it is not clear how to override links. I mean both links like [Duck Duck Go](https://duckduckgo.com) and also automatically convert URL in normal text to link. There is also no list of the default renderers which would be useful to see. Perhaps something like that could be added to the documentation? 🙏

Lastly, I would like to know how to configure bundle splitting in an efficient way, as I would like to not bundle all the default renderers in my application as they are not used.

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.