html-bundler-webpack-plugin icon indicating copy to clipboard operation
html-bundler-webpack-plugin copied to clipboard

Expose options for markdown-it

Open vralle opened this issue 11 months ago • 7 comments

Current behavior

I use eta.js as a template engine.

Now I tried to import markdown files into html, but it gives me errors.

Here's what I do:

src/view/index.html I'm trying to import md file with eta include()

 {{~ include("parts/head") }}
<body>
   {{~ include("content/home.md") }}
</body>

The plugin cfg - here I'm use postprocess to parse md into html

import markdownit from 'markdown-it';
const md = markdownit({
  // Enable HTML tags in source
  html: true,
  typographer: true,
});
...
new HtmlBundlerPlugin({
  entry: {
    index: {
      import: join(projectPaths.src, "views", "index.html"),
      data: renderData
    },
  },
  postprocess: (content) => {
    return md.render(content);
  }
}),

Result:

ERROR in ./src/views/index.html
Module build failed (from ../../node_modules/html-bundler-webpack-plugin/src/Loader/index.js):
LoaderException: 
 HTML Bundler Plugin  Preprocessor failed.
File: src/views/index.html

Error: line 22
    21|         <body>
 >> 22|                 {{~ include("content/home.md") }}
    23|         </body>

Cannot find module 'prismjs'. Please install the missing module: npm i -D prismjs

Here the plugin requires prismjs. But why? I don't have code highlighting)

I guess the error could be caused by eta.js, but the plugin informs about unnecessary actions, and now I don't understand what I need to fix.

In general, I have no other ideas on how to use markdown with eta.js

Appreciation for the useful project

  • [x] Do not forget to give a star ⭐

vralle avatar Feb 08 '25 19:02 vralle

Hello @vralle,

1 - doesn't use the postprocess to render md, the plugin do it itself 2 - {{~ include("content/home.md") }} - the path to the file must be relative to project directory, e.g. src/path/to/file.md.

TODO: provide the ability to customize built-in filters. Currently the markdown build-in filter is preconfigured with using a highlighting via prismjs.

To include a md file, should be installed the optional dependency prismjs. In next version I will fix it.

See the usage example eta-include-md.

webdiscus avatar Feb 08 '25 21:02 webdiscus

Hi @webdiscus!

1 - doesn't use the postprocess to render md, the plugin do it itself

Can I use my own options for markdown-it?

Now I'm trying to use another way.

I override Eta->readFile(path) and handle MD here.

In config:

import CustomEta from "./CustomEta.js";
const eta = new CustomEta(options);
...
preprocessor: (content, { data }) => eta.renderString(content, data),

vralle avatar Feb 08 '25 21:02 vralle

I override Eta->readFile(path) and handle MD here.

Ok.

Can I use my own options for markdown-it?

Currently not. But this is good issue to implement it.

webdiscus avatar Feb 08 '25 21:02 webdiscus

Eta: Customizing file handling

It was easy. A small change to the file loader in Eta.

import { Eta, EtaFileResolutionError } from 'eta';
import markdownit from 'markdown-it';
import { readFileSync } from "node:fs";

const md = markdownit({
    // Enable HTML tags in source
    html: true,
    // Use '/' to close single tags (<br />).
    xhtmlOut: false,
    // Convert '\n' in paragraphs into <br>
    breaks: false,
    // Autoconvert URL-like text to links
    linkify: true,
    // Enable some language-neutral replacement + quotes beautification
    typographer: true,
});

class EtaWithMarkdown extends Eta {
  /**
   * @override
   * @param {string} path
   * @returns {string}
   */
  readFile = (path) => {
    let res = "";
    try {
      res = readFileSync(path, "utf8");
    } catch (err) {
      // @ts-expect-error: Inherited from original code
      if (err?.code === "ENOENT") {
        throw new EtaFileResolutionError(`Could not find template: ${path}`);
      }

      throw err;
    }

    if (/\.md$/.test(path)) {
      return md.render(res);
    }

    return res;
  };
}

export default EtaWithMarkdown;

webpack.cfg.js

const eta = new EtaWithMarkdown({
  defaultExtension: ".html",
  tags: ["{{", "}}"],
  views: join(projectPaths.src, "views"),
});

...
plugins: [
  new HtmlBundlerPlugin({
    preprocessor: (content, { data }) => eta.renderString(content, data),
  }),
],

Now I can import Markdown files with eta file loader: {{~ include("content/markdown.md") }}

Thank you!

vralle avatar Feb 09 '25 08:02 vralle

Extended Eta implementation with Markdown support: https://github.com/vralle/webpack-html-bundler-starter-templates/tree/master/projects/eta-extended

vralle avatar Feb 22 '25 10:02 vralle

@vralle thanks for your extension, I appreciate your effort.

The plugin already contains the likely implementation. I just need to expose the markdown-it options to allow them to be specified in the plugin options. This is in TODO.

webdiscus avatar Feb 22 '25 11:02 webdiscus

You deprive users of writing even a line of code, even if it is for a special case)

vralle avatar Feb 22 '25 15:02 vralle