mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-25 20:33:41 +00:00
Compare commits
134 Commits
browser-me
...
element-ma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f29de0cb44 | ||
|
|
a14cd291ac | ||
|
|
b27d102d55 | ||
|
|
9aaab87b87 | ||
|
|
eb3a80968e | ||
|
|
62ae4b24bc | ||
|
|
ded76aa84f | ||
|
|
e42ed6808e | ||
|
|
844564180f | ||
|
|
a670de0e95 | ||
|
|
faee49ee01 | ||
|
|
dd20be49f0 | ||
|
|
a27f74bbdc | ||
|
|
ae4e99951a | ||
|
|
be84dee26b | ||
|
|
00e17874f0 | ||
|
|
9041f099a3 | ||
|
|
3ba31be2a8 | ||
|
|
99d8afd515 | ||
|
|
2ab5f26644 | ||
|
|
419fe68ee2 | ||
|
|
0e765bdbdb | ||
|
|
855d8a9638 | ||
|
|
afcf108d29 | ||
|
|
8f9acc0ca2 | ||
|
|
5e4b8fbb3c | ||
|
|
8e301178a4 | ||
|
|
a72d3a09bf | ||
|
|
56634ffe29 | ||
|
|
24c317e1ab | ||
|
|
07329c6849 | ||
|
|
47ab3476f6 | ||
|
|
f0e64660f2 | ||
|
|
9663e65f4b | ||
|
|
7cb422242a | ||
|
|
f075f24e6b | ||
|
|
5fa1098c03 | ||
|
|
92dc927c7b | ||
|
|
98a61f01bb | ||
|
|
f3fa69e229 | ||
|
|
e2fb22ade0 | ||
|
|
7fb8560908 | ||
|
|
ff7814360e | ||
|
|
2d9303c6ff | ||
|
|
6aee5eb0c7 | ||
|
|
6eb881bffe | ||
|
|
2a5ce95d99 | ||
|
|
bd4fdd8f2e | ||
|
|
09379abd5d | ||
|
|
c6906120d8 | ||
|
|
c4c60933f4 | ||
|
|
a3979cda9c | ||
|
|
3c8ee86e23 | ||
|
|
921c0174fb | ||
|
|
4196d96adc | ||
|
|
743e99d12d | ||
|
|
6beeb23d10 | ||
|
|
838fad916d | ||
|
|
935e89bd93 | ||
|
|
1b8a2caa23 | ||
|
|
ecba671bcf | ||
|
|
fc1e53a777 | ||
|
|
2b6bdcbf97 | ||
|
|
119706a918 | ||
|
|
86d15585b6 | ||
|
|
4b824795c8 | ||
|
|
cd173a959d | ||
|
|
86d61e09bd | ||
|
|
7c197f6ecc | ||
|
|
8f8b46dab7 | ||
|
|
7b013af240 | ||
|
|
05f3e6d5a0 | ||
|
|
48eeb4603a | ||
|
|
fc74219c0b | ||
|
|
86c4770a28 | ||
|
|
ffde2da16c | ||
|
|
da41a55f29 | ||
|
|
846ac9a0dd | ||
|
|
65edda224b | ||
|
|
41dac42f3b | ||
|
|
87d9754a4e | ||
|
|
5cd3084298 | ||
|
|
4c27c09b4d | ||
|
|
4bb0bc5527 | ||
|
|
6cb333b65b | ||
|
|
3378497816 | ||
|
|
033d5cf225 | ||
|
|
52d73eb1a8 | ||
|
|
5d1c1eaf87 | ||
|
|
ed4a186c9c | ||
|
|
f16c0d769b | ||
|
|
298508c104 | ||
|
|
f1e1532949 | ||
|
|
3e1078eff1 | ||
|
|
cc348fee96 | ||
|
|
24d45fd318 | ||
|
|
9fd345ec06 | ||
|
|
30e9b4f3b7 | ||
|
|
c6556d5207 | ||
|
|
a8da7e0207 | ||
|
|
d5762b1fbb | ||
|
|
2b0739f06e | ||
|
|
d81204c6ab | ||
|
|
e339f112a4 | ||
|
|
e001c21bf5 | ||
|
|
7a9235e9d1 | ||
|
|
bbbc8c2c03 | ||
|
|
538482e9a9 | ||
|
|
df7973fc3e | ||
|
|
ae79736e82 | ||
|
|
102c236267 | ||
|
|
06a2923adf | ||
|
|
244251ed44 | ||
|
|
9164f305e0 | ||
|
|
64f86c2187 | ||
|
|
54e5ef7489 | ||
|
|
2d2ba61949 | ||
|
|
0bbe170cf0 | ||
|
|
6f306d1ed6 | ||
|
|
845f988ab0 | ||
|
|
234667cc31 | ||
|
|
f1ce35036e | ||
|
|
5dfdbc8ea0 | ||
|
|
3cf71365a5 | ||
|
|
799618d9f5 | ||
|
|
4d4d9d9995 | ||
|
|
19177964c8 | ||
|
|
c8e41bfade | ||
|
|
fb4d417629 | ||
|
|
20d6be1e23 | ||
|
|
7898cb8446 | ||
|
|
9a5f4cc0ef | ||
|
|
cda8d7ca8c | ||
|
|
f38e9f0822 |
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
boot/** -linguist-generated
|
||||||
|
**/tiddlywiki.files linguist-language=JSON
|
||||||
|
**/tiddlywiki.info linguist-language=JSON
|
||||||
|
**/plugin.info linguist-language=JSON
|
||||||
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve TiddlyWiki 5
|
||||||
|
title: "[Report] "
|
||||||
|
type: report
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Remove elements, that you do not need -->
|
||||||
|
<!-- Add screenshots where needed -->
|
||||||
|
|
||||||
|
**Problem Description**
|
||||||
|
<!-- Describe your problem: A clear and concise description of what your problem is -->
|
||||||
|
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
|
1. At https://tiddlywiki.com
|
||||||
|
2. Click on ...
|
||||||
|
3. Scroll down to ...
|
||||||
|
4. See ...
|
||||||
|
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
|
||||||
|
As a user,
|
||||||
|
<!-- As a developer, -->
|
||||||
|
I would expect ...
|
||||||
|
|
||||||
|
|
||||||
|
**TiddlyWiki Configuration**
|
||||||
|
<!-- Please complete the following information -->
|
||||||
|
|
||||||
|
- Report created with: [Wiki Information](https://tiddlywiki.com/#%24%3A%2Fcore%2Fui%2FControlPanel%2FWikiInformation)
|
||||||
|
|
||||||
|
<!-- Your report comes here -->
|
||||||
|
<!-- or -->
|
||||||
|
<!-- Add it manually -->
|
||||||
|
|
||||||
|
- Version: <!-- e.g. v5.3.8 -->
|
||||||
|
- Saving mechanism: <!-- e.g. Node.js, TiddlyDesktop, TiddlyHost etc -->
|
||||||
|
- Plugins installed: <!-- e.g. Freelinks, TiddlyMap ... other 3rd party plugins -->
|
||||||
|
|
||||||
|
|
||||||
|
**Desktop**
|
||||||
|
<!-- Please complete the following information -->
|
||||||
|
|
||||||
|
- OS: <!-- e.g. iOS -->
|
||||||
|
- Browser: <!-- e.g. chrome, safari, FireFox -- Version: -->
|
||||||
|
|
||||||
|
**Smartphone**
|
||||||
|
<!-- Please complete the following information -->
|
||||||
|
|
||||||
|
- Device: <!-- e.g. iPhone6 -->
|
||||||
|
- OS: <!-- e.g. iOS8.1 -->
|
||||||
|
- Browser: <!-- e.g. stock browser, safari, FireFox -- Version: -->
|
||||||
|
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
<!-- Add any other context about the problem here. -->
|
||||||
67
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
67
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,67 +0,0 @@
|
|||||||
name: Bug report
|
|
||||||
description: Create a report to help us improve TiddlyWiki 5
|
|
||||||
title: "[BUG] "
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: Describe
|
|
||||||
attributes:
|
|
||||||
label: Describe the bug
|
|
||||||
description: A clear and concise description of what the bug is.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: Expected
|
|
||||||
attributes:
|
|
||||||
label: Expected behavior
|
|
||||||
description: A clear and concise description of what you expected to happen.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: Reproduce
|
|
||||||
attributes:
|
|
||||||
label: To Reproduce
|
|
||||||
description: "Steps to reproduce the behavior:"
|
|
||||||
placeholder: |
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: Screenshots
|
|
||||||
attributes:
|
|
||||||
label: Screenshots
|
|
||||||
description: If applicable, add screenshots to help explain your problem.
|
|
||||||
placeholder: Drag image here to upload screenshot!
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: Configuration
|
|
||||||
attributes:
|
|
||||||
label: TiddlyWiki Configuration
|
|
||||||
description: please complete the following information
|
|
||||||
placeholder: |
|
|
||||||
- Version [e.g. v5.1.24]
|
|
||||||
- Saving mechanism [e.g. Node.js, TiddlyDesktop, TiddlyHost etc]
|
|
||||||
- Plugins installed [e.g. Freelinks, TiddlyMap]
|
|
||||||
|
|
||||||
### Desktop (please complete the following information):
|
|
||||||
|
|
||||||
- OS: [e.g. iOS]
|
|
||||||
- Browser [e.g. chrome, safari]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
|
|
||||||
### Smartphone (please complete the following information):
|
|
||||||
|
|
||||||
- Device: [e.g. iPhone6]
|
|
||||||
- OS: [e.g. iOS8.1]
|
|
||||||
- Browser [e.g. stock browser, safari]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: Context
|
|
||||||
attributes:
|
|
||||||
label: Additional context
|
|
||||||
description: Add any other context about the problem here.
|
|
||||||
10
.github/ISSUE_TEMPLATE/feature_request.md
vendored
10
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -4,17 +4,23 @@ about: Suggest an idea for TiddlyWiki 5
|
|||||||
title: "[IDEA]"
|
title: "[IDEA]"
|
||||||
labels: ''
|
labels: ''
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
type: idea
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
**Is your idea related to a problem? Please describe.**
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
A clear and concise description of what the problem is. Eg:
|
||||||
|
As a user, I would like [...]
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
**Describe the solution you'd like**
|
||||||
|
|
||||||
A clear and concise description of what you want to happen.
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
**Describe alternatives you've considered**
|
||||||
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|||||||
2
.github/workflows/pr-check-build-size.yml
vendored
2
.github/workflows/pr-check-build-size.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: build-size-check
|
- name: build-size-check
|
||||||
id: get_sizes
|
id: get_sizes
|
||||||
uses: TiddlyWiki/cerebrus@v4
|
uses: TiddlyWiki/cerebrus@v6
|
||||||
with:
|
with:
|
||||||
pr_number: ${{ github.event.pull_request.number }}
|
pr_number: ${{ github.event.pull_request.number }}
|
||||||
repo: ${{ github.repository }}
|
repo: ${{ github.repository }}
|
||||||
|
|||||||
2
.github/workflows/pr-comment-build-size.yml
vendored
2
.github/workflows/pr-comment-build-size.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Build and check size
|
- name: Build and check size
|
||||||
uses: TiddlyWiki/cerebrus@v4
|
uses: TiddlyWiki/cerebrus@v6
|
||||||
with:
|
with:
|
||||||
pr_number: ${{ inputs.pr_number }}
|
pr_number: ${{ inputs.pr_number }}
|
||||||
repo: ${{ github.repository }}
|
repo: ${{ github.repository }}
|
||||||
|
|||||||
18
.github/workflows/pr-path-validation.yml
vendored
18
.github/workflows/pr-path-validation.yml
vendored
@@ -1,18 +0,0 @@
|
|||||||
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 }}
|
|
||||||
37
.github/workflows/pr-validation.yml
vendored
Normal file
37
.github/workflows/pr-validation.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: PR Validation
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened, reopened, synchronize]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
issues: write
|
||||||
|
jobs:
|
||||||
|
validate-pr:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Step 1: Validate PR paths
|
||||||
|
- name: Validate PR Paths
|
||||||
|
uses: TiddlyWiki/cerebrus@v6
|
||||||
|
with:
|
||||||
|
pr_number: ${{ github.event.pull_request.number }}
|
||||||
|
repo: ${{ github.repository }}
|
||||||
|
base_ref: ${{ github.event.pull_request.base.ref }}
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
mode: rules
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
# Step 2: Validate change notes
|
||||||
|
- name: Validate Change Notes
|
||||||
|
uses: TiddlyWiki/cerebrus@v6
|
||||||
|
with:
|
||||||
|
pr_number: ${{ github.event.pull_request.number }}
|
||||||
|
repo: ${{ github.repository }}
|
||||||
|
base_ref: ${{ github.event.pull_request.base.ref }}
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
mode: changenotes
|
||||||
|
continue-on-error: false
|
||||||
|
|
||||||
82
boot/boot.js
82
boot/boot.js
@@ -8,6 +8,8 @@ On the server this file is executed directly to boot TiddlyWiki. In the browser,
|
|||||||
|
|
||||||
\*/
|
\*/
|
||||||
|
|
||||||
|
/* eslint-disable @stylistic/indent */
|
||||||
|
|
||||||
var _boot = (function($tw) {
|
var _boot = (function($tw) {
|
||||||
|
|
||||||
/*jslint node: true, browser: true */
|
/*jslint node: true, browser: true */
|
||||||
@@ -44,12 +46,8 @@ $tw.utils.hop = function(object,property) {
|
|||||||
return object ? Object.prototype.hasOwnProperty.call(object,property) : false;
|
return object ? Object.prototype.hasOwnProperty.call(object,property) : false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/** @deprecated Use Array.isArray instead */
|
||||||
Determine if a value is an array
|
$tw.utils.isArray = value => Array.isArray(value);
|
||||||
*/
|
|
||||||
$tw.utils.isArray = function(value) {
|
|
||||||
return Object.prototype.toString.call(value) == "[object Array]";
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if an array is equal by value and by reference.
|
Check if an array is equal by value and by reference.
|
||||||
@@ -128,35 +126,22 @@ $tw.utils.pushTop = function(array,value) {
|
|||||||
return array;
|
return array;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/** @deprecated Use instanceof Date instead */
|
||||||
Determine if a value is a date
|
$tw.utils.isDate = value => value instanceof Date;
|
||||||
*/
|
|
||||||
$tw.utils.isDate = function(value) {
|
|
||||||
return Object.prototype.toString.call(value) === "[object Date]";
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/** @deprecated Use array iterative methods instead */
|
||||||
Iterate through all the own properties of an object or array. Callback is invoked with (element,title,object)
|
|
||||||
*/
|
|
||||||
$tw.utils.each = function(object,callback) {
|
$tw.utils.each = function(object,callback) {
|
||||||
var next,f,length;
|
|
||||||
if(object) {
|
if(object) {
|
||||||
if(Object.prototype.toString.call(object) == "[object Array]") {
|
if(Array.isArray(object)) {
|
||||||
for(f=0, length=object.length; f<length; f++) {
|
object.every((element,index,array) => {
|
||||||
next = callback(object[f],f,object);
|
const next = callback(element,index,array);
|
||||||
if(next === false) {
|
return next !== false;
|
||||||
break;
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
var keys = Object.keys(object);
|
Object.entries(object).every(entry => {
|
||||||
for(f=0, length=keys.length; f<length; f++) {
|
const next = callback(entry[1], entry[0], object);
|
||||||
var key = keys[f];
|
return next !== false;
|
||||||
next = callback(object[key],key,object);
|
});
|
||||||
if(next === false) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -331,32 +316,13 @@ $tw.utils.htmlDecode = function(s) {
|
|||||||
return s.toString().replace(/</mg,"<").replace(/ /mg,"\xA0").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&");
|
return s.toString().replace(/</mg,"<").replace(/ /mg,"\xA0").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&");
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/** @deprecated Use window.location.hash instead. */
|
||||||
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
|
$tw.utils.getLocationHash = () => window.location.hash;
|
||||||
*/
|
|
||||||
$tw.utils.getLocationHash = function() {
|
|
||||||
var href = window.location.href;
|
|
||||||
var idx = href.indexOf('#');
|
|
||||||
if(idx === -1) {
|
|
||||||
return "#";
|
|
||||||
} else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") {
|
|
||||||
// Special case: ignore location hash if it itself starts with a #
|
|
||||||
return "#";
|
|
||||||
} else {
|
|
||||||
return href.substring(idx);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/** @deprecated Pad a string to a given length with "0"s. Length defaults to 2 */
|
||||||
Pad a string to a given length with "0"s. Length defaults to 2
|
$tw.utils.pad = function(value,length = 2) {
|
||||||
*/
|
const s = value.toString();
|
||||||
$tw.utils.pad = function(value,length) {
|
return s.padStart(length, "0");
|
||||||
length = length || 2;
|
|
||||||
var s = value.toString();
|
|
||||||
if(s.length < length) {
|
|
||||||
s = "000000000000000000000000000".substr(0,length - s.length) + s;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert a date into UTC YYYYMMDDHHMMSSmmm format
|
// Convert a date into UTC YYYYMMDDHHMMSSmmm format
|
||||||
@@ -630,7 +596,7 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
|
|||||||
// Compile the code into a function
|
// Compile the code into a function
|
||||||
var fn;
|
var fn;
|
||||||
if($tw.browser) {
|
if($tw.browser) {
|
||||||
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
|
fn = window["eval"](code + "\n\n//# sourceURL=" + filename); // eslint-disable-line no-eval -- See https://github.com/TiddlyWiki/TiddlyWiki5/issues/6839
|
||||||
} else {
|
} else {
|
||||||
if(sandbox){
|
if(sandbox){
|
||||||
fn = vm.runInContext(code,sandbox,filename)
|
fn = vm.runInContext(code,sandbox,filename)
|
||||||
@@ -2801,6 +2767,8 @@ return $tw;
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* eslint-enable @stylistic/indent */
|
||||||
|
|
||||||
if(typeof(exports) !== "undefined") {
|
if(typeof(exports) !== "undefined") {
|
||||||
exports.TiddlyWiki = _boot;
|
exports.TiddlyWiki = _boot;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ See Boot.js for further details of the boot process.
|
|||||||
|
|
||||||
\*/
|
\*/
|
||||||
|
|
||||||
|
/* eslint-disable @stylistic/indent */
|
||||||
|
|
||||||
var _bootprefix = (function($tw) {
|
var _bootprefix = (function($tw) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -114,6 +116,8 @@ return $tw;
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* eslint-enable @stylistic/indent */
|
||||||
|
|
||||||
if(typeof(exports) === "undefined") {
|
if(typeof(exports) === "undefined") {
|
||||||
// Set up $tw global for the browser
|
// Set up $tw global for the browser
|
||||||
window.$tw = _bootprefix(window.$tw);
|
window.$tw = _bootprefix(window.$tw);
|
||||||
|
|||||||
14
community/people/ChristianByron.tid
Normal file
14
community/people/ChristianByron.tid
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
title: @Christian_Byron
|
||||||
|
tags: Community/Person
|
||||||
|
fullname: Christian Byron
|
||||||
|
talk.tiddlywiki.org: Christian_Byron
|
||||||
|
github: ceebeetree
|
||||||
|
linkedin: www.linkedin.com/in/christian-byron-b84a594/
|
||||||
|
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAuAAEBAAMBAAAAAAAAAAAAAAAHBgEDBQQBAAMBAAAAAAAAAAAAAAAAAAABAwX/2gAMAwEAAhADEAAAADv2xtJlY03sqePW3ARS1RSydIhcH//EACcQAAICAgIBAgYDAAAAAAAAAAECAwQFEQASMRMhBhBBk8HRIzJx/9oACAEBAAE/AMFQxs+NExqJLMCwYE+SOT4bF3qr+hAIpRsDQ6lWH0Yco4S/eVniRVQHXZzrZ5dwGQpQtNII2RfJVvHMRl5cbKxC94n/ALp+RxfiKpNcgMMUqPIwjcnWip/I5XtUowaL3Ujir/xt79Glb6/4OZ7MV5oEpUzuIa7MPB14A5jpoYLsEsydo1bbLre+CWEEEYab7Uf74ZYSSThpvtR/vmRmhnuzywp1jZtquta+VPM49qlcy24lf017At7g8uZnHrUsGK3Ez+m3UBvcnXy//8QAHhEAAgEFAAMAAAAAAAAAAAAAAQIDAAQRIkEyUaH/2gAIAQIBAT8AmiuVlZkLEeQOflJPcvMAF0z65V+h0YIW52rBDuxUrztf/8QAIxEBAAEDAwMFAAAAAAAAAAAAAgEAAxEEBSMSQcEiMVJxof/aAAgBAwEBPwC/Z1ZvNBOYz1Gc/lDUat3ySPRM/H2P3W4hcbIldpxnxW3BcjQk9oznzX//2Q==
|
||||||
|
|
||||||
|
Hello ~TiddlyWikiers - I have been a long time fan, recent contributor to the TW community.
|
||||||
|
Recently I have volunteered to run the [[TiddlyWiki Newsletter|https://tiddlywiki.substack.com/]] to spread the great news about TW.
|
||||||
|
|
||||||
|
I have been in the IT industry for about thirty years, mostly as a consultant and technical arcitect.
|
||||||
|
More recently I went back to study a masters in IT focussing on AI and data science.
|
||||||
|
Now my partner and I have started our own business ([[Sphere Innovations|https://sphere-innovations.com.au]]) - in consulting and building web applications for small to medium size businesses here in Australia.
|
||||||
19
community/people/LinOnetwo.tid
Normal file
19
community/people/LinOnetwo.tid
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
avatar: /9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAgICAgJCAkKCgkNDgwODRMREBARExwUFhQWFBwrGx8bGx8bKyYuJSMlLiZENS8vNUROQj5CTl9VVV93cXecnNEBCAgICAkICQoKCQ0ODA4NExEQEBETHBQWFBYUHCsbHxsbHxsrJi4lIyUuJkQ1Ly81RE5CPkJOX1VVX3dxd5yc0f/CABEIACAAIAMBIgACEQEDEQH/xAAuAAEAAwEBAAAAAAAAAAAAAAAGAwQHAgUBAAMBAAAAAAAAAAAAAAAAAAACAwT/2gAMAwEAAhADEAAAAOfCWAMdKKetM4wOvY5OcvZnrYf/xAApEAACAQQBBAECBwAAAAAAAAABAgMABAURQQYSIVETFCIxMkJicYKh/9oACAEBAAE/AEtysaStr7mPaPeuazWdMM4gEnfPryW8hBUuZvou2RXRxyreBWPmgyNqs8f8MOQalhdY7Vz+R4/s/qfP+1edNi/zl7HDcFbmS3E8CcMR4INP0PkBhklIm+sZNtFtQiV0nj57Owl+dSrSTFgD6/CtH4VV9lU3oAbPngAVY389lc5URuUZkMxhnR4pvW0VwDqsP1FNmLWYqCpikMbngmliJNY+aKzyTxXS6lRAyg/u5rq+5x2RsuyTa3MQMlvKniRGThTUd1JYXUdzAwDvqVxGdRXMbfrVOD7HBrG3mNEsU8z98TRhl9eRzX//xAAcEQACAgIDAAAAAAAAAAAAAAABAgARAzESIVH/2gAIAQIBAT8ARuXZPsul3Eoje5lBQWBP/8QAGREAAwEBAQAAAAAAAAAAAAAAAAECEiER/9oACAEDAQE/AM98Lk7LJe20z//Z
|
||||||
|
created: 20251110102157310
|
||||||
|
first-sighting: 2019-03-01
|
||||||
|
fullname: Lin Onetwo
|
||||||
|
github: linonetwo
|
||||||
|
homepage: https://wiki.onetwo.website/
|
||||||
|
modified: 20251111184556193
|
||||||
|
tags: Community/Person Community/Team/Contributors
|
||||||
|
talk.tiddlywiki.org: linonetwo
|
||||||
|
title: @linonetwo
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
Since 2014, when I started college, I've been on a quest for a lifelong PKM tool. I cherish my life and all my experiences, and I don’t want to forget any of them. When I’m deeply focused on a task, it’s easy to lose sight of other important parts of my life—so I needed a system to help me stay balanced.
|
||||||
|
|
||||||
|
Early on, I tried TiddlyWiki several times, but I was initially put off by its save mechanism and markup editing. That changed when I discovered an auto-backup script, which gave me the confidence to fully commit. Over time, I improved the script and eventually transitioned to using TidGi-Desktop and TidGi-Mobile.
|
||||||
|
|
||||||
|
Today, my TiddlyWiki holds all my game design ideas and progress logs—it has truly become my second brain. With the help of LLM-powered programming tools, I’ve enhanced it with numerous plugins, allowing me to manage my mind in a more programmable and structured way. As a game developer, TiddlyWiki isn't the core of my professional work; But I've invested so much time because it's fundamentally about upgrading my mind.
|
||||||
|
|
||||||
|
Most of my notes are open by default and shared publicly on my homepage as a digital garden.
|
||||||
25
community/people/PMario.tid
Normal file
25
community/people/PMario.tid
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
avatar: UklGRiwIAABXRUJQVlA4WAoAAAAwAAAAPwAAPwAASUNDUCACAAAAAAIgbGNtcwRAAABtbnRyR1JBWVhZWiAH6QALAAoACwADAAZhY3NwTVNGVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZkZXNjAAAAzAAAAG5jcHJ0AAABPAAAADZ3dHB0AAABdAAAABRrVFJDAAABiAAAACBkbW5kAAABqAAAACRkbWRkAAABzAAAAFJtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAFIAAAAcAEcASQBNAFAAIABiAHUAaQBsAHQALQBpAG4AIABEADYANQAgAEcAcgBhAHkAcwBjAGEAbABlACAAdwBpAHQAaAAgAHMAUgBHAEIAIABUAFIAQwAAbWx1YwAAAAAAAAABAAAADGVuVVMAAAAaAAAAHABQAHUAYgBsAGkAYwAgAEQAbwBtAGEAaQBuAABYWVogAAAAAAAA81EAAQAAAAEWzHBhcmEAAAAAAAMAAAACZmYAAPKnAAANWQAAE9AAAApbbWx1YwAAAAAAAAABAAAADGVuVVMAAAAIAAAAHABHAEkATQBQbWx1YwAAAAAAAAABAAAADGVuVVMAAAA2AAAAHABEADYANQAgAEcAcgBhAHkAcwBjAGEAbABlACAAdwBpAHQAaAAgAHMAUgBHAEIAIABUAFIAQwAAVlA4TOYFAAAvP8APEDWGgbRtWv+yt/0WImICOBvWn1C4dFi1bStbvpY8Qg2ePANNNAMh3N2db/7A91/7CHBvBBRr25ZFH+4k98ihkqi2CP4tsANvX8a+8y8Ct04dn0nuUt39ZiBJkowqt911M+MJ1G3bNiZJr1iP0DZ+2bbdadsqprOjAqmoUIX9hf3Fl5/uPYV7I3OMeoFzIvrvwG0kRUr3zPLdYMMXaqrMMsp0K4fufKO6c2hFV5Zh7kRROZX0PSCmB/3KWQwpuiekWelSRZDW94d0q750NrxavpFn1eLNQ9EV8nWlmAET6Q8lrCRTcjFLlLImluK3iXJW/hT47KGklS8OlzWUtXLFYDRCSS74ojUjxggqKMoxd6A1lTCyvsvyzC5/d7BsCHb7yIcHyrX2yR/NPnsAdRT2i0Pwp/o0Il6ix8hsRAuJmQgcr4KREfAiMgUVm9KqmfSxL5pOJspVwwTiV6jiIAg1RMhHpERhbvwgGI34Hc49T7UeKZtXwEqJ+BAaoBneperJH0POs1u4dufwv8Gf+qcOfjyvX6ZIVgxE0Rw87YF3BSc9c7jsXfdjOBG7FwmSb39pfGRwu8IuvUjJNoTpFzkEvDg6W3Qt/9nf99ZXPy8HM43IweTKyNR+WVatXcWWyakBksj9cqW+QetplcjsKElvZH/zuOO/PrCx//tL3/6x/O/C1PZZvSKuulLcS4l8M1ewGPR6ef5sllXW2eGQZ7hVSEZiPmcqrSS8e2ElX8o7t1fvB9LFetmEx5hx1Xuye2PpfjZnSjj7QfKTB3bZZo05Zvh6YuivX24cpc8+ddvADWG9odrSwFalVurxUiidDHmTiaoNkkh2gjbcpxMiAbd39aVP119/N9k4+euNKfcNjwaPhZEuUupUsJrHchw1LkPrRC9bQKa3M8Mj/xx903drdnHMpbirj1ENsUre0oo3N+7gat+2ZctKdsIUYc21sRu+Ucdhn+P7DyarftW00iu3Tmbv+hTfdCTmyaIPT4PrYZDFtBN2W8S9m4oTB5Z2P3Oe7weKjVBq86kXX/r0+WuvTAzfjqm1hsYRPWlbxm4n3IaeGOJEizv8orH9w5ejjmSrfOuEq/HxT6eDemtsZ/HTvvG1/8iVspxZILrlkz/cdsIbIroOgJileFSty2xiHNW5t9fbHJ3ze87bp5T9vc8RuqMB0ReDSt464R/BJxspvgpEsrVAJMTsYg2QovPTOHrvQ9et/S2Xx+40z7dY4JBX0Pz/ElH/T73U2DkK8EiqC9hM/zV3frQfzjaAqO16s1l6xCUXnBFlYxyIer3eEdth7u5xsHKxWoGLqzY3wIULt9G3K6soei9jZ+UcF+Ka3M/II9EUWrJ/LLxy+Q9xIh0vOl3NZCrVnBsuFUTOSnJnSioRWZ9q4g+ZDk5XVORoW2qX2hbIkna3JOrdR3jmpHVLovUkLES6grRO010u0GkDlX7SpH1DQ64Wl2zaSUJv1Mtti2G7kx5IyftWMhfDlGClcxvIUhP5crhp9LIb1Vne187oSAWxelcR/kXjYQTZboW+Oj1pqF0gmfZhSDD6bSgzGWrw3s7QLNtCV+2uatYrd/aFtjDI8R52e/DdyKgRKXBhEak3Ev50+GCUA9EFUor39htVMxmWvW8AM6ptG416rZvdWn+MarIEyH5r6ruZSrx8XrWDP370vbfTjqpmZGIbiFPFoihc4jcrlYi9p3ndSuymZ+XLaKza/P/HUWHn5Axdkd9OjBskY0+pIlz4AlFPFs+aStK5PBIRR4MVVJDihsy4JdEA4pVcrVqMZDyL2/8aYocikEAR9Xjc1BNG9zEiJG7n/cGyrtnblkClBhEgMW4Kx21BEBGJjLa0hcOGmTK64KsKLfKr9QyQELclxY3hqowTIZKdZNTSS5BWiBPlKxDWBVSS41bOepkhTkhGDajLfLyUBOKlkMHPgOhx3JoRN/cEiRgSWdgF2yCyDQu4IcbNo8ftTzxveOJ5y+h509h52+h549h569h587/M20f/b1AB
|
||||||
|
created: 20251110102157310
|
||||||
|
first-sighting: 2009-11-14
|
||||||
|
fullname: Mario Pietsch
|
||||||
|
github: pmario
|
||||||
|
homepage: https://wikilabs.github.io/
|
||||||
|
modified: 20251110124935183
|
||||||
|
tags: Community/Person Community/Team/Contributors
|
||||||
|
talk.tiddlywiki.org: pmario
|
||||||
|
title: @pmario
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
youtube: https://www.youtube.com/@pmario
|
||||||
|
|
||||||
|
''Hi, My name is Mario Pietsch''. Back in 2009 I was ''searching'' for ''a simple presentation tool'' and discovered ~TiddlyWiki Classic, Monkey Pirate ~TiddlyWiki ([[MPTW|https://mptw.tiddlyspot.com/]]) with ~TagglyTagging, Eric Shulman's ~TiddlyTools, Saq Imtiaz's navigation macros, and more. --- ''I was captivated''.
|
||||||
|
|
||||||
|
After a deep dive, I combined these elements into my own "Presentation Manager", along [[3 step by step tutorials|https://groups.google.com/g/tiddlywiki/c/qG_tZ1x0MEU/m/-vLA0luMicYJ]] to help others build it.
|
||||||
|
|
||||||
|
Thanks to ''the positive spirit'' of the ~TiddlyWiki community, I am proud to be part of it since 2009.
|
||||||
|
|
||||||
|
When Jeremy started developing ~TiddlyWiki 5 on ~GitHub, I joined in—opening [[issue no. 1|https://github.com/TiddlyWiki/TiddlyWiki5/issues/1]] all the way up to 13. For what that’s good ;) Since then, I have submitted nearly 600 pull requests and more than 500 issues, many of which have been merged or resolved.
|
||||||
|
|
||||||
|
My ~TiddlyWiki 5 "laboratory" is at https://wikilabs.github.io, and I also share content on my ''~YouTube'' channel: https://www.youtube.com/@pmario
|
||||||
|
|
||||||
|
Have fun!<br>
|
||||||
|
Mario
|
||||||
19
community/project/teams/Developer Experience Team.tid
Normal file
19
community/project/teams/Developer Experience Team.tid
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
title: Developer Experience Team
|
||||||
|
tags: Community/Team
|
||||||
|
modified: 20251109200632671
|
||||||
|
created: 20251109200632671
|
||||||
|
leader: @pmario
|
||||||
|
team: @saqimtiaz
|
||||||
|
|
||||||
|
The Developer Experience Team improves the experience of software contributors to the TiddlyWiki project. This includes enhancing documentation, streamlining contribution processes, and providing tools and resources to help developers effectively contribute to TiddlyWiki.
|
||||||
|
|
||||||
|
Tools and resources managed by the Developer Experience Team include:
|
||||||
|
|
||||||
|
* Advising and assisting contributors, particularly new developers
|
||||||
|
* Maintenance of developer-focused documentation on the https://tiddlywiki.com/dev/ site, including:
|
||||||
|
** Development environment setup guides
|
||||||
|
** Code review processes and best practices
|
||||||
|
** Contribution guidelines and documentation
|
||||||
|
* Continuous integration and deployment scripts providing feedback on pull requests
|
||||||
|
* Devising and implementing labelling systems for issues and pull requests
|
||||||
|
* Automation scripts to simplify common development tasks
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
title: Infrastructure Team
|
|
||||||
tags: Community/Team
|
|
||||||
modified: 20250909171928024
|
|
||||||
created: 20250909171928024
|
created: 20250909171928024
|
||||||
|
modified: 20251110133437795
|
||||||
|
tags: Community/Team
|
||||||
team: @MotovunJack
|
team: @MotovunJack
|
||||||
|
title: Infrastructure Team
|
||||||
|
|
||||||
The Infrastructure Team is responsible for maintaining and improving the infrastructure that supports the TiddlyWiki project. This includes the hosting, deployment, and management of the TiddlyWiki websites and services, as well as the tools and systems used by the TiddlyWiki community.
|
The Infrastructure Team is responsible for maintaining and improving the infrastructure that supports the TiddlyWiki project. This includes the hosting, deployment, and management of the TiddlyWiki websites and services, as well as the tools and systems used by the TiddlyWiki community.
|
||||||
|
|
||||||
@@ -12,3 +12,4 @@ The infrastructure includes:
|
|||||||
* github.com/TiddlyWiki
|
* github.com/TiddlyWiki
|
||||||
* tiddlywiki.com DNS
|
* tiddlywiki.com DNS
|
||||||
* Netlify account for PR previews
|
* Netlify account for PR previews
|
||||||
|
* edit.tiddlywiki.com
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
title: Newsletter Team
|
|
||||||
tags: Community/Team
|
|
||||||
modified: 20250909171928024
|
|
||||||
created: 20250909171928024
|
|
||||||
|
|
||||||
The Newsletter Team is responsible for producing the TiddlyWiki Newsletter, a monthly email newsletter that highlights news, updates, and community contributions related to TiddlyWiki.
|
|
||||||
11
community/project/teams/Quality Assurance Team.tid
Normal file
11
community/project/teams/Quality Assurance Team.tid
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
title: Quality Assurance Team
|
||||||
|
created: 20251112125742296
|
||||||
|
modified: 20251112125742296
|
||||||
|
tags: Community/Team
|
||||||
|
team:
|
||||||
|
leader: @Leilei332
|
||||||
|
|
||||||
|
title: Quality Assurance Team
|
||||||
|
|
||||||
|
The Quality Assurance Team is responsible for ensuring the quality and reliability of TiddlyWiki releases. This includes reviewing code submissions, testing new features, identifying bugs, and verifying that fixes are effective.
|
||||||
|
|
||||||
15
community/project/teams/TiddlyWiki Newsletter Team.tid
Normal file
15
community/project/teams/TiddlyWiki Newsletter Team.tid
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
title: TiddlyWiki Newsletter Team
|
||||||
|
tags: Community/Team
|
||||||
|
modified: 20251219090709874
|
||||||
|
created: 20250909171928024
|
||||||
|
leader: @Christian_Byron
|
||||||
|
|
||||||
|
The Newsletter Team is responsible for producing the [[TiddlyWiki Newsletter]]. We would love to have your help if you would like to get involved.
|
||||||
|
|
||||||
|
! Audience
|
||||||
|
|
||||||
|
The newsletter is intended for TiddlyWiki end users who do not track all the discussions on https://talk.tiddlywiki.org/.
|
||||||
|
|
||||||
|
Coverage of developer topics such as JavaScript and intricate wikitext should be handled thoughtfully to avoid alienating the core audience of end users.
|
||||||
|
|
||||||
|
Subscribing to the newsletter is intended to give people confidence that they will not miss any important developments.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
title: Community/Team
|
title: Community/Team
|
||||||
modified: 20250909171928024
|
modified: 20250909171928024
|
||||||
created: 20250909171928024
|
created: 20250909171928024
|
||||||
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Infrastructure Team]] [[Succession Team]]
|
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[Quality Assurance Team]] [[Infrastructure Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Succession Team]]
|
||||||
|
|
||||||
|
|||||||
30
core-server/utils/base64.js
Normal file
30
core-server/utils/base64.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core-modules/modules/utils/base64.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: utils-node
|
||||||
|
|
||||||
|
Base64 UTF-8 utlity functions.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const{ TextEncoder, TextDecoder } = require("node:util");
|
||||||
|
|
||||||
|
exports.btoa = binstr => Buffer.from(binstr, "binary").toString("base64");
|
||||||
|
|
||||||
|
exports.atob = b64 => Buffer.from(b64, "base64").toString("binary");
|
||||||
|
|
||||||
|
function base64ToBytes(base64) {
|
||||||
|
const binString = exports.atob(base64);
|
||||||
|
return Uint8Array.from(binString, m => m.codePointAt(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
function bytesToBase64(bytes) {
|
||||||
|
const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join("");
|
||||||
|
return exports.btoa(binString);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.base64EncodeUtf8 = str => bytesToBase64(new TextEncoder().encode(str));
|
||||||
|
|
||||||
|
exports.base64DecodeUtf8 = str => new TextDecoder().decode(base64ToBytes(str));
|
||||||
95
core-server/utils/escapecss.js
Normal file
95
core-server/utils/escapecss.js
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core-server/modules/utils/escapecss.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: utils-node
|
||||||
|
|
||||||
|
Provides CSS.escape() functionality.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.escapeCSS = (function() {
|
||||||
|
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
||||||
|
return function(value) {
|
||||||
|
if (arguments.length == 0) {
|
||||||
|
throw new TypeError('`CSS.escape` requires an argument.');
|
||||||
|
}
|
||||||
|
var string = String(value);
|
||||||
|
var length = string.length;
|
||||||
|
var index = -1;
|
||||||
|
var codeUnit;
|
||||||
|
var result = '';
|
||||||
|
var firstCodeUnit = string.charCodeAt(0);
|
||||||
|
while (++index < length) {
|
||||||
|
codeUnit = string.charCodeAt(index);
|
||||||
|
// Note: there’s no need to special-case astral symbols, surrogate
|
||||||
|
// pairs, or lone surrogates.
|
||||||
|
|
||||||
|
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
|
||||||
|
// (U+FFFD).
|
||||||
|
if (codeUnit == 0x0000) {
|
||||||
|
result += '\uFFFD';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
||||||
|
// U+007F, […]
|
||||||
|
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
|
||||||
|
// If the character is the first character and is in the range [0-9]
|
||||||
|
// (U+0030 to U+0039), […]
|
||||||
|
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
||||||
|
// If the character is the second character and is in the range [0-9]
|
||||||
|
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
||||||
|
(
|
||||||
|
index == 1 &&
|
||||||
|
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
||||||
|
firstCodeUnit == 0x002D
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
|
||||||
|
result += '\\' + codeUnit.toString(16) + ' ';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
// If the character is the first character and is a `-` (U+002D), and
|
||||||
|
// there is no second character, […]
|
||||||
|
index == 0 &&
|
||||||
|
length == 1 &&
|
||||||
|
codeUnit == 0x002D
|
||||||
|
) {
|
||||||
|
result += '\\' + string.charAt(index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the character is not handled by one of the above rules and is
|
||||||
|
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
|
||||||
|
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
|
||||||
|
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
||||||
|
if (
|
||||||
|
codeUnit >= 0x0080 ||
|
||||||
|
codeUnit == 0x002D ||
|
||||||
|
codeUnit == 0x005F ||
|
||||||
|
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
||||||
|
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
||||||
|
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
||||||
|
) {
|
||||||
|
// the character itself
|
||||||
|
result += string.charAt(index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, the escaped character.
|
||||||
|
// https://drafts.csswg.org/cssom/#escape-a-character
|
||||||
|
result += '\\' + string.charAt(index);
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
/* eslint-enable */
|
||||||
|
})();
|
||||||
@@ -5,3 +5,4 @@ TiddlyWiki incorporates code from these fine OpenSource projects:
|
|||||||
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
|
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
|
||||||
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
|
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
|
||||||
* [[modern-normalize by Sindre Sorhus|https://github.com/sindresorhus/modern-normalize]]
|
* [[modern-normalize by Sindre Sorhus|https://github.com/sindresorhus/modern-normalize]]
|
||||||
|
* [[diff-match-patch-es by antfu|https://github.com/antfu/diff-match-patch-es]]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
title: $:/language/
|
title: $:/language/
|
||||||
|
|
||||||
|
Alerts: Alerts
|
||||||
AboveStory/ClassicPlugin/Warning: It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|https://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected:
|
AboveStory/ClassicPlugin/Warning: It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|https://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected:
|
||||||
BinaryWarning/Prompt: This tiddler contains binary data
|
BinaryWarning/Prompt: This tiddler contains binary data
|
||||||
ClassicWarning/Hint: This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See https://tiddlywiki.com/static/Upgrading.html for more details.
|
ClassicWarning/Hint: This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See https://tiddlywiki.com/static/Upgrading.html for more details.
|
||||||
|
|||||||
@@ -156,8 +156,8 @@ Fix the height of textarea to fit content
|
|||||||
FramedEngine.prototype.fixHeight = function() {
|
FramedEngine.prototype.fixHeight = function() {
|
||||||
// Make sure styles are updated
|
// Make sure styles are updated
|
||||||
this.copyStyles();
|
this.copyStyles();
|
||||||
// Adjust height
|
// If .editRows is initialised, it takes precedence
|
||||||
if(this.widget.editTag === "textarea") {
|
if(this.widget.editTag === "textarea" && !this.widget.editRows) {
|
||||||
if(this.widget.editAutoHeight) {
|
if(this.widget.editAutoHeight) {
|
||||||
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
|
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
|
||||||
var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
|
var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ SimpleEngine.prototype.getText = function() {
|
|||||||
Fix the height of textarea to fit content
|
Fix the height of textarea to fit content
|
||||||
*/
|
*/
|
||||||
SimpleEngine.prototype.fixHeight = function() {
|
SimpleEngine.prototype.fixHeight = function() {
|
||||||
if(this.widget.editTag === "textarea") {
|
// If .editRows is initialised, it takes precedence
|
||||||
|
if((this.widget.editTag === "textarea") && !this.widget.editRows) {
|
||||||
if(this.widget.editAutoHeight) {
|
if(this.widget.editAutoHeight) {
|
||||||
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
|
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
|
||||||
$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
|
$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
|
||||||
|
|||||||
41
core/modules/filterrunprefixes/let.js
Normal file
41
core/modules/filterrunprefixes/let.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/filterrunprefixes/let.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: filterrunprefix
|
||||||
|
|
||||||
|
Assign a value to a variable
|
||||||
|
|
||||||
|
\*/
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Export our filter prefix function
|
||||||
|
*/
|
||||||
|
exports.let = function(operationSubFunction,options) {
|
||||||
|
// Return the filter run prefix function
|
||||||
|
return function(results,source,widget) {
|
||||||
|
// Save the result list
|
||||||
|
var resultList = results.toArray();
|
||||||
|
// Clear the results
|
||||||
|
results.clear();
|
||||||
|
// Evaluate the subfunction to get the variable name
|
||||||
|
var subFunctionResults = operationSubFunction(source,widget);
|
||||||
|
if(subFunctionResults.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var name = subFunctionResults[0];
|
||||||
|
if(typeof name !== "string" || name.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Assign the result of the subfunction to the variable
|
||||||
|
var variables = {};
|
||||||
|
variables[name] = resultList;
|
||||||
|
// Return the variables
|
||||||
|
return {
|
||||||
|
variables: variables
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -35,7 +35,7 @@ function parseFilterOperation(operators,filterString,p) {
|
|||||||
operator.prefix = filterString.charAt(p++);
|
operator.prefix = filterString.charAt(p++);
|
||||||
}
|
}
|
||||||
// Get the operator name
|
// Get the operator name
|
||||||
nextBracketPos = filterString.substring(p).search(/[\[\{<\/]/);
|
nextBracketPos = filterString.substring(p).search(/[\[\{<\/\(]/);
|
||||||
if(nextBracketPos === -1) {
|
if(nextBracketPos === -1) {
|
||||||
throw "Missing [ in filter expression";
|
throw "Missing [ in filter expression";
|
||||||
}
|
}
|
||||||
@@ -79,13 +79,17 @@ function parseFilterOperation(operators,filterString,p) {
|
|||||||
operand.variable = true;
|
operand.variable = true;
|
||||||
nextBracketPos = filterString.indexOf(">",p);
|
nextBracketPos = filterString.indexOf(">",p);
|
||||||
break;
|
break;
|
||||||
|
case "(": // Round brackets
|
||||||
|
operand.multiValuedVariable = true;
|
||||||
|
nextBracketPos = filterString.indexOf(")",p);
|
||||||
|
break;
|
||||||
case "/": // regexp brackets
|
case "/": // regexp brackets
|
||||||
var rex = /^((?:[^\\\/]|\\.)*)\/(?:\(([mygi]+)\))?/g,
|
var rex = /^((?:[^\\\/]|\\.)*)\/(?:\(([mygi]+)\))?/g,
|
||||||
rexMatch = rex.exec(filterString.substring(p));
|
rexMatch = rex.exec(filterString.substring(p));
|
||||||
if(rexMatch) {
|
if(rexMatch) {
|
||||||
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
|
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
|
||||||
// DEPRECATION WARNING
|
// DEPRECATION WARNING
|
||||||
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
|
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
|
||||||
nextBracketPos = p + rex.lastIndex - 1;
|
nextBracketPos = p + rex.lastIndex - 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -112,7 +116,7 @@ function parseFilterOperation(operators,filterString,p) {
|
|||||||
// Check for multiple operands
|
// Check for multiple operands
|
||||||
while(filterString.charAt(p) === ",") {
|
while(filterString.charAt(p) === ",") {
|
||||||
p++;
|
p++;
|
||||||
if(/^[\[\{<\/]/.test(filterString.substring(p))) {
|
if(/^[\[\{<\/\(]/.test(filterString.substring(p))) {
|
||||||
nextBracketPos = p;
|
nextBracketPos = p;
|
||||||
p++;
|
p++;
|
||||||
parseOperand(filterString.charAt(nextBracketPos));
|
parseOperand(filterString.charAt(nextBracketPos));
|
||||||
@@ -141,7 +145,15 @@ exports.parseFilter = function(filterString) {
|
|||||||
p = 0, // Current position in the filter string
|
p = 0, // Current position in the filter string
|
||||||
match;
|
match;
|
||||||
var whitespaceRegExp = /(\s+)/mg,
|
var whitespaceRegExp = /(\s+)/mg,
|
||||||
operandRegExp = /((?:\+|\-|~|=|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
|
// Groups:
|
||||||
|
// 1 - entire filter run prefix
|
||||||
|
// 2 - filter run prefix itself
|
||||||
|
// 3 - filter run prefix suffixes
|
||||||
|
// 4 - opening square bracket following filter run prefix
|
||||||
|
// 5 - double quoted string following filter run prefix
|
||||||
|
// 6 - single quoted string following filter run prefix
|
||||||
|
// 7 - anything except for whitespace and square brackets
|
||||||
|
operandRegExp = /((?:\+|\-|~|(?:=>?)|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
|
||||||
while(p < filterString.length) {
|
while(p < filterString.length) {
|
||||||
// Skip any whitespace
|
// Skip any whitespace
|
||||||
whitespaceRegExp.lastIndex = p;
|
whitespaceRegExp.lastIndex = p;
|
||||||
@@ -152,38 +164,45 @@ exports.parseFilter = function(filterString) {
|
|||||||
// Match the start of the operation
|
// Match the start of the operation
|
||||||
if(p < filterString.length) {
|
if(p < filterString.length) {
|
||||||
operandRegExp.lastIndex = p;
|
operandRegExp.lastIndex = p;
|
||||||
match = operandRegExp.exec(filterString);
|
|
||||||
if(!match || match.index !== p) {
|
|
||||||
throw $tw.language.getString("Error/FilterSyntax");
|
|
||||||
}
|
|
||||||
var operation = {
|
var operation = {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
operators: []
|
operators: []
|
||||||
};
|
};
|
||||||
if(match[1]) {
|
match = operandRegExp.exec(filterString);
|
||||||
operation.prefix = match[1];
|
if(match && match.index === p) {
|
||||||
p = p + operation.prefix.length;
|
// If there is a filter run prefix
|
||||||
if(match[2]) {
|
if(match[1]) {
|
||||||
operation.namedPrefix = match[2];
|
operation.prefix = match[1];
|
||||||
}
|
p = p + operation.prefix.length;
|
||||||
if(match[3]) {
|
// Name for named prefixes
|
||||||
operation.suffixes = [];
|
if(match[2]) {
|
||||||
$tw.utils.each(match[3].split(":"),function(subsuffix) {
|
operation.namedPrefix = match[2];
|
||||||
operation.suffixes.push([]);
|
}
|
||||||
$tw.utils.each(subsuffix.split(","),function(entry) {
|
// Suffixes for filter run prefix
|
||||||
entry = $tw.utils.trim(entry);
|
if(match[3]) {
|
||||||
if(entry) {
|
operation.suffixes = [];
|
||||||
operation.suffixes[operation.suffixes.length -1].push(entry);
|
$tw.utils.each(match[3].split(":"),function(subsuffix) {
|
||||||
}
|
operation.suffixes.push([]);
|
||||||
|
$tw.utils.each(subsuffix.split(","),function(entry) {
|
||||||
|
entry = $tw.utils.trim(entry);
|
||||||
|
if(entry) {
|
||||||
|
operation.suffixes[operation.suffixes.length -1].push(entry);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
// Opening square bracket
|
||||||
|
if(match[4]) {
|
||||||
|
p = parseFilterOperation(operation.operators,filterString,p);
|
||||||
|
} else {
|
||||||
|
p = match.index + match[0].length;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(match[4]) { // Opening square bracket
|
|
||||||
p = parseFilterOperation(operation.operators,filterString,p);
|
|
||||||
} else {
|
} else {
|
||||||
p = match.index + match[0].length;
|
// No filter run prefix
|
||||||
|
p = parseFilterOperation(operation.operators,filterString,p);
|
||||||
}
|
}
|
||||||
|
// Quoted strings and unquoted title
|
||||||
if(match[5] || match[6] || match[7]) { // Double quoted string, single quoted string or unquoted title
|
if(match[5] || match[6] || match[7]) { // Double quoted string, single quoted string or unquoted title
|
||||||
operation.operators.push(
|
operation.operators.push(
|
||||||
{operator: "title", operands: [{text: match[5] || match[6] || match[7]}]}
|
{operator: "title", operands: [{text: match[5] || match[6] || match[7]}]}
|
||||||
@@ -213,7 +232,12 @@ exports.getFilterRunPrefixes = function() {
|
|||||||
|
|
||||||
exports.filterTiddlers = function(filterString,widget,source) {
|
exports.filterTiddlers = function(filterString,widget,source) {
|
||||||
var fn = this.compileFilter(filterString);
|
var fn = this.compileFilter(filterString);
|
||||||
return fn.call(this,source,widget);
|
try {
|
||||||
|
const fnResult = fn.call(this,source,widget);
|
||||||
|
return fnResult;
|
||||||
|
} catch(e) {
|
||||||
|
return [`${$tw.language.getString("Error/Filter")}: ${e}`];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -251,6 +275,8 @@ exports.compileFilter = function(filterString) {
|
|||||||
results = [];
|
results = [];
|
||||||
$tw.utils.each(operation.operators,function(operator) {
|
$tw.utils.each(operation.operators,function(operator) {
|
||||||
var operands = [],
|
var operands = [],
|
||||||
|
multiValueOperands = [],
|
||||||
|
isMultiValueOperand = [],
|
||||||
operatorFunction;
|
operatorFunction;
|
||||||
if(!operator.operator) {
|
if(!operator.operator) {
|
||||||
// Use the "title" operator if no operator is specified
|
// Use the "title" operator if no operator is specified
|
||||||
@@ -266,28 +292,46 @@ exports.compileFilter = function(filterString) {
|
|||||||
if(operand.indirect) {
|
if(operand.indirect) {
|
||||||
var currTiddlerTitle = widget && widget.getVariable("currentTiddler");
|
var currTiddlerTitle = widget && widget.getVariable("currentTiddler");
|
||||||
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
|
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
|
||||||
|
operand.multiValue = [operand.value];
|
||||||
} else if(operand.variable) {
|
} else if(operand.variable) {
|
||||||
var varTree = $tw.utils.parseFilterVariable(operand.text);
|
var varTree = $tw.utils.parseFilterVariable(operand.text);
|
||||||
operand.value = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source})[0] || "";
|
operand.value = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source})[0] || "";
|
||||||
|
operand.multiValue = [operand.value];
|
||||||
|
} else if(operand.multiValuedVariable) {
|
||||||
|
var varTree = $tw.utils.parseFilterVariable(operand.text);
|
||||||
|
var resultList = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source});
|
||||||
|
if((resultList.length > 0 && resultList[0] !== undefined) || resultList.length === 0) {
|
||||||
|
operand.multiValue = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source}) || [];
|
||||||
|
operand.value = operand.multiValue[0] || "";
|
||||||
|
} else {
|
||||||
|
operand.value = "";
|
||||||
|
operand.multiValue = [];
|
||||||
|
}
|
||||||
|
operand.isMultiValueOperand = true;
|
||||||
} else {
|
} else {
|
||||||
operand.value = operand.text;
|
operand.value = operand.text;
|
||||||
|
operand.multiValue = [operand.value];
|
||||||
}
|
}
|
||||||
operands.push(operand.value);
|
operands.push(operand.value);
|
||||||
|
multiValueOperands.push(operand.multiValue);
|
||||||
|
isMultiValueOperand.push(!!operand.isMultiValueOperand);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Invoke the appropriate filteroperator module
|
// Invoke the appropriate filteroperator module
|
||||||
results = operatorFunction(accumulator,{
|
results = operatorFunction(accumulator,{
|
||||||
operator: operator.operator,
|
operator: operator.operator,
|
||||||
operand: operands.length > 0 ? operands[0] : undefined,
|
operand: operands.length > 0 ? operands[0] : undefined,
|
||||||
operands: operands,
|
operands: operands,
|
||||||
prefix: operator.prefix,
|
multiValueOperands: multiValueOperands,
|
||||||
suffix: operator.suffix,
|
isMultiValueOperand: isMultiValueOperand,
|
||||||
suffixes: operator.suffixes,
|
prefix: operator.prefix,
|
||||||
regexp: operator.regexp
|
suffix: operator.suffix,
|
||||||
},{
|
suffixes: operator.suffixes,
|
||||||
wiki: self,
|
regexp: operator.regexp
|
||||||
widget: widget
|
},{
|
||||||
});
|
wiki: self,
|
||||||
|
widget: widget
|
||||||
|
});
|
||||||
if($tw.utils.isArray(results)) {
|
if($tw.utils.isArray(results)) {
|
||||||
accumulator = self.makeTiddlerIterator(results);
|
accumulator = self.makeTiddlerIterator(results);
|
||||||
} else {
|
} else {
|
||||||
@@ -319,6 +363,8 @@ exports.compileFilter = function(filterString) {
|
|||||||
return filterRunPrefixes["and"](operationSubFunction, options);
|
return filterRunPrefixes["and"](operationSubFunction, options);
|
||||||
case "~": // This operation is unioned into the result only if the main result so far is empty
|
case "~": // This operation is unioned into the result only if the main result so far is empty
|
||||||
return filterRunPrefixes["else"](operationSubFunction, options);
|
return filterRunPrefixes["else"](operationSubFunction, options);
|
||||||
|
case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable
|
||||||
|
return filterRunPrefixes["let"](operationSubFunction, options);
|
||||||
default:
|
default:
|
||||||
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
|
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
|
||||||
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
|
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
|
||||||
@@ -345,7 +391,13 @@ exports.compileFilter = function(filterString) {
|
|||||||
self.filterRecursionCount = (self.filterRecursionCount || 0) + 1;
|
self.filterRecursionCount = (self.filterRecursionCount || 0) + 1;
|
||||||
if(self.filterRecursionCount < MAX_FILTER_DEPTH) {
|
if(self.filterRecursionCount < MAX_FILTER_DEPTH) {
|
||||||
$tw.utils.each(operationFunctions,function(operationFunction) {
|
$tw.utils.each(operationFunctions,function(operationFunction) {
|
||||||
operationFunction(results,source,widget);
|
var operationResult = operationFunction(results,source,widget);
|
||||||
|
if(operationResult) {
|
||||||
|
if(operationResult.variables) {
|
||||||
|
// If the filter run prefix has returned variables, create a new fake widget with those variables
|
||||||
|
widget = widget.makeFakeWidgetWithVariables(operationResult.variables);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
results.push("/**-- Excessive filter recursion --**/");
|
results.push("/**-- Excessive filter recursion --**/");
|
||||||
|
|||||||
@@ -16,12 +16,8 @@ exports.json = function(source,operand,options) {
|
|||||||
spaces = /^\d+$/.test(operand) ? parseInt(operand,10) : operand;
|
spaces = /^\d+$/.test(operand) ? parseInt(operand,10) : operand;
|
||||||
}
|
}
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
var data = $tw.utils.parseJSONSafe(title);
|
var data = $tw.utils.parseJSONSafe(title,function(){return undefined;});
|
||||||
try {
|
|
||||||
data = JSON.parse(title);
|
|
||||||
} catch(e) {
|
|
||||||
data = undefined;
|
|
||||||
}
|
|
||||||
if(data !== undefined) {
|
if(data !== undefined) {
|
||||||
results.push(JSON.stringify(data,null,spaces));
|
results.push(JSON.stringify(data,null,spaces));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ exports.function = function(source,operator,options) {
|
|||||||
var functionName = operator.operands[0],
|
var functionName = operator.operands[0],
|
||||||
params = [],
|
params = [],
|
||||||
results;
|
results;
|
||||||
$tw.utils.each(operator.operands.slice(1),function(param) {
|
$tw.utils.each(operator.multiValueOperands.slice(1),function(paramList) {
|
||||||
params.push({value: param});
|
params.push({value: paramList[0] || "",multiValue: paramList});
|
||||||
});
|
});
|
||||||
// console.log(`Calling ${functionName} with params ${JSON.stringify(params)}`);
|
// console.log(`Calling ${functionName} with params ${JSON.stringify(params)}`);
|
||||||
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(functionName,{params: params, source: source});
|
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(functionName,{params: params, source: source});
|
||||||
|
|||||||
@@ -113,6 +113,22 @@ exports["jsonset"] = function(source,operator,options) {
|
|||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports["jsondelete"] = function(source,operator,options) {
|
||||||
|
var indexes = operator.operands,
|
||||||
|
results = [];
|
||||||
|
source(function(tiddler,title) {
|
||||||
|
var data = $tw.utils.parseJSONSafe(title,title);
|
||||||
|
// If parsing failed (data equals original title and is a string), return unchanged
|
||||||
|
if(data === title && typeof data === "string") {
|
||||||
|
results.push(title);
|
||||||
|
} else if(data) {
|
||||||
|
data = deleteDataItem(data,indexes);
|
||||||
|
results.push(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Given a JSON data structure and an array of index strings, return an array of the string representation of the values at the end of the index chain, or "undefined" if any of the index strings are invalid
|
Given a JSON data structure and an array of index strings, return an array of the string representation of the values at the end of the index chain, or "undefined" if any of the index strings are invalid
|
||||||
*/
|
*/
|
||||||
@@ -144,7 +160,7 @@ function convertDataItemValueToStrings(item) {
|
|||||||
return ["null"]
|
return ["null"]
|
||||||
} else if(typeof item === "object") {
|
} else if(typeof item === "object") {
|
||||||
var results = [],i,t;
|
var results = [],i,t;
|
||||||
if($tw.utils.isArray(item)) {
|
if(Array.isArray(item)) {
|
||||||
// Return all the items in arrays recursively
|
// Return all the items in arrays recursively
|
||||||
for(i=0; i<item.length; i++) {
|
for(i=0; i<item.length; i++) {
|
||||||
t = convertDataItemValueToStrings(item[i])
|
t = convertDataItemValueToStrings(item[i])
|
||||||
@@ -178,7 +194,7 @@ function convertDataItemKeysToStrings(item) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
var results = [];
|
var results = [];
|
||||||
if($tw.utils.isArray(item)) {
|
if(Array.isArray(item)) {
|
||||||
for(var i=0; i<item.length; i++) {
|
for(var i=0; i<item.length; i++) {
|
||||||
results.push(i.toString());
|
results.push(i.toString());
|
||||||
}
|
}
|
||||||
@@ -201,7 +217,7 @@ function getDataItemType(data,indexes) {
|
|||||||
return item;
|
return item;
|
||||||
} else if(item === null) {
|
} else if(item === null) {
|
||||||
return "null";
|
return "null";
|
||||||
} else if($tw.utils.isArray(item)) {
|
} else if(Array.isArray(item)) {
|
||||||
return "array";
|
return "array";
|
||||||
} else if(typeof item === "object") {
|
} else if(typeof item === "object") {
|
||||||
return "object";
|
return "object";
|
||||||
@@ -213,7 +229,7 @@ function getDataItemType(data,indexes) {
|
|||||||
function getItemAtIndex(item,index) {
|
function getItemAtIndex(item,index) {
|
||||||
if($tw.utils.hop(item,index)) {
|
if($tw.utils.hop(item,index)) {
|
||||||
return item[index];
|
return item[index];
|
||||||
} else if($tw.utils.isArray(item)) {
|
} else if(Array.isArray(item)) {
|
||||||
index = $tw.utils.parseInt(index);
|
index = $tw.utils.parseInt(index);
|
||||||
if(index < 0) { index = index + item.length };
|
if(index < 0) { index = index + item.length };
|
||||||
return item[index]; // Will be undefined if index was out-of-bounds
|
return item[index]; // Will be undefined if index was out-of-bounds
|
||||||
@@ -223,15 +239,16 @@ function getItemAtIndex(item,index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Given a JSON data structure and an array of index strings, return the value at the end of the index chain, or "undefined" if any of the index strings are invalid
|
Traverse the index chain and return the item at the specified depth.
|
||||||
|
Returns the item at the end of the traversal, or undefined if traversal fails.
|
||||||
*/
|
*/
|
||||||
function getDataItem(data,indexes) {
|
function traverseIndexChain(data,indexes,stopBeforeLast) {
|
||||||
if(indexes.length === 0 || (indexes.length === 1 && indexes[0] === "")) {
|
if(indexes.length === 0 || (indexes.length === 1 && indexes[0] === "")) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
// Get the item
|
|
||||||
var item = data;
|
var item = data;
|
||||||
for(var i=0; i<indexes.length; i++) {
|
var stopIndex = stopBeforeLast ? indexes.length - 1 : indexes.length;
|
||||||
|
for(var i = 0; i < stopIndex; i++) {
|
||||||
if(item !== undefined) {
|
if(item !== undefined) {
|
||||||
if(item !== null && ["number","string","boolean"].indexOf(typeof item) === -1) {
|
if(item !== null && ["number","string","boolean"].indexOf(typeof item) === -1) {
|
||||||
item = getItemAtIndex(item,indexes[i]);
|
item = getItemAtIndex(item,indexes[i]);
|
||||||
@@ -243,6 +260,13 @@ function getDataItem(data,indexes) {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Given a JSON data structure and an array of index strings, return the value at the end of the index chain, or "undefined" if any of the index strings are invalid
|
||||||
|
*/
|
||||||
|
function getDataItem(data,indexes) {
|
||||||
|
return traverseIndexChain(data,indexes,false);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Given a JSON data structure, an array of index strings and a value, return the data structure with the value added at the end of the index chain. If any of the index strings are invalid then the JSON data structure is returned unmodified. If the root item is targetted then a different data object will be returned
|
Given a JSON data structure, an array of index strings and a value, return the data structure with the value added at the end of the index chain. If any of the index strings are invalid then the JSON data structure is returned unmodified. If the root item is targetted then a different data object will be returned
|
||||||
*/
|
*/
|
||||||
@@ -255,18 +279,15 @@ function setDataItem(data,indexes,value) {
|
|||||||
if(indexes.length === 0 || (indexes.length === 1 && indexes[0] === "")) {
|
if(indexes.length === 0 || (indexes.length === 1 && indexes[0] === "")) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
// Traverse the JSON data structure using the index chain
|
// Traverse the JSON data structure using the index chain up to the parent
|
||||||
var current = data;
|
var current = traverseIndexChain(data,indexes,true);
|
||||||
for(var i = 0; i < indexes.length - 1; i++) {
|
if(current === undefined) {
|
||||||
current = getItemAtIndex(current,indexes[i]);
|
// Return the original JSON data structure if any of the index strings are invalid
|
||||||
if(current === undefined) {
|
return data;
|
||||||
// Return the original JSON data structure if any of the index strings are invalid
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Add the value to the end of the index chain
|
// Add the value to the end of the index chain
|
||||||
var lastIndex = indexes[indexes.length - 1];
|
var lastIndex = indexes[indexes.length - 1];
|
||||||
if($tw.utils.isArray(current)) {
|
if(Array.isArray(current)) {
|
||||||
lastIndex = $tw.utils.parseInt(lastIndex);
|
lastIndex = $tw.utils.parseInt(lastIndex);
|
||||||
if(lastIndex < 0) { lastIndex = lastIndex + current.length };
|
if(lastIndex < 0) { lastIndex = lastIndex + current.length };
|
||||||
}
|
}
|
||||||
@@ -276,3 +297,32 @@ function setDataItem(data,indexes,value) {
|
|||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Given a JSON data structure and an array of index strings, return the data structure with the item at the end of the index chain deleted. If any of the index strings are invalid then the JSON data structure is returned unmodified. If the root item is targetted then the JSON data structure is returned unmodified.
|
||||||
|
*/
|
||||||
|
function deleteDataItem(data,indexes) {
|
||||||
|
// Check for the root item - don't delete the root
|
||||||
|
if(indexes.length === 0 || (indexes.length === 1 && indexes[0] === "")) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
// Traverse the JSON data structure using the index chain up to the parent
|
||||||
|
var current = traverseIndexChain(data,indexes,true);
|
||||||
|
if(current === undefined || current === null) {
|
||||||
|
// Return the original JSON data structure if any of the index strings are invalid
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
// Delete the item at the end of the index chain
|
||||||
|
var lastIndex = indexes[indexes.length - 1];
|
||||||
|
if(Array.isArray(current) && current !== null) {
|
||||||
|
lastIndex = $tw.utils.parseInt(lastIndex);
|
||||||
|
if(lastIndex < 0) { lastIndex = lastIndex + current.length };
|
||||||
|
// Check if index is valid before splicing
|
||||||
|
if(lastIndex >= 0 && lastIndex < current.length) {
|
||||||
|
current.splice(lastIndex,1);
|
||||||
|
}
|
||||||
|
} else if(typeof current === "object" && current !== null) {
|
||||||
|
delete current[lastIndex];
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,31 +14,31 @@ Export our filter function
|
|||||||
*/
|
*/
|
||||||
exports.sort = function(source,operator,options) {
|
exports.sort = function(source,operator,options) {
|
||||||
var results = prepare_results(source);
|
var results = prepare_results(source);
|
||||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,false);
|
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,false,undefined,operator.operands[1]);
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.nsort = function(source,operator,options) {
|
exports.nsort = function(source,operator,options) {
|
||||||
var results = prepare_results(source);
|
var results = prepare_results(source);
|
||||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,true);
|
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,true,undefined,operator.operands[1]);
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.sortan = function(source, operator, options) {
|
exports.sortan = function(source, operator, options) {
|
||||||
var results = prepare_results(source);
|
var results = prepare_results(source);
|
||||||
options.wiki.sortTiddlers(results, operator.operand || "title", operator.prefix === "!",false,false,true);
|
options.wiki.sortTiddlers(results, operator.operands[0] || "title", operator.prefix === "!",false,false,true,operator.operands[1]);
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.sortcs = function(source,operator,options) {
|
exports.sortcs = function(source,operator,options) {
|
||||||
var results = prepare_results(source);
|
var results = prepare_results(source);
|
||||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,false);
|
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,false,undefined,operator.operands[1]);
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.nsortcs = function(source,operator,options) {
|
exports.nsortcs = function(source,operator,options) {
|
||||||
var results = prepare_results(source);
|
var results = prepare_results(source);
|
||||||
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,true);
|
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,true,undefined,operator.operands[1]);
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -37,14 +37,14 @@ exports.trim = function(source,operator,options) {
|
|||||||
operand = (operator.operand || ""),
|
operand = (operator.operand || ""),
|
||||||
fnCalc;
|
fnCalc;
|
||||||
if(suffix === "prefix") {
|
if(suffix === "prefix") {
|
||||||
fnCalc = function(a,b) {return [$tw.utils.trimPrefix(a,b)];}
|
fnCalc = function(a,b) {return [$tw.utils.trimPrefix(a,b)];};
|
||||||
} else if(suffix === "suffix") {
|
} else if(suffix === "suffix") {
|
||||||
fnCalc = function(a,b) {return [$tw.utils.trimSuffix(a,b)];}
|
fnCalc = function(a,b) {return [$tw.utils.trimSuffix(a,b)];};
|
||||||
} else {
|
} else {
|
||||||
if(operand === "") {
|
if(operand === "") {
|
||||||
fnCalc = function(a) {return [$tw.utils.trim(a)];}
|
fnCalc = function(a) {return [$tw.utils.trim(a)];};
|
||||||
} else {
|
} else {
|
||||||
fnCalc = function(a,b) {return [$tw.utils.trimSuffix($tw.utils.trimPrefix(a,b),b)];}
|
fnCalc = function(a,b) {return [$tw.utils.trimSuffix($tw.utils.trimPrefix(a,b),b)];};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
@@ -71,107 +71,53 @@ exports.join = makeStringReducingOperator(
|
|||||||
},null
|
},null
|
||||||
);
|
);
|
||||||
|
|
||||||
var dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
|
const dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
|
||||||
|
|
||||||
exports.levenshtein = makeStringBinaryOperator(
|
exports.levenshtein = makeStringBinaryOperator(
|
||||||
function(a,b) {
|
function(a,b) {
|
||||||
var dmpObject = new dmp.diff_match_patch(),
|
const diffs = dmp.diffMain(a,b);
|
||||||
diffs = dmpObject.diff_main(a,b);
|
return [dmp.diffLevenshtein(diffs).toString()];
|
||||||
return [dmpObject.diff_levenshtein(diffs) + ""];
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// these two functions are adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
|
// this function is adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
|
||||||
function diffLineWordMode(text1,text2,mode) {
|
function diffLineWordMode(text1,text2,mode) {
|
||||||
var dmpObject = new dmp.diff_match_patch();
|
var a = $tw.utils.diffPartsToChars(text1,text2,mode);
|
||||||
var a = diffPartsToChars(text1,text2,mode);
|
|
||||||
var lineText1 = a.chars1;
|
var lineText1 = a.chars1;
|
||||||
var lineText2 = a.chars2;
|
var lineText2 = a.chars2;
|
||||||
var lineArray = a.lineArray;
|
var lineArray = a.lineArray;
|
||||||
var diffs = dmpObject.diff_main(lineText1,lineText2,false);
|
var diffs = dmp.diffMain(lineText1,lineText2,false);
|
||||||
dmpObject.diff_charsToLines_(diffs,lineArray);
|
dmp.diffCharsToLines(diffs,lineArray);
|
||||||
return diffs;
|
return diffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
function diffPartsToChars(text1,text2,mode) {
|
|
||||||
var lineArray = [];
|
|
||||||
var lineHash = {};
|
|
||||||
lineArray[0] = '';
|
|
||||||
|
|
||||||
function diff_linesToPartsMunge_(text,mode) {
|
|
||||||
var chars = '';
|
|
||||||
var lineStart = 0;
|
|
||||||
var lineEnd = -1;
|
|
||||||
var lineArrayLength = lineArray.length,
|
|
||||||
regexpResult;
|
|
||||||
var searchRegexp = /\W+/g;
|
|
||||||
while(lineEnd < text.length - 1) {
|
|
||||||
if(mode === "words") {
|
|
||||||
regexpResult = searchRegexp.exec(text);
|
|
||||||
lineEnd = searchRegexp.lastIndex;
|
|
||||||
if(regexpResult === null) {
|
|
||||||
lineEnd = text.length;
|
|
||||||
}
|
|
||||||
lineEnd = --lineEnd;
|
|
||||||
} else {
|
|
||||||
lineEnd = text.indexOf('\n', lineStart);
|
|
||||||
if(lineEnd == -1) {
|
|
||||||
lineEnd = text.length - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var line = text.substring(lineStart, lineEnd + 1);
|
|
||||||
|
|
||||||
if(lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : (lineHash[line] !== undefined)) {
|
|
||||||
chars += String.fromCharCode(lineHash[line]);
|
|
||||||
} else {
|
|
||||||
if(lineArrayLength == maxLines) {
|
|
||||||
line = text.substring(lineStart);
|
|
||||||
lineEnd = text.length;
|
|
||||||
}
|
|
||||||
chars += String.fromCharCode(lineArrayLength);
|
|
||||||
lineHash[line] = lineArrayLength;
|
|
||||||
lineArray[lineArrayLength++] = line;
|
|
||||||
}
|
|
||||||
lineStart = lineEnd + 1;
|
|
||||||
}
|
|
||||||
return chars;
|
|
||||||
}
|
|
||||||
var maxLines = 40000;
|
|
||||||
var chars1 = diff_linesToPartsMunge_(text1,mode);
|
|
||||||
maxLines = 65535;
|
|
||||||
var chars2 = diff_linesToPartsMunge_(text2,mode);
|
|
||||||
return {chars1: chars1, chars2: chars2, lineArray: lineArray};
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.makepatches = function(source,operator,options) {
|
exports.makepatches = function(source,operator,options) {
|
||||||
var dmpObject = new dmp.diff_match_patch(),
|
var suffix = operator.suffix || "",
|
||||||
suffix = operator.suffix || "",
|
|
||||||
result = [];
|
result = [];
|
||||||
|
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
var diffs, patches;
|
let diffs, patches;
|
||||||
if(suffix === "lines" || suffix === "words") {
|
if(suffix === "lines" || suffix === "words") {
|
||||||
diffs = diffLineWordMode(title,operator.operand,suffix);
|
diffs = diffLineWordMode(title,operator.operand,suffix);
|
||||||
patches = dmpObject.patch_make(title,diffs);
|
patches = dmp.patchMake(title,diffs);
|
||||||
} else {
|
} else {
|
||||||
patches = dmpObject.patch_make(title,operator.operand);
|
patches = dmp.patchMake(title,operator.operand);
|
||||||
}
|
}
|
||||||
Array.prototype.push.apply(result,[dmpObject.patch_toText(patches)]);
|
Array.prototype.push.apply(result,[dmp.patchToText(patches)]);
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.applypatches = makeStringBinaryOperator(
|
exports.applypatches = makeStringBinaryOperator(
|
||||||
function(a,b) {
|
function(a,b) {
|
||||||
var dmpObject = new dmp.diff_match_patch(),
|
let patches;
|
||||||
patches;
|
|
||||||
try {
|
try {
|
||||||
patches = dmpObject.patch_fromText(b);
|
patches = dmp.patchFromText(b);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
}
|
}
|
||||||
if(patches) {
|
if(patches) {
|
||||||
return [dmpObject.patch_apply(patches,a)[0]];
|
return [dmp.patchApply(patches,a)[0]];
|
||||||
} else {
|
} else {
|
||||||
return [a];
|
return [a];
|
||||||
}
|
}
|
||||||
@@ -279,7 +225,7 @@ exports.pad = function(source,operator,options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.charcode = function(source,operator,options) {
|
exports.charcode = function(source,operator,options) {
|
||||||
var chars = [];
|
var chars = [];
|
||||||
|
|||||||
@@ -16,12 +16,13 @@ exports.title = function(source,operator,options) {
|
|||||||
var results = [];
|
var results = [];
|
||||||
if(operator.prefix === "!") {
|
if(operator.prefix === "!") {
|
||||||
source(function(tiddler,title) {
|
source(function(tiddler,title) {
|
||||||
if(tiddler && tiddler.fields.title !== operator.operand) {
|
var titleList = operator.multiValueOperands[0] || [];
|
||||||
|
if(tiddler && titleList.indexOf(tiddler.fields.title) === -1) {
|
||||||
results.push(title);
|
results.push(title);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
results.push(operator.operand);
|
Array.prototype.push.apply(results,operator.multiValueOperands[0]);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ exports["[unknown]"] = function(source,operator,options) {
|
|||||||
// Check for a user defined filter operator
|
// Check for a user defined filter operator
|
||||||
if(operator.operator.indexOf(".") !== -1) {
|
if(operator.operator.indexOf(".") !== -1) {
|
||||||
var params = [];
|
var params = [];
|
||||||
$tw.utils.each(operator.operands,function(param) {
|
$tw.utils.each(operator.multiValueOperands,function(paramList) {
|
||||||
params.push({value: param});
|
params.push({value: paramList[0] || "",multiValue: paramList});
|
||||||
});
|
});
|
||||||
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(operator.operator,{params: params, source: source});
|
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(operator.operator,{params: params, source: source});
|
||||||
if(variableInfo && variableInfo.srcVariable) {
|
if(variableInfo && variableInfo.srcVariable) {
|
||||||
|
|||||||
@@ -11,10 +11,13 @@ The CSV text parser processes CSV files into a table wrapped in a scrollable wid
|
|||||||
|
|
||||||
var CsvParser = function(type,text,options) {
|
var CsvParser = function(type,text,options) {
|
||||||
// Special handler for tab-delimited files
|
// Special handler for tab-delimited files
|
||||||
if (type === 'text/tab-delimited-values' && !options.separator) {
|
if(
|
||||||
|
!options.separator &&
|
||||||
|
(type === "text/tab-delimited-values" || type === "text/tab-separated-values")
|
||||||
|
) {
|
||||||
options.separator = "\t";
|
options.separator = "\t";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Table framework
|
// Table framework
|
||||||
this.tree = [{
|
this.tree = [{
|
||||||
"type": "scrollable", "children": [{
|
"type": "scrollable", "children": [{
|
||||||
@@ -32,7 +35,7 @@ var CsvParser = function(type,text,options) {
|
|||||||
$tw.utils.each(lines, function(columns) {
|
$tw.utils.each(lines, function(columns) {
|
||||||
maxColumns = Math.max(columns.length, maxColumns);
|
maxColumns = Math.max(columns.length, maxColumns);
|
||||||
});
|
});
|
||||||
|
|
||||||
for(var line=0; line<lines.length; line++) {
|
for(var line=0; line<lines.length; line++) {
|
||||||
var columns = lines[line];
|
var columns = lines[line];
|
||||||
var row = {
|
var row = {
|
||||||
@@ -55,3 +58,4 @@ var CsvParser = function(type,text,options) {
|
|||||||
|
|
||||||
exports["text/csv"] = CsvParser;
|
exports["text/csv"] = CsvParser;
|
||||||
exports["text/tab-delimited-values"] = CsvParser;
|
exports["text/tab-delimited-values"] = CsvParser;
|
||||||
|
exports["text/tab-separated-values"] = CsvParser;
|
||||||
|
|||||||
@@ -11,17 +11,16 @@ The image parser parses an image into an embeddable HTML element
|
|||||||
|
|
||||||
var ImageParser = function(type,text,options) {
|
var ImageParser = function(type,text,options) {
|
||||||
var element = {
|
var element = {
|
||||||
type: "element",
|
type: "image",
|
||||||
tag: "img",
|
attributes: {}
|
||||||
attributes: {}
|
};
|
||||||
};
|
|
||||||
if(options._canonical_uri) {
|
if(options._canonical_uri) {
|
||||||
element.attributes.src = {type: "string", value: options._canonical_uri};
|
element.attributes.source = {type: "string", value: options._canonical_uri};
|
||||||
} else if(text) {
|
} else if(text) {
|
||||||
if(type === "image/svg+xml" || type === ".svg") {
|
if(type === "image/svg+xml" || type === ".svg") {
|
||||||
element.attributes.src = {type: "string", value: "data:image/svg+xml," + encodeURIComponent(text)};
|
element.attributes.source = {type: "string", value: "data:image/svg+xml," + encodeURIComponent(text)};
|
||||||
} else {
|
} else {
|
||||||
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
|
element.attributes.source = {type: "string", value: "data:" + type + ";base64," + text};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tree = [element];
|
this.tree = [element];
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Note that the syntax for comments is simplified to an opening "<!--" sequence an
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
exports.name = "commentblock";
|
exports.name = "commentblock";
|
||||||
exports.types = {block:true, pragma:true};
|
exports.types = {block: true, pragma: true};
|
||||||
|
|
||||||
exports.init = function(parser) {
|
exports.init = function(parser) {
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
@@ -43,9 +43,18 @@ exports.findNextMatch = function(startPos) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Move past the match
|
// Move past the match
|
||||||
this.parser.pos = this.endMatchRegExp.lastIndex;
|
this.parser.pos = this.endMatchRegExp.lastIndex;
|
||||||
// Don't return any elements
|
// Return a node representing the comment that is not rendered
|
||||||
return [];
|
var commentStart = this.match.index;
|
||||||
|
var commentEnd = this.endMatch.index + this.endMatch[0].length;
|
||||||
|
return [{
|
||||||
|
type: "void",
|
||||||
|
children: [],
|
||||||
|
text: this.parser.source.slice(commentStart, commentEnd),
|
||||||
|
start: commentStart,
|
||||||
|
end: commentEnd
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ exports.findNextMatch = function(startPos) {
|
|||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Move past the match
|
// Move past the match
|
||||||
this.parser.pos = this.endMatchRegExp.lastIndex;
|
this.parser.pos = this.endMatchRegExp.lastIndex;
|
||||||
// Don't return any elements
|
// Return a node representing the inline comment
|
||||||
return [];
|
var commentStart = this.match.index;
|
||||||
|
var commentEnd = this.endMatch.index + this.endMatch[0].length;
|
||||||
|
return [{
|
||||||
|
type: "void",
|
||||||
|
text: this.parser.source.slice(commentStart, commentEnd),
|
||||||
|
start: commentStart,
|
||||||
|
end: commentEnd
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ exports.init = function(parser) {
|
|||||||
|
|
||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Move past the match
|
// Move past the match
|
||||||
var start = this.parser.pos;
|
var start = this.parser.pos;
|
||||||
this.parser.pos = this.matchRegExp.lastIndex;
|
this.parser.pos = this.matchRegExp.lastIndex;
|
||||||
// Create the link unless it is suppressed
|
// Create the link unless it is suppressed
|
||||||
if(this.match[0].substr(0,1) === "~") {
|
if(this.match[0].substr(0,1) === "~") {
|
||||||
return [{type: "text", text: this.match[0].substr(1)}];
|
return [{type: "text", text: this.match[0].substr(1), start: start, end: this.parser.pos}];
|
||||||
} else {
|
} else {
|
||||||
return [{
|
return [{
|
||||||
type: "element",
|
type: "element",
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ module-type: wikirule
|
|||||||
Wiki pragma rule for function, procedure and widget definitions
|
Wiki pragma rule for function, procedure and widget definitions
|
||||||
|
|
||||||
```
|
```
|
||||||
\function name(param:defaultvalue,param2:defaultvalue)
|
\function name(param:"defaultvalue", param2:"defaultvalue")
|
||||||
definition text
|
definition text
|
||||||
\end
|
\end
|
||||||
|
|
||||||
\procedure name(param:defaultvalue,param2:defaultvalue)
|
\procedure name(param:"defaultvalue", param2:"defaultvalue")
|
||||||
definition text
|
definition text
|
||||||
\end
|
\end
|
||||||
|
|
||||||
\widget $mywidget(param:defaultvalue,param2:defaultvalue)
|
\widget $mywidget(param:"defaultvalue", param2:"defaultvalue")
|
||||||
definition text
|
definition text
|
||||||
\end
|
\end
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ exports.parse = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while(match && !match[1]);
|
} while(match && !match[1]);
|
||||||
// Return the nodes
|
// Mark first and last node, and return the nodes
|
||||||
|
if(tree[0]) tree[0].isRuleStart = true;
|
||||||
|
if(tree[tree.length-1]) tree[tree.length-1].isRuleEnd = true;
|
||||||
return tree;
|
return tree;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Parse the most recent match
|
|||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Retrieve the most recent match so that recursive calls don't overwrite it
|
// Retrieve the most recent match so that recursive calls don't overwrite it
|
||||||
var tag = this.nextTag;
|
var tag = this.nextTag;
|
||||||
if (!tag.isSelfClosing) {
|
if(!tag.isSelfClosing) {
|
||||||
tag.openTagStart = tag.start;
|
tag.openTagStart = tag.start;
|
||||||
tag.openTagEnd = tag.end;
|
tag.openTagEnd = tag.end;
|
||||||
}
|
}
|
||||||
@@ -63,22 +63,22 @@ exports.parse = function() {
|
|||||||
}
|
}
|
||||||
tag.end = this.parser.pos;
|
tag.end = this.parser.pos;
|
||||||
tag.closeTagEnd = tag.end;
|
tag.closeTagEnd = tag.end;
|
||||||
if (tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') {
|
if(tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== ">") {
|
||||||
tag.closeTagStart = tag.end;
|
tag.closeTagStart = tag.end;
|
||||||
} else {
|
} else {
|
||||||
tag.closeTagStart = tag.closeTagEnd - 2;
|
tag.closeTagStart = tag.closeTagEnd - 2;
|
||||||
var closeTagMinPos = tag.children.length > 0 ? tag.children[tag.children.length-1].end : tag.openTagEnd;
|
var closeTagMinPos = tag.children.length > 0 ? tag.children[tag.children.length-1].end : tag.openTagEnd;
|
||||||
if (!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd;
|
if(!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd;
|
||||||
while (tag.closeTagStart >= closeTagMinPos) {
|
while(tag.closeTagStart >= closeTagMinPos) {
|
||||||
var char = this.parser.source[tag.closeTagStart];
|
var char = this.parser.source[tag.closeTagStart];
|
||||||
if (char === '>') {
|
if(char === ">") {
|
||||||
tag.closeTagStart = -1;
|
tag.closeTagStart = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (char === '<') break;
|
if(char === "<") break;
|
||||||
tag.closeTagStart -= 1;
|
tag.closeTagStart -= 1;
|
||||||
}
|
}
|
||||||
if (tag.closeTagStart < closeTagMinPos) {
|
if(tag.closeTagStart < closeTagMinPos) {
|
||||||
tag.closeTagStart = tag.end;
|
tag.closeTagStart = tag.end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ var listTypes = {
|
|||||||
":": {listTag: "dl", itemTag: "dd"},
|
":": {listTag: "dl", itemTag: "dd"},
|
||||||
">": {listTag: "blockquote", itemTag: "div"}
|
">": {listTag: "blockquote", itemTag: "div"}
|
||||||
};
|
};
|
||||||
|
exports.listTypes = listTypes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parse the most recent match
|
Parse the most recent match
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ exports.findNextMatch = function(startPos) {
|
|||||||
var c = this.parser.source.charAt(nextCall.end);
|
var c = this.parser.source.charAt(nextCall.end);
|
||||||
// Ensure EOL after parsed macro
|
// Ensure EOL after parsed macro
|
||||||
// If we didn't need to support IE, we'd just use /(?:\r?\n|$)/ym
|
// If we didn't need to support IE, we'd just use /(?:\r?\n|$)/ym
|
||||||
if ((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) {
|
if((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) {
|
||||||
this.nextCall = nextCall;
|
this.nextCall = nextCall;
|
||||||
return nextStart;
|
return nextStart;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,3 +42,5 @@ exports.parse = function() {
|
|||||||
this.parser.pos = call.end;
|
this.parser.pos = call.end;
|
||||||
return [call];
|
return [call];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -52,9 +52,10 @@ exports.parse = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Is the remainder of the \define line blank after the parameter close paren?
|
// Is the remainder of the \define line blank after the parameter close paren?
|
||||||
var reEnd;
|
var reEnd,isBlock = true;
|
||||||
if(this.match[3]) {
|
if(this.match[3]) {
|
||||||
// If so, it is a multiline definition and the end of the body is marked with \end
|
// If so, it is a multiline definition and the end of the body is marked with \end
|
||||||
|
isBlock = false;
|
||||||
reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?\\s*?(?:$|\\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 {
|
} else {
|
||||||
// Otherwise, the end of the definition is marked by the end of the line
|
// Otherwise, the end of the definition is marked by the end of the line
|
||||||
@@ -79,7 +80,8 @@ exports.parse = function() {
|
|||||||
attributes: {},
|
attributes: {},
|
||||||
children: [],
|
children: [],
|
||||||
params: params,
|
params: params,
|
||||||
isMacroDefinition: true
|
isMacroDefinition: true,
|
||||||
|
isBlock: isBlock && !!endMatch
|
||||||
}];
|
}];
|
||||||
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]);
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]);
|
||||||
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text);
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ Parse the most recent match
|
|||||||
*/
|
*/
|
||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Move past the pragma invocation
|
// Move past the pragma invocation
|
||||||
|
var start = this.parser.pos;
|
||||||
this.parser.pos = this.matchRegExp.lastIndex;
|
this.parser.pos = this.matchRegExp.lastIndex;
|
||||||
// Parse whitespace delimited tokens terminated by a line break
|
// Parse whitespace delimited tokens terminated by a line break
|
||||||
var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg,
|
var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg,
|
||||||
@@ -58,6 +59,11 @@ exports.parse = function() {
|
|||||||
this.parser.parseAsInline = true;
|
this.parser.parseAsInline = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No parse tree nodes to return
|
return [{
|
||||||
return [];
|
type: "void",
|
||||||
|
children: [],
|
||||||
|
parseAsInline: this.parser.parseAsInline,
|
||||||
|
start: start,
|
||||||
|
end: this.parser.pos
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -113,3 +113,5 @@ exports.parseLink = function(source,pos) {
|
|||||||
node.end = closePos + 2;
|
node.end = closePos + 2;
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ exports.parse = function() {
|
|||||||
var text = this.match[1],
|
var text = this.match[1],
|
||||||
link = this.match[2] || text,
|
link = this.match[2] || text,
|
||||||
textEndPos = this.parser.source.indexOf("|", start);
|
textEndPos = this.parser.source.indexOf("|", start);
|
||||||
if (textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) {
|
if(textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) {
|
||||||
textEndPos = this.matchRegExp.lastIndex - 2;
|
textEndPos = this.matchRegExp.lastIndex - 2;
|
||||||
}
|
}
|
||||||
var linkStart = this.match[2] ? (start + this.match[1].length + 1) : start;
|
var linkStart = this.match[2] ? (start + this.match[1].length + 1) : start;
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ exports.parse = function() {
|
|||||||
if(tokens.length > 0) {
|
if(tokens.length > 0) {
|
||||||
this.parser.amendRules(tokens[0],tokens.slice(1));
|
this.parser.amendRules(tokens[0],tokens.slice(1));
|
||||||
}
|
}
|
||||||
// No parse tree nodes to return
|
// No widget to render, return void node.
|
||||||
return [];
|
return [{
|
||||||
|
type: "void",
|
||||||
|
attributes: {
|
||||||
|
action: {type: "string", value: tokens[0]},
|
||||||
|
rules: {type: "string", value: tokens.slice(1).join(" ")}
|
||||||
|
},
|
||||||
|
children: []
|
||||||
|
}];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -64,5 +64,8 @@ exports.parse = function() {
|
|||||||
$tw.utils.addAttributeToParseTreeNode(tree[t],"style",styles.join(""));
|
$tw.utils.addAttributeToParseTreeNode(tree[t],"style",styles.join(""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tree;
|
return [{
|
||||||
|
type: "void",
|
||||||
|
children: tree
|
||||||
|
}]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ exports.types = {inline: true};
|
|||||||
|
|
||||||
exports.init = function(parser) {
|
exports.init = function(parser) {
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
// Regexp to match
|
// Regexp to match /@@(styles)?\s*(\.class\s+)?/
|
||||||
this.matchRegExp = /@@((?:[^\.\r\n\s:]+:[^\r\n;]+;)+)?(\.(?:[^\r\n\s]+)\s+)?/mg;
|
this.matchRegExp = /@@((?:[^\.\r\n\s:]+:[^\r\n;]+;)+)?(\.(?:[^\r\n\s]+)\s+)?/mg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,22 +60,37 @@ exports.parse = function() {
|
|||||||
var parser = this.parser.wiki.parseText(parseType,text,{defaultType: "text/plain"});
|
var parser = this.parser.wiki.parseText(parseType,text,{defaultType: "text/plain"});
|
||||||
// If there's no render type, just return the parse tree
|
// If there's no render type, just return the parse tree
|
||||||
if(!renderType) {
|
if(!renderType) {
|
||||||
return parser.tree;
|
return [{
|
||||||
|
type: "void",
|
||||||
|
children: $tw.utils.isArray(parser.tree) ? parser.tree : [parser.tree],
|
||||||
|
parseType: parseType,
|
||||||
|
renderType: renderType,
|
||||||
|
text: text,
|
||||||
|
start: start,
|
||||||
|
end: this.parser.pos
|
||||||
|
}];
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, render to the rendertype and return in a <PRE> tag
|
// Otherwise, render to the rendertype and return in a <PRE> tag
|
||||||
var widgetNode = this.parser.wiki.makeWidget(parser),
|
var widgetNode = this.parser.wiki.makeWidget(parser),
|
||||||
container = $tw.fakeDocument.createElement("div");
|
container = $tw.fakeDocument.createElement("div");
|
||||||
widgetNode.render(container,null);
|
widgetNode.render(container,null);
|
||||||
text = renderType === "text/html" ? container.innerHTML : container.textContent;
|
var renderResult = renderType === "text/html" ? container.innerHTML : container.textContent;
|
||||||
|
// Use void node to carry important info for typedblock
|
||||||
return [{
|
return [{
|
||||||
type: "element",
|
type: "void",
|
||||||
tag: "pre",
|
|
||||||
children: [{
|
children: [{
|
||||||
type: "text",
|
type: "element",
|
||||||
text: text,
|
tag: "pre",
|
||||||
start: start,
|
children: [{
|
||||||
end: this.parser.pos
|
type: "text",
|
||||||
}]
|
text: renderResult,
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
parseType: parseType,
|
||||||
|
renderType: renderType,
|
||||||
|
text: text,
|
||||||
|
start: start,
|
||||||
|
end: this.parser.pos
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -215,8 +215,8 @@ WikiParser.prototype.parsePragmas = function() {
|
|||||||
var subTree = nextMatch.rule.parse();
|
var subTree = nextMatch.rule.parse();
|
||||||
if(subTree.length > 0) {
|
if(subTree.length > 0) {
|
||||||
// Set the start and end positions of the pragma rule if
|
// Set the start and end positions of the pragma rule if
|
||||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
if(subTree[0].start === undefined) subTree[0].start = start;
|
||||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||||
// Quick hack; we only cope with a single parse tree node being returned, which is true at the moment
|
// Quick hack; we only cope with a single parse tree node being returned, which is true at the moment
|
||||||
currentTreeBranch.push.apply(currentTreeBranch,subTree);
|
currentTreeBranch.push.apply(currentTreeBranch,subTree);
|
||||||
@@ -245,9 +245,9 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
|
|||||||
var start = this.pos;
|
var start = this.pos;
|
||||||
var subTree = nextMatch.rule.parse();
|
var subTree = nextMatch.rule.parse();
|
||||||
// Set the start and end positions of the first and last blocks if they're not already set
|
// Set the start and end positions of the first and last blocks if they're not already set
|
||||||
if (subTree.length > 0) {
|
if(subTree.length > 0) {
|
||||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
if(subTree[0].start === undefined) subTree[0].start = start;
|
||||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||||
}
|
}
|
||||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||||
return subTree;
|
return subTree;
|
||||||
@@ -256,7 +256,7 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
|
|||||||
var start = this.pos;
|
var start = this.pos;
|
||||||
var children = this.parseInlineRun(terminatorRegExp);
|
var children = this.parseInlineRun(terminatorRegExp);
|
||||||
var end = this.pos;
|
var end = this.pos;
|
||||||
return [{type: "element", tag: "p", children: children, start: start, end: end }];
|
return [{type: "element", tag: "p", children: children, start: start, end: end, rule: "parseblock" }];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -350,10 +350,10 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) {
|
|||||||
var start = this.pos;
|
var start = this.pos;
|
||||||
var subTree = nextMatch.rule.parse();
|
var subTree = nextMatch.rule.parse();
|
||||||
// Set the start and end positions of the first and last child if they're not already set
|
// Set the start and end positions of the first and last child if they're not already set
|
||||||
if (subTree.length > 0) {
|
if(subTree.length > 0) {
|
||||||
// Set the start and end positions of the first and last child if they're not already set
|
// Set the start and end positions of the first and last child if they're not already set
|
||||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
if(subTree[0].start === undefined) subTree[0].start = start;
|
||||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||||
}
|
}
|
||||||
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
$tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; });
|
||||||
tree.push.apply(tree,subTree);
|
tree.push.apply(tree,subTree);
|
||||||
@@ -410,9 +410,9 @@ WikiParser.prototype.parseInlineRunTerminatedExtended = function(terminatorRegEx
|
|||||||
var start = this.pos;
|
var start = this.pos;
|
||||||
var subTree = inlineRuleMatch.rule.parse();
|
var subTree = inlineRuleMatch.rule.parse();
|
||||||
// Set the start and end positions of the first and last child if they're not already set
|
// Set the start and end positions of the first and last child if they're not already set
|
||||||
if (subTree.length > 0) {
|
if(subTree.length > 0) {
|
||||||
if (subTree[0].start === undefined) subTree[0].start = start;
|
if(subTree[0].start === undefined) subTree[0].start = start;
|
||||||
if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos;
|
||||||
}
|
}
|
||||||
$tw.utils.each(subTree, function (node) { node.rule = inlineRuleMatch.rule.name; });
|
$tw.utils.each(subTree, function (node) { node.rule = inlineRuleMatch.rule.name; });
|
||||||
tree.push.apply(tree,subTree);
|
tree.push.apply(tree,subTree);
|
||||||
|
|||||||
66
core/modules/savers/postmessage.js
Normal file
66
core/modules/savers/postmessage.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/savers/postmessage.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: saver
|
||||||
|
|
||||||
|
Handles saving changes via window.postMessage() to the window.parent
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Select the appropriate saver module and set it up
|
||||||
|
*/
|
||||||
|
var PostMessageSaver = function(wiki) {
|
||||||
|
this.publisher = new $tw.utils.BrowserMessagingPublisher({type: "SAVE"});
|
||||||
|
};
|
||||||
|
|
||||||
|
PostMessageSaver.prototype.save = function(text,method,callback,options) {
|
||||||
|
// Fail if the publisher hasn't been fully initialised
|
||||||
|
if(!this.publisher.canSend()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Send the save request
|
||||||
|
this.publisher.send({
|
||||||
|
verb: "SAVE",
|
||||||
|
body: text
|
||||||
|
},function(err) {
|
||||||
|
if(err) {
|
||||||
|
callback("PostMessageSaver Error: " + err);
|
||||||
|
} else {
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Indicate that we handled the save
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Information about this saver
|
||||||
|
*/
|
||||||
|
PostMessageSaver.prototype.info = {
|
||||||
|
name: "postmessage",
|
||||||
|
capabilities: ["save", "autosave"],
|
||||||
|
priority: 100
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Static method that returns true if this saver is capable of working
|
||||||
|
*/
|
||||||
|
exports.canSave = function(wiki) {
|
||||||
|
// Provisionally say that we can save
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create an instance of this saver
|
||||||
|
*/
|
||||||
|
exports.create = function(wiki) {
|
||||||
|
return new PostMessageSaver(wiki);
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -19,6 +19,16 @@ exports.synchronous = true;
|
|||||||
var FAVICON_TITLE = "$:/favicon.ico";
|
var FAVICON_TITLE = "$:/favicon.ico";
|
||||||
|
|
||||||
exports.startup = function() {
|
exports.startup = function() {
|
||||||
|
var setFavicon = function() {
|
||||||
|
var tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);
|
||||||
|
if(tiddler) {
|
||||||
|
var faviconLink = document.getElementById("faviconLink"),
|
||||||
|
dataURI = $tw.utils.makeDataUri(tiddler.fields.text,tiddler.fields.type,tiddler.fields._canonical_uri);
|
||||||
|
faviconLink.setAttribute("href",dataURI);
|
||||||
|
$tw.faviconPublisher.send({verb: "FAVICON",body: dataURI});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tw.faviconPublisher = new $tw.utils.BrowserMessagingPublisher({type: "FAVICON", onsubscribe: setFavicon});
|
||||||
// Set up the favicon
|
// Set up the favicon
|
||||||
setFavicon();
|
setFavicon();
|
||||||
// Reset the favicon when the tiddler changes
|
// Reset the favicon when the tiddler changes
|
||||||
@@ -28,11 +38,3 @@ exports.startup = function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function setFavicon() {
|
|
||||||
var tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);
|
|
||||||
if(tiddler) {
|
|
||||||
var faviconLink = document.getElementById("faviconLink");
|
|
||||||
faviconLink.setAttribute("href",$tw.utils.makeDataUri(tiddler.fields.text,tiddler.fields.type,tiddler.fields._canonical_uri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -33,10 +33,15 @@ exports.startup = function() {
|
|||||||
});
|
});
|
||||||
$tw.titleContainer = $tw.fakeDocument.createElement("div");
|
$tw.titleContainer = $tw.fakeDocument.createElement("div");
|
||||||
$tw.titleWidgetNode.render($tw.titleContainer,null);
|
$tw.titleWidgetNode.render($tw.titleContainer,null);
|
||||||
document.title = $tw.titleContainer.textContent;
|
var publishTitle = function() {
|
||||||
|
$tw.titlePublisher.send({verb: "PAGETITLE",body: document.title});
|
||||||
|
document.title = $tw.titleContainer.textContent;
|
||||||
|
};
|
||||||
|
$tw.titlePublisher = new $tw.utils.BrowserMessagingPublisher({type: "PAGETITLE", onsubscribe: publishTitle});
|
||||||
|
publishTitle();
|
||||||
$tw.wiki.addEventListener("change",function(changes) {
|
$tw.wiki.addEventListener("change",function(changes) {
|
||||||
if($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {
|
if($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {
|
||||||
document.title = $tw.titleContainer.textContent;
|
publishTitle();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Set up the styles
|
// Set up the styles
|
||||||
|
|||||||
31
core/modules/utils/base64.js
Normal file
31
core/modules/utils/base64.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/utils/base64.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: utils-browser
|
||||||
|
|
||||||
|
Base64 utility functions
|
||||||
|
|
||||||
|
\*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Base64 utility functions that work in either browser or Node.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.btoa = binstr => window.btoa(binstr);
|
||||||
|
exports.atob = b64 => window.atob(b64);
|
||||||
|
|
||||||
|
function base64ToBytes(base64) {
|
||||||
|
const binString = exports.atob(base64);
|
||||||
|
return Uint8Array.from(binString, m => m.codePointAt(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
function bytesToBase64(bytes) {
|
||||||
|
const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join("");
|
||||||
|
return exports.btoa(binString);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.base64EncodeUtf8 = str => bytesToBase64(new TextEncoder().encode(str));
|
||||||
|
|
||||||
|
exports.base64DecodeUtf8 = str => new TextDecoder().decode(base64ToBytes(str));
|
||||||
58
core/modules/utils/deprecated.js
Normal file
58
core/modules/utils/deprecated.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/utils/deprecated.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: utils
|
||||||
|
|
||||||
|
Deprecated util functions
|
||||||
|
|
||||||
|
\*/
|
||||||
|
|
||||||
|
exports.logTable = data => console.table(data);
|
||||||
|
|
||||||
|
exports.repeat = (str,count) => str.repeat(count);
|
||||||
|
|
||||||
|
exports.startsWith = (str,search) => str.startsWith(search);
|
||||||
|
|
||||||
|
exports.endsWith = (str,search) => str.endsWith(search);
|
||||||
|
|
||||||
|
exports.trim = function(str) {
|
||||||
|
if(typeof str === "string") {
|
||||||
|
return str.trim();
|
||||||
|
} else {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.hopArray = (object,array) => array.some(element => $tw.utils.hop(object,element));
|
||||||
|
|
||||||
|
exports.sign = Math.sign;
|
||||||
|
|
||||||
|
exports.strEndsWith = (str,ending,position) => str.endsWith(ending,position);
|
||||||
|
|
||||||
|
exports.stringifyNumber = num => num.toString();
|
||||||
|
|
||||||
|
exports.tagToCssSelector = function(tagName) {
|
||||||
|
return "tc-tagged-" + encodeURIComponent(tagName).replace(/[!"#$%&'()*+,\-./:;<=>?@[\\\]^`{\|}~,]/mg,function(c) {
|
||||||
|
return "\\" + c;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.domContains = (a,b) => a.compareDocumentPosition(b) & 16;
|
||||||
|
|
||||||
|
exports.domMatchesSelector = (node,selector) => node.matches(selector);
|
||||||
|
|
||||||
|
exports.hasClass = (el,className) => el.classList && el.classList.contains(className);
|
||||||
|
|
||||||
|
exports.addClass = function(el,className) {
|
||||||
|
el.classList && className && el.classList.add(className);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.removeClass = function(el,className) {
|
||||||
|
el.classList && className && el.classList.remove(className);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.toggleClass = function(el,className,status) {
|
||||||
|
el.classList && className && el.classList.toggle(className, status);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getLocationPath = () => window.location.origin + window.location.pathname;
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -61,7 +61,7 @@ exports.convertStyleNameToPropertyName = function(styleName) {
|
|||||||
var propertyName = $tw.utils.unHyphenateCss(styleName);
|
var propertyName = $tw.utils.unHyphenateCss(styleName);
|
||||||
// Then check if it needs a prefix
|
// Then check if it needs a prefix
|
||||||
if($tw.browser && document.body.style[propertyName] === undefined) {
|
if($tw.browser && document.body.style[propertyName] === undefined) {
|
||||||
var prefixes = ["O","MS","Moz","webkit"];
|
var prefixes = ["Moz","webkit"];
|
||||||
for(var t=0; t<prefixes.length; t++) {
|
for(var t=0; t<prefixes.length; t++) {
|
||||||
var prefixedName = prefixes[t] + propertyName.substr(0,1).toUpperCase() + propertyName.substr(1);
|
var prefixedName = prefixes[t] + propertyName.substr(0,1).toUpperCase() + propertyName.substr(1);
|
||||||
if(document.body.style[prefixedName] !== undefined) {
|
if(document.body.style[prefixedName] !== undefined) {
|
||||||
@@ -112,8 +112,6 @@ var eventNameMappings = {
|
|||||||
correspondingCssProperty: "transition",
|
correspondingCssProperty: "transition",
|
||||||
mappings: {
|
mappings: {
|
||||||
transition: "transitionend",
|
transition: "transitionend",
|
||||||
OTransition: "oTransitionEnd",
|
|
||||||
MSTransition: "msTransitionEnd",
|
|
||||||
MozTransition: "transitionend",
|
MozTransition: "transitionend",
|
||||||
webkitTransition: "webkitTransitionEnd"
|
webkitTransition: "webkitTransitionEnd"
|
||||||
}
|
}
|
||||||
@@ -122,8 +120,6 @@ var eventNameMappings = {
|
|||||||
correspondingCssProperty: "animation",
|
correspondingCssProperty: "animation",
|
||||||
mappings: {
|
mappings: {
|
||||||
animation: "animationend",
|
animation: "animationend",
|
||||||
OAnimation: "oAnimationEnd",
|
|
||||||
MSAnimation: "msAnimationEnd",
|
|
||||||
MozAnimation: "animationend",
|
MozAnimation: "animationend",
|
||||||
webkitAnimation: "webkitAnimationEnd"
|
webkitAnimation: "webkitAnimationEnd"
|
||||||
}
|
}
|
||||||
@@ -156,19 +152,15 @@ exports.getFullScreenApis = function() {
|
|||||||
result = {
|
result = {
|
||||||
"_requestFullscreen": db.webkitRequestFullscreen !== undefined ? "webkitRequestFullscreen" :
|
"_requestFullscreen": db.webkitRequestFullscreen !== undefined ? "webkitRequestFullscreen" :
|
||||||
db.mozRequestFullScreen !== undefined ? "mozRequestFullScreen" :
|
db.mozRequestFullScreen !== undefined ? "mozRequestFullScreen" :
|
||||||
db.msRequestFullscreen !== undefined ? "msRequestFullscreen" :
|
|
||||||
db.requestFullscreen !== undefined ? "requestFullscreen" : "",
|
db.requestFullscreen !== undefined ? "requestFullscreen" : "",
|
||||||
"_exitFullscreen": d.webkitExitFullscreen !== undefined ? "webkitExitFullscreen" :
|
"_exitFullscreen": d.webkitExitFullscreen !== undefined ? "webkitExitFullscreen" :
|
||||||
d.mozCancelFullScreen !== undefined ? "mozCancelFullScreen" :
|
d.mozCancelFullScreen !== undefined ? "mozCancelFullScreen" :
|
||||||
d.msExitFullscreen !== undefined ? "msExitFullscreen" :
|
|
||||||
d.exitFullscreen !== undefined ? "exitFullscreen" : "",
|
d.exitFullscreen !== undefined ? "exitFullscreen" : "",
|
||||||
"_fullscreenElement": d.webkitFullscreenElement !== undefined ? "webkitFullscreenElement" :
|
"_fullscreenElement": d.webkitFullscreenElement !== undefined ? "webkitFullscreenElement" :
|
||||||
d.mozFullScreenElement !== undefined ? "mozFullScreenElement" :
|
d.mozFullScreenElement !== undefined ? "mozFullScreenElement" :
|
||||||
d.msFullscreenElement !== undefined ? "msFullscreenElement" :
|
|
||||||
d.fullscreenElement !== undefined ? "fullscreenElement" : "",
|
d.fullscreenElement !== undefined ? "fullscreenElement" : "",
|
||||||
"_fullscreenChange": d.webkitFullscreenElement !== undefined ? "webkitfullscreenchange" :
|
"_fullscreenChange": d.webkitFullscreenElement !== undefined ? "webkitfullscreenchange" :
|
||||||
d.mozFullScreenElement !== undefined ? "mozfullscreenchange" :
|
d.mozFullScreenElement !== undefined ? "mozfullscreenchange" :
|
||||||
d.msFullscreenElement !== undefined ? "MSFullscreenChange" :
|
|
||||||
d.fullscreenElement !== undefined ? "fullscreenchange" : ""
|
d.fullscreenElement !== undefined ? "fullscreenchange" : ""
|
||||||
};
|
};
|
||||||
if(!result._requestFullscreen || !result._exitFullscreen || !result._fullscreenElement || !result._fullscreenChange) {
|
if(!result._requestFullscreen || !result._exitFullscreen || !result._fullscreenElement || !result._fullscreenChange) {
|
||||||
|
|||||||
@@ -11,19 +11,6 @@ Various static DOM-related utility functions.
|
|||||||
|
|
||||||
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
||||||
|
|
||||||
/*
|
|
||||||
Determines whether element 'a' contains element 'b'
|
|
||||||
Code thanks to John Resig, http://ejohn.org/blog/comparing-document-position/
|
|
||||||
*/
|
|
||||||
exports.domContains = function(a,b) {
|
|
||||||
return a.contains ?
|
|
||||||
a !== b && a.contains(b) :
|
|
||||||
!!(a.compareDocumentPosition(b) & 16);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.domMatchesSelector = function(node,selector) {
|
|
||||||
return node.matches ? node.matches(selector) : node.msMatchesSelector(selector);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Select text in a an input or textarea (setSelectionRange crashes on certain input types)
|
Select text in a an input or textarea (setSelectionRange crashes on certain input types)
|
||||||
@@ -49,38 +36,6 @@ exports.removeChildren = function(node) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.hasClass = function(el,className) {
|
|
||||||
return el && el.hasAttribute && el.hasAttribute("class") && el.getAttribute("class").split(" ").indexOf(className) !== -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.addClass = function(el,className) {
|
|
||||||
var c = (el.getAttribute("class") || "").split(" ");
|
|
||||||
if(c.indexOf(className) === -1) {
|
|
||||||
c.push(className);
|
|
||||||
el.setAttribute("class",c.join(" "));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.removeClass = function(el,className) {
|
|
||||||
var c = (el.getAttribute("class") || "").split(" "),
|
|
||||||
p = c.indexOf(className);
|
|
||||||
if(p !== -1) {
|
|
||||||
c.splice(p,1);
|
|
||||||
el.setAttribute("class",c.join(" "));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.toggleClass = function(el,className,status) {
|
|
||||||
if(status === undefined) {
|
|
||||||
status = !exports.hasClass(el,className);
|
|
||||||
}
|
|
||||||
if(status) {
|
|
||||||
exports.addClass(el,className);
|
|
||||||
} else {
|
|
||||||
exports.removeClass(el,className);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get the first parent element that has scrollbars or use the body as fallback.
|
Get the first parent element that has scrollbars or use the body as fallback.
|
||||||
*/
|
*/
|
||||||
@@ -297,10 +252,6 @@ exports.copyToClipboard = function(text,options) {
|
|||||||
document.body.removeChild(textArea);
|
document.body.removeChild(textArea);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.getLocationPath = function() {
|
|
||||||
return window.location.toString().split("#")[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Collect DOM variables
|
Collect DOM variables
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*\
|
/*\
|
||||||
title: $:/core/modules/utils/escapecss.js
|
title: $:/core/modules/utils/escapecss.js
|
||||||
type: application/javascript
|
type: application/javascript
|
||||||
module-type: utils
|
module-type: utils-browser
|
||||||
|
|
||||||
Provides CSS.escape() functionality.
|
Provides CSS.escape() functionality.
|
||||||
|
|
||||||
@@ -9,92 +9,6 @@ Provides CSS.escape() functionality.
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// TODO -- resolve this construction
|
|
||||||
exports.escapeCSS = (function() {
|
exports.escapeCSS = (function() {
|
||||||
// use browser's native CSS.escape() function if available
|
return window.CSS.escape;
|
||||||
if ($tw.browser && window.CSS && window.CSS.escape) {
|
|
||||||
return window.CSS.escape;
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise, a utility method is provided
|
|
||||||
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
|
|
||||||
|
|
||||||
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
|
|
||||||
return function(value) {
|
|
||||||
if (arguments.length == 0) {
|
|
||||||
throw new TypeError('`CSS.escape` requires an argument.');
|
|
||||||
}
|
|
||||||
var string = String(value);
|
|
||||||
var length = string.length;
|
|
||||||
var index = -1;
|
|
||||||
var codeUnit;
|
|
||||||
var result = '';
|
|
||||||
var firstCodeUnit = string.charCodeAt(0);
|
|
||||||
while (++index < length) {
|
|
||||||
codeUnit = string.charCodeAt(index);
|
|
||||||
// Note: there’s no need to special-case astral symbols, surrogate
|
|
||||||
// pairs, or lone surrogates.
|
|
||||||
|
|
||||||
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
|
|
||||||
// (U+FFFD).
|
|
||||||
if (codeUnit == 0x0000) {
|
|
||||||
result += '\uFFFD';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
|
||||||
// U+007F, […]
|
|
||||||
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
|
|
||||||
// If the character is the first character and is in the range [0-9]
|
|
||||||
// (U+0030 to U+0039), […]
|
|
||||||
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
|
||||||
// If the character is the second character and is in the range [0-9]
|
|
||||||
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
|
||||||
(
|
|
||||||
index == 1 &&
|
|
||||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
|
||||||
firstCodeUnit == 0x002D
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
|
|
||||||
result += '\\' + codeUnit.toString(16) + ' ';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
// If the character is the first character and is a `-` (U+002D), and
|
|
||||||
// there is no second character, […]
|
|
||||||
index == 0 &&
|
|
||||||
length == 1 &&
|
|
||||||
codeUnit == 0x002D
|
|
||||||
) {
|
|
||||||
result += '\\' + string.charAt(index);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the character is not handled by one of the above rules and is
|
|
||||||
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
|
|
||||||
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
|
|
||||||
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
|
||||||
if (
|
|
||||||
codeUnit >= 0x0080 ||
|
|
||||||
codeUnit == 0x002D ||
|
|
||||||
codeUnit == 0x005F ||
|
|
||||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
|
||||||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
|
||||||
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
|
||||||
) {
|
|
||||||
// the character itself
|
|
||||||
result += string.charAt(index);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, the escaped character.
|
|
||||||
// https://drafts.csswg.org/cssom/#escape-a-character
|
|
||||||
result += '\\' + string.charAt(index);
|
|
||||||
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
126
core/modules/utils/messaging.js
Normal file
126
core/modules/utils/messaging.js
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/utils/messaging.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: utils-browser
|
||||||
|
|
||||||
|
Messaging utilities for use with window.postMessage() etc.
|
||||||
|
|
||||||
|
This module intentionally has no dependencies so that it can be included in non-TiddlyWiki projects
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var RESPONSE_TIMEOUT = 2 * 1000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class to handle subscribing to publishers
|
||||||
|
|
||||||
|
target: Target window (eg iframe.contentWindow)
|
||||||
|
type: String indicating type of item for which subscriptions are being provided (eg "SAVING")
|
||||||
|
onsubscribe: Function to be invoked with err parameter when the subscription is established, or there is a timeout
|
||||||
|
onmessage: Function to be invoked when a new message arrives, invoked with (data,callback). The callback is invoked with the argument (response)
|
||||||
|
*/
|
||||||
|
function BrowserMessagingSubscriber(options) {
|
||||||
|
var self = this;
|
||||||
|
this.target = options.target;
|
||||||
|
this.type = options.type;
|
||||||
|
this.onsubscribe = options.onsubscribe || function() {};
|
||||||
|
this.onmessage = options.onmessage;
|
||||||
|
this.hasConfirmed = false;
|
||||||
|
this.channel = new MessageChannel();
|
||||||
|
this.channel.port1.addEventListener("message",function(event) {
|
||||||
|
if(this.timerID) {
|
||||||
|
clearTimeout(this.timerID);
|
||||||
|
this.timerID = null;
|
||||||
|
}
|
||||||
|
if(event.data) {
|
||||||
|
if(event.data.verb === "SUBSCRIBED") {
|
||||||
|
self.hasConfirmed = true;
|
||||||
|
self.onsubscribe(null);
|
||||||
|
} else if(event.data.verb === self.type) {
|
||||||
|
self.onmessage(event.data,function(response) {
|
||||||
|
// Send the response back on the supplied port, and then close it
|
||||||
|
event.ports[0].postMessage(response);
|
||||||
|
event.ports[0].close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Set a timer so that if we don't hear from the iframe before a timeout we alert the user
|
||||||
|
this.timerID = setTimeout(function() {
|
||||||
|
if(!self.hasConfirmed) {
|
||||||
|
self.onsubscribe("NO_RESPONSE");
|
||||||
|
}
|
||||||
|
},RESPONSE_TIMEOUT);
|
||||||
|
this.channel.port1.start();
|
||||||
|
this.target.postMessage({verb: "SUBSCRIBE",to: self.type},"*",[this.channel.port2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.BrowserMessagingSubscriber = BrowserMessagingSubscriber;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class to handle publishing subscriptions
|
||||||
|
|
||||||
|
type: String indicating type of item for which subscriptions are being provided (eg "SAVING")
|
||||||
|
onsubscribe: Function to be invoked when a subscription occurs
|
||||||
|
*/
|
||||||
|
function BrowserMessagingPublisher(options) {
|
||||||
|
var self = this;
|
||||||
|
this.type = options.type;
|
||||||
|
this.hostIsListening = false;
|
||||||
|
this.port = null;
|
||||||
|
// Listen to connection requests from the host
|
||||||
|
window.addEventListener("message",function(event) {
|
||||||
|
if(event.data && event.data.verb === "SUBSCRIBE" && event.data.to === self.type) {
|
||||||
|
self.hostIsListening = true;
|
||||||
|
// Acknowledge
|
||||||
|
self.port = event.ports[0];
|
||||||
|
self.port.postMessage({verb: "SUBSCRIBED", to: self.type});
|
||||||
|
if(options.onsubscribe) {
|
||||||
|
options.onsubscribe(event.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserMessagingPublisher.prototype.canSend = function() {
|
||||||
|
return !!this.hostIsListening && !!this.port;
|
||||||
|
};
|
||||||
|
|
||||||
|
BrowserMessagingPublisher.prototype.send = function(data,callback) {
|
||||||
|
var self = this;
|
||||||
|
callback = callback || function() {};
|
||||||
|
// Check that we've been initialised by the host
|
||||||
|
if(!this.hostIsListening || !this.port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Create a channel for the confirmation
|
||||||
|
var channel = new MessageChannel();
|
||||||
|
channel.port1.addEventListener("message",function(event) {
|
||||||
|
if(event.data && event.data.verb === "OK") {
|
||||||
|
callback(null);
|
||||||
|
} else {
|
||||||
|
callback("BrowserMessagingPublisher for " + self.type + " error: " + (event.data || {}).verb);
|
||||||
|
}
|
||||||
|
channel.port1.close();
|
||||||
|
});
|
||||||
|
channel.port1.start();
|
||||||
|
// Send the save request with the port for the response
|
||||||
|
this.port.postMessage(data,[channel.port2]);
|
||||||
|
};
|
||||||
|
|
||||||
|
BrowserMessagingPublisher.prototype.close = function() {
|
||||||
|
if(this.port) {
|
||||||
|
this.port.close();
|
||||||
|
this.hostIsListening = false;
|
||||||
|
this.port = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.BrowserMessagingPublisher = BrowserMessagingPublisher;
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -119,3 +119,19 @@ exports.getParseTreeText = function getParseTreeText(tree) {
|
|||||||
}
|
}
|
||||||
return output.join("");
|
return output.join("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.getParser = function(type,options) {
|
||||||
|
options = options || {};
|
||||||
|
// Select a parser
|
||||||
|
var Parser = $tw.Wiki.parsers[type];
|
||||||
|
if(!Parser && $tw.utils.getFileExtensionInfo(type)) {
|
||||||
|
Parser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type];
|
||||||
|
}
|
||||||
|
if(!Parser) {
|
||||||
|
Parser = $tw.Wiki.parsers[options.defaultType || "text/vnd.tiddlywiki"];
|
||||||
|
}
|
||||||
|
if(!Parser) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Parser;
|
||||||
|
};
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ exports.repackPlugin = function(title,additionalTiddlers,excludeTiddlers) {
|
|||||||
version += "+" + pluginVersion.build;
|
version += "+" + pluginVersion.build;
|
||||||
}
|
}
|
||||||
// Save the tiddler
|
// Save the tiddler
|
||||||
$tw.wiki.addTiddler(new $tw.Tiddler(pluginTiddler,{text: JSON.stringify({tiddlers: plugins},null,4), version: version}));
|
$tw.wiki.addTiddler(new $tw.Tiddler(pluginTiddler,{text: JSON.stringify({tiddlers: plugins},null,4), version: version},$tw.wiki.getModificationFields()));
|
||||||
// Delete any non-shadow constituent tiddlers
|
// Delete any non-shadow constituent tiddlers
|
||||||
$tw.utils.each(tiddlers,function(title) {
|
$tw.utils.each(tiddlers,function(title) {
|
||||||
if($tw.wiki.tiddlerExists(title)) {
|
if($tw.wiki.tiddlerExists(title)) {
|
||||||
|
|||||||
@@ -48,19 +48,6 @@ exports.warning = function(text) {
|
|||||||
exports.log(text,"brown/orange");
|
exports.log(text,"brown/orange");
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Log a table of name: value pairs
|
|
||||||
*/
|
|
||||||
exports.logTable = function(data) {
|
|
||||||
if(console.table) {
|
|
||||||
console.table(data);
|
|
||||||
} else {
|
|
||||||
$tw.utils.each(data,function(value,name) {
|
|
||||||
console.log(name + ": " + value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return the integer represented by the str (string).
|
Return the integer represented by the str (string).
|
||||||
Return the dflt (default) parameter if str is not a base-10 number.
|
Return the dflt (default) parameter if str is not a base-10 number.
|
||||||
@@ -68,7 +55,7 @@ Return the dflt (default) parameter if str is not a base-10 number.
|
|||||||
exports.getInt = function(str,deflt) {
|
exports.getInt = function(str,deflt) {
|
||||||
var i = parseInt(str,10);
|
var i = parseInt(str,10);
|
||||||
return isNaN(i) ? deflt : i;
|
return isNaN(i) ? deflt : i;
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Repeatedly replaces a substring within a string. Like String.prototype.replace, but without any of the default special handling of $ sequences in the replace string
|
Repeatedly replaces a substring within a string. Like String.prototype.replace, but without any of the default special handling of $ sequences in the replace string
|
||||||
@@ -79,52 +66,15 @@ exports.replaceString = function(text,search,replace) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Repeats a string
|
|
||||||
*/
|
|
||||||
exports.repeat = function(str,count) {
|
|
||||||
var result = "";
|
|
||||||
for(var t=0;t<count;t++) {
|
|
||||||
result += str;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if a string starts with another string
|
|
||||||
*/
|
|
||||||
exports.startsWith = function(str,search) {
|
|
||||||
return str.substring(0, search.length) === search;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if a string ends with another string
|
|
||||||
*/
|
|
||||||
exports.endsWith = function(str,search) {
|
|
||||||
return str.substring(str.length - search.length) === search;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Trim whitespace from the start and end of a string
|
|
||||||
Thanks to Steven Levithan, http://blog.stevenlevithan.com/archives/faster-trim-javascript
|
|
||||||
*/
|
|
||||||
exports.trim = function(str) {
|
|
||||||
if(typeof str === "string") {
|
|
||||||
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
|
||||||
} else {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.trimPrefix = function(str,unwanted) {
|
exports.trimPrefix = function(str,unwanted) {
|
||||||
if(typeof str === "string" && typeof unwanted === "string") {
|
if(typeof str === "string" && typeof unwanted === "string") {
|
||||||
if(unwanted === "") {
|
if(unwanted === "") {
|
||||||
return str.replace(/^\s\s*/, '');
|
return str.replace(/^\s\s*/, "");
|
||||||
} else {
|
} else {
|
||||||
// Safely regexp-escape the unwanted text
|
// Safely regexp-escape the unwanted text
|
||||||
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
|
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||||
var regex = new RegExp('^(' + unwanted + ')+');
|
var regex = new RegExp("^(" + unwanted + ")+");
|
||||||
return str.replace(regex, '');
|
return str.replace(regex, "");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return str;
|
return str;
|
||||||
@@ -134,12 +84,12 @@ exports.trimPrefix = function(str,unwanted) {
|
|||||||
exports.trimSuffix = function(str,unwanted) {
|
exports.trimSuffix = function(str,unwanted) {
|
||||||
if(typeof str === "string" && typeof unwanted === "string") {
|
if(typeof str === "string" && typeof unwanted === "string") {
|
||||||
if(unwanted === "") {
|
if(unwanted === "") {
|
||||||
return str.replace(/\s\s*$/, '');
|
return str.replace(/\s\s*$/, "");
|
||||||
} else {
|
} else {
|
||||||
// Safely regexp-escape the unwanted text
|
// Safely regexp-escape the unwanted text
|
||||||
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
|
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||||
var regex = new RegExp('(' + unwanted + ')+$');
|
var regex = new RegExp("(" + unwanted + ")+$");
|
||||||
return str.replace(regex, '');
|
return str.replace(regex, "");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return str;
|
return str;
|
||||||
@@ -151,14 +101,14 @@ Convert a string to sentence case (ie capitalise first letter)
|
|||||||
*/
|
*/
|
||||||
exports.toSentenceCase = function(str) {
|
exports.toSentenceCase = function(str) {
|
||||||
return (str || "").replace(/^\S/, function(c) {return c.toUpperCase();});
|
return (str || "").replace(/^\S/, function(c) {return c.toUpperCase();});
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert a string to title case (ie capitalise each initial letter)
|
Convert a string to title case (ie capitalise each initial letter)
|
||||||
*/
|
*/
|
||||||
exports.toTitleCase = function(str) {
|
exports.toTitleCase = function(str) {
|
||||||
return (str || "").replace(/(^|\s)\S/g, function(c) {return c.toUpperCase();});
|
return (str || "").replace(/(^|\s)\S/g, function(c) {return c.toUpperCase();});
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Find the line break preceding a given position in a string
|
Find the line break preceding a given position in a string
|
||||||
@@ -200,18 +150,6 @@ exports.count = function(object) {
|
|||||||
return Object.keys(object || {}).length;
|
return Object.keys(object || {}).length;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Determine whether an array-item is an object-property
|
|
||||||
*/
|
|
||||||
exports.hopArray = function(object,array) {
|
|
||||||
for(var i=0; i<array.length; i++) {
|
|
||||||
if($tw.utils.hop(object,array[i])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Remove entries from an array
|
Remove entries from an array
|
||||||
array: array to modify
|
array: array to modify
|
||||||
@@ -420,8 +358,8 @@ exports.formatDateString = function(date,template) {
|
|||||||
}],
|
}],
|
||||||
[/^TZD/, function() {
|
[/^TZD/, function() {
|
||||||
var tz = date.getTimezoneOffset(),
|
var tz = date.getTimezoneOffset(),
|
||||||
atz = Math.abs(tz);
|
atz = Math.abs(tz);
|
||||||
return (tz < 0 ? '+' : '-') + $tw.utils.pad(Math.floor(atz / 60)) + ':' + $tw.utils.pad(atz % 60);
|
return (tz < 0 ? "+" : "-") + $tw.utils.pad(Math.floor(atz / 60)) + ":" + $tw.utils.pad(atz % 60);
|
||||||
}],
|
}],
|
||||||
[/^wYY/, function() {
|
[/^wYY/, function() {
|
||||||
return $tw.utils.pad($tw.utils.getYearForWeekNo(date) - 2000);
|
return $tw.utils.pad($tw.utils.getYearForWeekNo(date) - 2000);
|
||||||
@@ -630,9 +568,9 @@ exports.unescapeLineBreaks = function(s) {
|
|||||||
exports.escape = function(ch) {
|
exports.escape = function(ch) {
|
||||||
var charCode = ch.charCodeAt(0);
|
var charCode = ch.charCodeAt(0);
|
||||||
if(charCode <= 0xFF) {
|
if(charCode <= 0xFF) {
|
||||||
return '\\x' + $tw.utils.pad(charCode.toString(16).toUpperCase());
|
return "\\x" + $tw.utils.pad(charCode.toString(16).toUpperCase());
|
||||||
} else {
|
} else {
|
||||||
return '\\u' + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);
|
return "\\u" + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -649,11 +587,11 @@ exports.stringify = function(s, rawUnicode) {
|
|||||||
*/
|
*/
|
||||||
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
|
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
|
||||||
return (s || "")
|
return (s || "")
|
||||||
.replace(/\\/g, '\\\\') // backslash
|
.replace(/\\/g, "\\\\") // backslash
|
||||||
.replace(/"/g, '\\"') // double quote character
|
.replace(/"/g, '\\"') // double quote character
|
||||||
.replace(/'/g, "\\'") // single quote character
|
.replace(/'/g, "\\'") // single quote character
|
||||||
.replace(/\r/g, '\\r') // carriage return
|
.replace(/\r/g, "\\r") // carriage return
|
||||||
.replace(/\n/g, '\\n') // line feed
|
.replace(/\n/g, "\\n") // line feed
|
||||||
.replace(regex, exports.escape); // non-ASCII characters
|
.replace(regex, exports.escape); // non-ASCII characters
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -663,15 +601,15 @@ exports.jsonStringify = function(s, rawUnicode) {
|
|||||||
// See http://www.json.org/
|
// See http://www.json.org/
|
||||||
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
|
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
|
||||||
return (s || "")
|
return (s || "")
|
||||||
.replace(/\\/g, '\\\\') // backslash
|
.replace(/\\/g, "\\\\") // backslash
|
||||||
.replace(/"/g, '\\"') // double quote character
|
.replace(/"/g, '\\"') // double quote character
|
||||||
.replace(/\r/g, '\\r') // carriage return
|
.replace(/\r/g, "\\r") // carriage return
|
||||||
.replace(/\n/g, '\\n') // line feed
|
.replace(/\n/g, "\\n") // line feed
|
||||||
.replace(/\x08/g, '\\b') // backspace
|
.replace(/\x08/g, "\\b") // backspace
|
||||||
.replace(/\x0c/g, '\\f') // formfeed
|
.replace(/\x0c/g, "\\f") // formfeed
|
||||||
.replace(/\t/g, '\\t') // tab
|
.replace(/\t/g, "\\t") // tab
|
||||||
.replace(regex,function(s) {
|
.replace(regex,function(s) {
|
||||||
return '\\u' + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);
|
return "\\u" + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4);
|
||||||
}); // non-ASCII characters
|
}); // non-ASCII characters
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -679,7 +617,7 @@ exports.jsonStringify = function(s, rawUnicode) {
|
|||||||
Escape the RegExp special characters with a preceding backslash
|
Escape the RegExp special characters with a preceding backslash
|
||||||
*/
|
*/
|
||||||
exports.escapeRegExp = function(s) {
|
exports.escapeRegExp = function(s) {
|
||||||
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&');
|
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, "\\$&");
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -762,7 +700,7 @@ exports.parseTextReference = function(textRef) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If we couldn't parse it
|
// If we couldn't parse it
|
||||||
result.title = textRef
|
result.title = textRef;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@@ -821,60 +759,17 @@ Cryptographic hash function as used by sha256 filter operator
|
|||||||
options.length .. number of characters returned defaults to 64
|
options.length .. number of characters returned defaults to 64
|
||||||
*/
|
*/
|
||||||
exports.sha256 = function(str, options) {
|
exports.sha256 = function(str, options) {
|
||||||
options = options || {}
|
options = options || {};
|
||||||
return $tw.sjcl.codec.hex.fromBits($tw.sjcl.hash.sha256.hash(str)).substr(0,options.length || 64);
|
return $tw.sjcl.codec.hex.fromBits($tw.sjcl.hash.sha256.hash(str)).substr(0,options.length || 64);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Base64 utility functions that work in either browser or Node.js
|
|
||||||
*/
|
|
||||||
if(typeof window !== 'undefined') {
|
|
||||||
exports.btoa = function(binstr) { return window.btoa(binstr); }
|
|
||||||
exports.atob = function(b64) { return window.atob(b64); }
|
|
||||||
} else {
|
|
||||||
exports.btoa = function(binstr) {
|
|
||||||
return Buffer.from(binstr, 'binary').toString('base64');
|
|
||||||
}
|
|
||||||
exports.atob = function(b64) {
|
|
||||||
return Buffer.from(b64, 'base64').toString('binary');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.base64ToBytes = function(base64) {
|
|
||||||
const binString = exports.atob(base64);
|
|
||||||
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.bytesToBase64 = function(bytes) {
|
|
||||||
const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
|
|
||||||
return exports.btoa(binString);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.base64EncodeUtf8 = function(str) {
|
|
||||||
if ($tw.browser) {
|
|
||||||
return exports.bytesToBase64(new TextEncoder().encode(str));
|
|
||||||
} else {
|
|
||||||
const buff = Buffer.from(str, "utf-8");
|
|
||||||
return buff.toString("base64");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.base64DecodeUtf8 = function(str) {
|
|
||||||
if ($tw.browser) {
|
|
||||||
return new TextDecoder().decode(exports.base64ToBytes(str));
|
|
||||||
} else {
|
|
||||||
const buff = Buffer.from(str, "base64");
|
|
||||||
return buff.toString("utf-8");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Decode a base64 string
|
Decode a base64 string
|
||||||
*/
|
*/
|
||||||
exports.base64Decode = function(string64,binary,urlsafe) {
|
exports.base64Decode = function(string64,binary,urlsafe) {
|
||||||
const encoded = urlsafe ? string64.replace(/_/g,'/').replace(/-/g,'+') : string64;
|
const encoded = urlsafe ? string64.replace(/_/g,"/").replace(/-/g,"+") : string64;
|
||||||
if(binary) return exports.atob(encoded)
|
if(binary) return $tw.utils.atob(encoded);
|
||||||
else return exports.base64DecodeUtf8(encoded);
|
else return $tw.utils.base64DecodeUtf8(encoded);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -882,10 +777,10 @@ Encode a string to base64
|
|||||||
*/
|
*/
|
||||||
exports.base64Encode = function(string64,binary,urlsafe) {
|
exports.base64Encode = function(string64,binary,urlsafe) {
|
||||||
let encoded;
|
let encoded;
|
||||||
if(binary) encoded = exports.btoa(string64);
|
if(binary) encoded = $tw.utils.btoa(string64);
|
||||||
else encoded = exports.base64EncodeUtf8(string64);
|
else encoded = $tw.utils.base64EncodeUtf8(string64);
|
||||||
if(urlsafe) {
|
if(urlsafe) {
|
||||||
encoded = encoded.replace(/\+/g,'-').replace(/\//g,'_');
|
encoded = encoded.replace(/\+/g,"-").replace(/\//g,"_");
|
||||||
}
|
}
|
||||||
return encoded;
|
return encoded;
|
||||||
};
|
};
|
||||||
@@ -940,44 +835,6 @@ exports.makeDataUri = function(text,type,_canonical_uri) {
|
|||||||
return parts.join("");
|
return parts.join("");
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Useful for finding out the fully escaped CSS selector equivalent to a given tag. For example:
|
|
||||||
|
|
||||||
$tw.utils.tagToCssSelector("$:/tags/Stylesheet") --> tc-tagged-\%24\%3A\%2Ftags\%2FStylesheet
|
|
||||||
*/
|
|
||||||
exports.tagToCssSelector = function(tagName) {
|
|
||||||
return "tc-tagged-" + encodeURIComponent(tagName).replace(/[!"#$%&'()*+,\-./:;<=>?@[\\\]^`{\|}~,]/mg,function(c) {
|
|
||||||
return "\\" + c;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
IE does not have sign function
|
|
||||||
*/
|
|
||||||
exports.sign = Math.sign || function(x) {
|
|
||||||
x = +x; // convert to a number
|
|
||||||
if(x === 0 || isNaN(x)) {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
return x > 0 ? 1 : -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
IE does not have an endsWith function
|
|
||||||
*/
|
|
||||||
exports.strEndsWith = function(str,ending,position) {
|
|
||||||
if(str.endsWith) {
|
|
||||||
return str.endsWith(ending,position);
|
|
||||||
} else {
|
|
||||||
if(typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > str.length) {
|
|
||||||
position = str.length;
|
|
||||||
}
|
|
||||||
position -= ending.length;
|
|
||||||
var lastIndex = str.indexOf(ending, position);
|
|
||||||
return lastIndex !== -1 && lastIndex === position;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return system information useful for debugging
|
Return system information useful for debugging
|
||||||
*/
|
*/
|
||||||
@@ -1004,10 +861,6 @@ exports.parseInt = function(str) {
|
|||||||
return parseInt(str,10) || 0;
|
return parseInt(str,10) || 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.stringifyNumber = function(num) {
|
|
||||||
return num + "";
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.makeCompareFunction = function(type,options) {
|
exports.makeCompareFunction = function(type,options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
// set isCaseSensitive to true if not defined in options
|
// set isCaseSensitive to true if not defined in options
|
||||||
@@ -1061,3 +914,56 @@ exports.makeCompareFunction = function(type,options) {
|
|||||||
};
|
};
|
||||||
return (types[type] || types[options.defaultType] || types.number);
|
return (types[type] || types[options.defaultType] || types.number);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Split text into parts (lines or words) for diff operations
|
||||||
|
Adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
|
||||||
|
*/
|
||||||
|
exports.diffPartsToChars = function(text1,text2,mode) {
|
||||||
|
const lineArray = [""],
|
||||||
|
lineHash = Object.create(null);
|
||||||
|
|
||||||
|
function diff_linesToPartsMunge_(text,mode) {
|
||||||
|
let chars = "",
|
||||||
|
lineStart = 0,
|
||||||
|
lineEnd = -1,
|
||||||
|
lineArrayLength = lineArray.length,
|
||||||
|
regexpResult;
|
||||||
|
const searchRegexp = /\W+/g;
|
||||||
|
while(lineEnd < text.length - 1) {
|
||||||
|
if(mode === "words") {
|
||||||
|
regexpResult = searchRegexp.exec(text);
|
||||||
|
lineEnd = searchRegexp.lastIndex;
|
||||||
|
if(regexpResult === null) {
|
||||||
|
lineEnd = text.length;
|
||||||
|
}
|
||||||
|
lineEnd = --lineEnd;
|
||||||
|
} else {
|
||||||
|
lineEnd = text.indexOf("\n", lineStart);
|
||||||
|
if(lineEnd === -1) {
|
||||||
|
lineEnd = text.length - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let line = text.substring(lineStart, lineEnd + 1);
|
||||||
|
|
||||||
|
if(line in lineHash) {
|
||||||
|
chars += String.fromCharCode(lineHash[line]);
|
||||||
|
} else {
|
||||||
|
if(lineArrayLength === maxLines) {
|
||||||
|
line = text.substring(lineStart);
|
||||||
|
lineEnd = text.length;
|
||||||
|
}
|
||||||
|
chars += String.fromCharCode(lineArrayLength);
|
||||||
|
lineHash[line] = lineArrayLength;
|
||||||
|
lineArray[lineArrayLength++] = line;
|
||||||
|
}
|
||||||
|
lineStart = lineEnd + 1;
|
||||||
|
}
|
||||||
|
return chars;
|
||||||
|
}
|
||||||
|
let maxLines = 40000;
|
||||||
|
const chars1 = diff_linesToPartsMunge_(text1,mode);
|
||||||
|
maxLines = 65535;
|
||||||
|
const chars2 = diff_linesToPartsMunge_(text2,mode);
|
||||||
|
return {chars1, chars2, lineArray};
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable no-unused-vars */
|
||||||
/*\
|
/*\
|
||||||
title: $:/core/modules/widgets/action-log.js
|
title: $:/core/modules/widgets/action-log.js
|
||||||
type: application/javascript
|
type: application/javascript
|
||||||
@@ -32,7 +33,7 @@ LogWidget.prototype.execute = function(){
|
|||||||
this.message = this.getAttribute("$$message","debug");
|
this.message = this.getAttribute("$$message","debug");
|
||||||
this.logAll = this.getAttribute("$$all","no") === "yes" ? true : false;
|
this.logAll = this.getAttribute("$$all","no") === "yes" ? true : false;
|
||||||
this.filter = this.getAttribute("$$filter");
|
this.filter = this.getAttribute("$$filter");
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Refresh the widget by ensuring our attributes are up to date
|
Refresh the widget by ensuring our attributes are up to date
|
||||||
@@ -51,23 +52,30 @@ LogWidget.prototype.invokeAction = function(triggeringWidget,event) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
LogWidget.prototype.log = function() {
|
LogWidget.prototype.log = function() {
|
||||||
var data = {},
|
var self = this,
|
||||||
|
data = {}, // Hashmap by attribute name with string or array of string values
|
||||||
dataCount,
|
dataCount,
|
||||||
allVars = {},
|
allVars = {}, // Hashmap by variable name with string or array of string values
|
||||||
filteredVars;
|
filteredVars;
|
||||||
|
// Collect the attributes to be logged
|
||||||
$tw.utils.each(this.attributes,function(attribute,name) {
|
$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
|
||||||
if(name.substring(0,2) !== "$$") {
|
if(name.substring(0,2) !== "$$") {
|
||||||
data[name] = attribute;
|
var resultList = self.computeAttribute(attribute,{asList: true});
|
||||||
|
if(resultList.length <= 1) {
|
||||||
|
data[name] = resultList[0] || "";
|
||||||
|
} else {
|
||||||
|
data[name] = resultList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Collect values of all variables, using the source text for functions
|
||||||
for(var v in this.variables) {
|
for(var v in this.variables) {
|
||||||
var variable = this.parentWidget && this.parentWidget.variables[v];
|
var variable = this.parentWidget && this.parentWidget.variables[v];
|
||||||
if(variable && variable.isFunctionDefinition) {
|
if(variable && variable.isFunctionDefinition) {
|
||||||
allVars[v] = variable.value;
|
allVars[v] = variable.value;
|
||||||
} else {
|
} else {
|
||||||
allVars[v] = this.getVariable(v,{defaultValue:""});
|
var variableInfo = this.getVariableInfo(v);
|
||||||
|
allVars[v] = variableInfo.resultList.length > 1 ? variableInfo.resultList : variableInfo.text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.filter) {
|
if(this.filter) {
|
||||||
@@ -88,6 +96,6 @@ LogWidget.prototype.log = function() {
|
|||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
}
|
}
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
}
|
};
|
||||||
|
|
||||||
exports["action-log"] = LogWidget;
|
exports["action-log"] = LogWidget;
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ Button widget
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const ALLOWED_SELECTED_ARIA_ATTR = ["aria-checked", "aria-selected", "aria-pressed"];
|
||||||
|
|
||||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
var Popup = require("$:/core/modules/utils/dom/popup.js");
|
||||||
@@ -44,9 +46,14 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
var classes = this["class"].split(" ") || [],
|
var classes = this["class"].split(" ") || [],
|
||||||
isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp();
|
isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp();
|
||||||
if(this.selectedClass) {
|
if(this.selectedClass) {
|
||||||
if((this.set || this.setTitle) && this.setTo && this.isSelected()) {
|
if((this.set || this.setTitle) && this.setTo) {
|
||||||
$tw.utils.pushTop(classes, this.selectedClass.split(" "));
|
const selectedAria = ALLOWED_SELECTED_ARIA_ATTR.includes(this.selectedAria) ? this.selectedAria : "aria-checked";
|
||||||
domNode.setAttribute("aria-checked", "true");
|
if(this.isSelected()) {
|
||||||
|
$tw.utils.pushTop(classes, this.selectedClass.split(" "));
|
||||||
|
domNode.setAttribute(selectedAria, "true");
|
||||||
|
} else {
|
||||||
|
domNode.setAttribute(selectedAria, "false");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(isPoppedUp) {
|
if(isPoppedUp) {
|
||||||
$tw.utils.pushTop(classes,this.selectedClass.split(" "));
|
$tw.utils.pushTop(classes,this.selectedClass.split(" "));
|
||||||
@@ -221,6 +228,7 @@ ButtonWidget.prototype.execute = function() {
|
|||||||
this.style = this.getAttribute("style");
|
this.style = this.getAttribute("style");
|
||||||
this["class"] = this.getAttribute("class","");
|
this["class"] = this.getAttribute("class","");
|
||||||
this.selectedClass = this.getAttribute("selectedClass");
|
this.selectedClass = this.getAttribute("selectedClass");
|
||||||
|
this.selectedAria = this.getAttribute("selectedAria");
|
||||||
this.defaultSetValue = this.getAttribute("default","");
|
this.defaultSetValue = this.getAttribute("default","");
|
||||||
this.buttonTag = this.getAttribute("tag");
|
this.buttonTag = this.getAttribute("tag");
|
||||||
this.dragTiddler = this.getAttribute("dragTiddler");
|
this.dragTiddler = this.getAttribute("dragTiddler");
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ Widget to display a diff between two texts
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Widget = require("$:/core/modules/widgets/widget.js").widget,
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
|
const dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
|
||||||
|
|
||||||
var DiffTextWidget = function(parseTreeNode,options) {
|
var DiffTextWidget = function(parseTreeNode,options) {
|
||||||
this.initialise(parseTreeNode,options);
|
this.initialise(parseTreeNode,options);
|
||||||
@@ -34,19 +34,25 @@ DiffTextWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
this.execute();
|
||||||
// Create the diff
|
// Create the diff object
|
||||||
var dmpObject = new dmp.diff_match_patch(),
|
const editCost = $tw.utils.parseNumber(this.getAttribute("editcost","4"));
|
||||||
diffs = dmpObject.diff_main(this.getAttribute("source",""),this.getAttribute("dest",""));
|
const mode = this.getAttribute("mode") || "chars";
|
||||||
|
let diffs;
|
||||||
|
if(mode === "lines" || mode === "words") {
|
||||||
|
diffs = diffLineWordMode(this.getAttribute("source",""),this.getAttribute("dest",""),mode,editCost);
|
||||||
|
} else {
|
||||||
|
diffs = dmp.diffMain(this.getAttribute("source",""),this.getAttribute("dest",""),{diffEditCost: editCost});
|
||||||
|
}
|
||||||
// Apply required cleanup
|
// Apply required cleanup
|
||||||
switch(this.getAttribute("cleanup","semantic")) {
|
switch(this.getAttribute("cleanup","semantic")) {
|
||||||
case "none":
|
case "none":
|
||||||
// No cleanup
|
// No cleanup
|
||||||
break;
|
break;
|
||||||
case "efficiency":
|
case "efficiency":
|
||||||
dmpObject.diff_cleanupEfficiency(diffs);
|
dmp.diffCleanupEfficiency(diffs, {diffEditCost: editCost});
|
||||||
break;
|
break;
|
||||||
default: // case "semantic"
|
default: // case "semantic"
|
||||||
dmpObject.diff_cleanupSemantic(diffs);
|
dmp.diffCleanupSemantic(diffs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Create the elements
|
// Create the elements
|
||||||
@@ -132,7 +138,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
*/
|
*/
|
||||||
DiffTextWidget.prototype.refresh = function(changedTiddlers) {
|
DiffTextWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup) {
|
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup || changedAttributes.mode || changedAttributes.editcost) {
|
||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -140,4 +146,15 @@ DiffTextWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This function is adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
|
||||||
|
function diffLineWordMode(text1,text2,mode,editCost) {
|
||||||
|
var a = $tw.utils.diffPartsToChars(text1,text2,mode);
|
||||||
|
var lineText1 = a.chars1;
|
||||||
|
var lineText2 = a.chars2;
|
||||||
|
var lineArray = a.lineArray;
|
||||||
|
var diffs = dmp.diffMain(lineText1,lineText2,{diffEditCost: editCost});
|
||||||
|
dmp.diffCharsToLines(diffs,lineArray);
|
||||||
|
return diffs;
|
||||||
|
}
|
||||||
|
|
||||||
exports["diff-text"] = DiffTextWidget;
|
exports["diff-text"] = DiffTextWidget;
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ DroppableWidget.prototype.execute = function() {
|
|||||||
DroppableWidget.prototype.assignDomNodeClasses = function() {
|
DroppableWidget.prototype.assignDomNodeClasses = function() {
|
||||||
var classes = this.getAttribute("class","").split(" ");
|
var classes = this.getAttribute("class","").split(" ");
|
||||||
classes.push("tc-droppable");
|
classes.push("tc-droppable");
|
||||||
this.domNode.className = classes.join(" ");
|
this.domNode.className = classes.join(" ").trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ Render this widget into the DOM
|
|||||||
*/
|
*/
|
||||||
ElementWidget.prototype.render = function(parent,nextSibling) {
|
ElementWidget.prototype.render = function(parent,nextSibling) {
|
||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
this.computeAttributes();
|
|
||||||
// Neuter blacklisted elements
|
// Neuter blacklisted elements
|
||||||
this.tag = this.parseTreeNode.tag;
|
this.tag = this.parseTreeNode.tag;
|
||||||
if($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) {
|
if($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) {
|
||||||
@@ -42,6 +41,8 @@ ElementWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
headingLevel = Math.min(Math.max(headingLevel + 1 + baseLevel,1),6);
|
headingLevel = Math.min(Math.max(headingLevel + 1 + baseLevel,1),6);
|
||||||
this.tag = "h" + headingLevel;
|
this.tag = "h" + headingLevel;
|
||||||
}
|
}
|
||||||
|
// Compute the attributes, mapping the element tag if needed
|
||||||
|
this.computeAttributes();
|
||||||
// Select the namespace for the tag
|
// Select the namespace for the tag
|
||||||
var XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml",
|
var XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml",
|
||||||
tagNamespaces = {
|
tagNamespaces = {
|
||||||
@@ -99,4 +100,25 @@ ElementWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
return this.refreshChildren(changedTiddlers) || hasChangedAttributes;
|
return this.refreshChildren(changedTiddlers) || hasChangedAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Override the base computeAttributes method
|
||||||
|
*/
|
||||||
|
ElementWidget.prototype.computeAttributes = function() {
|
||||||
|
// Call the base class to compute the initial values of the attributes
|
||||||
|
var changedAttributes = Widget.prototype.computeAttributes.call(this);
|
||||||
|
// Check for element mapping
|
||||||
|
var mappedTag = this.getVariable("tv-map-" + this.tag),
|
||||||
|
mappedClass = this.getVariable("tv-map-" + this.tag + "-class");
|
||||||
|
if(mappedTag) {
|
||||||
|
this.tag = mappedTag.trim();
|
||||||
|
// Add an attribute to indicate the original tag
|
||||||
|
this.attributes["data-element-mapping-from"] = this.parseTreeNode.tag;
|
||||||
|
// Check for a mapped class
|
||||||
|
if(mappedClass) {
|
||||||
|
this.attributes["class"] = mappedClass.trim() + (this.attributes["class"] ? " " + this.attributes["class"] : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changedAttributes;
|
||||||
|
};
|
||||||
|
|
||||||
exports.element = ElementWidget;
|
exports.element = ElementWidget;
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ EventWidget.prototype.execute = function() {
|
|||||||
EventWidget.prototype.assignDomNodeClasses = function() {
|
EventWidget.prototype.assignDomNodeClasses = function() {
|
||||||
var classes = this.getAttribute("class","").split(" ");
|
var classes = this.getAttribute("class","").split(" ");
|
||||||
classes.push("tc-eventcatcher");
|
classes.push("tc-eventcatcher");
|
||||||
this.domNode.className = classes.join(" ");
|
this.domNode.className = classes.join(" ").trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
|||||||
var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true, configTrimWhiteSpace:false});
|
var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true, configTrimWhiteSpace:false});
|
||||||
if(parser) {
|
if(parser) {
|
||||||
var parseTreeNode = parser.tree[0];
|
var parseTreeNode = parser.tree[0];
|
||||||
while(parseTreeNode && ["setvariable","set","parameters"].indexOf(parseTreeNode.type) !== -1) {
|
// process AST nodes generated by pragma rules.
|
||||||
|
while(parseTreeNode && ["setvariable","set","parameters","void"].indexOf(parseTreeNode.type) !== -1) {
|
||||||
var node = {
|
var node = {
|
||||||
type: "set",
|
type: "set",
|
||||||
attributes: parseTreeNode.attributes,
|
attributes: parseTreeNode.attributes,
|
||||||
@@ -82,7 +83,7 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
|||||||
// this widget. If it needs to refresh,
|
// this widget. If it needs to refresh,
|
||||||
// it'll do so along with the the whole
|
// it'll do so along with the the whole
|
||||||
// importvariable tree.
|
// importvariable tree.
|
||||||
if (widgetPointer != this) {
|
if(widgetPointer != this) {
|
||||||
widgetPointer.makeChildWidgets = function(){};
|
widgetPointer.makeChildWidgets = function(){};
|
||||||
}
|
}
|
||||||
widgetPointer = widgetPointer.children[0];
|
widgetPointer = widgetPointer.children[0];
|
||||||
@@ -93,7 +94,7 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (widgetPointer != this) {
|
if(widgetPointer != this) {
|
||||||
widgetPointer.parseTreeNode.children = this.parseTreeNode.children;
|
widgetPointer.parseTreeNode.children = this.parseTreeNode.children;
|
||||||
} else {
|
} else {
|
||||||
widgetPointer.makeChildWidgets();
|
widgetPointer.makeChildWidgets();
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ KeyboardWidget.prototype.execute = function() {
|
|||||||
KeyboardWidget.prototype.assignDomNodeClasses = function() {
|
KeyboardWidget.prototype.assignDomNodeClasses = function() {
|
||||||
var classes = this.getAttribute("class","").split(" ");
|
var classes = this.getAttribute("class","").split(" ");
|
||||||
classes.push("tc-keyboard");
|
classes.push("tc-keyboard");
|
||||||
this.domNode.className = classes.join(" ");
|
this.domNode.className = classes.join(" ").trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ This widget allows defining multiple variables at once, while allowing
|
|||||||
the later variables to depend upon the earlier ones.
|
the later variables to depend upon the earlier ones.
|
||||||
|
|
||||||
```
|
```
|
||||||
\define helloworld() Hello world!
|
|
||||||
<$let currentTiddler="target" value={{!!value}} currentTiddler="different">
|
<$let currentTiddler="target" value={{!!value}} currentTiddler="different">
|
||||||
{{!!value}} will be different from <<value>>
|
{{!!value}} will be different from <<value>>
|
||||||
</$let>
|
</$let>
|
||||||
@@ -46,7 +45,7 @@ LetWidget.prototype.computeAttributes = function() {
|
|||||||
self = this;
|
self = this;
|
||||||
this.currentValueFor = Object.create(null);
|
this.currentValueFor = Object.create(null);
|
||||||
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) {
|
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) {
|
||||||
var value = self.computeAttribute(attribute),
|
var value = self.computeAttribute(attribute,{asList: true}),
|
||||||
name = attribute.name;
|
name = attribute.name;
|
||||||
// Now that it's prepped, we're allowed to look this variable up
|
// Now that it's prepped, we're allowed to look this variable up
|
||||||
// when defining later variables
|
// when defining later variables
|
||||||
@@ -56,7 +55,7 @@ LetWidget.prototype.computeAttributes = function() {
|
|||||||
});
|
});
|
||||||
// Run through again, setting variables and looking for differences
|
// Run through again, setting variables and looking for differences
|
||||||
$tw.utils.each(this.currentValueFor,function(value,name) {
|
$tw.utils.each(this.currentValueFor,function(value,name) {
|
||||||
if (self.attributes[name] !== value) {
|
if(self.attributes[name] === undefined || !$tw.utils.isArrayEqual(self.attributes[name],value)) {
|
||||||
self.attributes[name] = value;
|
self.attributes[name] = value;
|
||||||
self.setVariable(name,value);
|
self.setVariable(name,value);
|
||||||
changedAttributes[name] = true;
|
changedAttributes[name] = true;
|
||||||
@@ -68,9 +67,11 @@ LetWidget.prototype.computeAttributes = function() {
|
|||||||
LetWidget.prototype.getVariableInfo = function(name,options) {
|
LetWidget.prototype.getVariableInfo = function(name,options) {
|
||||||
// Special handling: If this variable exists in this very $let, we can
|
// Special handling: If this variable exists in this very $let, we can
|
||||||
// use it, but only if it's been staged.
|
// use it, but only if it's been staged.
|
||||||
if ($tw.utils.hop(this.currentValueFor,name)) {
|
if($tw.utils.hop(this.currentValueFor,name)) {
|
||||||
|
var value = this.currentValueFor[name];
|
||||||
return {
|
return {
|
||||||
text: this.currentValueFor[name]
|
text: value[0] || "",
|
||||||
|
resultList: value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return Widget.prototype.getVariableInfo.call(this,name,options);
|
return Widget.prototype.getVariableInfo.call(this,name,options);
|
||||||
|
|||||||
@@ -89,13 +89,33 @@ RevealWidget.prototype.positionPopup = function(domNode) {
|
|||||||
top = this.popup.top + this.popup.height;
|
top = this.popup.top + this.popup.height;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// if requested, clamp the popup so that it will always be fully inside its parent (the first upstream element with position:relative), as long as the popup is smaller than its parent
|
||||||
|
// if position is absolute then clamping is done to the canvas boundary, since there is no "parent"
|
||||||
|
if(this.clampToParent !== "none") {
|
||||||
|
if(this.popup.absolute) {
|
||||||
|
var parentWidth = window.innerWidth,
|
||||||
|
parentHeight = window.innerHeight;
|
||||||
|
} else {
|
||||||
|
var parentWidth = domNode.offsetParent.offsetWidth,
|
||||||
|
parentHeight = domNode.offsetParent.offsetHeight;
|
||||||
|
}
|
||||||
|
var right = left + domNode.offsetWidth,
|
||||||
|
bottom = top + domNode.offsetHeight;
|
||||||
|
if((this.clampToParent === "both" || this.clampToParent === "right") && right > parentWidth) {
|
||||||
|
left = parentWidth - domNode.offsetWidth;
|
||||||
|
}
|
||||||
|
if((this.clampToParent === "both" || this.clampToParent === "bottom") && bottom > parentHeight) {
|
||||||
|
top = parentHeight - domNode.offsetHeight;
|
||||||
|
}
|
||||||
|
// clamping on left and top sides is taken care of by positionAllowNegative
|
||||||
|
}
|
||||||
if(!this.positionAllowNegative) {
|
if(!this.positionAllowNegative) {
|
||||||
left = Math.max(0,left);
|
left = Math.max(0,left);
|
||||||
top = Math.max(0,top);
|
top = Math.max(0,top);
|
||||||
}
|
}
|
||||||
if (this.popup.absolute) {
|
if(this.popup.absolute) {
|
||||||
// Traverse the offsetParent chain and correct the offset to make it relative to the parent node.
|
// Traverse the offsetParent chain and correct the offset to make it relative to the parent node.
|
||||||
for (var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) {
|
for(var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) {
|
||||||
left -= offsetParentDomNode.offsetLeft;
|
left -= offsetParentDomNode.offsetLeft;
|
||||||
top -= offsetParentDomNode.offsetTop;
|
top -= offsetParentDomNode.offsetTop;
|
||||||
}
|
}
|
||||||
@@ -123,6 +143,7 @@ RevealWidget.prototype.execute = function() {
|
|||||||
this.openAnimation = this.animate === "no" ? undefined : "open";
|
this.openAnimation = this.animate === "no" ? undefined : "open";
|
||||||
this.closeAnimation = this.animate === "no" ? undefined : "close";
|
this.closeAnimation = this.animate === "no" ? undefined : "close";
|
||||||
this.updatePopupPosition = this.getAttribute("updatePopupPosition","no") === "yes";
|
this.updatePopupPosition = this.getAttribute("updatePopupPosition","no") === "yes";
|
||||||
|
this.clampToParent = this.getAttribute("clamp","none");
|
||||||
// Compute the title of the state tiddler and read it
|
// Compute the title of the state tiddler and read it
|
||||||
this.stateTiddlerTitle = this.state;
|
this.stateTiddlerTitle = this.state;
|
||||||
this.stateTitle = this.getAttribute("stateTitle");
|
this.stateTitle = this.getAttribute("stateTitle");
|
||||||
@@ -141,7 +162,7 @@ Read the state tiddler
|
|||||||
RevealWidget.prototype.readState = function() {
|
RevealWidget.prototype.readState = function() {
|
||||||
// Read the information from the state tiddler
|
// Read the information from the state tiddler
|
||||||
var state,
|
var state,
|
||||||
defaultState = this["default"];
|
defaultState = this["default"];
|
||||||
if(this.stateTitle) {
|
if(this.stateTitle) {
|
||||||
var stateTitleTiddler = this.wiki.getTiddler(this.stateTitle);
|
var stateTitleTiddler = this.wiki.getTiddler(this.stateTitle);
|
||||||
if(this.stateField) {
|
if(this.stateField) {
|
||||||
@@ -203,7 +224,7 @@ RevealWidget.prototype.readPopupState = function(state) {
|
|||||||
RevealWidget.prototype.assignDomNodeClasses = function() {
|
RevealWidget.prototype.assignDomNodeClasses = function() {
|
||||||
var classes = this.getAttribute("class","").split(" ");
|
var classes = this.getAttribute("class","").split(" ");
|
||||||
classes.push("tc-reveal");
|
classes.push("tc-reveal");
|
||||||
this.domNode.className = classes.join(" ");
|
this.domNode.className = classes.join(" ").trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -252,18 +273,18 @@ RevealWidget.prototype.updateState = function() {
|
|||||||
this.renderChildren(domNode,null);
|
this.renderChildren(domNode,null);
|
||||||
}
|
}
|
||||||
// Animate our DOM node
|
// Animate our DOM node
|
||||||
if(!domNode.isTiddlyWikiFakeDom && this.type === "popup" && this.isOpen) {
|
|
||||||
this.positionPopup(domNode);
|
|
||||||
$tw.utils.addClass(domNode,"tc-popup"); // Make sure that clicks don't dismiss popups within the revealed content
|
|
||||||
|
|
||||||
}
|
|
||||||
if(this.isOpen) {
|
if(this.isOpen) {
|
||||||
domNode.removeAttribute("hidden");
|
domNode.removeAttribute("hidden");
|
||||||
$tw.anim.perform(this.openAnimation,domNode);
|
// Position popup after making it visible to ensure correct dimensions
|
||||||
|
if(!domNode.isTiddlyWikiFakeDom && this.type === "popup") {
|
||||||
|
this.positionPopup(domNode);
|
||||||
|
$tw.utils.addClass(domNode,"tc-popup"); // Make sure that clicks don't dismiss popups within the revealed content
|
||||||
|
}
|
||||||
|
$tw.anim.perform(this.openAnimation,domNode);
|
||||||
} else {
|
} else {
|
||||||
$tw.anim.perform(this.closeAnimation,domNode,{callback: function() {
|
$tw.anim.perform(this.closeAnimation,domNode,{callback: function() {
|
||||||
//make sure that the state hasn't changed during the close animation
|
//make sure that the state hasn't changed during the close animation
|
||||||
self.readState()
|
self.readState();
|
||||||
if(!self.isOpen) {
|
if(!self.isOpen) {
|
||||||
domNode.setAttribute("hidden","true");
|
domNode.setAttribute("hidden","true");
|
||||||
}
|
}
|
||||||
|
|||||||
23
core/modules/widgets/void.js
Executable file
23
core/modules/widgets/void.js
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/widgets/void.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
Void widget that corresponds to pragma and comment AST nodes, etc. It does not render itself but renders all its children.
|
||||||
|
|
||||||
|
\*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
|
var VoidNodeWidget = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
VoidNodeWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
exports.void = VoidNodeWidget;
|
||||||
@@ -80,7 +80,7 @@ Widget.prototype.execute = function() {
|
|||||||
/*
|
/*
|
||||||
Set the value of a context variable
|
Set the value of a context variable
|
||||||
name: name of the variable
|
name: name of the variable
|
||||||
value: value of the variable
|
value: value of the variable, can be a string or an array
|
||||||
params: array of {name:, default:} for each parameter
|
params: array of {name:, default:} for each parameter
|
||||||
isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed)
|
isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed)
|
||||||
options includes:
|
options includes:
|
||||||
@@ -90,8 +90,10 @@ options includes:
|
|||||||
*/
|
*/
|
||||||
Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) {
|
Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
var valueIsArray = $tw.utils.isArray(value);
|
||||||
this.variables[name] = {
|
this.variables[name] = {
|
||||||
value: value,
|
value: valueIsArray ? (value[0] || "") : value,
|
||||||
|
resultList: valueIsArray ? value : [value],
|
||||||
params: params,
|
params: params,
|
||||||
isMacroDefinition: !!isMacroDefinition,
|
isMacroDefinition: !!isMacroDefinition,
|
||||||
isFunctionDefinition: !!options.isFunctionDefinition,
|
isFunctionDefinition: !!options.isFunctionDefinition,
|
||||||
@@ -114,7 +116,7 @@ allowSelfAssigned: if true, includes the current widget in the context chain ins
|
|||||||
|
|
||||||
Returns an object with the following fields:
|
Returns an object with the following fields:
|
||||||
|
|
||||||
params: array of {name:,value:} or {value:} of parameters to be applied
|
params: array of {name:,value:,multiValue:} of parameters to be applied (name is optional)
|
||||||
text: text of variable, with parameters properly substituted
|
text: text of variable, with parameters properly substituted
|
||||||
resultList: result of variable evaluation as an array
|
resultList: result of variable evaluation as an array
|
||||||
srcVariable: reference to the object defining the variable
|
srcVariable: reference to the object defining the variable
|
||||||
@@ -140,7 +142,9 @@ Widget.prototype.getVariableInfo = function(name,options) {
|
|||||||
params = self.resolveVariableParameters(variable.params,actualParams);
|
params = self.resolveVariableParameters(variable.params,actualParams);
|
||||||
// Substitute any parameters specified in the definition
|
// Substitute any parameters specified in the definition
|
||||||
$tw.utils.each(params,function(param) {
|
$tw.utils.each(params,function(param) {
|
||||||
value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value);
|
if("name" in param) {
|
||||||
|
value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
value = self.substituteVariableReferences(value,options);
|
value = self.substituteVariableReferences(value,options);
|
||||||
resultList = [value];
|
resultList = [value];
|
||||||
@@ -154,13 +158,20 @@ Widget.prototype.getVariableInfo = function(name,options) {
|
|||||||
variables[param.name] = param["default"];
|
variables[param.name] = param["default"];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Parameters are an array of {value:} or {name:, value:} pairs
|
// Parameters are an array of {name:, value:, multivalue:} pairs (name and multivalue are optional)
|
||||||
$tw.utils.each(params,function(param) {
|
$tw.utils.each(params,function(param) {
|
||||||
variables[param.name] = param.value;
|
if(param.multiValue) {
|
||||||
|
variables[param.name] = param.multiValue;
|
||||||
|
} else {
|
||||||
|
variables[param.name] = param.value || "";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
resultList = this.wiki.filterTiddlers(value,this.makeFakeWidgetWithVariables(variables),options.source);
|
resultList = this.wiki.filterTiddlers(value,this.makeFakeWidgetWithVariables(variables),options.source);
|
||||||
value = resultList[0] || "";
|
value = resultList[0] || "";
|
||||||
} else {
|
} else {
|
||||||
|
if(variable.resultList) {
|
||||||
|
resultList = variable.resultList;
|
||||||
|
}
|
||||||
params = variable.params;
|
params = variable.params;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -192,22 +203,24 @@ Widget.prototype.getVariable = function(name,options) {
|
|||||||
/*
|
/*
|
||||||
Maps actual parameters onto formal parameters, returning an array of {name:,value:} objects
|
Maps actual parameters onto formal parameters, returning an array of {name:,value:} objects
|
||||||
formalParams - Array of {name:,default:} (default value is optional)
|
formalParams - Array of {name:,default:} (default value is optional)
|
||||||
actualParams - Array of string values or {name:,value:} (name is optional)
|
actualParams - Array of string values or {name:,value:,multiValue} (name and multiValue is optional)
|
||||||
*/
|
*/
|
||||||
Widget.prototype.resolveVariableParameters = function(formalParams,actualParams) {
|
Widget.prototype.resolveVariableParameters = function(formalParams,actualParams) {
|
||||||
formalParams = formalParams || [];
|
formalParams = formalParams || [];
|
||||||
actualParams = actualParams || [];
|
actualParams = actualParams || [];
|
||||||
var nextAnonParameter = 0, // Next candidate anonymous parameter in macro call
|
var nextAnonParameter = 0, // Next candidate anonymous parameter in macro call
|
||||||
paramInfo, paramValue,
|
paramInfo, paramValue, paramMultiValue,
|
||||||
results = [];
|
results = [];
|
||||||
// Step through each of the parameters in the macro definition
|
// Step through each of the parameters in the macro definition
|
||||||
for(var p=0; p<formalParams.length; p++) {
|
for(var p=0; p<formalParams.length; p++) {
|
||||||
// Check if we've got a macro call parameter with the same name
|
// Check if we've got a macro call parameter with the same name
|
||||||
paramInfo = formalParams[p];
|
paramInfo = formalParams[p];
|
||||||
paramValue = undefined;
|
paramValue = undefined;
|
||||||
|
paramMultiValue = undefined;
|
||||||
for(var m=0; m<actualParams.length; m++) {
|
for(var m=0; m<actualParams.length; m++) {
|
||||||
if(typeof actualParams[m] !== "string" && actualParams[m].name === paramInfo.name) {
|
if(typeof actualParams[m] !== "string" && actualParams[m].name === paramInfo.name) {
|
||||||
paramValue = actualParams[m].value;
|
paramValue = actualParams[m].value;
|
||||||
|
paramMultiValue = actualParams[m].multiValue || [paramValue]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If not, use the next available anonymous macro call parameter
|
// If not, use the next available anonymous macro call parameter
|
||||||
@@ -217,11 +230,13 @@ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams)
|
|||||||
if(paramValue === undefined && nextAnonParameter < actualParams.length) {
|
if(paramValue === undefined && nextAnonParameter < actualParams.length) {
|
||||||
var param = actualParams[nextAnonParameter++];
|
var param = actualParams[nextAnonParameter++];
|
||||||
paramValue = typeof param === "string" ? param : param.value;
|
paramValue = typeof param === "string" ? param : param.value;
|
||||||
|
paramMultiValue = typeof param === "string" ? [param] : (param.multiValue || [paramValue]);
|
||||||
}
|
}
|
||||||
// If we've still not got a value, use the default, if any
|
// If we've still not got a value, use the default, if any
|
||||||
paramValue = paramValue || paramInfo["default"] || "";
|
paramValue = paramValue || paramInfo["default"] || "";
|
||||||
|
paramMultiValue = paramMultiValue || [paramValue];
|
||||||
// Store the parameter name and value
|
// Store the parameter name and value
|
||||||
results.push({name: paramInfo.name, value: paramValue});
|
results.push({name: paramInfo.name, value: paramValue, multiValue: paramMultiValue});
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
@@ -310,7 +325,7 @@ Widget.prototype.getStateQualifier = function(name) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Make a fake widget with specified variables, suitable for variable lookup in filters
|
Make a fake widget with specified variables, suitable for variable lookup in filters. Each variable can be a string or an array of strings
|
||||||
*/
|
*/
|
||||||
Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
|
Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
|
||||||
var self = this,
|
var self = this,
|
||||||
@@ -318,7 +333,12 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
|
|||||||
return {
|
return {
|
||||||
getVariable: function(name,opts) {
|
getVariable: function(name,opts) {
|
||||||
if($tw.utils.hop(variables,name)) {
|
if($tw.utils.hop(variables,name)) {
|
||||||
return variables[name];
|
var value = variables[name];
|
||||||
|
if($tw.utils.isArray(value)) {
|
||||||
|
return value[0];
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
opts.variables = variables;
|
opts.variables = variables;
|
||||||
@@ -327,9 +347,18 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
|
|||||||
},
|
},
|
||||||
getVariableInfo: function(name,opts) {
|
getVariableInfo: function(name,opts) {
|
||||||
if($tw.utils.hop(variables,name)) {
|
if($tw.utils.hop(variables,name)) {
|
||||||
return {
|
var value = variables[name];
|
||||||
text: variables[name]
|
if($tw.utils.isArray(value)) {
|
||||||
};
|
return {
|
||||||
|
text: value[0],
|
||||||
|
resultList: value
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
text: value,
|
||||||
|
resultList: [value]
|
||||||
|
};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
opts.variables = $tw.utils.extend({},variables,opts.variables);
|
opts.variables = $tw.utils.extend({},variables,opts.variables);
|
||||||
@@ -366,20 +395,45 @@ Widget.prototype.computeAttributes = function(options) {
|
|||||||
return changedAttributes;
|
return changedAttributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
Widget.prototype.computeAttribute = function(attribute) {
|
/*
|
||||||
|
Compute the value of a single attribute. Options include:
|
||||||
|
asList: boolean if true returns results as an array instead of a single value
|
||||||
|
*/
|
||||||
|
Widget.prototype.computeAttribute = function(attribute,options) {
|
||||||
|
options = options || {};
|
||||||
var self = this,
|
var self = this,
|
||||||
value;
|
value;
|
||||||
if(attribute.type === "filtered") {
|
if(attribute.type === "filtered") {
|
||||||
value = this.wiki.filterTiddlers(attribute.filter,this)[0] || "";
|
value = this.wiki.filterTiddlers(attribute.filter,this);
|
||||||
|
if(!options.asList) {
|
||||||
|
value = value[0] || "";
|
||||||
|
}
|
||||||
} else if(attribute.type === "indirect") {
|
} else if(attribute.type === "indirect") {
|
||||||
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler")) || "";
|
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler"));
|
||||||
|
if(value && options.asList) {
|
||||||
|
value = [value];
|
||||||
|
}
|
||||||
} else if(attribute.type === "macro") {
|
} else if(attribute.type === "macro") {
|
||||||
var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params});
|
var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params});
|
||||||
value = variableInfo.text;
|
if(options.asList) {
|
||||||
|
value = variableInfo.resultList;
|
||||||
|
} else {
|
||||||
|
value = variableInfo.text;
|
||||||
|
}
|
||||||
} else if(attribute.type === "substituted") {
|
} else if(attribute.type === "substituted") {
|
||||||
value = this.wiki.getSubstitutedText(attribute.rawValue,this) || "";
|
value = this.wiki.getSubstitutedText(attribute.rawValue,this) || "";
|
||||||
|
if(options.asList) {
|
||||||
|
value = [value];
|
||||||
|
}
|
||||||
} else { // String attribute
|
} else { // String attribute
|
||||||
value = attribute.value;
|
value = attribute.value;
|
||||||
|
if(options.asList) {
|
||||||
|
if(value === undefined) {
|
||||||
|
value = [];
|
||||||
|
} else {
|
||||||
|
value = [value];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ exports.generateNewTitle = function(baseTitle,options) {
|
|||||||
c = (parseInt(options.startCount,10) > 0) ? parseInt(options.startCount,10) : 0,
|
c = (parseInt(options.startCount,10) > 0) ? parseInt(options.startCount,10) : 0,
|
||||||
prefix = (typeof(options.prefix) === "string") ? options.prefix : " ";
|
prefix = (typeof(options.prefix) === "string") ? options.prefix : " ";
|
||||||
|
|
||||||
if (template) {
|
if(template) {
|
||||||
// "count" is important to avoid an endless loop in while(...)!!
|
// "count" is important to avoid an endless loop in while(...)!!
|
||||||
template = (/\$count:?(\d+)?\$/i.test(template)) ? template : template + "$count$";
|
template = (/\$count:?(\d+)?\$/i.test(template)) ? template : template + "$count$";
|
||||||
// .formatTitleString() expects strings as input
|
// .formatTitleString() expects strings as input
|
||||||
@@ -209,7 +209,7 @@ exports.generateNewTitle = function(baseTitle,options) {
|
|||||||
title = $tw.utils.formatTitleString(template,{"base":baseTitle,"separator":prefix,"counter":(++c)+""});
|
title = $tw.utils.formatTitleString(template,{"base":baseTitle,"separator":prefix,"counter":(++c)+""});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (c > 0) {
|
if(c > 0) {
|
||||||
title = baseTitle + prefix + c;
|
title = baseTitle + prefix + c;
|
||||||
}
|
}
|
||||||
while(this.tiddlerExists(title) || this.isShadowTiddler(title) || this.findDraft(title)) {
|
while(this.tiddlerExists(title) || this.isShadowTiddler(title) || this.findDraft(title)) {
|
||||||
@@ -369,31 +369,16 @@ Sort an array of tiddler titles by a specified field
|
|||||||
isDescending: true if the sort should be descending
|
isDescending: true if the sort should be descending
|
||||||
isCaseSensitive: true if the sort should consider upper and lower case letters to be different
|
isCaseSensitive: true if the sort should consider upper and lower case letters to be different
|
||||||
*/
|
*/
|
||||||
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) {
|
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric,locale) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if(sortField === "title") {
|
if(sortField === "title") {
|
||||||
if(!isNumeric && !isAlphaNumeric) {
|
if(!isNumeric && !isAlphaNumeric) {
|
||||||
if(isCaseSensitive) {
|
const sorter = new Intl.Collator(locale, { sensitivity: isCaseSensitive ? "variant" : "accent" });
|
||||||
if(isDescending) {
|
if(isDescending) {
|
||||||
titles.sort(function(a,b) {
|
titles.sort((a,b) => sorter.compare(b, a));
|
||||||
return b.localeCompare(a);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
titles.sort(function(a,b) {
|
|
||||||
return a.localeCompare(b);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if(isDescending) {
|
titles.sort((a,b) => sorter.compare(a, b));
|
||||||
titles.sort(function(a,b) {
|
}
|
||||||
return b.toLowerCase().localeCompare(a.toLowerCase());
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
titles.sort(function(a,b) {
|
|
||||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
titles.sort(function(a,b) {
|
titles.sort(function(a,b) {
|
||||||
var x,y;
|
var x,y;
|
||||||
@@ -414,14 +399,8 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(isAlphaNumeric) {
|
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
|
||||||
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
|
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
|
||||||
}
|
|
||||||
if(!isCaseSensitive) {
|
|
||||||
a = a.toLowerCase();
|
|
||||||
b = b.toLowerCase();
|
|
||||||
}
|
|
||||||
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -463,14 +442,8 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
|
|||||||
}
|
}
|
||||||
a = String(a);
|
a = String(a);
|
||||||
b = String(b);
|
b = String(b);
|
||||||
if(isAlphaNumeric) {
|
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
|
||||||
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
|
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
|
||||||
}
|
|
||||||
if(!isCaseSensitive) {
|
|
||||||
a = a.toLowerCase();
|
|
||||||
b = b.toLowerCase();
|
|
||||||
}
|
|
||||||
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -532,7 +505,7 @@ exports.getTiddlerLinks = function(title) {
|
|||||||
return self.extractLinks(parser.tree);
|
return self.extractLinks(parser.tree);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
});
|
}).slice(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -551,8 +524,9 @@ exports.getTiddlerBacklinks = function(targetTitle) {
|
|||||||
backlinks.push(title);
|
backlinks.push(title);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return backlinks;
|
||||||
}
|
}
|
||||||
return backlinks;
|
return backlinks.slice(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -578,7 +552,7 @@ exports.extractTranscludes = function(parseTreeRoot, title) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(parseTreeNode.attributes.tiddler) {
|
} else if(parseTreeNode.attributes.tiddler) {
|
||||||
if (parseTreeNode.attributes.tiddler.type === "string") {
|
if(parseTreeNode.attributes.tiddler.type === "string") {
|
||||||
// Old transclude widget usage
|
// Old transclude widget usage
|
||||||
value = parseTreeNode.attributes.tiddler.value;
|
value = parseTreeNode.attributes.tiddler.value;
|
||||||
}
|
}
|
||||||
@@ -618,7 +592,7 @@ exports.getTiddlerTranscludes = function(title) {
|
|||||||
return self.extractTranscludes(parser.tree,title);
|
return self.extractTranscludes(parser.tree,title);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
});
|
}).slice(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -630,9 +604,9 @@ exports.getTiddlerBacktranscludes = function(targetTitle) {
|
|||||||
backtranscludes = backIndexer && backIndexer.subIndexers.transclude.lookup(targetTitle);
|
backtranscludes = backIndexer && backIndexer.subIndexers.transclude.lookup(targetTitle);
|
||||||
|
|
||||||
if(!backtranscludes) {
|
if(!backtranscludes) {
|
||||||
backtranscludes = [];
|
return [];
|
||||||
}
|
}
|
||||||
return backtranscludes;
|
return backtranscludes.slice(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -641,7 +615,7 @@ Return a hashmap of tiddler titles that are referenced but not defined. Each val
|
|||||||
exports.getMissingTitles = function() {
|
exports.getMissingTitles = function() {
|
||||||
var self = this,
|
var self = this,
|
||||||
missing = [];
|
missing = [];
|
||||||
// We should cache the missing tiddler list, even if we recreate it every time any tiddler is modified
|
// We should cache the missing tiddler list, even if we recreate it every time any tiddler is modified
|
||||||
this.forEachTiddler(function(title,tiddler) {
|
this.forEachTiddler(function(title,tiddler) {
|
||||||
var links = self.getTiddlerLinks(title);
|
var links = self.getTiddlerLinks(title);
|
||||||
$tw.utils.each(links,function(link) {
|
$tw.utils.each(links,function(link) {
|
||||||
@@ -683,7 +657,7 @@ exports.getTiddlersWithTag = function(tag) {
|
|||||||
return self.sortByList(tagmap[tag],tag);
|
return self.sortByList(tagmap[tag],tag);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return results;
|
return results.slice(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -734,7 +708,7 @@ exports.findListingsOfTiddler = function(targetTitle,fieldName) {
|
|||||||
for(var i = 0; i < list.length; i++) {
|
for(var i = 0; i < list.length; i++) {
|
||||||
var listItem = list[i],
|
var listItem = list[i],
|
||||||
listing = listings[listItem] || [];
|
listing = listings[listItem] || [];
|
||||||
if (listing.indexOf(title) === -1) {
|
if(listing.indexOf(title) === -1) {
|
||||||
listing.push(title);
|
listing.push(title);
|
||||||
}
|
}
|
||||||
listings[listItem] = listing;
|
listings[listItem] = listing;
|
||||||
@@ -743,7 +717,7 @@ exports.findListingsOfTiddler = function(targetTitle,fieldName) {
|
|||||||
});
|
});
|
||||||
return listings;
|
return listings;
|
||||||
});
|
});
|
||||||
return listings[targetTitle] || [];
|
return (listings[targetTitle] || []).slice(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -782,7 +756,7 @@ exports.sortByList = function(array,listTitle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If a new position is specified, let's move it
|
// If a new position is specified, let's move it
|
||||||
if (newPos !== -1) {
|
if(newPos !== -1) {
|
||||||
// get its current Pos, and make sure
|
// get its current Pos, and make sure
|
||||||
// sure that it's _actually_ in the list
|
// sure that it's _actually_ in the list
|
||||||
// and that it would _actually_ move
|
// and that it would _actually_ move
|
||||||
@@ -1059,17 +1033,7 @@ Options include:
|
|||||||
exports.parseText = function(type,text,options) {
|
exports.parseText = function(type,text,options) {
|
||||||
text = text || "";
|
text = text || "";
|
||||||
options = options || {};
|
options = options || {};
|
||||||
// Select a parser
|
var Parser = $tw.utils.getParser(type,options);
|
||||||
var Parser = $tw.Wiki.parsers[type];
|
|
||||||
if(!Parser && $tw.utils.getFileExtensionInfo(type)) {
|
|
||||||
Parser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type];
|
|
||||||
}
|
|
||||||
if(!Parser) {
|
|
||||||
Parser = $tw.Wiki.parsers[options.defaultType || "text/vnd.tiddlywiki"];
|
|
||||||
}
|
|
||||||
if(!Parser) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Return the parser instance
|
// Return the parser instance
|
||||||
return new Parser(type,text,{
|
return new Parser(type,text,{
|
||||||
parseAsInline: options.parseAsInline,
|
parseAsInline: options.parseAsInline,
|
||||||
@@ -1083,16 +1047,16 @@ exports.parseText = function(type,text,options) {
|
|||||||
Parse a tiddler according to its MIME type
|
Parse a tiddler according to its MIME type
|
||||||
*/
|
*/
|
||||||
exports.parseTiddler = function(title,options) {
|
exports.parseTiddler = function(title,options) {
|
||||||
options = $tw.utils.extend({},options);
|
options = options || {};
|
||||||
var cacheType = options.parseAsInline ? "inlineParseTree" : "blockParseTree",
|
var cacheType = options.parseAsInline ? "inlineParseTree" : "blockParseTree",
|
||||||
tiddler = this.getTiddler(title),
|
tiddler = this.getTiddler(title),
|
||||||
self = this;
|
self = this;
|
||||||
return tiddler ? this.getCacheForTiddler(title,cacheType,function() {
|
return tiddler ? this.getCacheForTiddler(title,cacheType,function() {
|
||||||
if(tiddler.hasField("_canonical_uri")) {
|
if(tiddler.hasField("_canonical_uri")) {
|
||||||
options._canonical_uri = tiddler.fields._canonical_uri;
|
options._canonical_uri = tiddler.fields._canonical_uri;
|
||||||
}
|
}
|
||||||
return self.parseText(tiddler.fields.type,tiddler.fields.text,options);
|
return self.parseText(tiddler.fields.type,tiddler.fields.text,options);
|
||||||
}) : null;
|
}) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.parseTextReference = function(title,field,index,options) {
|
exports.parseTextReference = function(title,field,index,options) {
|
||||||
@@ -1148,7 +1112,7 @@ exports.getTextReferenceParserInfo = function(title,field,index,options) {
|
|||||||
parserInfo.parserType = null;
|
parserInfo.parserType = null;
|
||||||
}
|
}
|
||||||
return parserInfo;
|
return parserInfo;
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parse a block of text of a specified MIME type
|
Parse a block of text of a specified MIME type
|
||||||
@@ -1174,7 +1138,7 @@ exports.getSubstitutedText = function(text,widget,options) {
|
|||||||
});
|
});
|
||||||
// Substitute any variable references with their values
|
// Substitute any variable references with their values
|
||||||
return output.replace(/\$\((.+?)\)\$/g, function(match,varname) {
|
return output.replace(/\$\((.+?)\)\$/g, function(match,varname) {
|
||||||
return widget.getVariable(varname,{defaultValue: ""})
|
return widget.getVariable(varname,{defaultValue: ""});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1252,7 +1216,7 @@ exports.makeTranscludeWidget = function(title,options) {
|
|||||||
name: "recursionMarker",
|
name: "recursionMarker",
|
||||||
type: "string",
|
type: "string",
|
||||||
value: options.recursionMarker || "yes"
|
value: options.recursionMarker || "yes"
|
||||||
},
|
},
|
||||||
tiddler: {
|
tiddler: {
|
||||||
name: "tiddler",
|
name: "tiddler",
|
||||||
type: "string",
|
type: "string",
|
||||||
@@ -1395,7 +1359,7 @@ exports.search = function(text,options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Accumulate the array of fields to be searched or excluded from the search
|
// Accumulate the array of fields to be searched or excluded from the search
|
||||||
var fields = [];
|
var fields = [];
|
||||||
if(options.field) {
|
if(options.field) {
|
||||||
if($tw.utils.isArray(options.field)) {
|
if($tw.utils.isArray(options.field)) {
|
||||||
@@ -1528,7 +1492,7 @@ exports.checkTiddlerText = function(title,targetText,options) {
|
|||||||
targetText = targetText.toLowerCase();
|
targetText = targetText.toLowerCase();
|
||||||
}
|
}
|
||||||
return text === targetText;
|
return text === targetText;
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Execute an action string without an associated context widget
|
Execute an action string without an associated context widget
|
||||||
@@ -1652,7 +1616,7 @@ exports.findDraft = function(targetTitle) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return draftTitle;
|
return draftTitle;
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check whether the specified draft tiddler has been modified.
|
Check whether the specified draft tiddler has been modified.
|
||||||
@@ -1679,7 +1643,7 @@ historyTitle: title of history tiddler (defaults to $:/HistoryList)
|
|||||||
exports.addToHistory = function(title,fromPageRect,historyTitle) {
|
exports.addToHistory = function(title,fromPageRect,historyTitle) {
|
||||||
var story = new $tw.Story({wiki: this, historyTitle: historyTitle});
|
var story = new $tw.Story({wiki: this, historyTitle: historyTitle});
|
||||||
story.addToHistory(title,fromPageRect);
|
story.addToHistory(title,fromPageRect);
|
||||||
console.log("$tw.wiki.addToHistory() is deprecated since V5.1.23! Use the this.story.addToHistory() from the story-object!")
|
console.log("$tw.wiki.addToHistory() is deprecated since V5.1.23! Use the this.story.addToHistory() from the story-object!");
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1692,7 +1656,7 @@ options: see story.js
|
|||||||
exports.addToStory = function(title,fromTitle,storyTitle,options) {
|
exports.addToStory = function(title,fromTitle,storyTitle,options) {
|
||||||
var story = new $tw.Story({wiki: this, storyTitle: storyTitle});
|
var story = new $tw.Story({wiki: this, storyTitle: storyTitle});
|
||||||
story.addToStory(title,fromTitle,options);
|
story.addToStory(title,fromTitle,options);
|
||||||
console.log("$tw.wiki.addToStory() is deprecated since V5.1.23! Use the this.story.addToStory() from the story-object!")
|
console.log("$tw.wiki.addToStory() is deprecated since V5.1.23! Use the this.story.addToStory() from the story-object!");
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
title: $:/core/templates/tiddlywiki5-external-js.html
|
title: $:/core/templates/tiddlywiki5-external-js.html
|
||||||
|
|
||||||
<$set name="saveTiddlerAndShadowsFilter" filter="[subfilter<saveTiddlerFilter>] [subfilter<saveTiddlerFilter>plugintiddlers[]]">
|
<$set name="saveTiddlerAndShadowsFilter" filter="[subfilter<saveTiddlerFilter>] [subfilter<saveTiddlerFilter>plugintiddlers[]]">
|
||||||
<$set name="rawMarkupFilter" filter="[enlist<saveTiddlerAndShadowsFilter>] +[[$:/core]plugintiddlers[]]">
|
<$set name="rawMarkupFilter" filter="[enlist<saveTiddlerAndShadowsFilter>] [[$:/core]plugintiddlers[]]">
|
||||||
`<!doctype html>
|
`<!doctype html>
|
||||||
`{{$:/core/templates/MOTW.html}}`<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
|
`{{$:/core/templates/MOTW.html}}`<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
|
||||||
<head>
|
<head>
|
||||||
|
|||||||
@@ -49,6 +49,27 @@ title: $:/core/ui/ImportListing
|
|||||||
\end
|
\end
|
||||||
|
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
|
<$let importJson={{{ [{$:/Import}] }}}>
|
||||||
|
<$let importTitles={{{ [<importJson>jsonindexes[tiddlers]] }}}>
|
||||||
|
<$let importTypes={{{ [(importTitles)] :map[<importJson>jsonget[tiddlers],<currentTiddler>,[type]] }}}>
|
||||||
|
<$let anyMatch={{{ [all[shadows+tiddlers]tag[$:/tags/ImportOptions]get[condition]] :map[(importTypes)subfilter<currentTiddler>] +[!is[blank]limit[1]] }}}>
|
||||||
|
<%if [<anyMatch>!is[blank]] %>
|
||||||
|
<div class="tc-import-option">
|
||||||
|
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ImportOptions]]" variable="importOption">
|
||||||
|
<$let condition={{{ [<importOption>get[condition]] }}}>
|
||||||
|
<$let hasMatch={{{ [(importTypes)subfilter<condition>limit[1]] }}}>
|
||||||
|
<%if [<hasMatch>!is[blank]] %>
|
||||||
|
<$transclude tiddler=<<importOption>>/>
|
||||||
|
<%endif%>
|
||||||
|
</$let>
|
||||||
|
</$let>
|
||||||
|
</$list>
|
||||||
|
</div>
|
||||||
|
<%endif%>
|
||||||
|
</$let>
|
||||||
|
</$let>
|
||||||
|
</$let>
|
||||||
|
</$let>
|
||||||
<div class="tc-table-wrapper">
|
<div class="tc-table-wrapper">
|
||||||
<table class="tc-import-table">
|
<table class="tc-import-table">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|||||||
@@ -3,27 +3,26 @@ tags: $:/tags/ControlPanel/Appearance
|
|||||||
caption: {{$:/language/ControlPanel/LayoutSwitcher/Caption}}
|
caption: {{$:/language/ControlPanel/LayoutSwitcher/Caption}}
|
||||||
|
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
|
\function layout.filter() [all[current]field:title[$:/core/ui/PageTemplate]]
|
||||||
|
\function layout.empty.filter() [all[current]field:title{$:/layout}]
|
||||||
|
|
||||||
<$linkcatcher to="$:/layout">
|
<$linkcatcher to="$:/layout">
|
||||||
<div class="tc-chooser">
|
<div class="tc-chooser" role="listbox">
|
||||||
<$list filter="[all[tiddlers+shadows]tag[$:/tags/Layout]] [[$:/core/ui/PageTemplate]] +[!is[draft]sort[name]]">
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/Layout]] [[$:/core/ui/PageTemplate]] +[!is[draft]sort[name]]">
|
||||||
<$list
|
<$list filter="[{$:/layout}!has[text]]" variable="ignore">
|
||||||
filter="[{$:/layout}!has[text]]"
|
<$list-empty>
|
||||||
variable="ignore"
|
<div class={{{ [layout.empty.filter[]then[tc-chooser-item tc-chosen]else[tc-chooser-item]] }}}>
|
||||||
emptyMessage="""\whitespace trim
|
<$link to={{!!title}} role="option" aria-selected={{{ [layout.empty.filter[]then[true]else[false]] }}}>
|
||||||
<$set name="cls" filter="[all[current]field:title{$:/layout}]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item">
|
''<$transclude tiddler={{{ [<currentTiddler>get[icon]] }}}/><$transclude field="name"/>'' - <$transclude field="description"/>
|
||||||
<div class=<<cls>>>
|
</$link>
|
||||||
<$link to={{!!title}}>
|
</div>
|
||||||
''<$transclude tiddler={{{ [<currentTiddler>get[icon]] }}}/><$transclude field="name"/>'' - <$transclude field="description"/>
|
</$list-empty>
|
||||||
</$link></div></$set>
|
<div class={{{ [layout.filter[]then[tc-chooser-item tc-chosen]else[tc-chooser-item]] }}}>
|
||||||
""">
|
<$link to={{!!title}} role="option" aria-selected={{{ [layout.filter[]then[true]else[false]] }}}>
|
||||||
<$set name="cls" filter="[all[current]field:title[$:/core/ui/PageTemplate]]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item">
|
''<$transclude tiddler={{{ [<currentTiddler>get[icon]] }}}/><$transclude field="name"/>'' - <$transclude field="description"/>
|
||||||
<div class=<<cls>>>
|
</$link>
|
||||||
<$link to={{!!title}}>
|
</div>
|
||||||
''<$transclude tiddler={{{ [<currentTiddler>get[icon]] }}}/><$transclude field="name"/>'' - <$transclude field="description"/>
|
</$list>
|
||||||
</$link>
|
|
||||||
</div>
|
|
||||||
</$set>
|
|
||||||
</$list>
|
|
||||||
</$list>
|
</$list>
|
||||||
</div>
|
</div>
|
||||||
</$linkcatcher>
|
</$linkcatcher>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
title: $:/core/ui/PageTemplate/alerts
|
title: $:/core/ui/PageTemplate/alerts
|
||||||
tags: $:/tags/PageTemplate
|
tags: $:/tags/PageTemplate
|
||||||
|
|
||||||
<div class="tc-alerts" role="region" aria-label="Alerts">
|
<div class="tc-alerts" role="region" aria-label={{$:/language/Alerts}}>
|
||||||
|
|
||||||
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Alert]!is[draft]]" template="$:/core/ui/AlertTemplate" storyview="pop"/>
|
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Alert]!is[draft]]" template="$:/core/ui/AlertTemplate" storyview="pop"/>
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ caption: {{$:/language/SideBar/Open/Caption}}
|
|||||||
|
|
||||||
\define droppable-item(button)
|
\define droppable-item(button)
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
<$droppable actions=<<drop-actions>> enable=<<tv-allow-drag-and-drop>> tag="div">
|
<$droppable actions=<<drop-actions>> enable=<<tv-enable-drag-and-drop>> tag="div">
|
||||||
<<placeholder>>
|
<<placeholder>>
|
||||||
<div>
|
<div>
|
||||||
$button$
|
$button$
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ title: $:/core/ui/TiddlerInfo
|
|||||||
|
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
<div style="position:relative;">
|
<div style="position:relative;">
|
||||||
<div class="tc-tiddler-controls" style="position:absolute;right:0;">
|
<div class="tc-tiddler-controls tc-tiddler-info-controls">
|
||||||
<$reveal state="$:/config/TiddlerInfo/Mode" type="match" text="sticky">
|
<$reveal state="$:/config/TiddlerInfo/Mode" type="match" text="sticky">
|
||||||
<$button set=<<tiddlerInfoState>> setTo="" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class="tc-btn-invisible">
|
<$button set=<<tiddlerInfoState>> setTo="" tooltip={{$:/language/Buttons/Info/Hint}} aria-label={{$:/language/Buttons/Info/Caption}} class="tc-btn-invisible">
|
||||||
{{$:/core/images/close-button}}
|
{{$:/core/images/close-button}}
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ tags: $:/tags/ViewTemplate
|
|||||||
storyview="pop"
|
storyview="pop"
|
||||||
variable="listItem"
|
variable="listItem"
|
||||||
>
|
>
|
||||||
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
|
<$let condition={{{ [<listItem>get[condition]] }}}>
|
||||||
<$transclude tiddler=<<listItem>>/>
|
<%if [<condition>!is[blank]] :and[<currentTiddler>subfilter<condition>limit[1]] :else[<condition>is[blank]then[true]] %>
|
||||||
</$set>
|
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
|
||||||
|
<$transclude tiddler=<<listItem>>/>
|
||||||
|
</$set>
|
||||||
|
<%endif%>
|
||||||
|
</$let>
|
||||||
</$list>
|
</$list>
|
||||||
</span>
|
</span>
|
||||||
<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>
|
<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ Drag this link to copy this tool to another wiki
|
|||||||
</$wikify>
|
</$wikify>
|
||||||
\end capture-item-wikified
|
\end capture-item-wikified
|
||||||
|
|
||||||
|
\function get.shadow.source() [shadowsource[]]
|
||||||
|
|
||||||
\procedure capture-wiki-info(tempWikiInfo)
|
\procedure capture-wiki-info(tempWikiInfo)
|
||||||
<$transclude $variable="capture-item-wikified" label="TiddlyWiki Version" value="<<version>>"/>
|
<$transclude $variable="capture-item-wikified" label="TiddlyWiki Version" value="<<version>>"/>
|
||||||
<$transclude $variable="capture-item" label="Current palette" value={{$:/palette}}/>
|
<$transclude $variable="capture-item" label="Current palette" value={{$:/palette}}/>
|
||||||
@@ -64,6 +66,7 @@ Drag this link to copy this tool to another wiki
|
|||||||
<$transclude $variable="capture-item" label="Keyboard shortcuts that have been customised" value={{{ [all[tiddlers]prefix[$:/config/shortcuts]] +[join[,]] }}}/>
|
<$transclude $variable="capture-item" label="Keyboard shortcuts that have been customised" value={{{ [all[tiddlers]prefix[$:/config/shortcuts]] +[join[,]] }}}/>
|
||||||
<$transclude $variable="capture-item" label="Disabled plugins" value={{{ [all[tiddlers]prefix[$:/config/Plugins/Disabled/]] :filter[{!!text}match[yes]] :map[<currentTiddler>removeprefix[$:/config/Plugins/Disabled/]] +[join[,]] }}}/>
|
<$transclude $variable="capture-item" label="Disabled plugins" value={{{ [all[tiddlers]prefix[$:/config/Plugins/Disabled/]] :filter[{!!text}match[yes]] :map[<currentTiddler>removeprefix[$:/config/Plugins/Disabled/]] +[join[,]] }}}/>
|
||||||
<$transclude $variable="capture-item" label="Plugins" value={{{ [has[plugin-type]sort[]] :filter[<currentTiddler>addprefix[$:/config/Plugins/Disabled/]get[text]else[no]!match[yes]] :map[{!!version}addprefix[ - ]addprefix<currentTiddler>] +[addprefix[ ]addprefix<crlf>join[]] }}}/>
|
<$transclude $variable="capture-item" label="Plugins" value={{{ [has[plugin-type]sort[]] :filter[<currentTiddler>addprefix[$:/config/Plugins/Disabled/]get[text]else[no]!match[yes]] :map[{!!version}addprefix[ - ]addprefix<currentTiddler>] +[addprefix[ ]addprefix<crlf>join[]] }}}/>
|
||||||
|
<$transclude $variable="capture-item" label="Stylesheets" value={{{ [all[shadows+tiddlers]tag[$:/tags/Stylesheet]!is[draft]] :map[is[shadow]addsuffix[ ∈ ]addsuffix<get.shadow.source>else<currentTiddler>] +[addprefix[ ]addprefix<crlf>join[]] }}}/>
|
||||||
\end capture-wiki-info
|
\end capture-wiki-info
|
||||||
|
|
||||||
\procedure template-header()
|
\procedure template-header()
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
title: $:/snippets/languageswitcher
|
title: $:/snippets/languageswitcher
|
||||||
|
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
|
\function language.filter() [all[current]field:title{$:/language}]
|
||||||
|
|
||||||
<$linkcatcher to="$:/language">
|
<$linkcatcher to="$:/language">
|
||||||
<div class="tc-chooser tc-language-chooser">
|
<div class="tc-chooser tc-language-chooser" role="listbox">
|
||||||
<$list filter="[[$:/languages/en-GB]] [plugin-type[language]sort[description]]">
|
<$list filter="[[$:/languages/en-GB]] [plugin-type[language]sort[description]]">
|
||||||
<$set name="cls" filter="[all[current]field:title{$:/language}]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item">
|
<div class={{{ [language.filter[]then[tc-chooser-item tc-chosen]else[tc-chooser-item]] }}} lang={{!!name}}>
|
||||||
<div class=<<cls>> lang={{!!name}}>
|
<$link role="option" aria-selected={{{ [language.filter[]then[true]else[false]] }}}>
|
||||||
<$link>
|
<$view field="description">
|
||||||
<$view field="description">
|
<$view field="name">
|
||||||
<$view field="name">
|
<$view field="title"/>
|
||||||
<$view field="title"/>
|
</$view>
|
||||||
</$view>
|
</$view>
|
||||||
</$view>
|
</$link>
|
||||||
</$link>
|
</div>
|
||||||
</div>
|
|
||||||
</$set>
|
|
||||||
</$list>
|
</$list>
|
||||||
</div>
|
</div>
|
||||||
</$linkcatcher>
|
</$linkcatcher>
|
||||||
39
core/wiki/macros/CSS-property.tid
Normal file
39
core/wiki/macros/CSS-property.tid
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
title: $:/core/macros/CSS/property
|
||||||
|
|
||||||
|
<!-- CSS property macros -->
|
||||||
|
|
||||||
|
<!-- TODO: Deprecate the following CSS macros once 2020 baseline is supported -->
|
||||||
|
|
||||||
|
\procedure margin-start(size)
|
||||||
|
-webkit-margin-start: <<size>>;
|
||||||
|
margin-inline-start: <<size>>;
|
||||||
|
\end
|
||||||
|
|
||||||
|
\procedure margin-end(size)
|
||||||
|
-webkit-margin-end: <<size>>;
|
||||||
|
margin-inline-end: <<size>>;
|
||||||
|
\end
|
||||||
|
|
||||||
|
\procedure padding-start(size)
|
||||||
|
-webkit-padding-start: <<size>>;
|
||||||
|
padding-inline-start: <<size>>;
|
||||||
|
\end
|
||||||
|
|
||||||
|
\procedure padding-end(size)
|
||||||
|
-webkit-padding-end: <<size>>;
|
||||||
|
padding-inline-end: <<size>>;
|
||||||
|
\end
|
||||||
|
|
||||||
|
\procedure margin-inline(start,end)
|
||||||
|
-webkit-margin-start: <<start>>;
|
||||||
|
margin-inline-start: <<start>>;
|
||||||
|
-webkit-margin-end: <<end>>;
|
||||||
|
margin-inline-end: <<end>>;
|
||||||
|
\end
|
||||||
|
|
||||||
|
\procedure padding-inline(start,end)
|
||||||
|
-webkit-padding-start: <<start>>;
|
||||||
|
padding-inline-start: <<start>>;
|
||||||
|
-webkit-padding-end: <<end>>;
|
||||||
|
padding-inline-end: <<end>>;
|
||||||
|
\end
|
||||||
@@ -13,56 +13,6 @@ tags: $:/tags/Macro
|
|||||||
|
|
||||||
\define color(name) <<colour $name$>>
|
\define color(name) <<colour $name$>>
|
||||||
|
|
||||||
\define box-shadow(shadow)
|
|
||||||
``
|
|
||||||
-webkit-box-shadow: $shadow$;
|
|
||||||
-moz-box-shadow: $shadow$;
|
|
||||||
box-shadow: $shadow$;
|
|
||||||
``
|
|
||||||
\end
|
|
||||||
|
|
||||||
\define filter(filter)
|
|
||||||
``
|
|
||||||
-webkit-filter: $filter$;
|
|
||||||
-moz-filter: $filter$;
|
|
||||||
filter: $filter$;
|
|
||||||
``
|
|
||||||
\end
|
|
||||||
|
|
||||||
\define transition(transition)
|
|
||||||
``
|
|
||||||
-webkit-transition: $transition$;
|
|
||||||
-moz-transition: $transition$;
|
|
||||||
transition: $transition$;
|
|
||||||
``
|
|
||||||
\end
|
|
||||||
|
|
||||||
\define transform-origin(origin)
|
|
||||||
``
|
|
||||||
-webkit-transform-origin: $origin$;
|
|
||||||
-moz-transform-origin: $origin$;
|
|
||||||
transform-origin: $origin$;
|
|
||||||
``
|
|
||||||
\end
|
|
||||||
|
|
||||||
\define background-linear-gradient(gradient)
|
|
||||||
``
|
|
||||||
background-image: linear-gradient($gradient$);
|
|
||||||
background-image: -o-linear-gradient($gradient$);
|
|
||||||
background-image: -moz-linear-gradient($gradient$);
|
|
||||||
background-image: -webkit-linear-gradient($gradient$);
|
|
||||||
background-image: -ms-linear-gradient($gradient$);
|
|
||||||
``
|
|
||||||
\end
|
|
||||||
|
|
||||||
\define column-count(columns)
|
|
||||||
``
|
|
||||||
-moz-column-count: $columns$;
|
|
||||||
-webkit-column-count: $columns$;
|
|
||||||
column-count: $columns$;
|
|
||||||
``
|
|
||||||
\end
|
|
||||||
|
|
||||||
\procedure datauri(title)
|
\procedure datauri(title)
|
||||||
<$macrocall $name="makedatauri" type={{{ [<title>get[type]] }}} text={{{ [<title>get[text]] }}} _canonical_uri={{{ [<title>get[_canonical_uri]] }}}/>
|
<$macrocall $name="makedatauri" type={{{ [<title>get[type]] }}} text={{{ [<title>get[text]] }}} _canonical_uri={{{ [<title>get[_canonical_uri]] }}}/>
|
||||||
\end
|
\end
|
||||||
|
|||||||
43
core/wiki/macros/deprecated.tid
Normal file
43
core/wiki/macros/deprecated.tid
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
title: $:/core/macros/deprecated
|
||||||
|
tags: $:/tags/Macro
|
||||||
|
|
||||||
|
<!-- Deprecated Macros -->
|
||||||
|
<!-- DO NOT USE THESE MACROS. THEY MAY BE REMOVED AT ANY MOMENT -->
|
||||||
|
|
||||||
|
\define box-shadow(shadow)
|
||||||
|
``
|
||||||
|
box-shadow: $shadow$;
|
||||||
|
``
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define filter(filter)
|
||||||
|
``
|
||||||
|
filter: $filter$;
|
||||||
|
``
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define transition(transition)
|
||||||
|
``
|
||||||
|
transition: $transition$;
|
||||||
|
``
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define transform-origin(origin)
|
||||||
|
``
|
||||||
|
transform-origin: $origin$;
|
||||||
|
``
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define background-linear-gradient(gradient)
|
||||||
|
``
|
||||||
|
background-image: linear-gradient($gradient$);
|
||||||
|
background-image: -moz-linear-gradient($gradient$);
|
||||||
|
background-image: -webkit-linear-gradient($gradient$);
|
||||||
|
``
|
||||||
|
\end
|
||||||
|
|
||||||
|
\define column-count(columns)
|
||||||
|
``
|
||||||
|
column-count: $columns$;
|
||||||
|
``
|
||||||
|
\end
|
||||||
@@ -22,7 +22,7 @@ tags: $:/tags/Macro
|
|||||||
<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter="+[insertbefore<actionTiddler>,<currentTiddler>]"/>
|
<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter="+[insertbefore<actionTiddler>,<currentTiddler>]"/>
|
||||||
\end
|
\end
|
||||||
|
|
||||||
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate)
|
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate, displayField:"caption")
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
<$set name="_tiddler" value="""$tiddler$""" emptyValue=<<currentTiddler>> >
|
<$set name="_tiddler" value="""$tiddler$""" emptyValue=<<currentTiddler>> >
|
||||||
<$let field-reference={{{ [<_tiddler>] "!!" [[$field$]] +[join[]] }}}
|
<$let field-reference={{{ [<_tiddler>] "!!" [[$field$]] +[join[]] }}}
|
||||||
@@ -42,7 +42,7 @@ tags: $:/tags/Macro
|
|||||||
<$transclude tiddler="""$itemTemplate$""">
|
<$transclude tiddler="""$itemTemplate$""">
|
||||||
<$link to={{!!title}}>
|
<$link to={{!!title}}>
|
||||||
<$let tv-wikilinks="no">
|
<$let tv-wikilinks="no">
|
||||||
<$transclude field="caption">
|
<$transclude field=<<__displayField__>>>
|
||||||
<$view field="title"/>
|
<$view field="title"/>
|
||||||
</$transclude>
|
</$transclude>
|
||||||
</$let>
|
</$let>
|
||||||
@@ -92,7 +92,7 @@ tags: $:/tags/Macro
|
|||||||
</$set>
|
</$set>
|
||||||
\end
|
\end
|
||||||
|
|
||||||
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"")
|
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"",displayField:"title")
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
<span class="tc-tagged-draggable-list">
|
<span class="tc-tagged-draggable-list">
|
||||||
<$set name="tag" value=<<__tag__>>>
|
<$set name="tag" value=<<__tag__>>>
|
||||||
@@ -110,7 +110,11 @@ tags: $:/tags/Macro
|
|||||||
<$genesis $type=<<__elementTag__>>>
|
<$genesis $type=<<__elementTag__>>>
|
||||||
<$transclude tiddler="""$itemTemplate$""">
|
<$transclude tiddler="""$itemTemplate$""">
|
||||||
<$link to={{!!title}}>
|
<$link to={{!!title}}>
|
||||||
<$view field="title"/>
|
<$let tv-wikilinks="no">
|
||||||
|
<$transclude field=<<__displayField__>>>
|
||||||
|
<$view field="title"/>
|
||||||
|
</$transclude>
|
||||||
|
</$let>
|
||||||
</$link>
|
</$link>
|
||||||
</$transclude>
|
</$transclude>
|
||||||
</$genesis>
|
</$genesis>
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ code-body: yes
|
|||||||
setTo=<<currentTab>>
|
setTo=<<currentTab>>
|
||||||
default=<<__default__>>
|
default=<<__default__>>
|
||||||
selectedClass="tc-tab-selected"
|
selectedClass="tc-tab-selected"
|
||||||
|
selectedAria="aria-selected"
|
||||||
tooltip={{!!tooltip}}
|
tooltip={{!!tooltip}}
|
||||||
role="switch"
|
role="tab"
|
||||||
data-tab-title=<<currentTab>>
|
data-tab-title=<<currentTab>>
|
||||||
>
|
>
|
||||||
<$tiddler tiddler=<<save-currentTiddler>>>
|
<$tiddler tiddler=<<save-currentTiddler>>>
|
||||||
@@ -57,12 +58,12 @@ code-body: yes
|
|||||||
\whitespace trim
|
\whitespace trim
|
||||||
<$qualify title=<<__state__>> name="qualifiedState">
|
<$qualify title=<<__state__>> name="qualifiedState">
|
||||||
<$let tabsState={{{ [<__explicitState__>minlength[1]] ~[<qualifiedState>] }}}>
|
<$let tabsState={{{ [<__explicitState__>minlength[1]] ~[<qualifiedState>] }}}>
|
||||||
<div class={{{ [[tc-tab-set]addsuffix[ ]addsuffix<__class__>] }}}>
|
<div class={{{ [[tc-tab-set]addsuffix[ ]addsuffix<__class__>] }}} role="tablist">
|
||||||
<div class={{{ [[tc-tab-buttons]addsuffix[ ]addsuffix<__class__>] }}}>
|
<div class={{{ [[tc-tab-buttons]addsuffix[ ]addsuffix<__class__>] }}}>
|
||||||
<<tabs-tab-list>>
|
<<tabs-tab-list>>
|
||||||
</div>
|
</div>
|
||||||
<div class={{{ [[tc-tab-divider]addsuffix[ ]addsuffix<__class__>] }}}/>
|
<div class={{{ [[tc-tab-divider]addsuffix[ ]addsuffix<__class__>] }}}/>
|
||||||
<div class={{{ [[tc-tab-content]addsuffix[ ]addsuffix<__class__>] }}}>
|
<div class={{{ [[tc-tab-content]addsuffix[ ]addsuffix<__class__>] }}} role="tabpanel">
|
||||||
<<tabs-tab-body>>
|
<<tabs-tab-body>>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ second-search-filter: [subfilter<tagListFilter>is[system]search:title<userInput>
|
|||||||
|
|
||||||
<!-- clean up temporary tiddlers, so the next "pick" starts with a clean input -->
|
<!-- clean up temporary tiddlers, so the next "pick" starts with a clean input -->
|
||||||
<!-- This could probably be optimized / removed if we would use different temp-tiddlers
|
<!-- This could probably be optimized / removed if we would use different temp-tiddlers
|
||||||
(future improvement because keeping track is comlex for humans)
|
(future improvement because keeping track is complex for humans)
|
||||||
-->
|
-->
|
||||||
\procedure delete-tag-state-tiddlers()
|
\procedure delete-tag-state-tiddlers()
|
||||||
<$action-deletetiddler $filter="[<newTagNameTiddler>] [<storeTitle>] [<tagSelectionState>]"/>
|
<$action-deletetiddler $filter="[<newTagNameTiddler>] [<storeTitle>] [<tagSelectionState>]"/>
|
||||||
@@ -111,6 +111,7 @@ The second ESC tries to close the "draft tiddler"
|
|||||||
refreshTitle=<<refreshTitle>>
|
refreshTitle=<<refreshTitle>>
|
||||||
selectionStateTitle=<<tagSelectionState>>
|
selectionStateTitle=<<tagSelectionState>>
|
||||||
inputAcceptActions=<<add-tag-actions>>
|
inputAcceptActions=<<add-tag-actions>>
|
||||||
|
inputAcceptVariantActions=<<save-tiddler-actions>>
|
||||||
inputCancelActions=<<clear-tags-actions>>
|
inputCancelActions=<<clear-tags-actions>>
|
||||||
tag="input"
|
tag="input"
|
||||||
placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}
|
placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
title: $:/snippets/themeswitcher
|
title: $:/snippets/themeswitcher
|
||||||
|
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
|
\function theme.filter() [all[current]field:title{$:/theme}] [[$:/theme]!has[text]addsuffix[s/tiddlywiki/vanilla]field:title<currentTiddler>] +[limit[1]]
|
||||||
|
|
||||||
<$linkcatcher to="$:/theme">
|
<$linkcatcher to="$:/theme">
|
||||||
<div class="tc-chooser">
|
<div class="tc-chooser" role="listbox">
|
||||||
<$list filter="[plugin-type[theme]sort[title]]">
|
<$list filter="[plugin-type[theme]sort[title]]">
|
||||||
<$set name="cls" filter="[all[current]field:title{$:/theme}] [[$:/theme]!has[text]addsuffix[s/tiddlywiki/vanilla]field:title<currentTiddler>] +[limit[1]]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item">
|
<div class={{{ [theme.filter[]then[tc-chooser-item tc-chosen]else[tc-chooser-item]] }}}>
|
||||||
<div class=<<cls>>><$link to={{!!title}}>
|
<$link to={{!!title}} role="option" aria-selected={{{ [theme.filter[]then[true]else[false]] }}}>
|
||||||
''<$view field="name" format="text"/>''
|
''<$view field="name" format="text"/>''
|
||||||
 
|
 
|
||||||
<$view field="description" format="text"/>
|
<$view field="description" format="text"/>
|
||||||
</$link>
|
</$link>
|
||||||
</div>
|
</div>
|
||||||
</$set>
|
|
||||||
</$list>
|
</$list>
|
||||||
</div>
|
</div>
|
||||||
</$linkcatcher>
|
</$linkcatcher>
|
||||||
@@ -4,13 +4,14 @@ title: $:/snippets/viewswitcher
|
|||||||
$:/core/images/storyview-$(storyview)$
|
$:/core/images/storyview-$(storyview)$
|
||||||
\end
|
\end
|
||||||
\whitespace trim
|
\whitespace trim
|
||||||
|
\function view.filter() [<storyview>prefix{$:/view}]
|
||||||
|
|
||||||
<$linkcatcher to="$:/view">
|
<$linkcatcher to="$:/view">
|
||||||
<div class="tc-chooser tc-viewswitcher">
|
<div class="tc-chooser tc-viewswitcher" role="listbox">
|
||||||
<$list filter="[storyviews[]]" variable="storyview">
|
<$list filter="[storyviews[]]" variable="storyview">
|
||||||
<$set name="cls" filter="[<storyview>prefix{$:/view}]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item"><div class=<<cls>>>
|
<div class={{{ [view.filter[]then[tc-chooser-item tc-chosen]else[tc-chooser-item]] }}}>
|
||||||
<$button tag="a" class="tc-tiddlylink tc-btn-invisible" to=<<storyview>>><$transclude tiddler=<<icon>>/><$text text=<<storyview>>/></$button>
|
<$button tag="a" class="tc-tiddlylink tc-btn-invisible" role="option" to=<<storyview>> aria-selected={{{ [view.filter[]then[true]else[false]] }}}><$transclude tiddler=<<icon>>/><$text text=<<storyview>>/></$button>
|
||||||
</div>
|
</div>
|
||||||
</$set>
|
|
||||||
</$list>
|
</$list>
|
||||||
</div>
|
</div>
|
||||||
</$linkcatcher>
|
</$linkcatcher>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"tiddlers": [
|
"tiddlers": [
|
||||||
{
|
{
|
||||||
"file": "../../../tw5.com/tiddlers/images/New Release Banner.png",
|
"file": "../../../tw5.com/tiddlers/images/New Release Banner.webp",
|
||||||
"fields": {
|
"fields": {
|
||||||
"type": "image/jpeg",
|
"type": "image/webp",
|
||||||
"title": "New Release Banner",
|
"title": "New Release Banner",
|
||||||
"tags": "picture"
|
"tags": "picture"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ title: Using TiddlyWiki as a library in another Node.js application
|
|||||||
|
|
||||||
Node.js applications can include TiddlyWiki as a library so that they can use wikitext rendering.
|
Node.js applications can include TiddlyWiki as a library so that they can use wikitext rendering.
|
||||||
|
|
||||||
See the demo at https://github.com/TiddlyWiki/TiddlyWiki5DemoApp
|
See the demo at https://github.com/Jermolene/TiddlyWiki5DemoApp
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user