1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-25 04:14:40 +00:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Jeremy Ruston
1e47b88dc7 Merge branch 'master' into wikify-operator 2025-06-03 16:39:19 +01:00
Jason E Baldus
48b45f0e35 Fix stray space after named end breaking parsing #8976 (#9073)
This commit fixes #8976, and adds tests for procedures, functions,
and macro definitions with spaces after the end statements, both
with and without names.
2025-05-29 08:08:53 +01:00
Jeremy Ruston
da4f5c64ca Change experimental plugins to stable
See discussion at https://talk.tiddlywiki.org/t/introduction-to-the-geospatial-plugin/7984/37
2025-05-18 12:04:08 +01:00
Jeremy Ruston
a0fbd4e0f3 Merge branch 'tiddlywiki-com' 2025-05-18 11:57:22 +01:00
lin onetwo
77cb8335c1 Update Chinese Community.tid (#9060)
* Update Chinese Community.tid

(cherry picked from commit 3385f6899114037d8accd9adc4dc8fda55bfd521)

* Update Chinese Community.tid

(cherry picked from commit ffe91c987470c1527e8aafbb39b45b6861d09481)
2025-05-18 11:56:38 +01:00
Jeremy Ruston
55b680e485 Merge branch 'tiddlywiki-com' 2025-05-06 10:58:17 +01:00
Saq Imtiaz
80058e7f45 Resolves permissions issues in workflow to check PR build size (#9049)
* ci: use v3 of cerebrus that also posts a build size report to PRs

* fix: resolved permissions issues in checking PR build size
2025-05-06 10:57:35 +01:00
Jeremy Ruston
9df912a341 Trial commit to master for testing purposes
See https://github.com/TiddlyWiki/TiddlyWiki5/pull/9048#issuecomment-2850685095
2025-05-05 12:32:27 +01:00
Jeremy Ruston
082654564a Merge branch 'tiddlywiki-com' 2025-05-05 12:00:45 +01:00
Saq Imtiaz
1480d495b3 ci: use v3 of cerebrus that also posts a build size report to PRs (#9048) 2025-05-05 12:00:11 +01:00
Saq Imtiaz
5e8d6fb790 Adds a custom action to check the target branch (#9046)
* ci: added cerebrus action to validate files in PRs based on the target branch

* fix: reflect move of action repo to TW org

* use cerebrus v2

* fix: use pull_request_target to enable write access
2025-05-04 15:22:00 +01:00
Jeremy Ruston
55cf0b2965 Add wikify operator 2024-11-07 16:26:07 +00:00
19 changed files with 435 additions and 106 deletions

View File

@@ -0,0 +1,50 @@
name: Calculate PR build size
on:
pull_request_target:
types: [opened, reopened, synchronize]
jobs:
calculate-build-size:
runs-on: ubuntu-latest
permissions:
pull-requests: read
contents: read
outputs:
pr_size: ${{ steps.get_sizes.outputs.pr_size }}
base_size: ${{ steps.get_sizes.outputs.base_size }}
steps:
- name: build-size-check
id: get_sizes
uses: TiddlyWiki/cerebrus@v4
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
base_ref: ${{ github.base_ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
mode: size:calc
dispatch-followup:
needs: calculate-build-size
runs-on: ubuntu-latest
permissions:
actions: write # Required to dispatch another workflow
pull-requests: write
contents: read
steps:
- name: Trigger follow-up workflow
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'pr-comment-build-size.yml',
ref: 'master',
inputs: {
pr_number: '${{ github.event.pull_request.number }}',
base_ref: '${{ github.event.pull_request.base.ref }}',
pr_size: '${{ needs.calculate-build-size.outputs.pr_size }}',
base_size: '${{ needs.calculate-build-size.outputs.base_size }}'
}
});

View File

@@ -0,0 +1,36 @@
name: Comment on PR build size (Trusted workflow)
on:
workflow_dispatch:
inputs:
pr_number:
required: true
type: string
base_ref:
required: true
type: string
pr_size:
required: true
type: string
base_size:
required: true
type: string
jobs:
comment-on-pr:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Build and check size
uses: TiddlyWiki/cerebrus@v4
with:
pr_number: ${{ inputs.pr_number }}
repo: ${{ github.repository }}
base_ref: ${{ inputs.base_ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
mode: size:comment
pr_size: ${{ inputs.pr_size }}
base_size: ${{ inputs.base_size }}

View File

@@ -0,0 +1,18 @@
name: Validate PR Paths
on:
pull_request_target:
types: [opened, reopened, synchronize]
jobs:
validate-pr:
runs-on: ubuntu-latest
steps:
- name: Validate PR
uses: TiddlyWiki/cerebrus@v4
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
base_ref: ${{ github.base_ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,37 @@
/*\
title: $:/core/modules/filters/wikify.js
type: application/javascript
module-type: filteroperator
Filter operator wikifying each string in the input list and returning the result as a list of strings
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.wikify = function(source,operator,options) {
var output = operator.operands[0],
mode = operator.operands[1],
type = operator.operands[2],
results = [];
source(function(tiddler,title) {
var wikifier = new $tw.utils.Wikifier({
wiki: options.wiki,
widget: options.widget,
text: title,
type: type,
mode: mode,
output: output
});
results.push(wikifier.getResult());
});
return results;
};
})();

View File

@@ -50,7 +50,7 @@ exports.parse = function() {
var reEnd;
if(this.match[5]) {
// If so, it is a multiline definition and the end of the body is marked with \end
reEnd = new RegExp("((:?^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[2]) + ")?(?:$|\\r?\\n))","mg");
reEnd = new RegExp("((:?^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[2]) + ")?\\s*?(?:$|\\r?\\n))","mg");
} else {
// Otherwise, the end of the definition is marked by the end of the line
reEnd = /($|\r?\n)/mg;

View File

@@ -55,7 +55,7 @@ exports.parse = function() {
var reEnd;
if(this.match[3]) {
// If so, it is a multiline definition and the end of the body is marked with \end
reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg");
reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?\\s*?(?:$|\\r?\\n))","mg");
} else {
// Otherwise, the end of the definition is marked by the end of the line
reEnd = /($|\r?\n)/mg;

View File

@@ -0,0 +1,108 @@
/*\
title: $:/core/modules/utils/wikifier.js
type: application/javascript
module-type: utils
A high level helper class for parsing and wikification
\*/
(function(){
/*
Options include:
wiki: wiki to be used for wikification
widget: optional widget to be used as parent of wikified text
text: text to be parsed/wikified
type: type of the text
mode: inline or block
output: text, formattedtext, html, parsetree or widgettree
*/
function Wikifier(options) {
this.wiki = options.wiki || $tw.wiki;
this.widget = options.widget || $tw.rootWidget;
this.text = options.text || "";
this.type = options.type || "";
this.mode = options.mode || "block";
this.output = options.output || "text";
// Create the parse tree
this.parser = this.wiki.parseText(this.type,this.text,{
parseAsInline: this.mode === "inline"
});
// Create the widget tree
this.widgetNode = this.wiki.makeWidget(this.parser,{
document: $tw.fakeDocument,
parentWidget: this.widget
});
// Render the widget tree to the container
this.container = $tw.fakeDocument.createElement("div");
this.widgetNode.render(this.container,null);
};
Wikifier.prototype.refresh = function(changedTiddlers) {
// Refresh the widget tree
return this.widgetNode.refresh(changedTiddlers);
};
/*
Return the result string
*/
Wikifier.prototype.getResult = function() {
var result;
switch(this.output) {
case "text":
result = this.container.textContent;
break;
case "formattedtext":
result = this.container.formattedTextContent;
break;
case "html":
result = this.container.innerHTML;
break;
case "parsetree":
result = JSON.stringify(this.parser.tree,0,$tw.config.preferences.jsonSpaces);
break;
case "widgettree":
result = JSON.stringify(this.getWidgetTree(),0,$tw.config.preferences.jsonSpaces);
break;
}
return result;
};
/*
Return a string of the widget tree
*/
Wikifier.prototype.getWidgetTree = function() {
var copyNode = function(widgetNode,resultNode) {
var type = widgetNode.parseTreeNode.type;
resultNode.type = type;
switch(type) {
case "element":
resultNode.tag = widgetNode.parseTreeNode.tag;
break;
case "text":
resultNode.text = widgetNode.parseTreeNode.text;
break;
}
if(Object.keys(widgetNode.attributes || {}).length > 0) {
resultNode.attributes = {};
$tw.utils.each(widgetNode.attributes,function(attr,attrName) {
resultNode.attributes[attrName] = widgetNode.getAttribute(attrName);
});
}
if(Object.keys(widgetNode.children || {}).length > 0) {
resultNode.children = [];
$tw.utils.each(widgetNode.children,function(widgetChildNode) {
var node = {};
resultNode.children.push(node);
copyNode(widgetChildNode,node);
});
}
},
results = {};
copyNode(this.widgetNode,results);
return results;
};
exports.Wikifier = Wikifier;
})();

View File

@@ -36,89 +36,22 @@ Compute the internal state of the widget
WikifyWidget.prototype.execute = function() {
// Get our parameters
this.wikifyName = this.getAttribute("name");
this.wikifyText = this.getAttribute("text");
this.wikifyType = this.getAttribute("type");
this.wikifyMode = this.getAttribute("mode","block");
this.wikifyOutput = this.getAttribute("output","text");
// Create the parse tree
this.wikifyParser = this.wiki.parseText(this.wikifyType,this.wikifyText,{
parseAsInline: this.wikifyMode === "inline"
});
// Create the widget tree
this.wikifyWidgetNode = this.wiki.makeWidget(this.wikifyParser,{
document: $tw.fakeDocument,
parentWidget: this
});
// Render the widget tree to the container
this.wikifyContainer = $tw.fakeDocument.createElement("div");
this.wikifyWidgetNode.render(this.wikifyContainer,null);
this.wikifyResult = this.getResult();
// Create the wikifier
this.wikifier = new $tw.utils.Wikifier({
wiki: this.wiki,
widget: this,
text: this.getAttribute("text"),
type: this.getAttribute("type"),
mode: this.getAttribute("mode","block"),
output: this.getAttribute("output","text")
});
this.wikifyResult = this.wikifier.getResult();
// Set context variable
this.setVariable(this.wikifyName,this.wikifyResult);
// Construct the child widgets
this.makeChildWidgets();
};
/*
Return the result string
*/
WikifyWidget.prototype.getResult = function() {
var result;
switch(this.wikifyOutput) {
case "text":
result = this.wikifyContainer.textContent;
break;
case "formattedtext":
result = this.wikifyContainer.formattedTextContent;
break;
case "html":
result = this.wikifyContainer.innerHTML;
break;
case "parsetree":
result = JSON.stringify(this.wikifyParser.tree,0,$tw.config.preferences.jsonSpaces);
break;
case "widgettree":
result = JSON.stringify(this.getWidgetTree(),0,$tw.config.preferences.jsonSpaces);
break;
}
return result;
};
/*
Return a string of the widget tree
*/
WikifyWidget.prototype.getWidgetTree = function() {
var copyNode = function(widgetNode,resultNode) {
var type = widgetNode.parseTreeNode.type;
resultNode.type = type;
switch(type) {
case "element":
resultNode.tag = widgetNode.parseTreeNode.tag;
break;
case "text":
resultNode.text = widgetNode.parseTreeNode.text;
break;
}
if(Object.keys(widgetNode.attributes || {}).length > 0) {
resultNode.attributes = {};
$tw.utils.each(widgetNode.attributes,function(attr,attrName) {
resultNode.attributes[attrName] = widgetNode.getAttribute(attrName);
});
}
if(Object.keys(widgetNode.children || {}).length > 0) {
resultNode.children = [];
$tw.utils.each(widgetNode.children,function(widgetChildNode) {
var node = {};
resultNode.children.push(node);
copyNode(widgetChildNode,node);
});
}
},
results = {};
copyNode(this.wikifyWidgetNode,results);
return results;
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
@@ -130,9 +63,9 @@ WikifyWidget.prototype.refresh = function(changedTiddlers) {
return true;
} else {
// Refresh the widget tree
if(this.wikifyWidgetNode.refresh(changedTiddlers)) {
if(this.wikifier.refresh(changedTiddlers)) {
// Check if there was any change
var result = this.getResult();
var result = this.wikifier.getResult();
if(result !== this.wikifyResult) {
// If so, save the change
this.wikifyResult = result;

View File

@@ -0,0 +1,21 @@
title: Operators/Wikify/TextMode
description: Simple wikify operator
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\parsermode inline
<$text text={{{ [subfilter{Filter}] }}}/>
+
title: Filter
[{Text}wikify[html],[inline],[text/vnd.tiddlywiki]]
+
title: Text
This is ''the text'' that is __wikified__
+
title: ExpectedResult
This is &lt;strong&gt;the text&lt;/strong&gt; that is &lt;u&gt;wikified&lt;/u&gt;

View File

@@ -0,0 +1,64 @@
title: Operators/Wikify/ParseTreeMode
description: Simple wikify operator
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\parsermode inline
<$text text={{{ [subfilter{Filter}] }}}/>
+
title: Filter
[{Text}wikify[parsetree],[inline],[text/vnd.tiddlywiki]]
+
title: Text
This is ''the text'' that is __wikified__
+
title: ExpectedResult
[
{
"type": "text",
"text": "This is ",
"start": 0,
"end": 8
},
{
"type": "element",
"tag": "strong",
"children": [
{
"type": "text",
"text": "the text",
"start": 10,
"end": 18
}
],
"start": 8,
"end": 20,
"rule": "bold"
},
{
"type": "text",
"text": " that is ",
"start": 20,
"end": 29
},
{
"type": "element",
"tag": "u",
"children": [
{
"type": "text",
"text": "wikified",
"start": 31,
"end": 39
}
],
"start": 29,
"end": 41,
"rule": "underscore"
}
]

View File

@@ -0,0 +1,21 @@
title: Operators/Wikify/TextMode
description: Simple wikify operator
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\parsermode inline
<$text text={{{ [subfilter{Filter}] }}}/>
+
title: Filter
[{Text}wikify[text],[inline],[text/vnd.tiddlywiki]]
+
title: Text
This is ''the text'' that is __wikified__
+
title: ExpectedResult
This is the text that is wikified

View File

@@ -116,6 +116,22 @@ describe("WikiText parser tests", function() {
);
});
it("should parse macro definitions with end statements followed by spaces", function() {
expect(parse("\\define myMacro()\nnothing\n\\end \n")).toEqual(
[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":33,"rule":"macrodef"}]
);
});
it("should parse macro definitions with named end statements followed by spaces", function() {
expect(parse("\\define myMacro()\nnothing\n\\end myMacro \n")).toEqual(
[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":40,"rule":"macrodef"}]
);
});
it("should parse procedure definitions with no parameters", function() {
expect(parse("\\procedure myMacro()\nnothing\n\\end\n")).toEqual(
@@ -132,6 +148,22 @@ describe("WikiText parser tests", function() {
);
});
it("should parse procedure definitions with end statements followed by spaces", function() {
expect(parse("\\procedure myMacro()\nnothing\n\\end \n")).toEqual(
[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isProcedureDefinition":true,"start":0,"end":36,"rule":"fnprocdef"}]
);
});
it("should parse procedure definitions with named end statements followed by spaces", function() {
expect(parse("\\procedure myMacro()\nnothing\n\\end myMacro \n")).toEqual(
[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isProcedureDefinition":true,"start":0,"end":43,"rule":"fnprocdef"}]
);
});
it("should parse procedure definitions with parameters", function() {
expect(parse("\\procedure myMacro(one,two,three,four:elephant)\nnothing\n\\end\n")).toEqual(
@@ -155,6 +187,22 @@ describe("WikiText parser tests", function() {
);
});
it("should parse function definitions with end statements followed by spaces", function() {
expect(parse("\\function myMacro()\nnothing\n\\end \n")).toEqual(
[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isFunctionDefinition":true,"start":0,"end":35,"rule":"fnprocdef"}]
);
});
it("should parse function definitions with named end statements followed by spaces", function() {
expect(parse("\\function myMacro()\nnothing\n\\end myMacro \n")).toEqual(
[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isFunctionDefinition":true,"start":0,"end":42,"rule":"fnprocdef"}]
);
});
it("should parse single line function definitions with no parameters", function() {
expect(parse("\\function myMacro() nothing\n")).toEqual(

View File

@@ -1,20 +1,13 @@
title: 中文社区 - Chinese Community
tags: Community
# A Chinese community tutorial program that people can edit together:
#* Main site: [ext[https://tw-cn.netlify.app/]]
#* Accelerated access: [ext[https://tw-cn.cpolar.top/]]
#* Alternate: [ext[https://tiddly-wiki-chinese-tutorial.vercel.app]]
# Tiddlywiki Chinese Chat Forum: [ext[https://talk.tidgi.fun/topic/6]]
# Chinese translation of Tiddlywiki official website [ext[https://bramchen.github.io/tw5-docs/zh-Hans/]]
# The best Chinese introductory tutorial for newbies [ext[https://keatonlao.github.io/tiddlywiki-xp/]]
---
# 大家可以一起编辑的中文社区教程项目:
#* 主站:[ext[https://tw-cn.netlify.app/]]
#* 加速访问:[ext[https://tw-cn.cpolar.top/]]
#* 备用:[ext[https://tiddly-wiki-chinese-tutorial.vercel.app]]
# 太微中文交流论坛:[ext[https://talk.tidgi.fun/topic/6]]
# 太微官网汉化版:[ext[https://bramchen.github.io/tw5-docs/zh-Hans/]]
# 最适合新手的中文入门教程:[ext[https://keatonlao.github.io/tiddlywiki-xp/]]
* 大家可以一起编辑的中文社区教程项目:
*# 主站:[ext[https://tw-cn.netlify.app/]]
*# 加速访问:[ext[https://tw-cn.cpolar.top/]]
*# 备用:[ext[https://tiddly-wiki-chinese-tutorial.vercel.app]]
* 太微中文交流论坛:[ext[https://talk.tidgi.fun/topic/6]]
* 太微官网汉化版:[ext[https://bramchen.github.io/tw5-docs/zh-Hans/]]
* 最适合新手的中文入门教程:[ext[https://keatonlao.github.io/tiddlywiki-xp/]]
* TiddlyWiki 爱好者 QQ 群: 946052860
*# [ext[点击链接加入群聊【TiddlyWiki爱好者】|https://qm.qq.com/q/13SFxVArlu]]
*# [ext[点击链接加入腾讯频道【太微TiddlyWiki】|https://pd.qq.com/s/474hgpll1]]

View File

@@ -2,11 +2,11 @@
"description": "Documentation from https://tiddlywiki.com",
"plugins": [
"tiddlywiki/browser-sniff",
"tiddlywiki/railroad",
"tiddlywiki/internals",
"tiddlywiki/menubar",
"tiddlywiki/confetti",
"tiddlywiki/dynannotate",
"tiddlywiki/internals",
"tiddlywiki/menubar",
"tiddlywiki/railroad",
"tiddlywiki/tour"
],
"themes": [

View File

@@ -3,5 +3,5 @@
"name": "Confetti",
"description": "Animated confetti effect",
"list": "readme",
"stability": "STABILITY_1_EXPERIMENTAL"
"stability": "STABILITY_2_STABLE"
}

View File

@@ -3,5 +3,5 @@
"name": "Geospatial Utilities",
"description": "Geospatial utilities",
"list": "readme docs settings license",
"stability": "STABILITY_1_EXPERIMENTAL"
"stability": "STABILITY_2_STABLE"
}

View File

@@ -3,5 +3,5 @@
"name": "Stacked View",
"description": "Stacked card storyview",
"list": "readme",
"stability": "STABILITY_1_EXPERIMENTAL"
"stability": "STABILITY_2_STABLE"
}

View File

@@ -4,5 +4,5 @@
"description": "A tour of TiddlyWiki",
"list": "readme docs settings",
"dependents": ["$:/plugins/tiddlywiki/confetti","$:/plugins/tiddlywiki/dynannotate"],
"stability": "STABILITY_1_EXPERIMENTAL"
"stability": "STABILITY_2_STABLE"
}

View File

@@ -3,5 +3,5 @@
"name": "TW5.com Docs",
"description": "Documentation from tiddlywiki.com",
"list": "readme",
"stability": "STABILITY_1_EXPERIMENTAL"
"stability": "STABILITY_2_STABLE"
}