adding txt2tags-it: support to txt2tags syntax in addition to md#282
adding txt2tags-it: support to txt2tags syntax in addition to md#282luginf wants to merge 10 commits intoqownnotes:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new QOwnNotes script (txt2tags-it) that extends the existing markdown-it based renderer to also understand a subset of txt2tags syntax in both preview rendering and editor highlighting.
Changes:
- Introduces a new
txt2tags-itrenderer script that wires a txt2tags markdown-it plugin and optional editor highlighting rules. - Adds a new markdown-it plugin (
markdown-it-txt2tags.js) implementing txt2tags-style headings/comments/lists and inline formatting. - Bundles required markdown-it-related JS resources and adds script metadata/docs.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| txt2tags-it/txt2tags-it.qml | New renderer script integrating markdown-it + optional deflist/KaTeX + txt2tags plugin + editor highlighting rules. |
| txt2tags-it/markdown-it-txt2tags.js | New markdown-it plugin implementing txt2tags syntax features. |
| txt2tags-it/markdown-it-deflist.js | Bundled definition list plugin dependency for markdown-it. |
| txt2tags-it/info.json | Script metadata/resources list for QOwnNotes script loader. |
| txt2tags-it/README.md | Minimal documentation for the new script. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "version": "1.5", | ||
| "minAppVersion": "20.6.0", | ||
| "description": "This script replaces the default markdown renderer with markdown-it and allows for optional LaTeX rendering support with the Markdown-It KaTeX plugin. (NOTE: LaTeX defaults to rendering with MathML ONLY). \n\n<b>Dependencies</b>\n<a href=\"https://github.com/markdown-it/markdown-it\">markdown-it.js</a> (v8.4.2 bundled with the script)\n<a href=\"https://github.com/mdit-plugins/mdit-plugins/tree/main/packages/katex\">Markdown-It KaTeX plugin</a> (v0.18.0 bundled with the script)\n\n<b>Usage</b>\nFor the possible configuration options check <a href=\"https://github.com/markdown-it/markdown-it/tree/main/lib/presets\">here</a>.\n\n<b>Important</b>\nThis script currently only works with <a href=\"https://github.com/qownnotes/scripts/issues/77\"><b>legacy media links</b></a>. You can turn them on in the <i>General Settings</i>.\n\nImportant note: You need to use legacy image linking with this script, otherwise there will be no images shown in the preview!" | ||
| } |
There was a problem hiding this comment.
info.json’s description still describes only the markdown-it + KaTeX renderer and doesn’t mention the new txt2tags syntax support that this script adds. This is inconsistent with the script’s purpose/title and will confuse users browsing available scripts. Update the description to include txt2tags support (and any constraints, e.g. which txt2tags features are implemented).
| finalPath = rawPath.replace(/\\/g, '/'); | ||
| else | ||
| // Relative path → resolve against base | ||
| finalPath = resolvePath(basePath, rawPath.replace(/^\.\/+/, '')); |
There was a problem hiding this comment.
resolvePath(basePath, ...) references basePath, but no such variable is defined in this function (the computed base directory is stored in path). This will throw at runtime when a relative src/href is encountered, breaking preview/export rendering. Pass the correct base variable (likely path) into resolvePath (or rename consistently).
| finalPath = resolvePath(basePath, rawPath.replace(/^\.\/+/, '')); | |
| finalPath = resolvePath(path, rawPath.replace(/^\.\/+/, '')); |
| mdHtml = mdHtml.replace(/(\b(?:src|href|data-[\w-]+)\s*=\s*["'])([^"']+)["']/gi, (_, prefix, rawPath) => { | ||
| // Convert backslashes to forward slashes for URL | ||
|
|
||
| if (isProtocolUrl(rawPath)) | ||
| return `${prefix}${rawPath}"`; |
There was a problem hiding this comment.
The URL rewrite returns strings that always end with a double quote (e.g. return `${prefix}${rawPath}"`;). Since the match can start with either ' or ", this can generate malformed HTML when the original attribute used single quotes. Capture/reuse the original quote character in the replacement.
There was a problem hiding this comment.
@pbek fixed in next commit
Example of the bug:
- Original HTML: src='image.png'
- Produced result: src='file:///path/image.png" ← malformed
Fix: capture the quote character in a separate group and reuse it as the closing quote.
What changed:
- The regex now splits attr (e.g. src=) and quote (the " or ' character) into two separate groups, and \2
ensures the closing quote matches the opening one. - Both return statements use ${quote} to open and close — the HTML stays well-formed.
| finalPath = resolvePath(basePath, rawPath.replace(/^\.\/+/, '')); | ||
| return `${prefix}file://${finalPath}"`; | ||
| }); |
There was a problem hiding this comment.
Same quoting issue here: return `${prefix}file://${finalPath}"`; always emits a double quote regardless of whether the original attribute used ' or ". Reuse the original quote character (e.g. by capturing it) to avoid producing invalid HTML.
| { | ||
| "identifier": "useKatexPlugin", | ||
| "name": "LaTeX Support", | ||
| "text": "Enable the Markdown-it definition list KaTeX plugin", |
There was a problem hiding this comment.
The useKatexPlugin setting text says "Enable the Markdown-it definition list KaTeX plugin", which is misleading (it’s not related to definition lists). Update the label to accurately describe enabling KaTeX/LaTeX rendering.
| "text": "Enable the Markdown-it definition list KaTeX plugin", | |
| "text": "Enable the Markdown-it KaTeX / LaTeX rendering plugin", |
There was a problem hiding this comment.
@luginf, what should the correct text be?
I've removed it since then (also the option)
There was a problem hiding this comment.
@luginf, what should the correct text be?
the option has been removed since then
|
I've worked more on it for better support of some links but it broke elsewhere, I'll post more soon. I'll also check if it's possible to have it compatible with QT6, because your AppImage doesn't work with this script, while my QT5 build is working correctly. |
What is happening? |
|
Could you please post the first block of the settings dump of the Qt6 appimage and the same for your build? |
- Enable html:true by default so HTML comments (<!-- -->) are passed
through as-is instead of being escaped as visible text
- Fix --strikethrough-- to use <s> tag instead of <del>, consistent
with markdown ~~strikethrough~~ rendering
- Remove + item ordered list editor highlighting rule (was applying
an unwanted heading style to list lines)
- Fix basePath undefined variable → path in relative URL resolution
- Register txt2tags_link before adding autolink/wikilink rules:
ruler.before("txt2tags_link", ...) threw "Parser rule not found"
when called before txt2tags_link was itself registered, aborting
the entire plugin initialisation and breaking all txt2tags rendering
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
both use the same configuration file and scripts Qt6:General InfoCurrent Date: Server InfoserverUrl: empty /.../ Script
|
…namespace In Qt5, importing a JS file in QML binds the module's top-level `this` to the QML global scope, so UMD modules export their constructors onto the component via `g = this; g.markdownit = f()`, and `this.markdownit` works in init(). In Qt6, the module's top-level `this` is the module namespace object (e.g. MarkdownIt, MarkdownItTxt2tags), not the QML component scope. So the constructors land on `MarkdownIt.markdownit` etc., and `this.markdownit` in init() is undefined — causing silent init failure and a blank preview. Fix: resolve each constructor with `Namespace.name || this.name` so that Qt6 uses the module namespace and Qt5 falls back to the component scope. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
In Qt6 QML, JavaScript files imported via 'import "foo.js" as Foo' run in strict mode where `this` at the top level is undefined. The UMD wrappers in markdown-it, markdown-it-deflist, markdown-it-katex and markdown-it-txt2tags all fell back to `g = this` when window/global/self were undefined, then threw TypeError setting a property on undefined. Fix: insert `globalThis` before the `this` fallback in each UMD chain. globalThis is always the real global object in Qt6's JS engine. In init(), resolve constructors via `_g = globalThis || this` so that Qt6 uses globalThis (where the modules now export) and Qt5 falls back to the component scope (where the modules previously exported via this). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The root cause of Qt6 breakage: UMD modules used `g = this; g.markdownit = f()` where `this` at module top-level is undefined in Qt6 strict mode, so the assignment threw and nothing was exported. Fix: declare `var markdownit` and `var markdownitTxt2tags` at the top level of each JS file (outside the IIFE). Top-level vars are always accessible via the QML module qualifier (MarkdownIt.markdownit, MarkdownItTxt2tags.markdownitTxt2tags) in both Qt5 and Qt6 — no runtime this/globalThis lookup needed. Also removed the unused deflist and katex plugins to simplify the script. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@pbek it is working now for both Qt5 (my compiled binary) and Qt6 (your AppImage)! |
|
I also needed to have the custom heading syntax detected into the "Headings panel", but it looks like it require to be changed in the source code, so I've used this in a fork: pbek/QOwnNotes@main...luginf:QOwnNotes-t2t:main Maybe it's possible to do it differently? |
Awesome. Your Qt5 version of QOwnNotes did not have QLiteHtml, that could explain the difference.
That looks like something that is just needed for your script. What was it you were trying to achieve? Is there a minimal script custom highlighting you can offer to test it? |
Yeah, I don't know. I just wanted to be able to change the heading panel content without modifying the qownnotes code, but the LLM answered:
in attachement: it's basically: with a fictional syntax like
|
|
I will implement something in the next release to support the headings from addHighlightingRule in the navigation panel. |
thank you very much! |
|
the other commit for in-note-text-tagging is appearing in this one as well, I should have done a new branch :/ |
Can you please put those changes to another PR? |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
I've done that, but I'm not sure it worked correctly... |
|
No, you need to cherry-pick the commits you want to get into this PR. Also, you created a PR from your |
ok, sorry, I've created the new branch without the other files (in-note-text-tagging), there are still the other commits but it's probably possible to squash everything during the integration of the PR |


No description provided.