mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-27 18:40:28 +00:00
Revamp markdown plugin (#6528)
* Rename markdown to markdown-legacy * Change how default renderWikiTextPragma value is displayed To prevent out-of-sync, dynamically display the default value of renderWikiTextPragma from the shadow tiddler instead of hard coding the text in the "usage.tid". * Repackage remarkable-based markdown plugin as markdown-legacy - Rename plugin title to $:/plugins/tiddlywiki/markdown-legacy - Add support for "text/markdown" MIME type and set that as the default when creating new markdown tiddlers * Create new markdown plugin * add support to text/markdown MIME type * remove linkify and linkNewWindow config options - linkify feature should be controlled by "extlink" TW parser rule; enabling markdown's linkify option will interfere with parsing - remove the possibility to open external links in the same tab/window to match TW's behavior * Ignore latex-parser wikirule in rednerWikiTextPragma * Prevent camel-case link text from generating a link * Update editions/markdowndemo * Produce better parse tree * Improve markdown/tiddlywiki integration - widget block should not interrupt paragraph - ignore tw-syntax links inside markdown-syntax links - remove repeated renderWikiTextPragma parsing - more efficient findNextMatch when examining tw rules * Update user docs * Replace includes() with indexOf() for legacy browsers
This commit is contained in:
parent
b5134951e5
commit
0c328a1696
@ -1,4 +1,7 @@
|
||||
title: $:/DefaultTiddlers
|
||||
|
||||
[[HelloThere]]
|
||||
[[MarkdownExample]]
|
||||
$:/plugins/tiddlywiki/markdown
|
||||
[[MarkdownTutorial]]
|
||||
[[QuickDemo]]
|
||||
[[QuickDemo Source]]
|
||||
|
@ -1,11 +1,9 @@
|
||||
title: HelloThere
|
||||
|
||||
This is a demo of TiddlyWiki5 incorporating a plugin for parsing tiddlers written in the Markdown language. The plugin uses the [[Remarkable|https://github.com/jonschlinkert/remarkable]] Markdown parser internally. The MarkdownExample tiddler below is written in Markdown.
|
||||
This is a demo of TiddlyWiki5 incorporating a plugin for parsing tiddlers written in the Markdown language. The plugin uses the [[markdown-it|https://github.com/markdown-it/markdown-it]] Markdown parser internally. The MarkdownTutorial tiddler below is written in Markdown.
|
||||
|
||||
! Installation
|
||||
|
||||
To add the plugin to your own TiddlyWiki5, just drag this link to the browser window:
|
||||
|
||||
[[$:/plugins/tiddlywiki/markdown]]
|
||||
|
||||
{{$:/plugins/tiddlywiki/markdown/usage}}
|
||||
[[$:/plugins/tiddlywiki/markdown]]
|
@ -1,4 +1,4 @@
|
||||
title: MarkdownExample
|
||||
title: MarkdownTutorial
|
||||
type: text/x-markdown
|
||||
|
||||
Markdown: Basics
|
||||
@ -8,13 +8,13 @@ Getting the Gist of Markdown's Formatting Syntax
|
||||
------------------------------------------------
|
||||
|
||||
This page offers a brief overview of what it's like to use Markdown.
|
||||
The [syntax page] [s] provides complete, detailed documentation for
|
||||
The [syntax page][s] provides complete, detailed documentation for
|
||||
every feature, but Markdown should be very easy to pick up simply by
|
||||
looking at a few examples of it in action. The examples on this page
|
||||
are written in a before/after style, showing example syntax and the
|
||||
HTML output produced by Markdown.
|
||||
|
||||
It's also helpful to simply try Markdown out; the [Dingus] [d] is a
|
||||
It's also helpful to simply try Markdown out; the [Dingus][d] is a
|
||||
web application that allows you type your own Markdown-formatted text
|
||||
and translate it to XHTML.
|
||||
|
220
editions/markdowndemo/tiddlers/QuickDemo.tid
Normal file
220
editions/markdowndemo/tiddlers/QuickDemo.tid
Normal file
@ -0,0 +1,220 @@
|
||||
title: QuickDemo
|
||||
type: text/markdown
|
||||
|
||||
<style>
|
||||
.tc-image-loaded {
|
||||
width: 35%;
|
||||
}
|
||||
</style>
|
||||
# h1 Heading
|
||||
## h2 Heading
|
||||
### h3 Heading
|
||||
#### h4 Heading
|
||||
##### h5 Heading
|
||||
###### h6 Heading
|
||||
|
||||
|
||||
## Horizontal Rules
|
||||
|
||||
____
|
||||
|
||||
---
|
||||
|
||||
****
|
||||
|
||||
|
||||
## Emphasis
|
||||
|
||||
|
||||
**This is bold text**
|
||||
|
||||
__This is bold text__
|
||||
|
||||
*This is italic text*
|
||||
|
||||
_This is italic text_
|
||||
|
||||
~~Strikethrough~~
|
||||
|
||||
|
||||
## Blockquotes
|
||||
|
||||
|
||||
> Blockquotes can also be nested...
|
||||
>> ...by using additional greater-than signs right next to each other...
|
||||
> > > ...or with spaces between arrows.
|
||||
|
||||
|
||||
## Unordered List
|
||||
|
||||
|
||||
+ Create a list by starting a line with `+`, `-`, or `*`
|
||||
+ Sub-lists are made by indenting 2 spaces:
|
||||
- Marker character change forces new list start:
|
||||
* Ac tristique libero volutpat at
|
||||
+ Facilisis in pretium nisl aliquet
|
||||
- Nulla volutpat aliquam velit
|
||||
+ Very easy!
|
||||
|
||||
|
||||
## Ordered List
|
||||
|
||||
|
||||
1. Lorem ipsum dolor sit amet
|
||||
2. Consectetur adipiscing elit
|
||||
3. Integer molestie lorem at massa
|
||||
|
||||
|
||||
1. You can use sequential numbers...
|
||||
1. ...or keep all the numbers as `1.`
|
||||
|
||||
Start numbering with offset:
|
||||
|
||||
57. foo
|
||||
1. bar
|
||||
|
||||
|
||||
## Code
|
||||
|
||||
|
||||
Inline `code`
|
||||
|
||||
Indented code
|
||||
|
||||
// Some comments
|
||||
line 1 of code
|
||||
line 2 of code
|
||||
line 3 of code
|
||||
|
||||
Block code "fences"
|
||||
|
||||
```
|
||||
Sample text here...
|
||||
```
|
||||
|
||||
|
||||
## Syntax highlighting
|
||||
|
||||
``` js
|
||||
var foo = function (bar) {
|
||||
return bar++;
|
||||
};
|
||||
|
||||
console.log(foo(5));
|
||||
```
|
||||
|
||||
|
||||
## ~KaTeX
|
||||
|
||||
|
||||
Equation $c = \pm\sqrt{a^2 + b^2}$ is typeset in inline mode.
|
||||
|
||||
Display style: $$c = \pm\sqrt{a^2 + b^2}$$
|
||||
|
||||
|
||||
## Tables
|
||||
|
||||
|
||||
| Attribute | Description |
|
||||
| --------- | ----------- |
|
||||
| multiple | select multiple files to download |
|
||||
| param | parameter to be passed with the message |
|
||||
| tooltip | optional tooltip text |
|
||||
|
||||
Aligning columns:
|
||||
|
||||
| Column A | Column B | Column C |
|
||||
| :---- | :----: | ----: |
|
||||
| is | is | is |
|
||||
| left | nicely | right |
|
||||
| aligned | centered | aligned |
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
[link text](http://google.com)
|
||||
|
||||
[link with title](http://nodeca.github.io/pica/demo/ "title text!")
|
||||
|
||||
link to tiddler [QuickDemo Source](#QuickDemo%20Source)
|
||||
|
||||
URL can contain spaces if enclosed in brackets `<>`: [QuickDemo Source](<#QuickDemo Source>)
|
||||
|
||||
|
||||
## Images
|
||||
|
||||
|
||||
![Minion](https://octodex.github.com/images/minion.png)
|
||||
![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")
|
||||
|
||||
Like links, images also have a reference style syntax
|
||||
|
||||
![Alt text][id]
|
||||
|
||||
with a link reference defined later in the document.
|
||||
|
||||
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
|
||||
|
||||
|
||||
## Subscript & Superscript
|
||||
|
||||
|
||||
- 19^th^
|
||||
- H~2~O
|
||||
|
||||
|
||||
## \<ins\>
|
||||
|
||||
|
||||
++Inserted text++
|
||||
|
||||
|
||||
## \<mark\>
|
||||
|
||||
|
||||
==Marked text==
|
||||
|
||||
|
||||
## Footnotes
|
||||
|
||||
|
||||
Footnote 1 link[^first].
|
||||
|
||||
Footnote 2 link[^second].
|
||||
|
||||
Inline footnote^[Text of inline footnote] definition.
|
||||
|
||||
Duplicated footnote reference[^second].
|
||||
|
||||
[^first]: Footnote **can have markup**
|
||||
|
||||
and multiple paragraphs.
|
||||
|
||||
[^second]: Footnote text.
|
||||
|
||||
|
||||
## Definition Lists
|
||||
|
||||
|
||||
Term 1
|
||||
|
||||
: Definition 1
|
||||
with lazy continuation.
|
||||
|
||||
Term 2 with *inline markup*
|
||||
|
||||
: Definition 2
|
||||
|
||||
{ some code, part of Definition 2 }
|
||||
|
||||
Third paragraph of definition 2.
|
||||
|
||||
_Compact style:_
|
||||
|
||||
Term 1
|
||||
~ Definition 1
|
||||
|
||||
Term 2
|
||||
~ Definition 2a
|
||||
~ Definition 2b
|
5
editions/markdowndemo/tiddlers/QuickDemoSource.tid
Normal file
5
editions/markdowndemo/tiddlers/QuickDemoSource.tid
Normal file
@ -0,0 +1,5 @@
|
||||
title: QuickDemo Source
|
||||
|
||||
<$let tiddler="QuickDemo">
|
||||
<$codeblock code={{{ [<tiddler>get[text]] }}} language={{{ [<tiddler>get[type]else[text/vnd.tiddlywiki]] }}}/>
|
||||
</$let>
|
@ -1,7 +1,9 @@
|
||||
{
|
||||
"description": "Demo of the Markdown plugin",
|
||||
"plugins": [
|
||||
"tiddlywiki/markdown"
|
||||
"tiddlywiki/markdown",
|
||||
"tiddlywiki/highlight",
|
||||
"tiddlywiki/katex"
|
||||
],
|
||||
"themes": [
|
||||
"tiddlywiki/vanilla",
|
||||
|
@ -8,4 +8,5 @@ text/html: codemirror
|
||||
text/plain: codemirror
|
||||
text/vnd.tiddlywiki: codemirror
|
||||
text/x-markdown: codemirror
|
||||
text/markdown: codemirror
|
||||
text/x-tiddlywiki: codemirror
|
||||
|
@ -1 +1 @@
|
||||
!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../lib/codemirror")):"function"==typeof define&&define.amd?define(["../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.modeInfo=[{name:"CMake",mime:"text/x-cmake",mode:"cmake",ext:["cmake","cmake.in"],file:/^CMakeLists.txt$/},{name:"Cython",mime:"text/x-cython",mode:"python",ext:["pyx","pxd","pxi"]},{name:"CSS",mime:"text/css",mode:"css",ext:["css"]},{name:"diff",mime:"text/x-diff",mode:"diff",ext:["diff","patch"]},{name:"Embedded Javascript",mime:"application/x-ejs",mode:"htmlembedded",ext:["ejs"]},{name:"Embedded Ruby",mime:"application/x-erb",mode:"htmlembedded",ext:["erb"]},{name:"Erlang",mime:"text/x-erlang",mode:"erlang",ext:["erl"]},{name:"GitHub Flavored Markdown",mime:"text/x-gfm",mode:"gfm",file:/^(readme|contributing|history).md$/i},{name:"Go",mime:"text/x-go",mode:"go",ext:["go"]},{name:"ASP.NET",mime:"application/x-aspx",mode:"htmlembedded",ext:["aspx"],alias:["asp","aspx"]},{name:"HTML",mime:"text/html",mode:"htmlmixed",ext:["html","htm","handlebars","hbs"],alias:["xhtml"]},{name:"HTTP",mime:"message/http",mode:"http"},{name:"JavaScript",mimes:["text/javascript","text/ecmascript","application/javascript","application/x-javascript","application/ecmascript"],mode:"javascript",ext:["js"],alias:["ecmascript","js","node"]},{name:"JSON",mimes:["application/json","application/x-json"],mode:"javascript",ext:["json","map"],alias:["json5"]},{name:"JSON-LD",mime:"application/ld+json",mode:"javascript",ext:["jsonld"],alias:["jsonld"]},{name:"Lua",mime:"text/x-lua",mode:"lua",ext:["lua"]},{name:"Markdown",mime:"text/x-markdown",mode:"markdown",ext:["markdown","md","mkd"]},{name:"MySQL",mime:"text/x-mysql",mode:"sql"},{name:"Plain Text",mime:"text/plain",mode:"null",ext:["txt","text","conf","def","list","log"]},{name:"Python",mime:"text/x-python",mode:"python",ext:["BUILD","bzl","py","pyw"],file:/^(BUCK|BUILD)$/},{name:"SCSS",mime:"text/x-scss",mode:"css",ext:["scss"]},{name:"LaTeX",mime:"text/x-latex",mode:"stex",ext:["text","ltx","tex"],alias:["tex"]},{name:"TiddlyWiki ",mime:"text/x-tiddlywiki",mode:"tiddlywiki"}];for(var t=0;t<e.modeInfo.length;t++){var m=e.modeInfo[t];m.mimes&&(m.mime=m.mimes[0])}e.findModeByMIME=function(t){t=t.toLowerCase();for(var m=0;m<e.modeInfo.length;m++){var i=e.modeInfo[m];if(i.mime==t)return i;if(i.mimes)for(var a=0;a<i.mimes.length;a++)if(i.mimes[a]==t)return i}return/\+xml$/.test(t)?e.findModeByMIME("application/xml"):/\+json$/.test(t)?e.findModeByMIME("application/json"):void 0},e.findModeByExtension=function(t){for(var m=0;m<e.modeInfo.length;m++){var i=e.modeInfo[m];if(i.ext)for(var a=0;a<i.ext.length;a++)if(i.ext[a]==t)return i}},e.findModeByFileName=function(t){for(var m=0;m<e.modeInfo.length;m++){var i=e.modeInfo[m];if(i.file&&i.file.test(t))return i}var a=t.lastIndexOf("."),o=a>-1&&t.substring(a+1,t.length);if(o)return e.findModeByExtension(o)},e.findModeByName=function(t){t=t.toLowerCase();for(var m=0;m<e.modeInfo.length;m++){var i=e.modeInfo[m];if(i.name.toLowerCase()==t)return i;if(i.alias)for(var a=0;a<i.alias.length;a++)if(i.alias[a].toLowerCase()==t)return i}}});
|
||||
!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../lib/codemirror")):"function"==typeof define&&define.amd?define(["../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.modeInfo=[{name:"CMake",mime:"text/x-cmake",mode:"cmake",ext:["cmake","cmake.in"],file:/^CMakeLists.txt$/},{name:"Cython",mime:"text/x-cython",mode:"python",ext:["pyx","pxd","pxi"]},{name:"CSS",mime:"text/css",mode:"css",ext:["css"]},{name:"diff",mime:"text/x-diff",mode:"diff",ext:["diff","patch"]},{name:"Embedded Javascript",mime:"application/x-ejs",mode:"htmlembedded",ext:["ejs"]},{name:"Embedded Ruby",mime:"application/x-erb",mode:"htmlembedded",ext:["erb"]},{name:"Erlang",mime:"text/x-erlang",mode:"erlang",ext:["erl"]},{name:"GitHub Flavored Markdown",mime:"text/x-gfm",mode:"gfm",file:/^(readme|contributing|history).md$/i},{name:"Go",mime:"text/x-go",mode:"go",ext:["go"]},{name:"ASP.NET",mime:"application/x-aspx",mode:"htmlembedded",ext:["aspx"],alias:["asp","aspx"]},{name:"HTML",mime:"text/html",mode:"htmlmixed",ext:["html","htm","handlebars","hbs"],alias:["xhtml"]},{name:"HTTP",mime:"message/http",mode:"http"},{name:"JavaScript",mimes:["text/javascript","text/ecmascript","application/javascript","application/x-javascript","application/ecmascript"],mode:"javascript",ext:["js"],alias:["ecmascript","js","node"]},{name:"JSON",mimes:["application/json","application/x-json"],mode:"javascript",ext:["json","map"],alias:["json5"]},{name:"JSON-LD",mime:"application/ld+json",mode:"javascript",ext:["jsonld"],alias:["jsonld"]},{name:"Lua",mime:"text/x-lua",mode:"lua",ext:["lua"]},{name:"Markdown",mimes:["text/x-markdown","text/markdown"],mode:"markdown",ext:["markdown","md","mkd"]},{name:"MySQL",mime:"text/x-mysql",mode:"sql"},{name:"Plain Text",mime:"text/plain",mode:"null",ext:["txt","text","conf","def","list","log"]},{name:"Python",mime:"text/x-python",mode:"python",ext:["BUILD","bzl","py","pyw"],file:/^(BUCK|BUILD)$/},{name:"SCSS",mime:"text/x-scss",mode:"css",ext:["scss"]},{name:"LaTeX",mime:"text/x-latex",mode:"stex",ext:["text","ltx","tex"],alias:["tex"]},{name:"TiddlyWiki ",mime:"text/x-tiddlywiki",mode:"tiddlywiki"}];for(var t=0;t<e.modeInfo.length;t++){var m=e.modeInfo[t];m.mimes&&(m.mime=m.mimes[0])}e.findModeByMIME=function(t){t=t.toLowerCase();for(var m=0;m<e.modeInfo.length;m++){var i=e.modeInfo[m];if(i.mime==t)return i;if(i.mimes)for(var a=0;a<i.mimes.length;a++)if(i.mimes[a]==t)return i}return/\+xml$/.test(t)?e.findModeByMIME("application/xml"):/\+json$/.test(t)?e.findModeByMIME("application/json"):void 0},e.findModeByExtension=function(t){for(var m=0;m<e.modeInfo.length;m++){var i=e.modeInfo[m];if(i.ext)for(var a=0;a<i.ext.length;a++)if(i.ext[a]==t)return i}},e.findModeByFileName=function(t){for(var m=0;m<e.modeInfo.length;m++){var i=e.modeInfo[m];if(i.file&&i.file.test(t))return i}var a=t.lastIndexOf("."),o=a>-1&&t.substring(a+1,t.length);if(o)return e.findModeByExtension(o)},e.findModeByName=function(t){t=t.toLowerCase();for(var m=0;m<e.modeInfo.length;m++){var i=e.modeInfo[m];if(i.name.toLowerCase()==t)return i;if(i.alias)for(var a=0;a<i.alias.length;a++)if(i.alias[a].toLowerCase()==t)return i}}});
|
||||
|
@ -6,3 +6,4 @@ text/css: css
|
||||
text/html: html
|
||||
image/svg+xml: xml
|
||||
text/x-markdown: markdown
|
||||
text/markdown: markdown
|
@ -6,3 +6,4 @@ text/css: css
|
||||
text/html: html
|
||||
image/svg+xml: xml
|
||||
text/x-markdown: markdown
|
||||
text/markdown: markdown
|
||||
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/bold.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/bold.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/bold
|
||||
list-after: $:/core/ui/EditorToolbar/bold
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/bold
|
||||
caption: {{$:/language/Buttons/Bold/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Bold/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((bold))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="wrap-selection"
|
||||
prefix="**"
|
||||
suffix="**"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-1.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-1.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-1
|
||||
list-after: $:/core/ui/EditorToolbar/heading-1
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-1
|
||||
caption: {{$:/language/Buttons/Heading1/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading1/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-1))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character="#"
|
||||
count="1"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-2.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-2.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-2
|
||||
list-after: $:/core/ui/EditorToolbar/heading-2
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-2
|
||||
caption: {{$:/language/Buttons/Heading2/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading2/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-2))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character="#"
|
||||
count="2"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-3.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-3.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-3
|
||||
list-after: $:/core/ui/EditorToolbar/heading-3
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-3
|
||||
caption: {{$:/language/Buttons/Heading3/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading3/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-3))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character="#"
|
||||
count="3"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-4.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-4.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-4
|
||||
list-after: $:/core/ui/EditorToolbar/heading-4
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-4
|
||||
caption: {{$:/language/Buttons/Heading4/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading4/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-4))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character="#"
|
||||
count="4"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-5.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-5.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-5
|
||||
list-after: $:/core/ui/EditorToolbar/heading-5
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-5
|
||||
caption: {{$:/language/Buttons/Heading5/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading5/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-5))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character="#"
|
||||
count="5"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-6.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-6.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/heading-6
|
||||
list-after: $:/core/ui/EditorToolbar/heading-6
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-6
|
||||
caption: {{$:/language/Buttons/Heading6/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading6/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-6))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character="#"
|
||||
count="6"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/italic.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/italic.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/italic
|
||||
list-after: $:/core/ui/EditorToolbar/italic
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/italic
|
||||
caption: {{$:/language/Buttons/Italic/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Italic/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((italic))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="wrap-selection"
|
||||
prefix="*"
|
||||
suffix="*"
|
||||
/>
|
@ -0,0 +1,73 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/link-dropdown
|
||||
|
||||
\define lingo-base() $:/language/Buttons/Link/
|
||||
|
||||
\define add-link-actions()
|
||||
\whitespace trim
|
||||
<$action-sendmessage $message="tm-edit-text-operation" $param="make-markdown-link" text={{$(linkTiddler)$}} />
|
||||
<$action-deletetiddler $filter="[<dropdown-state>] [<searchTiddler>] [<linkTiddler>] [<storeTitle>] [<searchListState>]"/>
|
||||
\end
|
||||
|
||||
\define get-focus-selector() [data-tiddler-title="$(cssEscapedTitle)$"] .tc-create-wikitext-link input
|
||||
|
||||
\define cancel-search-actions-inner()
|
||||
<$set name="userInput" value={{{ [<storeTitle>get[text]] }}}><$list filter="[<searchTiddler>get[text]!match<userInput>]" emptyMessage="<$action-deletetiddler $filter='[<searchTiddler>] [<linkTiddler>] [<storeTitle>] [<searchListState>]'/>"><$action-setfield $tiddler=<<searchTiddler>> text=<<userInput>>/><$action-setfield $tiddler=<<refreshTitle>> text="yes"/></$list></$set>
|
||||
\end
|
||||
|
||||
\define cancel-search-actions() <$list filter="[<storeTitle>!has[text]] +[<searchTiddler>!has[text]]" emptyMessage="<<cancel-search-actions-inner>>"><$action-sendmessage $message="tm-edit-text-operation" $param="focus-editor"/></$list>
|
||||
|
||||
\define external-link()
|
||||
\whitespace trim
|
||||
<$button class="tc-btn-invisible" style="width: auto; display: inline-block; background-colour: inherit;" actions=<<add-link-actions>>>
|
||||
{{$:/core/images/chevron-right}}
|
||||
</$button>
|
||||
\end
|
||||
|
||||
\define set-next-input-tab(beforeafter:"after") <$macrocall $name="change-input-tab" stateTitle="$:/state/tab/search-results/sidebar" tag="$:/tags/SearchResults" beforeafter="$beforeafter$" defaultState={{$:/config/SearchResults/Default}} actions="<$action-setfield $tiddler='$:/state/search/currentTab' text=<<nextTab>>/>"/>
|
||||
|
||||
\define body(config-title)
|
||||
\whitespace trim
|
||||
''<<lingo Hint>>''
|
||||
|
||||
<$vars searchTiddler="""$config-title$/search""" linkTiddler="""$config-title$/link""" linktext="" searchListState=<<qualify "$:/temp/link-search/selected-item">> refreshTitle=<<qualify "$:/temp/link-search/refresh">> storeTitle=<<qualify "$:/temp/link-search/input">>>
|
||||
|
||||
<$vars linkTiddler=<<searchTiddler>>>
|
||||
<$keyboard key="((input-tab-right))" actions=<<set-next-input-tab>>>
|
||||
<$keyboard key="((input-tab-left))" actions=<<set-next-input-tab "before">> class="tc-create-wikitext-link">
|
||||
<$macrocall $name="keyboard-driven-input" tiddler=<<searchTiddler>> storeTitle=<<storeTitle>>
|
||||
selectionStateTitle=<<searchListState>> refreshTitle=<<refreshTitle>> type="search" filterMinLength="1"
|
||||
tag="input" focus="true" class="tc-popup-handle" inputCancelActions=<<cancel-search-actions>>
|
||||
inputAcceptActions=<<add-link-actions>> placeholder={{$:/language/Search/Search}} default=""
|
||||
configTiddlerFilter="[[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}]" />
|
||||
</$keyboard>
|
||||
</$keyboard>
|
||||
 
|
||||
<$reveal tag="span" state=<<storeTitle>> type="nomatch" text="">
|
||||
<<external-link>>
|
||||
 
|
||||
<$button class="tc-btn-invisible" style="width: auto; display: inline-block; background-colour: inherit;">
|
||||
<<cancel-search-actions>><$set name="cssEscapedTitle" value={{{ [<storyTiddler>escapecss[]] }}}><$action-sendmessage $message="tm-focus-selector" $param=<<get-focus-selector>>/></$set>
|
||||
{{$:/core/images/close-button}}
|
||||
</$button>
|
||||
</$reveal>
|
||||
</$vars>
|
||||
|
||||
<$reveal tag="div" state=<<storeTitle>> type="nomatch" text="">
|
||||
|
||||
<$linkcatcher actions=<<add-link-actions>> to=<<linkTiddler>>>
|
||||
|
||||
<$vars userInput={{{ [<storeTitle>get[text]] }}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}}>
|
||||
|
||||
{{$:/core/ui/SearchResults}}
|
||||
|
||||
</$vars>
|
||||
|
||||
</$linkcatcher>
|
||||
|
||||
</$reveal>
|
||||
|
||||
</$vars>
|
||||
|
||||
\end
|
||||
|
||||
<$macrocall $name="body" config-title=<<qualify "$:/state/Link/">>/>
|
11
plugins/tiddlywiki/markdown-legacy/EditorToolbar/link.tid
Executable file
11
plugins/tiddlywiki/markdown-legacy/EditorToolbar/link.tid
Executable file
@ -0,0 +1,11 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/link
|
||||
list-after: $:/core/ui/EditorToolbar/link
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/link
|
||||
caption: {{$:/language/Buttons/Link/Caption}}
|
||||
description: {{$:/language/Buttons/Link/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
button-classes: tc-text-editor-toolbar-item-start-group
|
||||
shortcuts: ((link))
|
||||
dropdown: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/link-dropdown
|
||||
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/linkify.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/linkify.tid
Executable file
@ -0,0 +1,15 @@
|
||||
caption: {{$:/language/Buttons/Linkify/Caption}} (Markdown)
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
description: {{$:/language/Buttons/Linkify/Hint}}
|
||||
icon: $:/plugins/tiddlywiki/markdown-legacy/images/markdown-linkify
|
||||
list-after: $:/core/ui/EditorToolbar/linkify
|
||||
shortcuts: ((linkify))
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/linkify
|
||||
tags: $:/tags/EditorToolbar
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="wrap-selection"
|
||||
prefix="["
|
||||
suffix="]()"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/list-bullet.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/list-bullet.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/list-bullet
|
||||
list-after: $:/core/ui/EditorToolbar/list-bullet
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/list-bullet
|
||||
caption: {{$:/language/Buttons/ListBullet/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/ListBullet/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((list-bullet))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character="*"
|
||||
count="1"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/list-number.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/list-number.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/list-number
|
||||
list-after: $:/core/ui/EditorToolbar/list-number
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/list-number
|
||||
caption: {{$:/language/Buttons/ListNumber/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/ListNumber/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((list-number))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character="1."
|
||||
count="1"
|
||||
/>
|
17
plugins/tiddlywiki/markdown-legacy/EditorToolbar/mono-block.tid
Executable file
17
plugins/tiddlywiki/markdown-legacy/EditorToolbar/mono-block.tid
Executable file
@ -0,0 +1,17 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/mono-block
|
||||
list-after: $:/core/ui/EditorToolbar/mono-block
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/mono-block
|
||||
caption: {{$:/language/Buttons/MonoBlock/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/MonoBlock/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
button-classes: tc-text-editor-toolbar-item-start-group
|
||||
shortcuts: ((mono-block))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="wrap-lines"
|
||||
prefix="
|
||||
```"
|
||||
suffix="```"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/mono-line.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/mono-line.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/mono-line
|
||||
list-after: $:/core/ui/EditorToolbar/mono-line
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/mono-line
|
||||
caption: {{$:/language/Buttons/MonoLine/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/MonoLine/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((mono-line))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="wrap-selection"
|
||||
prefix="`"
|
||||
suffix="`"
|
||||
/>
|
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/quote.tid
Executable file
15
plugins/tiddlywiki/markdown-legacy/EditorToolbar/quote.tid
Executable file
@ -0,0 +1,15 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/EditorToolbar/quote
|
||||
list-after: $:/core/ui/EditorToolbar/quote
|
||||
tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/quote
|
||||
caption: {{$:/language/Buttons/Quote/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Quote/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((quote))
|
||||
|
||||
<$action-sendmessage
|
||||
$message="tm-edit-text-operation"
|
||||
$param="prefix-lines"
|
||||
character=">"
|
||||
count="1"
|
||||
/>
|
@ -0,0 +1,8 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/KeyboardShortcuts/new-markdown-tiddler
|
||||
tags: $:/tags/KeyboardShortcut
|
||||
key: ((new-markdown-tiddler))
|
||||
|
||||
\whitespace trim
|
||||
<$navigator story="$:/StoryList" history="$:/HistoryList" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>
|
||||
<$action-sendmessage $message="tm-new-tiddler" type="text/markdown"/>
|
||||
</$navigator>
|
5
plugins/tiddlywiki/markdown-legacy/config.multids
Normal file
5
plugins/tiddlywiki/markdown-legacy/config.multids
Normal file
@ -0,0 +1,5 @@
|
||||
title: $:/config/
|
||||
|
||||
ShortcutInfo/new-markdown-tiddler: {{$:/language/Buttons/NewMarkdown/Hint}}
|
||||
shortcuts-mac/new-markdown-tiddler: ctrl-M
|
||||
shortcuts-not-mac/new-markdown-tiddler: alt-M
|
4
plugins/tiddlywiki/markdown-legacy/docs_type_markdown.tid
Executable file
4
plugins/tiddlywiki/markdown-legacy/docs_type_markdown.tid
Executable file
@ -0,0 +1,4 @@
|
||||
title: $:/language/Docs/Types/text/markdown
|
||||
description: Markdown
|
||||
name: text/markdown
|
||||
group: Text
|
@ -0,0 +1,37 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/editor-operations/make-markdown-link.js
|
||||
type: application/javascript
|
||||
module-type: texteditoroperation
|
||||
|
||||
Text editor operation to make a markdown link
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports["make-markdown-link"] = function(event,operation) {
|
||||
if(operation.selection) {
|
||||
if(event.paramObject.text.indexOf("://") !== -1) {
|
||||
operation.replacement = "[" + operation.selection + "](" + event.paramObject.text + ")";
|
||||
} else {
|
||||
operation.replacement = "[" + operation.selection + "](#" + event.paramObject.text.replaceAll(" ", "%20") + ")";
|
||||
}
|
||||
operation.cutStart = operation.selStart;
|
||||
operation.cutEnd = operation.selEnd;
|
||||
} else {
|
||||
if(event.paramObject.text.indexOf("://") !== -1) {
|
||||
operation.replacement = "<" + event.paramObject.text + ">";
|
||||
} else {
|
||||
operation.replacement = "[](#" + event.paramObject.text.replaceAll(" ", "%20") + ")";
|
||||
}
|
||||
operation.cutStart = operation.selStart;
|
||||
operation.cutEnd = operation.selEnd;
|
||||
}
|
||||
operation.newSelStart = operation.selStart + operation.replacement.length;
|
||||
operation.newSelEnd = operation.newSelStart;
|
||||
};
|
||||
|
||||
})();
|
36
plugins/tiddlywiki/markdown-legacy/files/tiddlywiki.files
Executable file
36
plugins/tiddlywiki/markdown-legacy/files/tiddlywiki.files
Executable file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"tiddlers": [
|
||||
{
|
||||
"file": "remarkable.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown-legacy/remarkable.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "remarkable-license.txt",
|
||||
"fields": {
|
||||
"type": "text/plain",
|
||||
"title": "$:/plugins/tiddlywiki/markdown-legacy/remarkable-license"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "remarkable-katex.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown-legacy/remarkable-katex.js",
|
||||
"module-type": "library"
|
||||
},
|
||||
"prefix": "(function(realRequire) {var require = function(m) {if(m===\"katex\"){m = \"$:/plugins/tiddlywiki/katex/katex.min.js\"};return realRequire(m);};",
|
||||
"suffix": "})(require);\n"
|
||||
},
|
||||
{
|
||||
"file": "remarkable-katex-license.txt",
|
||||
"fields": {
|
||||
"type": "text/plain",
|
||||
"title": "$:/plugins/tiddlywiki/markdown-legacy/remarkable-katex-license"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/images/markdown-linkify
|
||||
tags: $:/tags/Image
|
||||
|
||||
<svg width="22pt" height="22pt" class="tc-markdown-linkify-button tc-image-button" viewBox="0 0 128 128">
|
||||
<path d="M17.031185,32.1989189 L9.04781705,32.1989189 L9.04781705,97.1303119 L17.031185,97.1303119 L17.031185,104.049231 L0,104.049231 L0,25.28 L17.031185,25.28 L17.031185,32.1989189 Z M93.6716009,24.75 C90.4007675,30.8326023 88.0193713,37.1590826 86.5274123,43.7294408 C85.0354532,50.299799 84.2894737,56.9705775 84.2894737,63.7417763 C84.2894737,70.6277412 85.0211075,77.3702485 86.484375,83.9692982 C87.9476425,90.568348 90.314693,96.9952485 93.5855263,103.25 L93.5855263,103.25 L83.4287281,103.25 C79.8135965,97.3395468 77.0161732,91.1134868 75.0364583,84.5718202 C73.0567434,78.0301535 72.066886,71.3737208 72.066886,64.6025219 C72.066886,61.3890716 72.3107639,58.017818 72.7985197,54.488761 C73.2862756,50.9597039 74.0035636,47.4449927 74.9503838,43.9446272 C75.8972039,40.4442617 77.0735563,37.0586623 78.4794408,33.7878289 C79.8853253,30.5169956 81.5350877,27.504386 83.4287281,24.75 L83.4287281,24.75 Z M116.638158,24.75 C120.253289,30.6604532 123.050713,36.9152047 125.030428,43.5142544 C127.010143,50.1133041 128,56.7984284 128,63.5696272 C128,66.7830775 127.770468,70.1543311 127.311404,73.6833882 C126.852339,77.2124452 126.149397,80.7128107 125.202577,84.1844846 C124.255757,87.6561586 123.065058,91.0274123 121.630482,94.2982456 C120.195906,97.5690789 118.531798,100.552997 116.638158,103.25 L116.638158,103.25 L106.48136,103.25 C109.637427,97.1673977 111.975786,90.8696089 113.496436,84.3566338 C115.017087,77.8436586 115.777412,71.2015716 115.777412,64.4303728 C115.777412,57.5444079 115.031433,50.7732091 113.539474,44.1167763 C112.047515,37.4603436 109.723501,31.0047515 106.567434,24.75 L106.567434,24.75 Z M37.1101871,44.1061384 L37.1101871,56.702119 L49.0852391,52.799139 L51.3915454,59.8954661 L39.3277893,63.798446 L46.956341,74.1768244 L40.8357588,78.6120289 L33.2072072,68.1449464 L25.7560638,78.3459166 L19.8128898,73.8220081 L27.4414414,63.798446 L15.2889813,59.6293539 L17.5952876,52.5330268 L29.6590437,56.702119 L29.6590437,44.1061384 L37.1101871,44.1061384 Z M49.6493416,97.1303119 L57.6327096,97.1303119 L57.6327096,32.1989189 L49.6493416,32.1989189 L49.6493416,25.28 L66.6805267,25.28 L66.6805267,104.049231 L49.6493416,104.049231 L49.6493416,97.1303119 Z"></path>
|
||||
</svg>
|
10
plugins/tiddlywiki/markdown-legacy/images/new-markdown-button.tid
Executable file
10
plugins/tiddlywiki/markdown-legacy/images/new-markdown-button.tid
Executable file
@ -0,0 +1,10 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/images/new-markdown-button
|
||||
tags: $:/tags/Image
|
||||
|
||||
<svg class="tc-image-new-markdown-button tc-image-button" viewBox="0 0 128 128" width="22pt" height="22pt">
|
||||
<g fill-rule="evenodd">
|
||||
<rect x="80" y="96" width="48" height="16" rx="8"></rect>
|
||||
<rect x="96" y="80" width="16" height="48" rx="8"></rect>
|
||||
<path d="M3.23876972,39.5396716 C3.23876972,35.9653274 6.13586353,33.0691646 9.7141757,33.0691646 L98.1283744,33.0691646 C101.706101,33.0691646 104.60378,35.9646626 104.60378,39.5396716 L104.60378,84.8296213 C104.60378,88.4039654 101.706687,91.3001282 98.1283744,91.3001282 L9.7141757,91.3001282 C6.13644944,91.3001282 3.23876972,88.4046302 3.23876972,84.8296213 L3.23876972,39.5396716 L3.23876972,39.5396716 Z M-2.15298617,39.5396716 L-2.15298617,84.8296213 C-2.15298617,91.3833243 3.15957363,96.6918841 9.7141757,96.6918841 L98.1283744,96.6918841 C104.684083,96.6918841 109.995536,91.382138 109.995536,84.8296213 L109.995536,39.5396716 C109.995536,32.9859686 104.682977,27.6774087 98.1283744,27.6774087 L9.7141757,27.6774087 C3.15846686,27.6774087 -2.15298617,32.9871549 -2.15298617,39.5396716 Z M14.0222815,80.5166164 L14.0222815,43.8526764 L24.8057933,43.8526764 L35.589305,57.3320661 L46.3728168,43.8526764 L57.1563286,43.8526764 L57.1563286,80.5166164 L46.3728168,80.5166164 L46.3728168,59.4887685 L35.589305,72.9681582 L24.8057933,59.4887685 L24.8057933,80.5166164 L14.0222815,80.5166164 Z M81.4192301,80.5166164 L65.2439624,62.723822 L76.0274742,62.723822 L76.0274742,43.8526764 L86.810986,43.8526764 L86.810986,62.723822 L97.5944978,62.723822 L81.4192301,80.5166164 Z"transform="translate(53.921275, 62.184646) rotate(-60.000000) translate(-53.921275, -62.184646) "></path>
|
||||
</g>
|
||||
</svg>
|
16
plugins/tiddlywiki/markdown-legacy/new-markdown.tid
Executable file
16
plugins/tiddlywiki/markdown-legacy/new-markdown.tid
Executable file
@ -0,0 +1,16 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/new-markdown-button
|
||||
tags: $:/tags/PageControls
|
||||
caption: {{$:/plugins/tiddlywiki/markdown-legacy/images/new-markdown-button}} {{$:/language/Buttons/NewMarkdown/Caption}}
|
||||
description: {{$:/language/Buttons/NewMarkdown/Hint}}
|
||||
list-after: $:/core/ui/Buttons/new-tiddler
|
||||
|
||||
\whitespace trim
|
||||
<$button tooltip={{$:/language/Buttons/NewMarkdown/Hint}} aria-label={{$:/language/Buttons/NewMarkdown/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$action-sendmessage $message="tm-new-tiddler" type="text/markdown"/>
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/plugins/tiddlywiki/markdown-legacy/images/new-markdown-button}}
|
||||
</$list>
|
||||
<$list filter="[<tv-config-toolbar-text>match[yes]]">
|
||||
<span class="tc-btn-text"><$text text={{$:/language/Buttons/NewMarkdown/Caption}}/></span>
|
||||
</$list>
|
||||
</$button>
|
6
plugins/tiddlywiki/markdown-legacy/plugin.info
Executable file
6
plugins/tiddlywiki/markdown-legacy/plugin.info
Executable file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"title": "$:/plugins/tiddlywiki/markdown-legacy",
|
||||
"name": "Markdown (Legacy)",
|
||||
"description": "Markdown parser based on remarkable by Jon Schlinkert and remarkable-katex by Brad Howes",
|
||||
"list": "readme usage remarkable-license remarkable-katex-license"
|
||||
}
|
7
plugins/tiddlywiki/markdown-legacy/readme.tid
Executable file
7
plugins/tiddlywiki/markdown-legacy/readme.tid
Executable file
@ -0,0 +1,7 @@
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/readme
|
||||
|
||||
This is a TiddlyWiki plugin for parsing Markdown text, using the [[Remarkable|https://github.com/jonschlinkert/remarkable]] library. If the KaTeX TiddlyWiki plugin is installed, KaTeX support is enabled using the [[remarkable-katex|https://github.com/bradhowes/remarkable-katex]] Remarkable plugin.
|
||||
|
||||
It is completely self-contained, and doesn't need an Internet connection in order to work. It works both in the browser and under Node.js.
|
||||
|
||||
[[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/markdown-legacy]]
|
@ -1,4 +1,4 @@
|
||||
title: $:/plugins/tiddlywiki/markdown/usage
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/usage
|
||||
|
||||
! Plugin Configuration
|
||||
|
||||
@ -8,7 +8,7 @@ title: $:/plugins/tiddlywiki/markdown/usage
|
||||
| <code>[[linkNewWindow|$:/config/markdown/linkNewWindow]]</code>| ``true``|For external links, should clicking on them open a new window/tab automatically? |
|
||||
| <code>[[quotes|$:/config/markdown/quotes]]</code>| ``“”‘’``|Remarkable library config: Double + single quotes replacement pairs, when ``typographer`` enabled |
|
||||
| <code>[[renderWikiText|$:/config/markdown/renderWikiText]]</code>| ``true``|After Markdown is parsed, should any text elements be handed off to the ~WikiText parser for further processing? |
|
||||
| <code>[[renderWikiTextPragma|$:/config/markdown/renderWikiTextPragma]]</code>| ``\rules only html image macrocallinline syslink transcludeinline wikilink filteredtranscludeblock macrocallblock transcludeblock``|When handing off to the ~WikiText parser, what pragma rules should it follow? |
|
||||
| <code>[[renderWikiTextPragma|$:/config/markdown/renderWikiTextPragma]]</code>|<code><$view tiddler="$:/plugins/tiddlywiki/markdown-legacy" subtiddler="$:/config/markdown/renderWikiTextPragma" mode="inline"/></code>|When handing off to the ~WikiText parser, what pragma rules should it follow? |
|
||||
| <code>[[typographer|$:/config/markdown/typographer]]</code>| ``false``|Remarkable library config: Enable some language-neutral replacement + quotes beautification |
|
||||
|
||||
! Creating ~WikiLinks
|
341
plugins/tiddlywiki/markdown-legacy/wrapper.js
Executable file
341
plugins/tiddlywiki/markdown-legacy/wrapper.js
Executable file
@ -0,0 +1,341 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/markdown-legacy/wrapper.js
|
||||
type: application/javascript
|
||||
module-type: parser
|
||||
|
||||
Wraps up the remarkable parser for use as a Parser in TiddlyWiki
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var r = require("$:/plugins/tiddlywiki/markdown-legacy/remarkable.js");
|
||||
|
||||
var Remarkable = r.Remarkable,
|
||||
linkify = r.linkify,
|
||||
utils = r.utils;
|
||||
|
||||
///// Set up configuration options /////
|
||||
function parseAsBoolean(tiddlerName) {
|
||||
return $tw.wiki.getTiddlerText(tiddlerName).toLowerCase() === "true";
|
||||
}
|
||||
var pluginOpts = {
|
||||
linkNewWindow: parseAsBoolean("$:/config/markdown/linkNewWindow"),
|
||||
renderWikiText: parseAsBoolean("$:/config/markdown/renderWikiText"),
|
||||
renderWikiTextPragma: $tw.wiki.getTiddlerText("$:/config/markdown/renderWikiTextPragma").trim()
|
||||
};
|
||||
var remarkableOpts = {
|
||||
breaks: parseAsBoolean("$:/config/markdown/breaks"),
|
||||
quotes: $tw.wiki.getTiddlerText("$:/config/markdown/quotes"),
|
||||
typographer: parseAsBoolean("$:/config/markdown/typographer")
|
||||
};
|
||||
var accumulatingTypes = {
|
||||
"text": true,
|
||||
"softbreak": true
|
||||
};
|
||||
// If rendering WikiText, we treat katex nodes as text.
|
||||
if(pluginOpts.renderWikiText) {
|
||||
accumulatingTypes["katex"] = true;
|
||||
}
|
||||
|
||||
var md = new Remarkable(remarkableOpts);
|
||||
|
||||
// If tiddlywiki/katex plugin is present, use remarkable-katex to enable katex support.
|
||||
if($tw.modules.titles["$:/plugins/tiddlywiki/katex/katex.min.js"]) {
|
||||
var rk = require("$:/plugins/tiddlywiki/markdown-legacy/remarkable-katex.js");
|
||||
md = md.use(rk);
|
||||
}
|
||||
|
||||
if(parseAsBoolean("$:/config/markdown/linkify")) {
|
||||
md = md.use(linkify);
|
||||
}
|
||||
|
||||
function findTagWithType(nodes, startPoint, type, level) {
|
||||
for (var i = startPoint; i < nodes.length; i++) {
|
||||
if(nodes[i].type === type && nodes[i].level === level) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remarkable creates nodes that look like:
|
||||
* [
|
||||
* { type: 'paragraph_open'},
|
||||
* { type: 'inline', content: 'Hello World', children:[{type: 'text', content: 'Hello World'}]},
|
||||
* { type: 'paragraph_close'}
|
||||
* ]
|
||||
*
|
||||
* But TiddlyWiki wants the Parser (https://tiddlywiki.com/dev/static/Parser.html) to emit nodes like:
|
||||
*
|
||||
* [
|
||||
* { type: 'element', tag: 'p', children: [{type: 'text', text: 'Hello World'}]}
|
||||
* ]
|
||||
*/
|
||||
function convertNodes(remarkableTree, isStartOfInline) {
|
||||
let out = [];
|
||||
var accumulatedText = '';
|
||||
function withChildren(currentIndex, currentLevel, closingType, nodes, callback) {
|
||||
var j = findTagWithType(nodes, currentIndex + 1, closingType, currentLevel);
|
||||
if(j === false) {
|
||||
console.error("Failed to find a " + closingType + " node after position " + currentIndex);
|
||||
console.log(nodes);
|
||||
return currentIndex + 1;
|
||||
}
|
||||
let children = convertNodes(nodes.slice(currentIndex + 1, j));
|
||||
callback(children);
|
||||
return j;
|
||||
}
|
||||
function wrappedElement(elementTag, currentIndex, currentLevel, closingType, nodes) {
|
||||
return withChildren(currentIndex, currentLevel, closingType, nodes, function(children) {
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: elementTag,
|
||||
children: children
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0; i < remarkableTree.length; i++) {
|
||||
var currentNode = remarkableTree[i];
|
||||
switch (currentNode.type) {
|
||||
case "paragraph_open":
|
||||
// If the paragraph is a "tight" layout paragraph, don't wrap children in a <p> tag.
|
||||
if(currentNode.tight) {
|
||||
i = withChildren(i, currentNode.level, "paragraph_close", remarkableTree, function(children) {
|
||||
Array.prototype.push.apply(out, children);
|
||||
});
|
||||
} else {
|
||||
i = wrappedElement("p", i, currentNode.level, "paragraph_close", remarkableTree);
|
||||
}
|
||||
break;
|
||||
|
||||
case "heading_open":
|
||||
i = wrappedElement("h" + currentNode.hLevel, i, currentNode.level, "heading_close", remarkableTree);
|
||||
break;
|
||||
|
||||
case "bullet_list_open":
|
||||
i = wrappedElement("ul", i, currentNode.level, "bullet_list_close", remarkableTree);
|
||||
break;
|
||||
|
||||
case "ordered_list_open":
|
||||
i = wrappedElement('ol', i, currentNode.level,'ordered_list_close', remarkableTree);
|
||||
break;
|
||||
|
||||
case "list_item_open":
|
||||
i = wrappedElement("li", i, currentNode.level, "list_item_close", remarkableTree);
|
||||
break;
|
||||
|
||||
case "link_open":
|
||||
i = withChildren(i, currentNode.level, "link_close", remarkableTree, function(children) {
|
||||
if(currentNode.href[0] !== "#") {
|
||||
// External link
|
||||
var attributes = {
|
||||
class: { type: "string", value: "tc-tiddlylink-external" },
|
||||
href: { type: "string", value: currentNode.href },
|
||||
rel: { type: "string", value: "noopener noreferrer" }
|
||||
};
|
||||
if(pluginOpts.linkNewWindow) {
|
||||
attributes.target = { type: "string", value: "_blank" };
|
||||
}
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: "a",
|
||||
attributes: attributes,
|
||||
children: children
|
||||
});
|
||||
} else {
|
||||
// Internal link
|
||||
out.push({
|
||||
type: "link",
|
||||
attributes: {
|
||||
to: { type: "string", value: $tw.utils.decodeURISafe(currentNode.href.substr(1)) }
|
||||
},
|
||||
children: children
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "code":
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: currentNode.block ? "pre" : "code",
|
||||
children: [{ type: "text", text: currentNode.content }]
|
||||
});
|
||||
break;
|
||||
|
||||
case "fence":
|
||||
out.push({
|
||||
type: "codeblock",
|
||||
attributes: {
|
||||
language: { type: "string", value: currentNode.params },
|
||||
code: { type: "string", value: currentNode.content }
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "image":
|
||||
out.push({
|
||||
type: "image",
|
||||
attributes: {
|
||||
tooltip: { type: "string", value: currentNode.alt },
|
||||
source: { type: "string", value: $tw.utils.decodeURIComponentSafe(currentNode.src) }
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "softbreak":
|
||||
if(remarkableOpts.breaks) {
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: "br",
|
||||
});
|
||||
} else {
|
||||
accumulatedText = accumulatedText + '\n';
|
||||
}
|
||||
break;
|
||||
|
||||
case "hardbreak":
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: "br",
|
||||
});
|
||||
break;
|
||||
|
||||
case "th_open":
|
||||
case "td_open":
|
||||
var elementTag = currentNode.type.slice(0, 2);
|
||||
i = withChildren(i, currentNode.level, elementTag + "_close", remarkableTree, function(children) {
|
||||
var attributes = {};
|
||||
if(currentNode.align) {
|
||||
attributes.style = { type: "string", value: "text-align:" + currentNode.align };
|
||||
}
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: elementTag,
|
||||
attributes: attributes,
|
||||
children: children
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
case "hr":
|
||||
out.push({
|
||||
type: 'element',
|
||||
tag: 'hr',
|
||||
});
|
||||
break;
|
||||
|
||||
case "inline":
|
||||
out = out.concat(convertNodes(currentNode.children, true));
|
||||
break;
|
||||
|
||||
case "text":
|
||||
// We need to merge this text block with the upcoming text block and parse it all together.
|
||||
accumulatedText = accumulatedText + currentNode.content;
|
||||
break;
|
||||
|
||||
case "katex":
|
||||
// If rendering WikiText, convert the katex node back to text for parsing by the WikiText LaTeX parser.
|
||||
if(pluginOpts.renderWikiText) {
|
||||
// If this is a block, add a newline to trigger the KaTeX plugins block detection.
|
||||
var displayModeSuffix = currentNode.block ? "\n" : "";
|
||||
accumulatedText = accumulatedText + "$$" + currentNode.content + displayModeSuffix + "$$";
|
||||
} else {
|
||||
out.push({
|
||||
type: "latex",
|
||||
attributes: {
|
||||
text: { type: "text", value: currentNode.content },
|
||||
displayMode: { type: "text", value: currentNode.block ? "true" : "false" }
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(currentNode.type.substr(currentNode.type.length - 5) === "_open") {
|
||||
var tagName = currentNode.type.substr(0, currentNode.type.length - 5);
|
||||
i = wrappedElement(tagName, i, currentNode.level, tagName + "_close", remarkableTree);
|
||||
} else {
|
||||
console.error("Unknown node type: " + currentNode.type, currentNode);
|
||||
out.push({
|
||||
type: "text",
|
||||
text: currentNode.content
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
// We test to see if we process the block now, or if there's
|
||||
// more to accumulate first.
|
||||
if(accumulatedText
|
||||
&& (
|
||||
remarkableOpts.breaks ||
|
||||
(i+1) >= remarkableTree.length ||
|
||||
!accumulatingTypes[remarkableTree[i+1].type]
|
||||
)
|
||||
) {
|
||||
// The Markdown compiler thinks this is just text.
|
||||
// Hand off to the WikiText parser to see if there's more to render
|
||||
// But only if it's configured to, and we have more than whitespace
|
||||
if(!pluginOpts.renderWikiText || accumulatedText.match(/^\s*$/)) {
|
||||
out.push({
|
||||
type: "text",
|
||||
text: accumulatedText
|
||||
});
|
||||
} else {
|
||||
// If we're inside a block element (div, p, td, h1), and this is the first child in the tree,
|
||||
// handle as a block-level parse. Otherwise not.
|
||||
var parseAsInline = !(isStartOfInline && i === 0);
|
||||
var textToParse = accumulatedText;
|
||||
if(pluginOpts.renderWikiTextPragma !== "") {
|
||||
textToParse = pluginOpts.renderWikiTextPragma + "\n" + textToParse;
|
||||
}
|
||||
var wikiParser = $tw.wiki.parseText("text/vnd.tiddlywiki", textToParse, {
|
||||
parseAsInline: parseAsInline
|
||||
});
|
||||
var rs = wikiParser.tree;
|
||||
|
||||
// If we parsed as a block, but the root element the WikiText parser gave is a paragraph,
|
||||
// we should discard the paragraph, since the way Remarkable nests its nodes, this "inline"
|
||||
// node is always inside something else that's a block-level element
|
||||
if(!parseAsInline
|
||||
&& rs.length === 1
|
||||
&& rs[0].type === "element"
|
||||
&& rs[0].tag === "p"
|
||||
) {
|
||||
rs = rs[0].children;
|
||||
}
|
||||
|
||||
// If the original text element started with a space, add it back in
|
||||
if(rs.length > 0
|
||||
&& rs[0].type === "text"
|
||||
&& (accumulatedText[0] === " " || accumulatedText[0] === "\n")
|
||||
) {
|
||||
rs[0].text = " " + rs[0].text;
|
||||
}
|
||||
out = out.concat(rs);
|
||||
}
|
||||
accumulatedText = '';
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
var MarkdownParser = function(type, text, options) {
|
||||
var tree = md.parse(text, {});
|
||||
//console.debug(tree);
|
||||
tree = convertNodes(tree);
|
||||
//console.debug(tree);
|
||||
|
||||
this.tree = tree;
|
||||
};
|
||||
|
||||
exports["text/x-markdown"] = MarkdownParser;
|
||||
exports["text/markdown"] = MarkdownParser;
|
||||
|
||||
})();
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/bold
|
||||
caption: {{$:/language/Buttons/Bold/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Bold/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((bold))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-1
|
||||
caption: {{$:/language/Buttons/Heading1/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading1/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-1))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-2
|
||||
caption: {{$:/language/Buttons/Heading2/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading2/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-2))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-3
|
||||
caption: {{$:/language/Buttons/Heading3/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading3/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-3))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-4
|
||||
caption: {{$:/language/Buttons/Heading4/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading4/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-4))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-5
|
||||
caption: {{$:/language/Buttons/Heading5/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading5/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-5))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/heading-6
|
||||
caption: {{$:/language/Buttons/Heading6/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Heading6/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((heading-6))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/italic
|
||||
caption: {{$:/language/Buttons/Italic/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Italic/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((italic))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/list-bullet
|
||||
caption: {{$:/language/Buttons/ListBullet/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/ListBullet/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((list-bullet))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/list-number
|
||||
caption: {{$:/language/Buttons/ListNumber/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/ListNumber/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((list-number))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/mono-line
|
||||
caption: {{$:/language/Buttons/MonoLine/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/MonoLine/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((mono-line))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,7 +4,7 @@ tags: $:/tags/EditorToolbar
|
||||
icon: $:/core/images/quote
|
||||
caption: {{$:/language/Buttons/Quote/Caption}} (Markdown)
|
||||
description: {{$:/language/Buttons/Quote/Hint}}
|
||||
condition: [<targetTiddler>type[text/x-markdown]]
|
||||
condition: [<targetTiddler>type[text/x-markdown]] [<targetTiddler>type[text/markdown]]
|
||||
shortcuts: ((quote))
|
||||
|
||||
<$action-sendmessage
|
||||
|
@ -4,5 +4,5 @@ key: ((new-markdown-tiddler))
|
||||
|
||||
\whitespace trim
|
||||
<$navigator story="$:/StoryList" history="$:/HistoryList" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>
|
||||
<$action-sendmessage $message="tm-new-tiddler" type="text/x-markdown"/>
|
||||
<$action-sendmessage $message="tm-new-tiddler" type="text/markdown"/>
|
||||
</$navigator>
|
||||
|
@ -3,3 +3,9 @@ title: $:/config/
|
||||
ShortcutInfo/new-markdown-tiddler: {{$:/language/Buttons/NewMarkdown/Hint}}
|
||||
shortcuts-mac/new-markdown-tiddler: ctrl-M
|
||||
shortcuts-not-mac/new-markdown-tiddler: alt-M
|
||||
markdown/breaks: false
|
||||
markdown/linkify: false
|
||||
markdown/quotes: “”‘’
|
||||
markdown/renderWikiText: true
|
||||
markdown/renderWikiTextPragma: \rules only html entity syslink wikilink commentblock commentinline macrocallblock macrocallinline transcludeblock transcludeinline filteredtranscludeblock filteredtranscludeinline
|
||||
markdown/typographer: false
|
80
plugins/tiddlywiki/markdown/config.tid
Executable file
80
plugins/tiddlywiki/markdown/config.tid
Executable file
@ -0,0 +1,80 @@
|
||||
title: $:/plugins/tiddlywiki/markdown/config
|
||||
|
||||
! Plugin Configuration
|
||||
|
||||
|!Config |!Default |!Description |
|
||||
|[[breaks|$:/config/markdown/breaks]]|`false`|markdown-it library config: Convert '\n' in paragraphs into `<br>` |
|
||||
|[[linkify|$:/config/markdown/linkify]]|`false`|markdown-it library config: Autoconvert URL-like text to links |
|
||||
|[[renderWikiText|$:/config/markdown/renderWikiText]]|`true`|After Markdown is parsed, should any text elements be handed off to the ~WikiText parser for further processing? |
|
||||
|[[renderWikiTextPragma|$:/config/markdown/renderWikiTextPragma]]|<code><$view tiddler="$:/plugins/tiddlywiki/markdown" subtiddler="$:/config/markdown/renderWikiTextPragma" mode="inline"/></code>|When handing off to the ~WikiText parser, what parser rules should it follow? |
|
||||
|[[typographer|$:/config/markdown/typographer]]|`false`|markdown-it library config: Enable some language-neutral replacement + quotes beautification |
|
||||
|[[quotes|$:/config/markdown/quotes]]|`“”‘’`|markdown-it library config: Double + single quotes replacement pairs, when `typographer` is enabled |
|
||||
|
||||
''IMPORTANT:'' You must reload your wiki for changes to take effect.
|
||||
|
||||
<h2 style="margin-top:1.5em">~WikiText Pragma</h2>
|
||||
|
||||
The value of [[renderWikiTextPragma|$:/config/markdown/renderWikiTextPragma]] has been carefully tuned to properly integrate markdown with ~TiddlyWiki. Changing this setting may produce unexpected results, but the inclusion of the following parser rules should be fine:
|
||||
|
||||
; image
|
||||
: embed images using ~TiddlyWiki's image syntax:
|
||||
|
||||
<p style="margin-left:1em">
|
||||
|
||||
```
|
||||
[img[An explanatory tooltip|TiddlerTitle]]
|
||||
|
||||
[img width=23 class="tc-image" [https://tiddlywiki.com/fractalveg.jpg]]
|
||||
```
|
||||
</p>
|
||||
|
||||
; prettylink
|
||||
: create links the ~TiddlyWiki way:
|
||||
|
||||
<p style="margin-left:1em">
|
||||
|
||||
```
|
||||
[[TiddlerTitle]]
|
||||
|
||||
[[Displayed Link Title|Tiddler Title]]
|
||||
|
||||
[[TW5|https://tiddlywiki.com/]]
|
||||
```
|
||||
</p>
|
||||
|
||||
; prettyextlink
|
||||
: create external links using the following syntax:
|
||||
|
||||
<p style="margin-left:1em">
|
||||
|
||||
```
|
||||
[ext[Open file|index.html]]
|
||||
|
||||
[ext[Open file|../README.md]]
|
||||
```
|
||||
</p>
|
||||
|
||||
; wikilink
|
||||
: auto-link ~CamelCase titles
|
||||
|
||||
; syslink
|
||||
: auto-link system tiddlers
|
||||
|
||||
<h2 style="margin-top:1.5em">Typographical Replacements</h2>
|
||||
|
||||
When [[typographer|$:/config/markdown/typographer]] is enabled, markdown-it will provide these typographical replacements:
|
||||
|
||||
```
|
||||
(c) (C) → ©
|
||||
(tm) (TM) → ™
|
||||
(r) (R) → ®
|
||||
+- → ±
|
||||
... → …
|
||||
?.... → ?..
|
||||
!.... → !..
|
||||
????? → ???
|
||||
!!!!! → !!!
|
||||
,, → ,
|
||||
-- → –
|
||||
--- → —
|
||||
```
|
@ -1,4 +1,4 @@
|
||||
title: $:/language/Docs/Types/text/x-markdown
|
||||
title: $:/language/Docs/Types/text/markdown
|
||||
description: Markdown
|
||||
name: text/x-markdown
|
||||
name: text/markdown
|
||||
group: Text
|
||||
|
@ -13,19 +13,25 @@ Text editor operation to make a markdown link
|
||||
"use strict";
|
||||
|
||||
exports["make-markdown-link"] = function(event,operation) {
|
||||
var rx = /[()\\]/g, rs = '\\$&';
|
||||
|
||||
if(operation.selection) {
|
||||
if(event.paramObject.text.includes("://")) {
|
||||
operation.replacement = "[" + operation.selection + "](" + event.paramObject.text + ")";
|
||||
var desc = operation.selection.replace(/[\[\]\\]/g, rs);
|
||||
|
||||
if(event.paramObject.text.indexOf("://") !== -1) {
|
||||
operation.replacement = "[" + desc + "](" + event.paramObject.text.replace(rx, rs) + ")";
|
||||
} else {
|
||||
operation.replacement = "[" + operation.selection + "](#" + event.paramObject.text.replaceAll(" ", "%20") + ")";
|
||||
operation.replacement = "[" + desc + "](#" + encodeURIComponent(event.paramObject.text).replace(rx, rs) + ")";
|
||||
}
|
||||
operation.cutStart = operation.selStart;
|
||||
operation.cutEnd = operation.selEnd;
|
||||
} else {
|
||||
if(event.paramObject.text.includes("://")) {
|
||||
operation.replacement = "<" + event.paramObject.text + ">";
|
||||
if(event.paramObject.text.indexOf("://") !== -1) {
|
||||
operation.replacement = "<" + event.paramObject.text.replace(/[<>]/g, function(m, offset, str) {
|
||||
return encodeURI(m);
|
||||
}) + ">";
|
||||
} else {
|
||||
operation.replacement = "[](#" + event.paramObject.text.replaceAll(" ", "%20") + ")";
|
||||
operation.replacement = "[](#" + encodeURIComponent(event.paramObject.text).replace(rx, rs) + ")";
|
||||
}
|
||||
operation.cutStart = operation.selStart;
|
||||
operation.cutEnd = operation.selEnd;
|
||||
|
22
plugins/tiddlywiki/markdown/files/LICENSE
Normal file
22
plugins/tiddlywiki/markdown/files/LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
7
plugins/tiddlywiki/markdown/files/markdown-it-deflist.min.js
vendored
Normal file
7
plugins/tiddlywiki/markdown/files/markdown-it-deflist.min.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/*!
|
||||
|
||||
markdown-it-deflist
|
||||
https://github.com/markdown-it/markdown-it-deflist
|
||||
|
||||
*/
|
||||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).markdownitDeflist=e()}}((function(){return function e(t,n,r){function i(f,d){if(!n[f]){if(!t[f]){var s="function"==typeof require&&require;if(!d&&s)return s(f,!0);if(o)return o(f,!0);var u=new Error("Cannot find module '"+f+"'");throw u.code="MODULE_NOT_FOUND",u}var a=n[f]={exports:{}};t[f][0].call(a.exports,(function(e){return i(t[f][1][e]||e)}),a,a.exports,e,t,n,r)}return n[f].exports}for(var o="function"==typeof require&&require,f=0;f<r.length;f++)i(r[f]);return i}({"/":[function(e,t,n){"use strict";t.exports=function(e){var t=e.utils.isSpace;function n(e,t){var n,r,i=e.bMarks[t]+e.tShift[t],o=e.eMarks[t];return i>=o||126!==(r=e.src.charCodeAt(i++))&&58!==r||i===(n=e.skipSpaces(i))||n>=o?-1:i}e.block.ruler.before("paragraph","deflist",(function(e,r,i,o){var f,d,s,u,a,l,p,k,c,h,b,y,m,g,C,I,v,_,w,x;if(o)return!(e.ddIndent<0)&&n(e,r)>=0;if((c=r+1)>=i)return!1;if(e.isEmpty(c)&&++c>=i)return!1;if(e.sCount[c]<e.blkIndent)return!1;if((d=n(e,c))<0)return!1;p=e.tokens.length,w=!0,(x=e.push("dl_open","dl",1)).map=l=[r,0],u=r,s=c;e:for(;;){for(_=!1,(x=e.push("dt_open","dt",1)).map=[u,u],(x=e.push("inline","",0)).map=[u,u],x.content=e.getLines(u,u+1,e.blkIndent,!1).trim(),x.children=[],x=e.push("dt_close","dt",-1);;){for((x=e.push("dd_open","dd",1)).map=a=[c,0],v=d,k=e.eMarks[s],h=e.sCount[s]+d-(e.bMarks[s]+e.tShift[s]);v<k&&(f=e.src.charCodeAt(v),t(f));)9===f?h+=4-h%4:h++,v++;if(d=v,I=e.tight,b=e.ddIndent,y=e.blkIndent,C=e.tShift[s],g=e.sCount[s],m=e.parentType,e.blkIndent=e.ddIndent=e.sCount[s]+2,e.tShift[s]=d-e.bMarks[s],e.sCount[s]=h,e.tight=!0,e.parentType="deflist",e.md.block.tokenize(e,s,i,!0),e.tight&&!_||(w=!1),_=e.line-s>1&&e.isEmpty(e.line-1),e.tShift[s]=C,e.sCount[s]=g,e.tight=I,e.parentType=m,e.blkIndent=y,e.ddIndent=b,x=e.push("dd_close","dd",-1),a[1]=c=e.line,c>=i)break e;if(e.sCount[c]<e.blkIndent)break e;if((d=n(e,c))<0)break;s=c}if(c>=i)break;if(u=c,e.isEmpty(u))break;if(e.sCount[u]<e.blkIndent)break;if((s=u+1)>=i)break;if(e.isEmpty(s)&&s++,s>=i)break;if(e.sCount[s]<e.blkIndent)break;if((d=n(e,s))<0)break}return x=e.push("dl_close","dl",-1),l[1]=c,e.line=c,w&&function(e,t){var n,r,i=e.level+2;for(n=t+2,r=e.tokens.length-2;n<r;n++)e.tokens[n].level===i&&"paragraph_open"===e.tokens[n].type&&(e.tokens[n+2].hidden=!0,e.tokens[n].hidden=!0,n+=2)}(e,p),!0}),{alt:["paragraph","reference","blockquote"]})}},{}]},{},[])("/")}));
|
1
plugins/tiddlywiki/markdown/files/markdown-it-footnote.min.js
vendored
Normal file
1
plugins/tiddlywiki/markdown/files/markdown-it-footnote.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
plugins/tiddlywiki/markdown/files/markdown-it-ins.min.js
vendored
Normal file
2
plugins/tiddlywiki/markdown/files/markdown-it-ins.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*! markdown-it-ins 3.0.1 https://github.com/markdown-it/markdown-it-mark @license MIT */
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).markdownitIns=n()}(this,(function(){"use strict";return function(e){function n(e,n){var t,o,s,i,r,l=[],f=n.length;for(t=0;t<f;t++)43===(s=n[t]).marker&&-1!==s.end&&(i=n[s.end],(r=e.tokens[s.token]).type="ins_open",r.tag="ins",r.nesting=1,r.markup="++",r.content="",(r=e.tokens[i.token]).type="ins_close",r.tag="ins",r.nesting=-1,r.markup="++",r.content="","text"===e.tokens[i.token-1].type&&"+"===e.tokens[i.token-1].content&&l.push(i.token-1));for(;l.length;){for(o=(t=l.pop())+1;o<e.tokens.length&&"ins_close"===e.tokens[o].type;)o++;t!==--o&&(r=e.tokens[o],e.tokens[o]=e.tokens[t],e.tokens[t]=r)}}e.inline.ruler.before("emphasis","ins",(function(e,n){var t,o,s,i,r=e.pos,l=e.src.charCodeAt(r);if(n)return!1;if(43!==l)return!1;if(s=(o=e.scanDelims(e.pos,!0)).length,i=String.fromCharCode(l),s<2)return!1;for(s%2&&(e.push("text","",0).content=i,s--),t=0;t<s;t+=2)e.push("text","",0).content=i+i,(o.can_open||o.can_close)&&e.delimiters.push({marker:l,length:0,jump:t/2,token:e.tokens.length-1,end:-1,open:o.can_open,close:o.can_close});return e.pos+=o.length,!0})),e.inline.ruler2.before("emphasis","ins",(function(e){var t,o=e.tokens_meta,s=(e.tokens_meta||[]).length;for(n(e,e.delimiters),t=0;t<s;t++)o[t]&&o[t].delimiters&&n(e,o[t].delimiters)}))}}));
|
2
plugins/tiddlywiki/markdown/files/markdown-it-mark.min.js
vendored
Normal file
2
plugins/tiddlywiki/markdown/files/markdown-it-mark.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*! markdown-it-mark 3.0.1 https://github.com/markdown-it/markdown-it-mark @license MIT */
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).markdownitMark=n()}(this,(function(){"use strict";return function(e){function n(e,n){var t,o,r,s,i,a=[],k=n.length;for(t=0;t<k;t++)61===(r=n[t]).marker&&-1!==r.end&&(s=n[r.end],(i=e.tokens[r.token]).type="mark_open",i.tag="mark",i.nesting=1,i.markup="==",i.content="",(i=e.tokens[s.token]).type="mark_close",i.tag="mark",i.nesting=-1,i.markup="==",i.content="","text"===e.tokens[s.token-1].type&&"="===e.tokens[s.token-1].content&&a.push(s.token-1));for(;a.length;){for(o=(t=a.pop())+1;o<e.tokens.length&&"mark_close"===e.tokens[o].type;)o++;t!==--o&&(i=e.tokens[o],e.tokens[o]=e.tokens[t],e.tokens[t]=i)}}e.inline.ruler.before("emphasis","mark",(function(e,n){var t,o,r,s,i=e.pos,a=e.src.charCodeAt(i);if(n)return!1;if(61!==a)return!1;if(r=(o=e.scanDelims(e.pos,!0)).length,s=String.fromCharCode(a),r<2)return!1;for(r%2&&(e.push("text","",0).content=s,r--),t=0;t<r;t+=2)e.push("text","",0).content=s+s,(o.can_open||o.can_close)&&e.delimiters.push({marker:a,length:0,jump:t/2,token:e.tokens.length-1,end:-1,open:o.can_open,close:o.can_close});return e.pos+=o.length,!0})),e.inline.ruler2.before("emphasis","mark",(function(e){var t,o=e.tokens_meta,r=(e.tokens_meta||[]).length;for(n(e,e.delimiters),t=0;t<r;t++)o[t]&&o[t].delimiters&&n(e,o[t].delimiters)}))}}));
|
2
plugins/tiddlywiki/markdown/files/markdown-it-sub.min.js
vendored
Normal file
2
plugins/tiddlywiki/markdown/files/markdown-it-sub.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*! markdown-it-sub 1.0.0 https://github.com//markdown-it/markdown-it-sub @license MIT */
|
||||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.markdownitSub=e()}}(function(){return function e(r,o,n){function t(i,u){if(!o[i]){if(!r[i]){var f="function"==typeof require&&require;if(!u&&f)return f(i,!0);if(s)return s(i,!0);var p=new Error("Cannot find module '"+i+"'");throw p.code="MODULE_NOT_FOUND",p}var a=o[i]={exports:{}};r[i][0].call(a.exports,function(e){var o=r[i][1][e];return t(o?o:e)},a,a.exports,e,r,o,n)}return o[i].exports}for(var s="function"==typeof require&&require,i=0;i<n.length;i++)t(n[i]);return t}({1:[function(e,r){"use strict";function o(e,r){var o,t,s,i=e.posMax,u=e.pos;if(126!==e.src.charCodeAt(u))return!1;if(r)return!1;if(u+2>=i)return!1;for(e.pos=u+1;e.pos<i;){if(126===e.src.charCodeAt(e.pos)){o=!0;break}e.md.inline.skipToken(e)}return o&&u+1!==e.pos?(t=e.src.slice(u+1,e.pos),t.match(/(^|[^\\])(\\\\)*\s/)?(e.pos=u,!1):(e.posMax=e.pos,e.pos=u+1,s=e.push("sub_open","sub",1),s.markup="~",s=e.push("text","",0),s.content=t.replace(n,"$1"),s=e.push("sub_close","sub",-1),s.markup="~",e.pos=e.posMax+1,e.posMax=i,!0)):(e.pos=u,!1)}var n=/\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;r.exports=function(e){e.inline.ruler.after("emphasis","sub",o)}},{}]},{},[1])(1)});
|
2
plugins/tiddlywiki/markdown/files/markdown-it-sup.min.js
vendored
Normal file
2
plugins/tiddlywiki/markdown/files/markdown-it-sup.min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*! markdown-it-sup 1.0.0 https://github.com//markdown-it/markdown-it-sup @license MIT */
|
||||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.markdownitSup=e()}}(function(){return function e(r,o,n){function t(i,p){if(!o[i]){if(!r[i]){var u="function"==typeof require&&require;if(!p&&u)return u(i,!0);if(s)return s(i,!0);var f=new Error("Cannot find module '"+i+"'");throw f.code="MODULE_NOT_FOUND",f}var a=o[i]={exports:{}};r[i][0].call(a.exports,function(e){var o=r[i][1][e];return t(o?o:e)},a,a.exports,e,r,o,n)}return o[i].exports}for(var s="function"==typeof require&&require,i=0;i<n.length;i++)t(n[i]);return t}({1:[function(e,r){"use strict";function o(e,r){var o,t,s,i=e.posMax,p=e.pos;if(94!==e.src.charCodeAt(p))return!1;if(r)return!1;if(p+2>=i)return!1;for(e.pos=p+1;e.pos<i;){if(94===e.src.charCodeAt(e.pos)){o=!0;break}e.md.inline.skipToken(e)}return o&&p+1!==e.pos?(t=e.src.slice(p+1,e.pos),t.match(/(^|[^\\])(\\\\)*\s/)?(e.pos=p,!1):(e.posMax=e.pos,e.pos=p+1,s=e.push("sup_open","sup",1),s.markup="^",s=e.push("text","",0),s.content=t.replace(n,"$1"),s=e.push("sup_close","sup",-1),s.markup="^",e.pos=e.posMax+1,e.posMax=i,!0)):(e.pos=p,!1)}var n=/\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;r.exports=function(e){e.inline.ruler.after("emphasis","sup",o)}},{}]},{},[1])(1)});
|
3
plugins/tiddlywiki/markdown/files/markdown-it.min.js
vendored
Normal file
3
plugins/tiddlywiki/markdown/files/markdown-it.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,35 +1,66 @@
|
||||
{
|
||||
"tiddlers": [
|
||||
{
|
||||
"file": "remarkable.js",
|
||||
"file": "markdown-it.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/remarkable.js",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/markdown-it.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "remarkable-license.txt",
|
||||
"file": "markdown-it-deflist.min.js",
|
||||
"fields": {
|
||||
"type": "text/plain",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/remarkable-license"
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/markdown-it-deflist.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "remarkable-katex.min.js",
|
||||
"file": "markdown-it-footnote.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/remarkable-katex.js",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/markdown-it-footnote.js",
|
||||
"module-type": "library"
|
||||
},
|
||||
"prefix": "(function(realRequire) {var require = function(m) {if(m===\"katex\"){m = \"$:/plugins/tiddlywiki/katex/katex.min.js\"};return realRequire(m);};",
|
||||
"suffix": "})(require);\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "remarkable-katex-license.txt",
|
||||
"file": "markdown-it-ins.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/markdown-it-ins.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "markdown-it-mark.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/markdown-it-mark.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "markdown-it-sub.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/markdown-it-sub.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "markdown-it-sup.min.js",
|
||||
"fields": {
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/markdown-it-sup.js",
|
||||
"module-type": "library"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "LICENSE",
|
||||
"fields": {
|
||||
"type": "text/plain",
|
||||
"title": "$:/plugins/tiddlywiki/markdown/remarkable-katex-license"
|
||||
"title": "$:/plugins/tiddlywiki/markdown/license"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
170
plugins/tiddlywiki/markdown/markdown-it-katex.js
Normal file
170
plugins/tiddlywiki/markdown/markdown-it-katex.js
Normal file
@ -0,0 +1,170 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/markdown/markdown-it-katex.js
|
||||
type: application/javascript
|
||||
module-type: library
|
||||
|
||||
Based on markdown-it-katex v2.0.0 by @waylonflinn https://github.com/waylonflinn/markdown-it-katex | MIT License
|
||||
\*/
|
||||
(function(){
|
||||
/* Process inline math */
|
||||
/*
|
||||
Like markdown-it-simplemath, this is a stripped down, simplified version of:
|
||||
https://github.com/runarberg/markdown-it-math
|
||||
|
||||
It differs in that it takes (a subset of) LaTeX as input and relies on KaTeX
|
||||
for rendering output.
|
||||
*/
|
||||
|
||||
/*jslint node: true */
|
||||
'use strict';
|
||||
|
||||
// Test if potential opening or closing delimieter
|
||||
// Assumes that there is a "$" at state.src[pos]
|
||||
function isValidDelim(state, pos) {
|
||||
var prevChar, nextChar,
|
||||
max = state.posMax,
|
||||
can_open = true,
|
||||
can_close = true;
|
||||
|
||||
prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
|
||||
nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
|
||||
|
||||
// Check non-whitespace conditions for opening and closing, and
|
||||
// check that closing delimeter isn't followed by a number
|
||||
if (prevChar === 0x20/* " " */ || prevChar === 0x09/* \t */ ||
|
||||
prevChar === 0x0d/* "\r" */ || prevChar === 0x0a/* \n */ ||
|
||||
(nextChar >= 0x30/* "0" */ && nextChar <= 0x39/* "9" */)) {
|
||||
can_close = false;
|
||||
}
|
||||
if (nextChar === 0x20/* " " */ || nextChar === 0x09/* \t */ ||
|
||||
nextChar === 0x0d/* "\r" */ || nextChar === 0x0a/* \ns */) {
|
||||
can_open = false;
|
||||
}
|
||||
|
||||
if (state.src.substring(pos,pos+3) === "$:/") {
|
||||
can_open = false;
|
||||
can_close = false;
|
||||
}
|
||||
|
||||
return {
|
||||
can_open: can_open,
|
||||
can_close: can_close
|
||||
};
|
||||
}
|
||||
|
||||
function math_inline(state, silent) {
|
||||
var start, match, token, res, pos, esc_count;
|
||||
|
||||
if (state.src[state.pos] !== "$") { return false; }
|
||||
|
||||
res = isValidDelim(state, state.pos);
|
||||
if (!res.can_open) {
|
||||
if (!silent) { state.pending += "$"; }
|
||||
state.pos += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// First check for and bypass all properly escaped delimieters
|
||||
// This loop will assume that the first leading backtick can not
|
||||
// be the first character in state.src, which is known since
|
||||
// we have found an opening delimieter already.
|
||||
start = state.pos + 1;
|
||||
match = start;
|
||||
while ( (match = state.src.indexOf("$", match)) !== -1) {
|
||||
// Found potential $, look for escapes, pos will point to
|
||||
// first non escape when complete
|
||||
pos = match - 1;
|
||||
while (state.src[pos] === "\\") { pos -= 1; }
|
||||
|
||||
// Even number of escapes, potential closing delimiter found
|
||||
if ( ((match - pos) % 2) == 1 ) { break; }
|
||||
match += 1;
|
||||
}
|
||||
|
||||
// No closing delimter found. Consume $ and continue.
|
||||
if (match === -1) {
|
||||
if (!silent) { state.pending += "$"; }
|
||||
state.pos = start;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if we have empty content, ie: $$. Do not parse.
|
||||
if (match - start === 0) {
|
||||
if (!silent) { state.pending += "$$"; }
|
||||
state.pos = start + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for valid closing delimiter
|
||||
res = isValidDelim(state, match);
|
||||
if (!res.can_close) {
|
||||
if (!silent) { state.pending += "$"; }
|
||||
state.pos = start;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
token = state.push('math_inline', '$latex', 0);
|
||||
token.markup = "$";
|
||||
token.content = state.src.slice(start, match);
|
||||
token.attrs = [["displayMode", "false"], ["text", token.content]];
|
||||
}
|
||||
|
||||
state.pos = match + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! https://github.com/iktakahiro/markdown-it-katex/pull/2 by @shinhermit */
|
||||
function math_inline_block(state, silent) {
|
||||
var start, match, token, res, pos, esc_count;
|
||||
|
||||
if(state.src.slice(state.pos, state.pos+2) !== "$$") { return false; }
|
||||
|
||||
// First check for and bypass all properly escaped delimieters
|
||||
// This loop will assume that the first leading backtick can not
|
||||
// be the first character in state.src, which is known since
|
||||
// we have found an opening delimieter already.
|
||||
start = state.pos + 2;
|
||||
match = start;
|
||||
while ( (match = state.src.indexOf("$$", match)) !== -1) {
|
||||
// Found potential $$, look for escapes, pos will point to
|
||||
// first non escape when complete
|
||||
pos = match - 1;
|
||||
while (state.src[pos] === "\\") { pos -= 1; }
|
||||
|
||||
// Even number of escapes, potential closing delimiter found
|
||||
if ( ((match - pos) % 2) == 1 ) { break; }
|
||||
match += 2;
|
||||
}
|
||||
|
||||
// No closing delimter found. Consume $$ and continue.
|
||||
if (match === -1) {
|
||||
if (!silent) { state.pending += "$$"; }
|
||||
state.pos = start;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if we have empty content, ie: $$$$. Do not parse.
|
||||
if (match - start === 0) {
|
||||
if (!silent) { state.pending += "$$$$"; }
|
||||
state.pos = start + 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
token = state.push('math_inline_block', '$latex', 0);
|
||||
token.block = true;
|
||||
token.markup = "$$";
|
||||
token.content = state.src.slice(start, match);
|
||||
token.attrs = [["displayMode", "true"], ["text", token.content]];
|
||||
}
|
||||
|
||||
state.pos = match + 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = function math_plugin(md, options) {
|
||||
md.inline.ruler.after('escape', 'math_inline', math_inline);
|
||||
md.inline.ruler.after('escape', 'math_inline_block', math_inline_block);
|
||||
};
|
||||
})();
|
522
plugins/tiddlywiki/markdown/markdown-it-tiddlywiki.js
Normal file
522
plugins/tiddlywiki/markdown/markdown-it-tiddlywiki.js
Normal file
@ -0,0 +1,522 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/markdown/markdown-it-tiddlywiki.js
|
||||
type: application/javascript
|
||||
module-type: library
|
||||
|
||||
Wraps up the markdown-it parser for use as a Parser in TiddlyWiki
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var md;
|
||||
var pluginOpts;
|
||||
|
||||
var TWMarkReplacements = {
|
||||
"{" : "{",
|
||||
"[" : "[",
|
||||
"$" : "$"
|
||||
};
|
||||
|
||||
var TWMarkRegEx = /[{[$]/g;
|
||||
function encodeTWMark(match) {
|
||||
return TWMarkReplacements[match];
|
||||
}
|
||||
|
||||
// escpae {, [ and $ in string s
|
||||
function escapeTWMarks(s) {
|
||||
s = String(s);
|
||||
TWMarkRegEx.lastIndex = 0;
|
||||
return s.replace(TWMarkRegEx,encodeTWMark);
|
||||
}
|
||||
|
||||
// escape anything that could be interpreted as transclusion or syslink
|
||||
function render_code_inline(tokens,idx,options,env,slf) {
|
||||
tokens[idx].attrJoin('class','_codified_');
|
||||
return '<code' + slf.renderAttrs(tokens[idx]) + '>'
|
||||
+ escapeTWMarks(md.utils.escapeHtml(tokens[idx].content))
|
||||
+ '</code>';
|
||||
}
|
||||
|
||||
function render_code_block(tokens,idx) {
|
||||
return '<$codeblock code=e"' + md.utils.escapeHtml(tokens[idx].content) + '" language=""/>\n';
|
||||
}
|
||||
|
||||
function render_fence(tokens,idx) {
|
||||
var info = tokens[idx].info ? md.utils.unescapeAll(tokens[idx].info).trim() : '';
|
||||
return '<$codeblock code=e"' + md.utils.escapeHtml(tokens[idx].content) + '" language="' + info.split(/(\s+)/g)[0] + '"/>\n';
|
||||
}
|
||||
|
||||
// add a blank line after opening tag to activate TW block parsing
|
||||
function render_paragraph_open(tokens,idx) {
|
||||
return tokens[idx].hidden ? '' : '<p>\n\n';
|
||||
}
|
||||
|
||||
function render_paragraph_close(tokens,idx) {
|
||||
return tokens[idx].hidden ? '' : '\n</p>\n';
|
||||
}
|
||||
|
||||
// Replace footnote links with "qualified" internal links
|
||||
function render_footnote_ref(tokens,idx,options,env,slf) {
|
||||
var id = slf.rules.footnote_anchor_name(tokens,idx,options,env,slf);
|
||||
var caption = slf.rules.footnote_caption(tokens,idx,options,env,slf);
|
||||
var refid = id;
|
||||
|
||||
if(tokens[idx].meta.subId > 0) {
|
||||
refid += ':' + tokens[idx].meta.subId;
|
||||
}
|
||||
return '<a class="footnote-ref" href=<<qualify "##fn' + id + '">> id=<<qualify "#fnref' + refid + '">>>' + caption + '</a>';
|
||||
}
|
||||
|
||||
function render_footnote_open(tokens,idx,options,env,slf) {
|
||||
var id = slf.rules.footnote_anchor_name(tokens,idx,options,env,slf);
|
||||
|
||||
if(tokens[idx].meta.subId > 0) {
|
||||
id += ':' + tokens[idx].meta.subId;
|
||||
}
|
||||
return '<li id=<<qualify "#fn' + id + '">> class="footnote-item">';
|
||||
}
|
||||
|
||||
function render_footnote_anchor(tokens,idx,options,env,slf) {
|
||||
var id = slf.rules.footnote_anchor_name(tokens,idx,options,env,slf);
|
||||
|
||||
if(tokens[idx].meta.subId > 0) {
|
||||
id += ':' + tokens[idx].meta.subId;
|
||||
}
|
||||
|
||||
// append variation selector to prevent display as Apple Emoji on iOS
|
||||
return '<a href=<<qualify "##fnref' + id + '">> class="footnote-backref">\u21A5\uFE0E</a>';
|
||||
}
|
||||
|
||||
// do not un-escape html entities and escape characters
|
||||
function render_text_special(tokens,idx) {
|
||||
if(tokens[idx].info === 'entity') {
|
||||
return tokens[idx].markup;
|
||||
}
|
||||
return escapeTWMarks(md.utils.escapeHtml(tokens[idx].content));
|
||||
}
|
||||
|
||||
function render_tw_expr(tokens,idx) {
|
||||
return tokens[idx].content;
|
||||
}
|
||||
|
||||
// Overwrite default: render attribute strings in e"..." format instead,
|
||||
// so HTML entities can be decoded. See parseStringLiteralExt() below.
|
||||
function render_token_attrs(token) {
|
||||
var i, l, result;
|
||||
|
||||
if(!token.attrs) { return ''; }
|
||||
|
||||
result = '';
|
||||
|
||||
for(i=0, l=token.attrs.length; i<l; i++) {
|
||||
result += ' ' + md.utils.escapeHtml(token.attrs[i][0]) + '=e"' + md.utils.escapeHtml(token.attrs[i][1]) + '"';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// given tw parsing rule and starting pos, returns match index or undefined
|
||||
// assumes pos >= 0
|
||||
function findNextMatch(ruleinfo,pos) {
|
||||
// ruleinfo.matchIndex needs to be -1 at the start of inline state
|
||||
if(ruleinfo.matchIndex < pos) {
|
||||
ruleinfo.matchIndex = ruleinfo.rule.findNextMatch(pos);
|
||||
}
|
||||
|
||||
return ruleinfo.matchIndex;
|
||||
}
|
||||
|
||||
// Add inline rule "macrocall" to parse <<macroname ...>>
|
||||
var MacroCallRegEx = /<<([^\s>"'=]+)[^>]*>>/g;
|
||||
function tw_macrocallinline(state,silent) {
|
||||
var match, max, pos = state.pos;
|
||||
|
||||
// Check start
|
||||
max = state.posMax;
|
||||
if(state.src.charCodeAt(pos) !== 0x3C || state.src.charCodeAt(pos+1) !== 0x3C /* << */|| pos + 3 >= max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MacroCallRegEx.lastIndex = pos;
|
||||
match = MacroCallRegEx.exec(state.src);
|
||||
if(!match || match.index !== pos) { return false; }
|
||||
|
||||
if(!silent) {
|
||||
var token = state.push('tw_expr','',0);
|
||||
token.content = state.src.slice(pos,pos+match[0].length);
|
||||
}
|
||||
state.pos = MacroCallRegEx.lastIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse transclusion elements
|
||||
function tw_transcludeinline(state,silent) {
|
||||
var ruleinfo = pluginOpts.inlineRules.transcludeinline;
|
||||
|
||||
var pos = state.pos;
|
||||
var matchIndex = findNextMatch(ruleinfo,pos);
|
||||
if(matchIndex === undefined || matchIndex !== pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!silent) {
|
||||
var token = state.push('tw_expr','',0);
|
||||
token.content = state.src.slice(pos,pos+ruleinfo.rule.match[0].length);
|
||||
}
|
||||
state.pos += ruleinfo.rule.match[0].length;
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse filtered transclusion elements
|
||||
function tw_filteredtranscludeinline(state,silent) {
|
||||
var ruleinfo = pluginOpts.inlineRules.filteredtranscludeinline;
|
||||
|
||||
var pos = state.pos;
|
||||
var matchIndex = findNextMatch(ruleinfo,pos);
|
||||
if(matchIndex === undefined || matchIndex !== pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!silent) {
|
||||
var token = state.push('tw_expr','',0);
|
||||
if(state.linkLevel > 0) {
|
||||
var filter = ruleinfo.rule.match[1];
|
||||
token.content = '<$text text={{{' + filter + '}}}/>';
|
||||
} else {
|
||||
token.content = state.src.slice(pos,pos+ruleinfo.rule.match[0].length);
|
||||
}
|
||||
}
|
||||
state.pos += ruleinfo.rule.match[0].length;
|
||||
return true;
|
||||
}
|
||||
|
||||
// based on markdown-it html_block()
|
||||
var WidgetTagRegEx = [/^<\/?\$[a-zA-Z0-9\-\$]+(?=(\s|\/?>|$))/, /^$/];
|
||||
function tw_block(state,startLine,endLine,silent) {
|
||||
var i, nextLine, token, lineText,
|
||||
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||||
max = state.eMarks[startLine];
|
||||
|
||||
// if it's indented more than 3 spaces, it should be a code block
|
||||
if(state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||||
|
||||
if(!state.md.options.html) { return false; }
|
||||
|
||||
if(state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
|
||||
|
||||
lineText = state.src.slice(pos,max);
|
||||
|
||||
if(!WidgetTagRegEx[0].test(lineText)) { return false; }
|
||||
|
||||
if(silent) {
|
||||
// don't let widgets interrupt a paragrpah
|
||||
return false;
|
||||
}
|
||||
|
||||
nextLine = startLine + 1;
|
||||
|
||||
// If we are here - we detected HTML block.
|
||||
// Let's roll down till block end.
|
||||
if(!WidgetTagRegEx[1].test(lineText)) {
|
||||
for(; nextLine < endLine; nextLine++) {
|
||||
if(state.sCount[nextLine] < state.blkIndent) { break; }
|
||||
|
||||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||||
max = state.eMarks[nextLine];
|
||||
lineText = state.src.slice(pos,max);
|
||||
|
||||
if(WidgetTagRegEx[1].test(lineText)) {
|
||||
if(lineText.length !== 0) { nextLine++; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.line = nextLine;
|
||||
|
||||
token = state.push('html_block','',0);
|
||||
token.map = [ startLine, nextLine ];
|
||||
token.content = state.getLines(startLine,nextLine,state.blkIndent,true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse [img[...]] elements
|
||||
function tw_image(state,silent) {
|
||||
var ruleinfo = pluginOpts.inlineRules.image;
|
||||
|
||||
// ignore at parseLinkLabel stage; will be recognized in tokenize()
|
||||
if(state.parsingLinkLabel > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var pos = state.pos;
|
||||
var matchIndex = findNextMatch(ruleinfo,pos);
|
||||
if(matchIndex === undefined || matchIndex !== pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!silent) {
|
||||
var twNode = ruleinfo.rule.parse()[0];
|
||||
var token = state.push('$image','$image',0);
|
||||
$tw.utils.each(twNode.attributes,function(attr,id) {
|
||||
token.attrSet(id,attr.value);
|
||||
});
|
||||
token.markup = 'tw_image';
|
||||
}
|
||||
state.pos = ruleinfo.rule.parser.pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse [[link]] elements
|
||||
function tw_prettylink(state,silent) {
|
||||
var ruleinfo = pluginOpts.inlineRules.prettylink;
|
||||
|
||||
// skip if in link label
|
||||
if(state.linkLevel > 0 || state.parsingLinkLabel > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var pos = state.pos;
|
||||
var matchIndex = findNextMatch(ruleinfo,pos);
|
||||
if(matchIndex === undefined || matchIndex !== pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!silent) {
|
||||
var twNode = ruleinfo.rule.parse()[0];
|
||||
var tag = (twNode.type==='link' ? '$link' : 'a');
|
||||
// push a link_open token so markdown's core.linkify will ignore
|
||||
var token = state.push('link_open',tag,1);
|
||||
|
||||
$tw.utils.each(twNode.attributes,function(attr,id) {
|
||||
token.attrSet(id,attr.value);
|
||||
});
|
||||
token.attrJoin('class','_codified_');
|
||||
token.markup = 'tw_prettylink';
|
||||
|
||||
state.linkLevel++;
|
||||
token = state.push('text','',0);
|
||||
token.content = twNode.children[0].text;
|
||||
state.linkLevel--;
|
||||
|
||||
token = state.push('link_close',tag,-1);
|
||||
token.markup = 'tw_prettylink';
|
||||
}
|
||||
state.pos = ruleinfo.rule.parser.pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
function tw_prettyextlink(state,silent) {
|
||||
var ruleinfo = pluginOpts.inlineRules.prettyextlink;
|
||||
|
||||
// skip if in link label
|
||||
if(state.linkLevel > 0 || state.parsingLinkLabel > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var pos = state.pos;
|
||||
var matchIndex = findNextMatch(ruleinfo,pos);
|
||||
if(matchIndex === undefined || matchIndex !== pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!silent) {
|
||||
var twNode = ruleinfo.rule.parse()[0];
|
||||
var token = state.push('link_open','a',1);
|
||||
|
||||
$tw.utils.each(twNode.attributes,function(attr,id) {
|
||||
token.attrSet(id,attr.value);
|
||||
});
|
||||
token.attrJoin('class','_codified_');
|
||||
token.markup = 'tw_prettyextlink';
|
||||
|
||||
state.linkLevel++;
|
||||
token = state.push('text','',0);
|
||||
token.content = twNode.children[0].text;
|
||||
state.linkLevel--;
|
||||
|
||||
token = state.push('link_close','a',-1);
|
||||
token.markup = 'tw_prettyextlink';
|
||||
}
|
||||
state.pos = ruleinfo.rule.parser.pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
var TWCloseTagRegEx = /<\/\$[A-Za-z0-9\-\$]+\s*>/gm;
|
||||
function extendHtmlInline(origRule) {
|
||||
return function(state,silent) {
|
||||
if(origRule(state,silent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var token, pos = state.pos;
|
||||
var parseTag = $tw.Wiki.parsers['text/vnd.tiddlywiki'].prototype.inlineRuleClasses.html.prototype.parseTag;
|
||||
var tag = parseTag(state.src,pos,{});
|
||||
if(tag) {
|
||||
if(!silent) {
|
||||
token = state.push('html_inline','',0);
|
||||
token.content = state.src.slice(pos,tag.end);
|
||||
}
|
||||
state.pos = tag.end;
|
||||
return true;
|
||||
}
|
||||
|
||||
TWCloseTagRegEx.lastIndex = pos;
|
||||
var match = TWCloseTagRegEx.exec(state.src);
|
||||
if(!match || match.index !== pos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!silent) {
|
||||
token = state.push('html_inline','',0);
|
||||
token.content = state.src.slice(pos,pos + match[0].length);
|
||||
}
|
||||
state.pos = TWCloseTagRegEx.lastIndex;
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function extendParseLinkLabel(origFunc) {
|
||||
return function(state,start,disableNested) {
|
||||
if(state.parsingLinkLabel === undefined) {
|
||||
state.parsingLinkLabel = 0;
|
||||
}
|
||||
state.parsingLinkLabel++;
|
||||
var labelEnd = origFunc(state,start,disableNested);
|
||||
state.parsingLinkLabel--;
|
||||
return labelEnd;
|
||||
};
|
||||
}
|
||||
|
||||
// reset each tw inline rule to initial inline state
|
||||
function extendInlineParse(thisArg,origFunc,twInlineRules) {
|
||||
return function(str,md,env,outTokens) {
|
||||
var i, ruleinfo, key;
|
||||
for(key in twInlineRules) {
|
||||
ruleinfo = twInlineRules[key];
|
||||
ruleinfo.rule.parser.source = str;
|
||||
ruleinfo.rule.parser.sourceLength = str.length;
|
||||
ruleinfo.rule.parser.pos = 0; // not used
|
||||
ruleinfo.matchIndex = -1;
|
||||
}
|
||||
origFunc.call(thisArg,str,md,env,outTokens);
|
||||
}
|
||||
}
|
||||
|
||||
/// post processing ///
|
||||
|
||||
function wikify(state) {
|
||||
var href, title, src, alt;
|
||||
var tagStack = [];
|
||||
|
||||
state.tokens.forEach(function(blockToken) {
|
||||
if(blockToken.type === 'inline' && blockToken.children) {
|
||||
blockToken.children.forEach(function(token) {
|
||||
switch(token.type) {
|
||||
case 'link_open':
|
||||
if(token.markup === 'tw_prettylink' || token.markup === 'tw_prettyextlink') {
|
||||
return;
|
||||
}
|
||||
href = token.attrGet('href');
|
||||
if(href[0] === '#') {
|
||||
token.tag = '$link';
|
||||
href = $tw.utils.decodeURIComponentSafe(href.substring(1));
|
||||
title = token.attrGet('title');
|
||||
token.attrs = [['to', href], ['class', '_codified_']];
|
||||
if(title) {
|
||||
token.attrSet('tooltip',title);
|
||||
}
|
||||
} else {
|
||||
token.attrSet('target','_blank');
|
||||
token.attrJoin('class','tc-tiddlylink-external');
|
||||
token.attrJoin('class','_codified_');
|
||||
token.attrSet('rel','noopener noreferrer');
|
||||
}
|
||||
tagStack.push(token.tag);
|
||||
break;
|
||||
case 'link_close':
|
||||
if(token.markup === 'tw_prettylink' || token.markup === 'tw_prettyextlink') {
|
||||
return;
|
||||
}
|
||||
token.tag = tagStack.pop();
|
||||
break;
|
||||
case 'image':
|
||||
token.tag = '$image';
|
||||
src = token.attrGet('src');
|
||||
alt = token.attrGet('alt');
|
||||
title = token.attrGet('title');
|
||||
|
||||
token.attrs[token.attrIndex('src')][0] = 'source';
|
||||
if(src[0] === '#') {
|
||||
src = $tw.utils.decodeURIComponentSafe(src.substring(1));
|
||||
token.attrSet('source',src);
|
||||
}
|
||||
if(title) {
|
||||
token.attrs[token.attrIndex('title')][0] = 'tooltip';
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function tiddlyWikiPlugin(markdown,options) {
|
||||
var defaults = {
|
||||
renderWikiText: false,
|
||||
blockRules: {},
|
||||
inlineRules: {}
|
||||
};
|
||||
|
||||
md = markdown;
|
||||
pluginOpts = md.utils.assign({},defaults,options||{});
|
||||
|
||||
md.renderer.rules.code_inline = render_code_inline;
|
||||
md.renderer.rules.code_block = render_code_block;
|
||||
md.renderer.rules.fence = render_fence;
|
||||
md.renderer.rules.paragraph_open = render_paragraph_open;
|
||||
md.renderer.rules.paragraph_close = render_paragraph_close;
|
||||
md.renderer.rules.footnote_ref = render_footnote_ref;
|
||||
md.renderer.rules.footnote_open = render_footnote_open;
|
||||
md.renderer.rules.footnote_anchor = render_footnote_anchor;
|
||||
md.renderer.rules.text_special = render_text_special;
|
||||
md.renderer.rules.tw_expr = render_tw_expr;
|
||||
md.renderer.renderAttrs = render_token_attrs;
|
||||
|
||||
if(pluginOpts.renderWikiText) {
|
||||
md.helpers.parseLinkLabel = extendParseLinkLabel(md.helpers.parseLinkLabel);
|
||||
|
||||
if(pluginOpts.inlineRules.image) {
|
||||
md.inline.ruler.after('link','tw_image',tw_image);
|
||||
}
|
||||
if(pluginOpts.inlineRules.prettyextlink) {
|
||||
md.inline.ruler.after('link','tw_prettyextlink',tw_prettyextlink);
|
||||
}
|
||||
if(pluginOpts.inlineRules.prettylink) {
|
||||
md.inline.ruler.after('link','tw_prettylink',tw_prettylink);
|
||||
}
|
||||
if(pluginOpts.inlineRules.filteredtranscludeinline) {
|
||||
md.inline.ruler.before('html_inline','tw_filteredtranscludeinline',tw_filteredtranscludeinline);
|
||||
}
|
||||
if(pluginOpts.inlineRules.transcludeinline) {
|
||||
md.inline.ruler.before('html_inline','tw_transcludeinline',tw_transcludeinline);
|
||||
}
|
||||
|
||||
md.inline.ruler.before('html_inline','tw_macrocallinline',tw_macrocallinline);
|
||||
md.inline.ruler.at('html_inline',extendHtmlInline(md.inline.ruler.__rules__[md.inline.ruler.__find__('html_inline')].fn));
|
||||
md.block.ruler.after('html_block','tw_block',tw_block,{
|
||||
alt: [ 'paragraph', 'reference', 'blockquote' ]
|
||||
});
|
||||
md.inline.parse = extendInlineParse(md.inline,md.inline.parse,options.inlineRules);
|
||||
}
|
||||
|
||||
md.core.ruler.disable('text_join');
|
||||
md.core.ruler.push('wikify',wikify);
|
||||
};
|
||||
|
||||
})();
|
@ -6,7 +6,7 @@ list-after: $:/core/ui/Buttons/new-tiddler
|
||||
|
||||
\whitespace trim
|
||||
<$button tooltip={{$:/language/Buttons/NewMarkdown/Hint}} aria-label={{$:/language/Buttons/NewMarkdown/Caption}} class=<<tv-config-toolbar-class>>>
|
||||
<$action-sendmessage $message="tm-new-tiddler" type="text/x-markdown"/>
|
||||
<$action-sendmessage $message="tm-new-tiddler" type="text/markdown"/>
|
||||
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
|
||||
{{$:/plugins/tiddlywiki/markdown/images/new-markdown-button}}
|
||||
</$list>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"title": "$:/plugins/tiddlywiki/markdown",
|
||||
"name": "Markdown",
|
||||
"description": "Markdown parser based on remarkable by Jon Schlinkert and remarkable-katex by Brad Howes",
|
||||
"list": "readme usage remarkable-license remarkable-katex-license"
|
||||
"description": "Markdown parser based on markdown-it",
|
||||
"list": "readme config syntax license"
|
||||
}
|
||||
|
@ -1,7 +1,32 @@
|
||||
title: $:/plugins/tiddlywiki/markdown/readme
|
||||
|
||||
This is a TiddlyWiki plugin for parsing Markdown text, using the [[Remarkable|https://github.com/jonschlinkert/remarkable]] library. If the KaTeX TiddlyWiki plugin is installed, KaTeX support is enabled using the [[remarkable-katex|https://github.com/bradhowes/remarkable-katex]] Remarkable plugin.
|
||||
This plugin provides Markdown support via the [[markdown-it|https://github.com/markdown-it/markdown-it]] parser and its associated plugins:
|
||||
|
||||
It is completely self-contained, and doesn't need an Internet connection in order to work. It works both in the browser and under Node.js.
|
||||
* markdown-it-deflist
|
||||
* markdown-it-footnote
|
||||
* markdown-it-ins
|
||||
* markdown-it-mark
|
||||
* markdown-it-sub
|
||||
* markdown-it-sup
|
||||
|
||||
[[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/markdown]]
|
||||
!! Compatibility Notes
|
||||
|
||||
* <p>A tab character in Markdown has a size of four spaces. Configure the tab size of your code editor accordingly. For example, if you use <$text text="CodeMirror"/>, it is recommended that you set $:/config/codemirror/indentUnit and $:/config/codemirror/tabSize to `4` to avoid inconsistent indentations.</p>
|
||||
* <p>HTML blocks are ultimately parsed by the <$text text=WikiText/> parser: //an opening tag followed by a blank line will activate block-level parsing for its content//. When working with tags designed to contain literal content, such as `<pre>` and `<style>` tags, refrain from adding blank lines after the opening tags.</p>
|
||||
* <p>You must terminate a table with either a blank line or another block-level structure.</p>
|
||||
* <p>`latex-parser` in $:/config/markdown/renderWikiTextPragma is no longer required and will be ignored.</p>
|
||||
* <p>Config option `linkNewWindow` is removed.</p>
|
||||
|
||||
!! Extending the Parser
|
||||
|
||||
You can extend the parser by loading additional markdown-it plugins this way:
|
||||
|
||||
```js
|
||||
var plugin1 = require(...);
|
||||
var plugin2 = require(...);
|
||||
|
||||
var md = $tw.Wiki.parsers["text/markdown"].prototype.md;
|
||||
|
||||
md.use(plugin1)
|
||||
.use(plugin2, opts, ...);
|
||||
```
|
50
plugins/tiddlywiki/markdown/styles.tid
Normal file
50
plugins/tiddlywiki/markdown/styles.tid
Normal file
@ -0,0 +1,50 @@
|
||||
title: $:/plugins/tiddlywiki/markdown/styles
|
||||
tags: [[$:/tags/Stylesheet]]
|
||||
code-body: yes
|
||||
|
||||
.markdown {
|
||||
display: block;
|
||||
margin: 0px;
|
||||
}
|
||||
.markdown hr {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
border: 0;
|
||||
border-top: 1px solid <<colour muted-foreground>>;
|
||||
}
|
||||
.markdown .footnotes {
|
||||
font-size: 0.9em;
|
||||
line-height: 1.32;
|
||||
}
|
||||
.markdown a.footnote-ref {
|
||||
color: <<colour tiddler-link-foreground>>;
|
||||
font-size: 0.75em;
|
||||
text-decoration: none;
|
||||
vertical-align: super;
|
||||
padding:0px 1px;
|
||||
}
|
||||
.markdown ol.footnotes-list {
|
||||
padding-left: 2em;
|
||||
}
|
||||
.markdown .footnote-item p {
|
||||
margin: 0.7em 0px;
|
||||
}
|
||||
.markdown a.footnote-backref {
|
||||
color: <<colour tiddler-link-foreground>>;
|
||||
font-size: 0.8em;
|
||||
text-decoration: none;
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
.markdown a.footnote-ref:target, .markdown .footnote-item:target {
|
||||
background-color: <<colour message-background>>;
|
||||
scroll-margin-top: {{{ [{$:/themes/tiddlywiki/vanilla/options/stickytitles}match[yes]then[120px]else[60px]] }}};
|
||||
}
|
||||
.markdown li > p:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.markdown li + li {
|
||||
margin-top: 2px;
|
||||
}
|
||||
.markdown mark {
|
||||
padding: 1px 3px;
|
||||
}
|
224
plugins/tiddlywiki/markdown/syntax.tid
Normal file
224
plugins/tiddlywiki/markdown/syntax.tid
Normal file
@ -0,0 +1,224 @@
|
||||
|
||||
title: $:/plugins/tiddlywiki/markdown/syntax
|
||||
|
||||
To review standard Markdown syntax, see: [ext[CommonMark quick reference|https://commonmark.org/help/]]. For formal specification, consult the [ext[CommonMark Spec|https://spec.commonmark.org/current/]].
|
||||
|
||||
! Linking to Tiddlers
|
||||
|
||||
Prepend `#` to tiddler titles to form link addresses. If a tiddler title contains spaces or other special characters, you must either (1) URI-encode the title, or (2) surround the #title with `<` `>` and backslash-escape any `<` or `>` in the title.
|
||||
|
||||
!! Links
|
||||
|
||||
<pre><code>[link text](<strong>#</strong><$text text="TiddlerTitle"/> "optional tooltip")
|
||||
|
||||
[link text](<strong>#</strong>New<strong>%20</strong>Tiddler)
|
||||
|
||||
[link text](<strong><#</strong>New Tiddler<strong>></strong>)
|
||||
|
||||
[](<strong><#</strong>How to use <strong>\</strong><$list<strong>\</strong>> widget?<strong>></strong>)
|
||||
</code></pre>
|
||||
|
||||
You can also use the `<$link>` widget to generate links to tiddlers:
|
||||
|
||||
```
|
||||
<$link to="Tiddler Title">Displayed Link Title</$link>
|
||||
```
|
||||
|
||||
!! Reference Style Links
|
||||
|
||||
```
|
||||
[link text][1]
|
||||
[link text][2]
|
||||
|
||||
[1]: #New%20Tiddler "optional tooltip"
|
||||
|
||||
[2]: <#Another Tiddler>
|
||||
```
|
||||
|
||||
!! Images
|
||||
|
||||
```
|
||||
![alt text](#Motovun%20Jack.jpg "optional tooltip")
|
||||
|
||||
![alt text](<#Motovun Jack.jpg>)
|
||||
```
|
||||
|
||||
! Escaping Special Characters
|
||||
|
||||
Markdown allows you to escape ASCII punctuation characters with `\`.
|
||||
|
||||
! HTML Blocks
|
||||
|
||||
An [[HTML block|https://spec.commonmark.org/0.30/#html-blocks]] is a group of lines that starts with an HTML tag and is treated as raw HTML. Block-level tags such as `<div>` and `<p>` can interrupt a paragraph. Inline elements such as `<strong>` and `<em>` can start an HTML block if the //complete// tag begins on a new paragraph by itself. In most cases, an HTML block continues until a blank line is reached.
|
||||
|
||||
A widget tag that begins on a new paragraph will also be treated as an HTML block. Markdown elements are not recognized inside the HTML block. For example:
|
||||
|
||||
```
|
||||
see
|
||||
|
||||
<$link to="New Tiddler">
|
||||
_New_ Tiddler
|
||||
</$link>
|
||||
```
|
||||
|
||||
rendered as:
|
||||
|
||||
```
|
||||
<p>see</p>
|
||||
<$link to="New Tiddler">
|
||||
_New_ Tiddler
|
||||
</$link>
|
||||
```
|
||||
|
||||
A widget tag not preceded by a blank line is an inline element.
|
||||
|
||||
```
|
||||
see
|
||||
<$link to="New Tiddler">
|
||||
_New_ Tiddler
|
||||
</$link>
|
||||
```
|
||||
|
||||
rendered as:
|
||||
|
||||
```
|
||||
<p>see <$link to="New Tiddler"><em>New</em> Tiddler</$link></p>
|
||||
```
|
||||
|
||||
! Syntax Extensions
|
||||
|
||||
!! <$text text=KaTeX/>
|
||||
|
||||
You need to install the <$text text=KaTeX/> plugin to activate this syntax extension.
|
||||
|
||||
Surround your math expression with `$` for inline rendering. Whitespace characters cannot immediately follow the opening `$` or precede the closing `$`, and the closing delimiter must not immediately precede a digit. Furthermore, `$` followed by `:/` will not be recognized as a valid opening or closing delimiter either.
|
||||
|
||||
Here's an example of an inline math expression:
|
||||
|
||||
```
|
||||
$c = \pm\sqrt{a^2 + b^2}$
|
||||
```
|
||||
|
||||
Use `$$` to center the math in display mode:
|
||||
|
||||
```
|
||||
$$c = \pm\sqrt{a^2 + b^2}$$
|
||||
```
|
||||
|
||||
!! Superscript and Subscript
|
||||
|
||||
```
|
||||
X^2^
|
||||
```
|
||||
x<sup>2</sup>
|
||||
|
||||
```
|
||||
H~2~O
|
||||
```
|
||||
H<sub>2</sub>O
|
||||
|
||||
!! Marked Text
|
||||
|
||||
```
|
||||
==marked text==
|
||||
```
|
||||
|
||||
<mark>marked text</mark>
|
||||
|
||||
!! Strikethrough
|
||||
|
||||
```
|
||||
~~striked through text~~
|
||||
```
|
||||
|
||||
<s>striked through text</s>
|
||||
|
||||
!! Inserted Text
|
||||
|
||||
```
|
||||
++inserted text++
|
||||
```
|
||||
|
||||
<ins>inserted text</ins>
|
||||
|
||||
!! Tables
|
||||
|
||||
markdown-it supports <$text text="GitHub Flavored Markdown"/> (GFM) [ext[table syntax|https://github.github.com/gfm/#tables-extension-]].
|
||||
|
||||
```
|
||||
|Left Aligned |Centered |Right Aligned |
|
||||
|:--- | :---: | ---:|
|
||||
|apple |bat |candle |
|
||||
```
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th style="text-align:left">Left Aligned</th><th style="text-align:center">Centered</th><th style="text-align:right">Right Aligned</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td style="text-align:left">apple</td><td style="text-align:center">bat</td><td style="text-align:right">candle</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
!! Definition Lists
|
||||
|
||||
```
|
||||
Term One
|
||||
: Definition with
|
||||
lazy continuation.
|
||||
|
||||
Term Two
|
||||
: Here is the first defintion.
|
||||
|
||||
: Here is the second definition.
|
||||
|
||||
As you can see. A definition can have
|
||||
more than one paragrpah. It can also have
|
||||
|
||||
And indended code block...
|
||||
```
|
||||
|
||||
<dl>
|
||||
<dt>Term One</dt>
|
||||
<dd><p>Definition with
|
||||
lazy continuation.
|
||||
</p></dd>
|
||||
<dt>Term Two</dt>
|
||||
<dd><p>Here is the first defintion.
|
||||
</p></dd>
|
||||
<dd><p>Here is the second definition.</p><p>As you can see. A definition can have
|
||||
more than one paragrpah. It can also have
|
||||
<pre><code>And indended code block...
|
||||
</code></pre>
|
||||
</p></dd>
|
||||
</dl>
|
||||
|
||||
!! Footnotes
|
||||
|
||||
For detailed explanation, see [[Creating Footnotes|https://www.markdownguide.org/extended-syntax/#footnotes]].
|
||||
|
||||
```
|
||||
Here's a simple footnote,[^1] and here's a longer one.[^bignote]
|
||||
|
||||
[^1]: This is the first footnote.
|
||||
|
||||
[^bignote]: Here's one with multiple paragraphs and code.
|
||||
|
||||
Indent paragraphs to include them in the footnote.
|
||||
|
||||
`{ my code }`
|
||||
|
||||
Add as many paragraphs as you like.
|
||||
```
|
||||
|
||||
<div class="markdown"><p>Here’s a simple footnote,<a class="footnote-ref" href="##fn1--doc639182" id="#fnref1--doc639182">[1]</a> and here’s a longer one.<a class="footnote-ref" href="##fn2--doc639182" id="#fnref2--doc639182">[2]</a>
|
||||
<hr class="footnotes-sep">
|
||||
<section class="footnotes">
|
||||
<ol class="footnotes-list">
|
||||
<li id="#fn1--doc639182" class="footnote-item"><p>This is the first footnote. <a href="##fnref1--doc639182" class="footnote-backref">↥︎</a>
|
||||
</p></li>
|
||||
<li id="#fn2--doc639182" class="footnote-item"><p>Here’s one with multiple paragraphs and code.</p><p>Indent paragraphs to include them in the footnote.</p><p><code class="codified">{ my code }</code></p><p>Add as many paragraphs as you like. <a href="##fnref2--doc639182" class="footnote-backref">↥︎</a>
|
||||
</p></li>
|
||||
</ol>
|
||||
</section>
|
||||
</p></div>
|
@ -3,338 +3,264 @@ title: $:/plugins/tiddlywiki/markdown/wrapper.js
|
||||
type: application/javascript
|
||||
module-type: parser
|
||||
|
||||
Wraps up the remarkable parser for use as a Parser in TiddlyWiki
|
||||
Wraps up the markdown-it parser for use as a Parser in TiddlyWiki
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
(function(realRequire){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var r = require("$:/plugins/tiddlywiki/markdown/remarkable.js");
|
||||
var require = function(m) {
|
||||
return realRequire("$:/plugins/tiddlywiki/markdown/" + m + ".js");
|
||||
};
|
||||
|
||||
var Remarkable = r.Remarkable,
|
||||
linkify = r.linkify,
|
||||
utils = r.utils;
|
||||
var MarkdownIt = require("markdown-it");
|
||||
|
||||
///// Set up configuration options /////
|
||||
function parseAsBoolean(tiddlerName) {
|
||||
return $tw.wiki.getTiddlerText(tiddlerName).toLowerCase() === "true";
|
||||
return $tw.wiki.getTiddlerText(tiddlerName,"false").trim().toLowerCase() === "true";
|
||||
}
|
||||
|
||||
var pluginOpts = {
|
||||
linkNewWindow: parseAsBoolean("$:/config/markdown/linkNewWindow"),
|
||||
renderWikiText: parseAsBoolean("$:/config/markdown/renderWikiText"),
|
||||
renderWikiTextPragma: $tw.wiki.getTiddlerText("$:/config/markdown/renderWikiTextPragma").trim()
|
||||
};
|
||||
var remarkableOpts = {
|
||||
|
||||
var markdownOpts = {
|
||||
html: true,
|
||||
xhtmlOut: true,
|
||||
breaks: parseAsBoolean("$:/config/markdown/breaks"),
|
||||
quotes: $tw.wiki.getTiddlerText("$:/config/markdown/quotes"),
|
||||
typographer: parseAsBoolean("$:/config/markdown/typographer")
|
||||
quotes: $tw.wiki.getTiddlerText("$:/config/markdown/quotes").trim(),
|
||||
typographer: parseAsBoolean("$:/config/markdown/typographer"),
|
||||
linkify: parseAsBoolean("$:/config/markdown/linkify")
|
||||
};
|
||||
var accumulatingTypes = {
|
||||
"text": true,
|
||||
"softbreak": true
|
||||
};
|
||||
// If rendering WikiText, we treat katex nodes as text.
|
||||
if(pluginOpts.renderWikiText) {
|
||||
accumulatingTypes["katex"] = true;
|
||||
}
|
||||
|
||||
var md = new Remarkable(remarkableOpts);
|
||||
// Retrieve needed TW rule classes and instantiated rules
|
||||
function setupWikiRules(pluginOptions) {
|
||||
var results = {};
|
||||
|
||||
// If tiddlywiki/katex plugin is present, use remarkable-katex to enable katex support.
|
||||
if($tw.modules.titles["$:/plugins/tiddlywiki/katex/katex.min.js"]) {
|
||||
var rk = require("$:/plugins/tiddlywiki/markdown/remarkable-katex.js");
|
||||
md = md.use(rk);
|
||||
}
|
||||
function collectAllRules(classes,type) {
|
||||
var rulesInfo = [], key,
|
||||
self = wikiParser;
|
||||
for(key in classes) {
|
||||
// instantiate the rule
|
||||
var RuleClass = classes[key];
|
||||
var rule = new RuleClass(self);
|
||||
rule.name = key;
|
||||
rule.class = RuleClass;
|
||||
rule.is = {};
|
||||
rule.is[type] = true;
|
||||
rule.init(self);
|
||||
|
||||
if(parseAsBoolean("$:/config/markdown/linkify")) {
|
||||
md = md.use(linkify);
|
||||
}
|
||||
|
||||
function findTagWithType(nodes, startPoint, type, level) {
|
||||
for (var i = startPoint; i < nodes.length; i++) {
|
||||
if(nodes[i].type === type && nodes[i].level === level) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remarkable creates nodes that look like:
|
||||
* [
|
||||
* { type: 'paragraph_open'},
|
||||
* { type: 'inline', content: 'Hello World', children:[{type: 'text', content: 'Hello World'}]},
|
||||
* { type: 'paragraph_close'}
|
||||
* ]
|
||||
*
|
||||
* But TiddlyWiki wants the Parser (https://tiddlywiki.com/dev/static/Parser.html) to emit nodes like:
|
||||
*
|
||||
* [
|
||||
* { type: 'element', tag: 'p', children: [{type: 'text', text: 'Hello World'}]}
|
||||
* ]
|
||||
*/
|
||||
function convertNodes(remarkableTree, isStartOfInline) {
|
||||
let out = [];
|
||||
var accumulatedText = '';
|
||||
function withChildren(currentIndex, currentLevel, closingType, nodes, callback) {
|
||||
var j = findTagWithType(nodes, currentIndex + 1, closingType, currentLevel);
|
||||
if(j === false) {
|
||||
console.error("Failed to find a " + closingType + " node after position " + currentIndex);
|
||||
console.log(nodes);
|
||||
return currentIndex + 1;
|
||||
}
|
||||
let children = convertNodes(nodes.slice(currentIndex + 1, j));
|
||||
callback(children);
|
||||
return j;
|
||||
}
|
||||
function wrappedElement(elementTag, currentIndex, currentLevel, closingType, nodes) {
|
||||
return withChildren(currentIndex, currentLevel, closingType, nodes, function(children) {
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: elementTag,
|
||||
children: children
|
||||
rulesInfo.push({
|
||||
rule: rule,
|
||||
matchIndex: -1
|
||||
});
|
||||
};
|
||||
return rulesInfo;
|
||||
}
|
||||
|
||||
// first pass: get all rule classes
|
||||
var wikiParser = new $tw.Wiki.parsers["text/vnd.tiddlywiki"](null, '', {parseAsInline: true, wiki: $tw.wiki});
|
||||
|
||||
// restore all possible rules from each rule class
|
||||
wikiParser.pragmaRules = collectAllRules(wikiParser.pragmaRuleClasses,'pragma');
|
||||
wikiParser.blockRules = collectAllRules(wikiParser.blockRuleClasses,'block');
|
||||
wikiParser.inlineRules = collectAllRules(wikiParser.inlineRuleClasses,'inline');
|
||||
|
||||
var pragma = pluginOptions.renderWikiText
|
||||
? "\\rules except latex-parser extlink\n" + pluginOptions.renderWikiTextPragma
|
||||
: "\\rules only html entity commentinline commentblock";
|
||||
|
||||
wikiParser.pos = 0;
|
||||
wikiParser.source = pragma;
|
||||
wikiParser.sourceLength = pragma.length;
|
||||
|
||||
// second pass: remove uninterested rules based on \rules pragma
|
||||
wikiParser.parsePragmas();
|
||||
|
||||
results.blockRules = {};
|
||||
results.inlineRules = {}
|
||||
results.blockRuleClasses = {};
|
||||
results.inlineRuleClasses = {};
|
||||
|
||||
// save the rule sets for future markdown parsing
|
||||
wikiParser.blockRules.forEach(function(ruleinfo) {
|
||||
results.blockRules[ruleinfo.rule.name] = ruleinfo;
|
||||
results.blockRuleClasses[ruleinfo.rule.name] = ruleinfo.rule.class;
|
||||
});
|
||||
wikiParser.inlineRules.forEach(function(ruleinfo) {
|
||||
results.inlineRules[ruleinfo.rule.name] = ruleinfo;
|
||||
results.inlineRuleClasses[ruleinfo.rule.name] = ruleinfo.rule.class;
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
// Creates markdown-it parser
|
||||
function createMarkdownEngine(markdownItOptions, pluginOptions) {
|
||||
var md = new MarkdownIt(markdownItOptions)
|
||||
.use(require("markdown-it-sub"))
|
||||
.use(require("markdown-it-sup"))
|
||||
.use(require("markdown-it-ins"))
|
||||
.use(require("markdown-it-mark"))
|
||||
.use(require("markdown-it-footnote"))
|
||||
.use(require("markdown-it-deflist"));
|
||||
|
||||
var results = setupWikiRules(pluginOptions);
|
||||
|
||||
MarkdownParser.prototype.blockRuleClasses = results.blockRuleClasses;
|
||||
MarkdownParser.prototype.blockRules = results.blockRules;
|
||||
|
||||
MarkdownParser.prototype.inlineRuleClasses = results.inlineRuleClasses;
|
||||
MarkdownParser.prototype.inlineRules = results.inlineRules;
|
||||
|
||||
if(pluginOptions.renderWikiText && $tw.modules.titles["$:/plugins/tiddlywiki/katex/katex.min.js"]) {
|
||||
md.use(require("markdown-it-katex"));
|
||||
}
|
||||
|
||||
md.use(require("markdown-it-tiddlywiki"),{
|
||||
renderWikiText: pluginOptions.renderWikiText,
|
||||
blockRules: results.blockRules,
|
||||
inlineRules: results.inlineRules
|
||||
});
|
||||
|
||||
$tw.utils.each(['image','prettylink','prettyextlink'], function(rule) {
|
||||
if(MarkdownParser.prototype.inlineRules[rule]) {
|
||||
// delegate to md; ignore the rule class in WikiParser
|
||||
delete MarkdownParser.prototype.inlineRuleClasses[rule];
|
||||
}
|
||||
});
|
||||
return md;
|
||||
}
|
||||
|
||||
/// Parse tree post processing ///
|
||||
|
||||
function deactivateLinks(tree) {
|
||||
$tw.utils.each(tree,function(node) {
|
||||
if(node.type === "link") {
|
||||
node.type = "text";
|
||||
node.text = node.children[0].text;
|
||||
delete node.attributes;
|
||||
delete node.children;
|
||||
delete node.attributes;
|
||||
} else {
|
||||
deactivateLinks(node.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// true if the node contains "_codified_" class attribute
|
||||
function isCodified(node) {
|
||||
return node.attributes
|
||||
&& node.attributes.class
|
||||
&& node.attributes.class.type === "string"
|
||||
&& (node.attributes.class.value.split(" ").indexOf("_codified_") !== -1);
|
||||
}
|
||||
|
||||
function decodeEntities(s) {
|
||||
return s.replace(/(&#?[a-zA-Z0-9]{2,8};)/g,$tw.utils.entityDecode);
|
||||
}
|
||||
|
||||
// Add e"..." and e'....' syntax to enable decoding of HTML entities
|
||||
// in string literals.
|
||||
function parseStringLiteralExtended(source,pos) {
|
||||
var node = {
|
||||
type: "string",
|
||||
start: pos
|
||||
};
|
||||
var reString = /(?:"""([\s\S]*?)"""|e?"([^"]*)")|(?:e?'([^']*)')/g;
|
||||
reString.lastIndex = pos;
|
||||
var match = reString.exec(source);
|
||||
if(match && match.index === pos) {
|
||||
node.value = match[1] !== undefined ? match[1] :
|
||||
(match[2] !== undefined ? match[2] : match[3]);
|
||||
node.end = pos + match[0].length;
|
||||
if(match[0].charAt(0) === "e") {
|
||||
node.value = decodeEntities(node.value);
|
||||
}
|
||||
return node;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function processWikiTree(tree,hasWikiLinkRule) {
|
||||
var stack = [].concat(tree);
|
||||
|
||||
var mergeable = function(node) {
|
||||
return node.type === "element" && node.tag === "p" && (!node.attributes || Object.keys(node.attributes).length === 0);
|
||||
};
|
||||
|
||||
while(stack.length) {
|
||||
var node = stack.pop();
|
||||
if(node.type === "element" && node.tag === "p") {
|
||||
// reduce nested <p> nodes
|
||||
while(node.children && node.children.length === 1 && mergeable(node.children[0])) {
|
||||
node.children = node.children[0].children;
|
||||
}
|
||||
} else if(hasWikiLinkRule && isCodified(node)) {
|
||||
deactivateLinks(node.children);
|
||||
continue;
|
||||
}
|
||||
if(node.children && node.children.length > 0) {
|
||||
stack.push.apply(stack,node.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// to extend MarkdownIt outside of this module, do:
|
||||
//
|
||||
// md = $tw.Wiki.parsers["text/markdown"].prototype.md;
|
||||
// md.use(plugin[, options]);
|
||||
MarkdownParser.prototype.md = createMarkdownEngine(markdownOpts,pluginOpts);
|
||||
|
||||
function MarkdownParser(type,text,options) {
|
||||
var env = {}
|
||||
var md = this.md;
|
||||
var mdTree = md.parse(text,env);
|
||||
var textToParse = '<div class="markdown">\n' + md.renderer.render(mdTree,md.options,env) + '</div>';
|
||||
|
||||
//console.log(JSON.stringify(mdTree,null,2));
|
||||
//console.log("\n----------------\n" + textToParse);
|
||||
|
||||
var wikiParser;
|
||||
|
||||
var origParseStringLiteral = $tw.utils.parseStringLiteral;
|
||||
$tw.utils.parseStringLiteral = parseStringLiteralExtended;
|
||||
|
||||
try {
|
||||
wikiParser = new $tw.Wiki.parsers["text/vnd.tiddlywiki"](null,textToParse,{
|
||||
parseAsInline: true,
|
||||
wiki: options.wiki,
|
||||
rules: { pragma: {}, block: this.blockRuleClasses, inline: this.inlineRuleClasses }
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0; i < remarkableTree.length; i++) {
|
||||
var currentNode = remarkableTree[i];
|
||||
switch (currentNode.type) {
|
||||
case "paragraph_open":
|
||||
// If the paragraph is a "tight" layout paragraph, don't wrap children in a <p> tag.
|
||||
if(currentNode.tight) {
|
||||
i = withChildren(i, currentNode.level, "paragraph_close", remarkableTree, function(children) {
|
||||
Array.prototype.push.apply(out, children);
|
||||
});
|
||||
} else {
|
||||
i = wrappedElement("p", i, currentNode.level, "paragraph_close", remarkableTree);
|
||||
}
|
||||
break;
|
||||
|
||||
case "heading_open":
|
||||
i = wrappedElement("h" + currentNode.hLevel, i, currentNode.level, "heading_close", remarkableTree);
|
||||
break;
|
||||
|
||||
case "bullet_list_open":
|
||||
i = wrappedElement("ul", i, currentNode.level, "bullet_list_close", remarkableTree);
|
||||
break;
|
||||
|
||||
case "ordered_list_open":
|
||||
i = wrappedElement('ol', i, currentNode.level,'ordered_list_close', remarkableTree);
|
||||
break;
|
||||
|
||||
case "list_item_open":
|
||||
i = wrappedElement("li", i, currentNode.level, "list_item_close", remarkableTree);
|
||||
break;
|
||||
|
||||
case "link_open":
|
||||
i = withChildren(i, currentNode.level, "link_close", remarkableTree, function(children) {
|
||||
if(currentNode.href[0] !== "#") {
|
||||
// External link
|
||||
var attributes = {
|
||||
class: { type: "string", value: "tc-tiddlylink-external" },
|
||||
href: { type: "string", value: currentNode.href },
|
||||
rel: { type: "string", value: "noopener noreferrer" }
|
||||
};
|
||||
if(pluginOpts.linkNewWindow) {
|
||||
attributes.target = { type: "string", value: "_blank" };
|
||||
}
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: "a",
|
||||
attributes: attributes,
|
||||
children: children
|
||||
});
|
||||
} else {
|
||||
// Internal link
|
||||
out.push({
|
||||
type: "link",
|
||||
attributes: {
|
||||
to: { type: "string", value: $tw.utils.decodeURISafe(currentNode.href.substr(1)) }
|
||||
},
|
||||
children: children
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "code":
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: currentNode.block ? "pre" : "code",
|
||||
children: [{ type: "text", text: currentNode.content }]
|
||||
});
|
||||
break;
|
||||
|
||||
case "fence":
|
||||
out.push({
|
||||
type: "codeblock",
|
||||
attributes: {
|
||||
language: { type: "string", value: currentNode.params },
|
||||
code: { type: "string", value: currentNode.content }
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "image":
|
||||
out.push({
|
||||
type: "image",
|
||||
attributes: {
|
||||
tooltip: { type: "string", value: currentNode.alt },
|
||||
source: { type: "string", value: $tw.utils.decodeURIComponentSafe(currentNode.src) }
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "softbreak":
|
||||
if(remarkableOpts.breaks) {
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: "br",
|
||||
});
|
||||
} else {
|
||||
accumulatedText = accumulatedText + '\n';
|
||||
}
|
||||
break;
|
||||
|
||||
case "hardbreak":
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: "br",
|
||||
});
|
||||
break;
|
||||
|
||||
case "th_open":
|
||||
case "td_open":
|
||||
var elementTag = currentNode.type.slice(0, 2);
|
||||
i = withChildren(i, currentNode.level, elementTag + "_close", remarkableTree, function(children) {
|
||||
var attributes = {};
|
||||
if(currentNode.align) {
|
||||
attributes.style = { type: "string", value: "text-align:" + currentNode.align };
|
||||
}
|
||||
out.push({
|
||||
type: "element",
|
||||
tag: elementTag,
|
||||
attributes: attributes,
|
||||
children: children
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
||||
case "hr":
|
||||
out.push({
|
||||
type: 'element',
|
||||
tag: 'hr',
|
||||
});
|
||||
break;
|
||||
|
||||
case "inline":
|
||||
out = out.concat(convertNodes(currentNode.children, true));
|
||||
break;
|
||||
|
||||
case "text":
|
||||
// We need to merge this text block with the upcoming text block and parse it all together.
|
||||
accumulatedText = accumulatedText + currentNode.content;
|
||||
break;
|
||||
|
||||
case "katex":
|
||||
// If rendering WikiText, convert the katex node back to text for parsing by the WikiText LaTeX parser.
|
||||
if(pluginOpts.renderWikiText) {
|
||||
// If this is a block, add a newline to trigger the KaTeX plugins block detection.
|
||||
var displayModeSuffix = currentNode.block ? "\n" : "";
|
||||
accumulatedText = accumulatedText + "$$" + currentNode.content + displayModeSuffix + "$$";
|
||||
} else {
|
||||
out.push({
|
||||
type: "latex",
|
||||
attributes: {
|
||||
text: { type: "text", value: currentNode.content },
|
||||
displayMode: { type: "text", value: currentNode.block ? "true" : "false" }
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(currentNode.type.substr(currentNode.type.length - 5) === "_open") {
|
||||
var tagName = currentNode.type.substr(0, currentNode.type.length - 5);
|
||||
i = wrappedElement(tagName, i, currentNode.level, tagName + "_close", remarkableTree);
|
||||
} else {
|
||||
console.error("Unknown node type: " + currentNode.type, currentNode);
|
||||
out.push({
|
||||
type: "text",
|
||||
text: currentNode.content
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
// We test to see if we process the block now, or if there's
|
||||
// more to accumulate first.
|
||||
if(accumulatedText
|
||||
&& (
|
||||
remarkableOpts.breaks ||
|
||||
(i+1) >= remarkableTree.length ||
|
||||
!accumulatingTypes[remarkableTree[i+1].type]
|
||||
)
|
||||
) {
|
||||
// The Markdown compiler thinks this is just text.
|
||||
// Hand off to the WikiText parser to see if there's more to render
|
||||
// But only if it's configured to, and we have more than whitespace
|
||||
if(!pluginOpts.renderWikiText || accumulatedText.match(/^\s*$/)) {
|
||||
out.push({
|
||||
type: "text",
|
||||
text: accumulatedText
|
||||
});
|
||||
} else {
|
||||
// If we're inside a block element (div, p, td, h1), and this is the first child in the tree,
|
||||
// handle as a block-level parse. Otherwise not.
|
||||
var parseAsInline = !(isStartOfInline && i === 0);
|
||||
var textToParse = accumulatedText;
|
||||
if(pluginOpts.renderWikiTextPragma !== "") {
|
||||
textToParse = pluginOpts.renderWikiTextPragma + "\n" + textToParse;
|
||||
}
|
||||
var wikiParser = $tw.wiki.parseText("text/vnd.tiddlywiki", textToParse, {
|
||||
parseAsInline: parseAsInline
|
||||
});
|
||||
var rs = wikiParser.tree;
|
||||
|
||||
// If we parsed as a block, but the root element the WikiText parser gave is a paragraph,
|
||||
// we should discard the paragraph, since the way Remarkable nests its nodes, this "inline"
|
||||
// node is always inside something else that's a block-level element
|
||||
if(!parseAsInline
|
||||
&& rs.length === 1
|
||||
&& rs[0].type === "element"
|
||||
&& rs[0].tag === "p"
|
||||
) {
|
||||
rs = rs[0].children;
|
||||
}
|
||||
|
||||
// If the original text element started with a space, add it back in
|
||||
if(rs.length > 0
|
||||
&& rs[0].type === "text"
|
||||
&& (accumulatedText[0] === " " || accumulatedText[0] === "\n")
|
||||
) {
|
||||
rs[0].text = " " + rs[0].text;
|
||||
}
|
||||
out = out.concat(rs);
|
||||
}
|
||||
accumulatedText = '';
|
||||
}
|
||||
catch (err) {
|
||||
wikiParser = $tw.wiki.parseText("text/vnd.tiddlywiki",
|
||||
"<strong>Error encountered while parsing the tiddler:</strong><p>" + err.message + "</p>",
|
||||
{parseAsInline: false, wiki: options.wiki});
|
||||
}
|
||||
return out;
|
||||
finally {
|
||||
$tw.utils.parseStringLiteral = origParseStringLiteral;
|
||||
}
|
||||
if(wikiParser.tree.length > 0) {
|
||||
var hasWikiLinkRule = false;
|
||||
// see if wikilink rule has been invoked
|
||||
$tw.utils.each(wikiParser.inlineRules,function(ruleInfo) {
|
||||
if(ruleInfo.rule.name === "wikilink") {
|
||||
hasWikiLinkRule = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
processWikiTree(wikiParser.tree,hasWikiLinkRule);
|
||||
}
|
||||
this.tree = wikiParser.tree;
|
||||
this.source = text;
|
||||
this.type = type || "text/markdown";
|
||||
this.wiki = options.wiki;
|
||||
}
|
||||
|
||||
var MarkdownParser = function(type, text, options) {
|
||||
var tree = md.parse(text, {});
|
||||
//console.debug(tree);
|
||||
tree = convertNodes(tree);
|
||||
//console.debug(tree);
|
||||
|
||||
this.tree = tree;
|
||||
};
|
||||
|
||||
exports["text/markdown"] = MarkdownParser;
|
||||
exports["text/x-markdown"] = MarkdownParser;
|
||||
|
||||
})();
|
||||
})(require);
|
||||
|
Loading…
Reference in New Issue
Block a user