hexojs / hexo

A fast, simple & powerful blog framework, powered by Node.js.
https://hexo.io
MIT License
39.28k stars 4.83k forks source link

Renderer not completely working if not using content parameter for tag plugins #5541

Open BlueWhaleYT opened 4 weeks ago

BlueWhaleYT commented 4 weeks ago

Check List

Expected behavior

The renderer should correctly renders the given text or source content, not just viable when using the content parameter.

Actual behavior

I want to create a notation bubble (something like a dictionary) for the section which is able to be reused by defining a tag plugin, the notation is created in markdown format file. However, when I develop this tag plugin, I found something abnormal behavior from the hexo render.

TL;DR: The hexo render only renders correctly when directly using the content parameter. It can only render basic markdown, others like tag plugins, code block cannot be correctly rendered.

Retrieving the file content as the markdown content

bubble.js

const fs = require('hexo-fs');

hexo.extend.tag.register('bubble', bubble, { async: true });

const REGEX = /^---\n([\s\S]*?)\n---/;

function bubble(args) {
    const notationPath = hexo.source_dir + 'assets/notation/' + args[0] + '.md';
    const notation = fs.readFileSync(notationPath).trim();

    const properties = getProperty(notation);
    const title = properties ? properties.title : 'Unnamed';

    const notationContent = hexo.render.renderSync({
        text: notation.replace(REGEX, ''),
        engine: 'markdown'
    })

    return `
        <div class="bubble-content">${title}</div>
        <div class="bubble-notation">
            <div class="bubble-item">${notationContent}</div>
        </div><p>
    `
}

function getProperty(notation) {
    const frontMatterRegex = REGEX;
    const match = notation.match(frontMatterRegex);

    if (match && match[1]) {
        const frontMatter = match[1];
        const properties = {};

        frontMatter.split('\n').forEach(line => {
            const [key, value] = line.split(':').map(item => item.trim());
            if (key) {
                properties[key] = value;
            }
        });

        return properties;
    }

    return null;
}

here is the final HTML of the notation:

<div class="bubble-notation">
            <div class="bubble-item"><p>testing paragraph</p>
<p>another paragraph</p>
<ol>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ol>
<pre><code class="js">const express = require('express');
const app = express();
app.get('/', (req, res) =&gt; {

});
app.listen(3000);
</code></pre>
</div>
        </div>

the result preview:

螢幕截圖 2024-09-02 下午12 55 57

as you see, the fenced code block only defines the <pre> tag, instead of the hexo's modified one (figure > table)

Retrieving content parameter as the markdown content

bubble2.js

hexo.extend.tag.register('bubble2', bubble, { ends: true, async: true });

const REGEX = /^---\n([\s\S]*?)\n---/;

function bubble(args, content) {
    const properties = getProperty(content);
    const title = properties ? properties.title : 'Unnamed';

    const notationContent = hexo.render.renderSync({
        text: content.replace(REGEX, ''),
        engine: 'markdown'
    })

    return `
        <div class="bubble-content">${title}</div>
        <div class="bubble-notation">
            <div class="bubble-item">${notationContent}</div>
        </div><p>
    `
}

function getProperty(notation) {
    const frontMatterRegex = REGEX;
    const match = notation.match(frontMatterRegex);

    if (match && match[1]) {
        const frontMatter = match[1];
        const properties = {};

        frontMatter.split('\n').forEach(line => {
            const [key, value] = line.split(':').map(item => item.trim());
            if (key) {
                properties[key] = value;
            }
        });

        return properties;
    }

    return null;
}

the final HTML:

<div class="bubble-notation">
            <div class="bubble-item"><p>testing paragraph</p>
<p>another paragraph</p>
<ol>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ol>
<figure class="highlight js"><div class="highlight-tools "><i class="solitude fas fa-angle-down expand"></i><div class="code-lang">js</div><i class="solitude fas fa-copy copy-button"></i></div><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">'express'</span>);</span><br><span class="line"><span class="keyword">const</span> app = <span class="title function_">express</span>();</span><br><span class="line">app.<span class="title function_">get</span>(<span class="string">'/'</span>, <span class="function">(<span class="params">req, res</span>) =&gt;</span> {</span><br><span class="line">    </span><br><span class="line">});</span><br><span class="line">app.<span class="title function_">listen</span>(<span class="number">3000</span>);</span><br></pre></td></tr></tbody></table></figure></div>
        </div>

the result preview:

螢幕截圖 2024-09-02 下午12 56 10

How to reproduce?

I found this bug when I trying to render markdown content that is not from content parameter.

Is the problem still there under Safe mode?

yes

Your Node.js & npm version

node: v18.12.1
npm: 9.8.1

Your Hexo and Plugin version

hexo-site@0.0.0 /Users/bluewhaleyt/PersonalProjects/Blog
├── @types/node@22.5.0
├── hexo-asset-image@1.0.0
├── hexo-browsersync@0.3.0
├── hexo-generator-archive@2.0.0
├── hexo-generator-category@2.0.0
├── hexo-generator-index@4.0.0
├── hexo-generator-search@2.4.3
├── hexo-generator-tag@2.0.0
├── hexo-pangu@0.2.2
├── hexo-renderer-ejs@2.0.0
├── hexo-renderer-marked@6.3.0
├── hexo-renderer-pug@3.0.0
├── hexo-renderer-stylus@3.0.1
├── hexo-server@3.0.0
├── hexo-theme-landscape@1.0.0
├── hexo-theme-solitude@2.0.11
├── hexo-wordcount@6.0.1
└── hexo@7.3.0

Your package.json

{
  "name": "hexo-site",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "build": "hexo generate",
    "clean": "hexo clean",
    "deploy": "hexo deploy",
    "server": "hexo server"
  },
  "hexo": {
    "version": "7.3.0"
  },
  "dependencies": {
    "hexo": "^7.3.0",
    "hexo-asset-image": "^1.0.0",
    "hexo-browsersync": "^0.3.0",
    "hexo-generator-archive": "^2.0.0",
    "hexo-generator-category": "^2.0.0",
    "hexo-generator-index": "^4.0.0",
    "hexo-generator-search": "^2.4.3",
    "hexo-generator-tag": "^2.0.0",
    "hexo-pangu": "^0.2.2",
    "hexo-renderer-ejs": "^2.0.0",
    "hexo-renderer-marked": "^6.3.0",
    "hexo-renderer-pug": "^3.0.0",
    "hexo-renderer-stylus": "^3.0.1",
    "hexo-server": "^3.0.0",
    "hexo-theme-landscape": "^1.0.0",
    "hexo-theme-solitude": "^2.0.10",
    "hexo-wordcount": "^6.0.1"
  },
  "devDependencies": {
    "@types/node": "^22.5.0"
  }
}

Your site's _config.yml (Optional)

No response

Others

No response