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

Compare commits

..

10 Commits

Author SHA1 Message Date
Jeremy Ruston
2fab886564 Add incompleteness warning 2025-11-09 15:42:33 +00:00
Jeremy Ruston
f4db2300be Disable the #8702 changenote as it is not yet merged 2025-11-09 15:42:11 +00:00
Jeremy Ruston
33d3372229 Styling refinements 2025-11-09 15:37:50 +00:00
Jeremy Ruston
7a304df673 Update field names 2025-11-09 15:16:07 +00:00
Jeremy Ruston
a273ed05eb Embarrassing typo 2025-11-06 21:26:54 +00:00
Jeremy Ruston
a4721ce24a Merge branch 'master' into new-release-note-architecture 2025-11-05 12:37:59 +00:00
Jeremy Ruston
3ab6302353 Formatting. More to do. 2025-11-05 10:54:32 +00:00
Jeremy Ruston
85ed513bef Slightly better description for v5.4.0 2025-11-05 10:54:15 +00:00
Jeremy Ruston
1832aff565 Add more tickets for demo and testing purposes 2025-11-05 10:54:02 +00:00
Jeremy Ruston
a07ecb6156 Introduce impact notes attached to change notes
No styles yet
2025-11-02 12:09:03 +00:00
327 changed files with 3290 additions and 5013 deletions

4
.gitattributes vendored
View File

@@ -1,4 +0,0 @@
boot/** -linguist-generated
**/tiddlywiki.files linguist-language=JSON
**/tiddlywiki.info linguist-language=JSON
**/plugin.info linguist-language=JSON

View File

@@ -1,62 +0,0 @@
---
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 Normal file
View File

@@ -0,0 +1,67 @@
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.

View File

@@ -4,23 +4,17 @@ about: Suggest an idea for TiddlyWiki 5
title: "[IDEA]"
labels: ''
assignees: ''
type: idea
---
**Is your idea related to a problem? Please describe.**
A clear and concise description of what the problem is. Eg:
As a user, I would like [...]
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -20,7 +20,7 @@ jobs:
steps:
- name: build-size-check
id: get_sizes
uses: TiddlyWiki/cerebrus@v6
uses: TiddlyWiki/cerebrus@v4
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}

View File

@@ -25,7 +25,7 @@ jobs:
steps:
- name: Build and check size
uses: TiddlyWiki/cerebrus@v6
uses: TiddlyWiki/cerebrus@v4
with:
pr_number: ${{ inputs.pr_number }}
repo: ${{ github.repository }}

View File

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

View File

@@ -1,37 +0,0 @@
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

View File

@@ -8,8 +8,6 @@ On the server this file is executed directly to boot TiddlyWiki. In the browser,
\*/
/* eslint-disable @stylistic/indent */
var _boot = (function($tw) {
/*jslint node: true, browser: true */
@@ -46,8 +44,12 @@ $tw.utils.hop = function(object,property) {
return object ? Object.prototype.hasOwnProperty.call(object,property) : false;
};
/** @deprecated Use Array.isArray instead */
$tw.utils.isArray = value => Array.isArray(value);
/*
Determine if a value is an array
*/
$tw.utils.isArray = function(value) {
return Object.prototype.toString.call(value) == "[object Array]";
};
/*
Check if an array is equal by value and by reference.
@@ -126,22 +128,35 @@ $tw.utils.pushTop = function(array,value) {
return array;
};
/** @deprecated Use instanceof Date instead */
$tw.utils.isDate = value => value instanceof Date;
/*
Determine if a value is a 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) {
var next,f,length;
if(object) {
if(Array.isArray(object)) {
object.every((element,index,array) => {
const next = callback(element,index,array);
return next !== false;
});
if(Object.prototype.toString.call(object) == "[object Array]") {
for(f=0, length=object.length; f<length; f++) {
next = callback(object[f],f,object);
if(next === false) {
break;
}
}
} else {
Object.entries(object).every(entry => {
const next = callback(entry[1], entry[0], object);
return next !== false;
});
var keys = Object.keys(object);
for(f=0, length=keys.length; f<length; f++) {
var key = keys[f];
next = callback(object[key],key,object);
if(next === false) {
break;
}
}
}
}
};
@@ -316,13 +331,32 @@ $tw.utils.htmlDecode = function(s) {
return s.toString().replace(/&lt;/mg,"<").replace(/&nbsp;/mg,"\xA0").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/mg,"&");
};
/** @deprecated Use window.location.hash instead. */
$tw.utils.getLocationHash = () => window.location.hash;
/*
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 = 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 */
$tw.utils.pad = function(value,length = 2) {
const s = value.toString();
return s.padStart(length, "0");
/*
Pad a string to a given length with "0"s. Length defaults to 2
*/
$tw.utils.pad = function(value,length) {
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
@@ -596,7 +630,7 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
// Compile the code into a function
var fn;
if($tw.browser) {
fn = window["eval"](code + "\n\n//# sourceURL=" + filename); // eslint-disable-line no-eval -- See https://github.com/TiddlyWiki/TiddlyWiki5/issues/6839
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
} else {
if(sandbox){
fn = vm.runInContext(code,sandbox,filename)
@@ -2767,8 +2801,6 @@ return $tw;
});
/* eslint-enable @stylistic/indent */
if(typeof(exports) !== "undefined") {
exports.TiddlyWiki = _boot;
} else {

View File

@@ -12,8 +12,6 @@ See Boot.js for further details of the boot process.
\*/
/* eslint-disable @stylistic/indent */
var _bootprefix = (function($tw) {
"use strict";
@@ -116,8 +114,6 @@ return $tw;
});
/* eslint-enable @stylistic/indent */
if(typeof(exports) === "undefined") {
// Set up $tw global for the browser
window.$tw = _bootprefix(window.$tw);

View File

@@ -1,14 +0,0 @@
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.

View File

@@ -1,19 +0,0 @@
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 dont want to forget any of them. When Im deeply focused on a task, its 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, Ive 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.

View File

@@ -1,25 +0,0 @@
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 thats 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

View File

@@ -1,19 +0,0 @@
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

View File

@@ -1,8 +1,8 @@
created: 20250909171928024
modified: 20251110133437795
tags: Community/Team
team: @MotovunJack
title: Infrastructure Team
tags: Community/Team
modified: 20250909171928024
created: 20250909171928024
team: @MotovunJack
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,4 +12,3 @@ The infrastructure includes:
* github.com/TiddlyWiki
* tiddlywiki.com DNS
* Netlify account for PR previews
* edit.tiddlywiki.com

View File

@@ -0,0 +1,6 @@
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.

View File

@@ -1,11 +0,0 @@
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.

View File

@@ -1,15 +0,0 @@
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.

View File

@@ -1,5 +1,5 @@
title: Community/Team
modified: 20250909171928024
created: 20250909171928024
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[Quality Assurance Team]] [[Infrastructure Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Succession Team]]
list: [[Project Team]] [[Core Team]] [[Documentation Team]] [[MultiWikiServer Team]] [[Newsletter Team]] [[Infrastructure Team]] [[Succession Team]]

View File

@@ -1,30 +0,0 @@
/*\
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));

View File

@@ -1,95 +0,0 @@
/*\
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: theres 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 */
})();

View File

@@ -5,4 +5,3 @@ TiddlyWiki incorporates code from these fine OpenSource projects:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[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]]

View File

@@ -1,6 +1,5 @@
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:
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.

View File

@@ -156,8 +156,8 @@ Fix the height of textarea to fit content
FramedEngine.prototype.fixHeight = function() {
// Make sure styles are updated
this.copyStyles();
// If .editRows is initialised, it takes precedence
if(this.widget.editTag === "textarea" && !this.widget.editRows) {
// Adjust height
if(this.widget.editTag === "textarea") {
if(this.widget.editAutoHeight) {
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);

View File

@@ -100,8 +100,7 @@ SimpleEngine.prototype.getText = function() {
Fix the height of textarea to fit content
*/
SimpleEngine.prototype.fixHeight = function() {
// If .editRows is initialised, it takes precedence
if((this.widget.editTag === "textarea") && !this.widget.editRows) {
if(this.widget.editTag === "textarea") {
if(this.widget.editAutoHeight) {
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);

View File

@@ -1,41 +0,0 @@
/*\
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
};
};
};

View File

@@ -35,7 +35,7 @@ function parseFilterOperation(operators,filterString,p) {
operator.prefix = filterString.charAt(p++);
}
// Get the operator name
nextBracketPos = filterString.substring(p).search(/[\[\{<\/\(]/);
nextBracketPos = filterString.substring(p).search(/[\[\{<\/]/);
if(nextBracketPos === -1) {
throw "Missing [ in filter expression";
}
@@ -79,17 +79,13 @@ function parseFilterOperation(operators,filterString,p) {
operand.variable = true;
nextBracketPos = filterString.indexOf(">",p);
break;
case "(": // Round brackets
operand.multiValuedVariable = true;
nextBracketPos = filterString.indexOf(")",p);
break;
case "/": // regexp brackets
var rex = /^((?:[^\\\/]|\\.)*)\/(?:\(([mygi]+)\))?/g,
rexMatch = rex.exec(filterString.substring(p));
if(rexMatch) {
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
// DEPRECATION WARNING
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
// DEPRECATION WARNING
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
nextBracketPos = p + rex.lastIndex - 1;
}
else {
@@ -116,7 +112,7 @@ function parseFilterOperation(operators,filterString,p) {
// Check for multiple operands
while(filterString.charAt(p) === ",") {
p++;
if(/^[\[\{<\/\(]/.test(filterString.substring(p))) {
if(/^[\[\{<\/]/.test(filterString.substring(p))) {
nextBracketPos = p;
p++;
parseOperand(filterString.charAt(nextBracketPos));
@@ -145,15 +141,7 @@ exports.parseFilter = function(filterString) {
p = 0, // Current position in the filter string
match;
var whitespaceRegExp = /(\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;
operandRegExp = /((?:\+|\-|~|=|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
while(p < filterString.length) {
// Skip any whitespace
whitespaceRegExp.lastIndex = p;
@@ -164,45 +152,38 @@ exports.parseFilter = function(filterString) {
// Match the start of the operation
if(p < filterString.length) {
operandRegExp.lastIndex = p;
match = operandRegExp.exec(filterString);
if(!match || match.index !== p) {
throw $tw.language.getString("Error/FilterSyntax");
}
var operation = {
prefix: "",
operators: []
};
match = operandRegExp.exec(filterString);
if(match && match.index === p) {
// If there is a filter run prefix
if(match[1]) {
operation.prefix = match[1];
p = p + operation.prefix.length;
// Name for named prefixes
if(match[2]) {
operation.namedPrefix = match[2];
}
// Suffixes for filter run prefix
if(match[3]) {
operation.suffixes = [];
$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);
}
});
if(match[1]) {
operation.prefix = match[1];
p = p + operation.prefix.length;
if(match[2]) {
operation.namedPrefix = match[2];
}
if(match[3]) {
operation.suffixes = [];
$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;
}
} else {
// No filter run prefix
p = parseFilterOperation(operation.operators,filterString,p);
}
// Quoted strings and unquoted title
if(match[4]) { // Opening square bracket
p = parseFilterOperation(operation.operators,filterString,p);
} else {
p = match.index + match[0].length;
}
if(match[5] || match[6] || match[7]) { // Double quoted string, single quoted string or unquoted title
operation.operators.push(
{operator: "title", operands: [{text: match[5] || match[6] || match[7]}]}
@@ -232,12 +213,7 @@ exports.getFilterRunPrefixes = function() {
exports.filterTiddlers = function(filterString,widget,source) {
var fn = this.compileFilter(filterString);
try {
const fnResult = fn.call(this,source,widget);
return fnResult;
} catch(e) {
return [`${$tw.language.getString("Error/Filter")}: ${e}`];
}
return fn.call(this,source,widget);
};
/*
@@ -275,8 +251,6 @@ exports.compileFilter = function(filterString) {
results = [];
$tw.utils.each(operation.operators,function(operator) {
var operands = [],
multiValueOperands = [],
isMultiValueOperand = [],
operatorFunction;
if(!operator.operator) {
// Use the "title" operator if no operator is specified
@@ -292,46 +266,28 @@ exports.compileFilter = function(filterString) {
if(operand.indirect) {
var currTiddlerTitle = widget && widget.getVariable("currentTiddler");
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
operand.multiValue = [operand.value];
} else if(operand.variable) {
var varTree = $tw.utils.parseFilterVariable(operand.text);
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 {
operand.value = operand.text;
operand.multiValue = [operand.value];
}
operands.push(operand.value);
multiValueOperands.push(operand.multiValue);
isMultiValueOperand.push(!!operand.isMultiValueOperand);
});
// Invoke the appropriate filteroperator module
results = operatorFunction(accumulator,{
operator: operator.operator,
operand: operands.length > 0 ? operands[0] : undefined,
operands: operands,
multiValueOperands: multiValueOperands,
isMultiValueOperand: isMultiValueOperand,
prefix: operator.prefix,
suffix: operator.suffix,
suffixes: operator.suffixes,
regexp: operator.regexp
},{
wiki: self,
widget: widget
});
operator: operator.operator,
operand: operands.length > 0 ? operands[0] : undefined,
operands: operands,
prefix: operator.prefix,
suffix: operator.suffix,
suffixes: operator.suffixes,
regexp: operator.regexp
},{
wiki: self,
widget: widget
});
if($tw.utils.isArray(results)) {
accumulator = self.makeTiddlerIterator(results);
} else {
@@ -363,8 +319,6 @@ exports.compileFilter = function(filterString) {
return filterRunPrefixes["and"](operationSubFunction, options);
case "~": // This operation is unioned into the result only if the main result so far is empty
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:
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
@@ -391,13 +345,7 @@ exports.compileFilter = function(filterString) {
self.filterRecursionCount = (self.filterRecursionCount || 0) + 1;
if(self.filterRecursionCount < MAX_FILTER_DEPTH) {
$tw.utils.each(operationFunctions,function(operationFunction) {
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);
}
}
operationFunction(results,source,widget);
});
} else {
results.push("/**-- Excessive filter recursion --**/");

View File

@@ -16,8 +16,8 @@ exports.function = function(source,operator,options) {
var functionName = operator.operands[0],
params = [],
results;
$tw.utils.each(operator.multiValueOperands.slice(1),function(paramList) {
params.push({value: paramList[0] || "",multiValue: paramList});
$tw.utils.each(operator.operands.slice(1),function(param) {
params.push({value: param});
});
// console.log(`Calling ${functionName} with params ${JSON.stringify(params)}`);
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(functionName,{params: params, source: source});

View File

@@ -113,22 +113,6 @@ exports["jsonset"] = function(source,operator,options) {
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
*/
@@ -160,7 +144,7 @@ function convertDataItemValueToStrings(item) {
return ["null"]
} else if(typeof item === "object") {
var results = [],i,t;
if(Array.isArray(item)) {
if($tw.utils.isArray(item)) {
// Return all the items in arrays recursively
for(i=0; i<item.length; i++) {
t = convertDataItemValueToStrings(item[i])
@@ -194,7 +178,7 @@ function convertDataItemKeysToStrings(item) {
return [];
}
var results = [];
if(Array.isArray(item)) {
if($tw.utils.isArray(item)) {
for(var i=0; i<item.length; i++) {
results.push(i.toString());
}
@@ -217,7 +201,7 @@ function getDataItemType(data,indexes) {
return item;
} else if(item === null) {
return "null";
} else if(Array.isArray(item)) {
} else if($tw.utils.isArray(item)) {
return "array";
} else if(typeof item === "object") {
return "object";
@@ -229,7 +213,7 @@ function getDataItemType(data,indexes) {
function getItemAtIndex(item,index) {
if($tw.utils.hop(item,index)) {
return item[index];
} else if(Array.isArray(item)) {
} else if($tw.utils.isArray(item)) {
index = $tw.utils.parseInt(index);
if(index < 0) { index = index + item.length };
return item[index]; // Will be undefined if index was out-of-bounds
@@ -239,16 +223,15 @@ function getItemAtIndex(item,index) {
}
/*
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.
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 traverseIndexChain(data,indexes,stopBeforeLast) {
function getDataItem(data,indexes) {
if(indexes.length === 0 || (indexes.length === 1 && indexes[0] === "")) {
return data;
}
// Get the item
var item = data;
var stopIndex = stopBeforeLast ? indexes.length - 1 : indexes.length;
for(var i = 0; i < stopIndex; i++) {
for(var i=0; i<indexes.length; i++) {
if(item !== undefined) {
if(item !== null && ["number","string","boolean"].indexOf(typeof item) === -1) {
item = getItemAtIndex(item,indexes[i]);
@@ -260,13 +243,6 @@ function traverseIndexChain(data,indexes,stopBeforeLast) {
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
*/
@@ -279,15 +255,18 @@ function setDataItem(data,indexes,value) {
if(indexes.length === 0 || (indexes.length === 1 && indexes[0] === "")) {
return value;
}
// Traverse the JSON data structure using the index chain up to the parent
var current = traverseIndexChain(data,indexes,true);
if(current === undefined) {
// Return the original JSON data structure if any of the index strings are invalid
return data;
// Traverse the JSON data structure using the index chain
var current = data;
for(var i = 0; i < indexes.length - 1; i++) {
current = getItemAtIndex(current,indexes[i]);
if(current === undefined) {
// 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
var lastIndex = indexes[indexes.length - 1];
if(Array.isArray(current)) {
if($tw.utils.isArray(current)) {
lastIndex = $tw.utils.parseInt(lastIndex);
if(lastIndex < 0) { lastIndex = lastIndex + current.length };
}
@@ -297,32 +276,3 @@ function setDataItem(data,indexes,value) {
}
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;
}

View File

@@ -14,31 +14,31 @@ Export our filter function
*/
exports.sort = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,false,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,false);
return results;
};
exports.nsort = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,true,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,true);
return results;
};
exports.sortan = function(source, operator, options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results, operator.operands[0] || "title", operator.prefix === "!",false,false,true,operator.operands[1]);
options.wiki.sortTiddlers(results, operator.operand || "title", operator.prefix === "!",false,false,true);
return results;
};
exports.sortcs = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,false,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,false);
return results;
};
exports.nsortcs = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,true,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,true);
return results;
};

View File

@@ -37,14 +37,14 @@ exports.trim = function(source,operator,options) {
operand = (operator.operand || ""),
fnCalc;
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") {
fnCalc = function(a,b) {return [$tw.utils.trimSuffix(a,b)];};
fnCalc = function(a,b) {return [$tw.utils.trimSuffix(a,b)];}
} else {
if(operand === "") {
fnCalc = function(a) {return [$tw.utils.trim(a)];};
fnCalc = function(a) {return [$tw.utils.trim(a)];}
} 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) {
@@ -71,53 +71,107 @@ exports.join = makeStringReducingOperator(
},null
);
const dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
var dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
exports.levenshtein = makeStringBinaryOperator(
function(a,b) {
const diffs = dmp.diffMain(a,b);
return [dmp.diffLevenshtein(diffs).toString()];
var dmpObject = new dmp.diff_match_patch(),
diffs = dmpObject.diff_main(a,b);
return [dmpObject.diff_levenshtein(diffs) + ""];
}
);
// this function is adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
// these two functions are adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
function diffLineWordMode(text1,text2,mode) {
var a = $tw.utils.diffPartsToChars(text1,text2,mode);
var dmpObject = new dmp.diff_match_patch();
var a = diffPartsToChars(text1,text2,mode);
var lineText1 = a.chars1;
var lineText2 = a.chars2;
var lineArray = a.lineArray;
var diffs = dmp.diffMain(lineText1,lineText2,false);
dmp.diffCharsToLines(diffs,lineArray);
var diffs = dmpObject.diff_main(lineText1,lineText2,false);
dmpObject.diff_charsToLines_(diffs,lineArray);
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) {
var suffix = operator.suffix || "",
var dmpObject = new dmp.diff_match_patch(),
suffix = operator.suffix || "",
result = [];
source(function(tiddler,title) {
let diffs, patches;
if(suffix === "lines" || suffix === "words") {
diffs = diffLineWordMode(title,operator.operand,suffix);
patches = dmp.patchMake(title,diffs);
} else {
patches = dmp.patchMake(title,operator.operand);
}
Array.prototype.push.apply(result,[dmp.patchToText(patches)]);
});
source(function(tiddler,title) {
var diffs, patches;
if(suffix === "lines" || suffix === "words") {
diffs = diffLineWordMode(title,operator.operand,suffix);
patches = dmpObject.patch_make(title,diffs);
} else {
patches = dmpObject.patch_make(title,operator.operand);
}
Array.prototype.push.apply(result,[dmpObject.patch_toText(patches)]);
});
return result;
};
exports.applypatches = makeStringBinaryOperator(
function(a,b) {
let patches;
var dmpObject = new dmp.diff_match_patch(),
patches;
try {
patches = dmp.patchFromText(b);
patches = dmpObject.patch_fromText(b);
} catch(e) {
}
if(patches) {
return [dmp.patchApply(patches,a)[0]];
return [dmpObject.patch_apply(patches,a)[0]];
} else {
return [a];
}
@@ -225,7 +279,7 @@ exports.pad = function(source,operator,options) {
}
});
return results;
};
}
exports.charcode = function(source,operator,options) {
var chars = [];

View File

@@ -16,13 +16,12 @@ exports.title = function(source,operator,options) {
var results = [];
if(operator.prefix === "!") {
source(function(tiddler,title) {
var titleList = operator.multiValueOperands[0] || [];
if(tiddler && titleList.indexOf(tiddler.fields.title) === -1) {
if(tiddler && tiddler.fields.title !== operator.operand) {
results.push(title);
}
});
} else {
Array.prototype.push.apply(results,operator.multiValueOperands[0]);
results.push(operator.operand);
}
return results;
};

View File

@@ -20,8 +20,8 @@ exports["[unknown]"] = function(source,operator,options) {
// Check for a user defined filter operator
if(operator.operator.indexOf(".") !== -1) {
var params = [];
$tw.utils.each(operator.multiValueOperands,function(paramList) {
params.push({value: paramList[0] || "",multiValue: paramList});
$tw.utils.each(operator.operands,function(param) {
params.push({value: param});
});
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(operator.operator,{params: params, source: source});
if(variableInfo && variableInfo.srcVariable) {

View File

@@ -11,13 +11,10 @@ The CSV text parser processes CSV files into a table wrapped in a scrollable wid
var CsvParser = function(type,text,options) {
// Special handler for tab-delimited files
if(
!options.separator &&
(type === "text/tab-delimited-values" || type === "text/tab-separated-values")
) {
if (type === 'text/tab-delimited-values' && !options.separator) {
options.separator = "\t";
}
// Table framework
this.tree = [{
"type": "scrollable", "children": [{
@@ -35,7 +32,7 @@ var CsvParser = function(type,text,options) {
$tw.utils.each(lines, function(columns) {
maxColumns = Math.max(columns.length, maxColumns);
});
for(var line=0; line<lines.length; line++) {
var columns = lines[line];
var row = {
@@ -58,4 +55,3 @@ var CsvParser = function(type,text,options) {
exports["text/csv"] = CsvParser;
exports["text/tab-delimited-values"] = CsvParser;
exports["text/tab-separated-values"] = CsvParser;

View File

@@ -11,16 +11,17 @@ The image parser parses an image into an embeddable HTML element
var ImageParser = function(type,text,options) {
var element = {
type: "image",
attributes: {}
};
type: "element",
tag: "img",
attributes: {}
};
if(options._canonical_uri) {
element.attributes.source = {type: "string", value: options._canonical_uri};
element.attributes.src = {type: "string", value: options._canonical_uri};
} else if(text) {
if(type === "image/svg+xml" || type === ".svg") {
element.attributes.source = {type: "string", value: "data:image/svg+xml," + encodeURIComponent(text)};
element.attributes.src = {type: "string", value: "data:image/svg+xml," + encodeURIComponent(text)};
} else {
element.attributes.source = {type: "string", value: "data:" + type + ";base64," + text};
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
}
}
this.tree = [element];

View File

@@ -1,31 +0,0 @@
/*\
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));

View File

@@ -1,58 +0,0 @@
/*\
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

View File

@@ -61,7 +61,7 @@ exports.convertStyleNameToPropertyName = function(styleName) {
var propertyName = $tw.utils.unHyphenateCss(styleName);
// Then check if it needs a prefix
if($tw.browser && document.body.style[propertyName] === undefined) {
var prefixes = ["Moz","webkit"];
var prefixes = ["O","MS","Moz","webkit"];
for(var t=0; t<prefixes.length; t++) {
var prefixedName = prefixes[t] + propertyName.substr(0,1).toUpperCase() + propertyName.substr(1);
if(document.body.style[prefixedName] !== undefined) {
@@ -112,6 +112,8 @@ var eventNameMappings = {
correspondingCssProperty: "transition",
mappings: {
transition: "transitionend",
OTransition: "oTransitionEnd",
MSTransition: "msTransitionEnd",
MozTransition: "transitionend",
webkitTransition: "webkitTransitionEnd"
}
@@ -120,6 +122,8 @@ var eventNameMappings = {
correspondingCssProperty: "animation",
mappings: {
animation: "animationend",
OAnimation: "oAnimationEnd",
MSAnimation: "msAnimationEnd",
MozAnimation: "animationend",
webkitAnimation: "webkitAnimationEnd"
}
@@ -152,15 +156,19 @@ exports.getFullScreenApis = function() {
result = {
"_requestFullscreen": db.webkitRequestFullscreen !== undefined ? "webkitRequestFullscreen" :
db.mozRequestFullScreen !== undefined ? "mozRequestFullScreen" :
db.msRequestFullscreen !== undefined ? "msRequestFullscreen" :
db.requestFullscreen !== undefined ? "requestFullscreen" : "",
"_exitFullscreen": d.webkitExitFullscreen !== undefined ? "webkitExitFullscreen" :
d.mozCancelFullScreen !== undefined ? "mozCancelFullScreen" :
d.msExitFullscreen !== undefined ? "msExitFullscreen" :
d.exitFullscreen !== undefined ? "exitFullscreen" : "",
"_fullscreenElement": d.webkitFullscreenElement !== undefined ? "webkitFullscreenElement" :
d.mozFullScreenElement !== undefined ? "mozFullScreenElement" :
d.msFullscreenElement !== undefined ? "msFullscreenElement" :
d.fullscreenElement !== undefined ? "fullscreenElement" : "",
"_fullscreenChange": d.webkitFullscreenElement !== undefined ? "webkitfullscreenchange" :
d.mozFullScreenElement !== undefined ? "mozfullscreenchange" :
d.msFullscreenElement !== undefined ? "MSFullscreenChange" :
d.fullscreenElement !== undefined ? "fullscreenchange" : ""
};
if(!result._requestFullscreen || !result._exitFullscreen || !result._fullscreenElement || !result._fullscreenChange) {

View File

@@ -11,6 +11,19 @@ Various static DOM-related utility functions.
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)
@@ -36,6 +49,38 @@ 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.
*/
@@ -252,6 +297,10 @@ exports.copyToClipboard = function(text,options) {
document.body.removeChild(textArea);
};
exports.getLocationPath = function() {
return window.location.toString().split("#")[0];
};
/*
Collect DOM variables
*/

View File

@@ -1,7 +1,7 @@
/*\
title: $:/core/modules/utils/escapecss.js
type: application/javascript
module-type: utils-browser
module-type: utils
Provides CSS.escape() functionality.
@@ -9,6 +9,92 @@ Provides CSS.escape() functionality.
"use strict";
// TODO -- resolve this construction
exports.escapeCSS = (function() {
return window.CSS.escape;
// use browser's native CSS.escape() function if available
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: theres 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;
};
})();

View File

@@ -60,7 +60,7 @@ exports.repackPlugin = function(title,additionalTiddlers,excludeTiddlers) {
version += "+" + pluginVersion.build;
}
// Save the tiddler
$tw.wiki.addTiddler(new $tw.Tiddler(pluginTiddler,{text: JSON.stringify({tiddlers: plugins},null,4), version: version},$tw.wiki.getModificationFields()));
$tw.wiki.addTiddler(new $tw.Tiddler(pluginTiddler,{text: JSON.stringify({tiddlers: plugins},null,4), version: version}));
// Delete any non-shadow constituent tiddlers
$tw.utils.each(tiddlers,function(title) {
if($tw.wiki.tiddlerExists(title)) {

View File

@@ -48,6 +48,19 @@ exports.warning = function(text) {
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 dflt (default) parameter if str is not a base-10 number.
@@ -55,7 +68,7 @@ Return the dflt (default) parameter if str is not a base-10 number.
exports.getInt = function(str,deflt) {
var i = parseInt(str,10);
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
@@ -66,15 +79,52 @@ 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) {
if(typeof str === "string" && typeof unwanted === "string") {
if(unwanted === "") {
return str.replace(/^\s\s*/, "");
return str.replace(/^\s\s*/, '');
} else {
// Safely regexp-escape the unwanted text
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
var regex = new RegExp("^(" + unwanted + ")+");
return str.replace(regex, "");
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
var regex = new RegExp('^(' + unwanted + ')+');
return str.replace(regex, '');
}
} else {
return str;
@@ -84,12 +134,12 @@ exports.trimPrefix = function(str,unwanted) {
exports.trimSuffix = function(str,unwanted) {
if(typeof str === "string" && typeof unwanted === "string") {
if(unwanted === "") {
return str.replace(/\s\s*$/, "");
return str.replace(/\s\s*$/, '');
} else {
// Safely regexp-escape the unwanted text
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
var regex = new RegExp("(" + unwanted + ")+$");
return str.replace(regex, "");
unwanted = unwanted.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
var regex = new RegExp('(' + unwanted + ')+$');
return str.replace(regex, '');
}
} else {
return str;
@@ -101,14 +151,14 @@ Convert a string to sentence case (ie capitalise first letter)
*/
exports.toSentenceCase = function(str) {
return (str || "").replace(/^\S/, function(c) {return c.toUpperCase();});
};
}
/*
Convert a string to title case (ie capitalise each initial letter)
*/
exports.toTitleCase = function(str) {
return (str || "").replace(/(^|\s)\S/g, function(c) {return c.toUpperCase();});
};
}
/*
Find the line break preceding a given position in a string
@@ -150,6 +200,18 @@ exports.count = function(object) {
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
array: array to modify
@@ -358,8 +420,8 @@ exports.formatDateString = function(date,template) {
}],
[/^TZD/, function() {
var tz = date.getTimezoneOffset(),
atz = Math.abs(tz);
return (tz < 0 ? "+" : "-") + $tw.utils.pad(Math.floor(atz / 60)) + ":" + $tw.utils.pad(atz % 60);
atz = Math.abs(tz);
return (tz < 0 ? '+' : '-') + $tw.utils.pad(Math.floor(atz / 60)) + ':' + $tw.utils.pad(atz % 60);
}],
[/^wYY/, function() {
return $tw.utils.pad($tw.utils.getYearForWeekNo(date) - 2000);
@@ -568,9 +630,9 @@ exports.unescapeLineBreaks = function(s) {
exports.escape = function(ch) {
var charCode = ch.charCodeAt(0);
if(charCode <= 0xFF) {
return "\\x" + $tw.utils.pad(charCode.toString(16).toUpperCase());
return '\\x' + $tw.utils.pad(charCode.toString(16).toUpperCase());
} else {
return "\\u" + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);
return '\\u' + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);
}
};
@@ -587,11 +649,11 @@ exports.stringify = function(s, rawUnicode) {
*/
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
return (s || "")
.replace(/\\/g, "\\\\") // backslash
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // double quote character
.replace(/'/g, "\\'") // single quote character
.replace(/\r/g, "\\r") // carriage return
.replace(/\n/g, "\\n") // line feed
.replace(/\r/g, '\\r') // carriage return
.replace(/\n/g, '\\n') // line feed
.replace(regex, exports.escape); // non-ASCII characters
};
@@ -601,15 +663,15 @@ exports.jsonStringify = function(s, rawUnicode) {
// See http://www.json.org/
var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g;
return (s || "")
.replace(/\\/g, "\\\\") // backslash
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // double quote character
.replace(/\r/g, "\\r") // carriage return
.replace(/\n/g, "\\n") // line feed
.replace(/\x08/g, "\\b") // backspace
.replace(/\x0c/g, "\\f") // formfeed
.replace(/\t/g, "\\t") // tab
.replace(/\r/g, '\\r') // carriage return
.replace(/\n/g, '\\n') // line feed
.replace(/\x08/g, '\\b') // backspace
.replace(/\x0c/g, '\\f') // formfeed
.replace(/\t/g, '\\t') // tab
.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
};
@@ -617,7 +679,7 @@ exports.jsonStringify = function(s, rawUnicode) {
Escape the RegExp special characters with a preceding backslash
*/
exports.escapeRegExp = function(s) {
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, "\\$&");
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&');
};
/*
@@ -700,7 +762,7 @@ exports.parseTextReference = function(textRef) {
}
} else {
// If we couldn't parse it
result.title = textRef;
result.title = textRef
}
return result;
};
@@ -759,17 +821,60 @@ Cryptographic hash function as used by sha256 filter operator
options.length .. number of characters returned defaults to 64
*/
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);
}
/*
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
*/
exports.base64Decode = function(string64,binary,urlsafe) {
const encoded = urlsafe ? string64.replace(/_/g,"/").replace(/-/g,"+") : string64;
if(binary) return $tw.utils.atob(encoded);
else return $tw.utils.base64DecodeUtf8(encoded);
const encoded = urlsafe ? string64.replace(/_/g,'/').replace(/-/g,'+') : string64;
if(binary) return exports.atob(encoded)
else return exports.base64DecodeUtf8(encoded);
};
/*
@@ -777,10 +882,10 @@ Encode a string to base64
*/
exports.base64Encode = function(string64,binary,urlsafe) {
let encoded;
if(binary) encoded = $tw.utils.btoa(string64);
else encoded = $tw.utils.base64EncodeUtf8(string64);
if(binary) encoded = exports.btoa(string64);
else encoded = exports.base64EncodeUtf8(string64);
if(urlsafe) {
encoded = encoded.replace(/\+/g,"-").replace(/\//g,"_");
encoded = encoded.replace(/\+/g,'-').replace(/\//g,'_');
}
return encoded;
};
@@ -835,6 +940,44 @@ exports.makeDataUri = function(text,type,_canonical_uri) {
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
*/
@@ -861,6 +1004,10 @@ exports.parseInt = function(str) {
return parseInt(str,10) || 0;
};
exports.stringifyNumber = function(num) {
return num + "";
};
exports.makeCompareFunction = function(type,options) {
options = options || {};
// set isCaseSensitive to true if not defined in options
@@ -914,56 +1061,3 @@ exports.makeCompareFunction = function(type,options) {
};
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};
};

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-unused-vars */
/*\
title: $:/core/modules/widgets/action-log.js
type: application/javascript
@@ -33,7 +32,7 @@ LogWidget.prototype.execute = function(){
this.message = this.getAttribute("$$message","debug");
this.logAll = this.getAttribute("$$all","no") === "yes" ? true : false;
this.filter = this.getAttribute("$$filter");
};
}
/*
Refresh the widget by ensuring our attributes are up to date
@@ -52,30 +51,23 @@ LogWidget.prototype.invokeAction = function(triggeringWidget,event) {
};
LogWidget.prototype.log = function() {
var self = this,
data = {}, // Hashmap by attribute name with string or array of string values
var data = {},
dataCount,
allVars = {}, // Hashmap by variable name with string or array of string values
allVars = {},
filteredVars;
// Collect the attributes to be logged
$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
$tw.utils.each(this.attributes,function(attribute,name) {
if(name.substring(0,2) !== "$$") {
var resultList = self.computeAttribute(attribute,{asList: true});
if(resultList.length <= 1) {
data[name] = resultList[0] || "";
} else {
data[name] = resultList;
}
data[name] = attribute;
}
});
// Collect values of all variables, using the source text for functions
for(var v in this.variables) {
var variable = this.parentWidget && this.parentWidget.variables[v];
if(variable && variable.isFunctionDefinition) {
allVars[v] = variable.value;
} else {
var variableInfo = this.getVariableInfo(v);
allVars[v] = variableInfo.resultList.length > 1 ? variableInfo.resultList : variableInfo.text;
allVars[v] = this.getVariable(v,{defaultValue:""});
}
}
if(this.filter) {
@@ -96,6 +88,6 @@ LogWidget.prototype.log = function() {
console.groupEnd();
}
console.groupEnd();
};
}
exports["action-log"] = LogWidget;

View File

@@ -9,8 +9,6 @@ Button widget
"use strict";
const ALLOWED_SELECTED_ARIA_ATTR = ["aria-checked", "aria-selected", "aria-pressed"];
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var Popup = require("$:/core/modules/utils/dom/popup.js");
@@ -46,14 +44,9 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
var classes = this["class"].split(" ") || [],
isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp();
if(this.selectedClass) {
if((this.set || this.setTitle) && this.setTo) {
const selectedAria = ALLOWED_SELECTED_ARIA_ATTR.includes(this.selectedAria) ? this.selectedAria : "aria-checked";
if(this.isSelected()) {
$tw.utils.pushTop(classes, this.selectedClass.split(" "));
domNode.setAttribute(selectedAria, "true");
} else {
domNode.setAttribute(selectedAria, "false");
}
if((this.set || this.setTitle) && this.setTo && this.isSelected()) {
$tw.utils.pushTop(classes, this.selectedClass.split(" "));
domNode.setAttribute("aria-checked", "true");
}
if(isPoppedUp) {
$tw.utils.pushTop(classes,this.selectedClass.split(" "));
@@ -228,7 +221,6 @@ ButtonWidget.prototype.execute = function() {
this.style = this.getAttribute("style");
this["class"] = this.getAttribute("class","");
this.selectedClass = this.getAttribute("selectedClass");
this.selectedAria = this.getAttribute("selectedAria");
this.defaultSetValue = this.getAttribute("default","");
this.buttonTag = this.getAttribute("tag");
this.dragTiddler = this.getAttribute("dragTiddler");

View File

@@ -9,8 +9,8 @@ Widget to display a diff between two texts
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
const dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
var Widget = require("$:/core/modules/widgets/widget.js").widget,
dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
var DiffTextWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
@@ -34,25 +34,19 @@ DiffTextWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
// Create the diff object
const editCost = $tw.utils.parseNumber(this.getAttribute("editcost","4"));
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});
}
// Create the diff
var dmpObject = new dmp.diff_match_patch(),
diffs = dmpObject.diff_main(this.getAttribute("source",""),this.getAttribute("dest",""));
// Apply required cleanup
switch(this.getAttribute("cleanup","semantic")) {
case "none":
// No cleanup
break;
case "efficiency":
dmp.diffCleanupEfficiency(diffs, {diffEditCost: editCost});
dmpObject.diff_cleanupEfficiency(diffs);
break;
default: // case "semantic"
dmp.diffCleanupSemantic(diffs);
dmpObject.diff_cleanupSemantic(diffs);
break;
}
// Create the elements
@@ -138,7 +132,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
*/
DiffTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup || changedAttributes.mode || changedAttributes.editcost) {
if(changedAttributes.source || changedAttributes.dest || changedAttributes.cleanup) {
this.refreshSelf();
return true;
} else {
@@ -146,15 +140,4 @@ 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;

View File

@@ -177,7 +177,7 @@ DroppableWidget.prototype.execute = function() {
DroppableWidget.prototype.assignDomNodeClasses = function() {
var classes = this.getAttribute("class","").split(" ");
classes.push("tc-droppable");
this.domNode.className = classes.join(" ").trim();
this.domNode.className = classes.join(" ");
};
/*

View File

@@ -25,6 +25,7 @@ Render this widget into the DOM
*/
ElementWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
// Neuter blacklisted elements
this.tag = this.parseTreeNode.tag;
if($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) {
@@ -41,8 +42,6 @@ ElementWidget.prototype.render = function(parent,nextSibling) {
headingLevel = Math.min(Math.max(headingLevel + 1 + baseLevel,1),6);
this.tag = "h" + headingLevel;
}
// Compute the attributes, mapping the element tag if needed
this.computeAttributes();
// Select the namespace for the tag
var XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml",
tagNamespaces = {
@@ -100,25 +99,4 @@ ElementWidget.prototype.refresh = function(changedTiddlers) {
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;

View File

@@ -130,7 +130,7 @@ EventWidget.prototype.execute = function() {
EventWidget.prototype.assignDomNodeClasses = function() {
var classes = this.getAttribute("class","").split(" ");
classes.push("tc-eventcatcher");
this.domNode.className = classes.join(" ").trim();
this.domNode.className = classes.join(" ");
};
/*

View File

@@ -110,7 +110,7 @@ KeyboardWidget.prototype.execute = function() {
KeyboardWidget.prototype.assignDomNodeClasses = function() {
var classes = this.getAttribute("class","").split(" ");
classes.push("tc-keyboard");
this.domNode.className = classes.join(" ").trim();
this.domNode.className = classes.join(" ");
};
/*

View File

@@ -7,6 +7,7 @@ This widget allows defining multiple variables at once, while allowing
the later variables to depend upon the earlier ones.
```
\define helloworld() Hello world!
<$let currentTiddler="target" value={{!!value}} currentTiddler="different">
{{!!value}} will be different from <<value>>
</$let>
@@ -45,7 +46,7 @@ LetWidget.prototype.computeAttributes = function() {
self = this;
this.currentValueFor = Object.create(null);
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(this.parseTreeNode),function(attribute) {
var value = self.computeAttribute(attribute,{asList: true}),
var value = self.computeAttribute(attribute),
name = attribute.name;
// Now that it's prepped, we're allowed to look this variable up
// when defining later variables
@@ -55,7 +56,7 @@ LetWidget.prototype.computeAttributes = function() {
});
// Run through again, setting variables and looking for differences
$tw.utils.each(this.currentValueFor,function(value,name) {
if(self.attributes[name] === undefined || !$tw.utils.isArrayEqual(self.attributes[name],value)) {
if (self.attributes[name] !== value) {
self.attributes[name] = value;
self.setVariable(name,value);
changedAttributes[name] = true;
@@ -67,11 +68,9 @@ LetWidget.prototype.computeAttributes = function() {
LetWidget.prototype.getVariableInfo = function(name,options) {
// Special handling: If this variable exists in this very $let, we can
// use it, but only if it's been staged.
if($tw.utils.hop(this.currentValueFor,name)) {
var value = this.currentValueFor[name];
if ($tw.utils.hop(this.currentValueFor,name)) {
return {
text: value[0] || "",
resultList: value
text: this.currentValueFor[name]
};
}
return Widget.prototype.getVariableInfo.call(this,name,options);

View File

@@ -89,33 +89,13 @@ RevealWidget.prototype.positionPopup = function(domNode) {
top = this.popup.top + this.popup.height;
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) {
left = Math.max(0,left);
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.
for(var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) {
for (var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) {
left -= offsetParentDomNode.offsetLeft;
top -= offsetParentDomNode.offsetTop;
}
@@ -143,7 +123,6 @@ RevealWidget.prototype.execute = function() {
this.openAnimation = this.animate === "no" ? undefined : "open";
this.closeAnimation = this.animate === "no" ? undefined : "close";
this.updatePopupPosition = this.getAttribute("updatePopupPosition","no") === "yes";
this.clampToParent = this.getAttribute("clamp","none");
// Compute the title of the state tiddler and read it
this.stateTiddlerTitle = this.state;
this.stateTitle = this.getAttribute("stateTitle");
@@ -162,7 +141,7 @@ Read the state tiddler
RevealWidget.prototype.readState = function() {
// Read the information from the state tiddler
var state,
defaultState = this["default"];
defaultState = this["default"];
if(this.stateTitle) {
var stateTitleTiddler = this.wiki.getTiddler(this.stateTitle);
if(this.stateField) {
@@ -224,7 +203,7 @@ RevealWidget.prototype.readPopupState = function(state) {
RevealWidget.prototype.assignDomNodeClasses = function() {
var classes = this.getAttribute("class","").split(" ");
classes.push("tc-reveal");
this.domNode.className = classes.join(" ").trim();
this.domNode.className = classes.join(" ");
};
/*
@@ -273,18 +252,18 @@ RevealWidget.prototype.updateState = function() {
this.renderChildren(domNode,null);
}
// 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) {
domNode.removeAttribute("hidden");
// 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);
$tw.anim.perform(this.openAnimation,domNode);
} else {
$tw.anim.perform(this.closeAnimation,domNode,{callback: function() {
//make sure that the state hasn't changed during the close animation
self.readState();
self.readState()
if(!self.isOpen) {
domNode.setAttribute("hidden","true");
}

View File

@@ -80,7 +80,7 @@ Widget.prototype.execute = function() {
/*
Set the value of a context variable
name: name of the variable
value: value of the variable, can be a string or an array
value: value of the variable
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)
options includes:
@@ -90,10 +90,8 @@ options includes:
*/
Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) {
options = options || {};
var valueIsArray = $tw.utils.isArray(value);
this.variables[name] = {
value: valueIsArray ? (value[0] || "") : value,
resultList: valueIsArray ? value : [value],
value: value,
params: params,
isMacroDefinition: !!isMacroDefinition,
isFunctionDefinition: !!options.isFunctionDefinition,
@@ -116,7 +114,7 @@ allowSelfAssigned: if true, includes the current widget in the context chain ins
Returns an object with the following fields:
params: array of {name:,value:,multiValue:} of parameters to be applied (name is optional)
params: array of {name:,value:} or {value:} of parameters to be applied
text: text of variable, with parameters properly substituted
resultList: result of variable evaluation as an array
srcVariable: reference to the object defining the variable
@@ -142,9 +140,7 @@ Widget.prototype.getVariableInfo = function(name,options) {
params = self.resolveVariableParameters(variable.params,actualParams);
// Substitute any parameters specified in the definition
$tw.utils.each(params,function(param) {
if("name" in param) {
value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value);
}
value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value);
});
value = self.substituteVariableReferences(value,options);
resultList = [value];
@@ -158,20 +154,13 @@ Widget.prototype.getVariableInfo = function(name,options) {
variables[param.name] = param["default"];
}
});
// Parameters are an array of {name:, value:, multivalue:} pairs (name and multivalue are optional)
// Parameters are an array of {value:} or {name:, value:} pairs
$tw.utils.each(params,function(param) {
if(param.multiValue) {
variables[param.name] = param.multiValue;
} else {
variables[param.name] = param.value || "";
}
variables[param.name] = param.value;
});
resultList = this.wiki.filterTiddlers(value,this.makeFakeWidgetWithVariables(variables),options.source);
value = resultList[0] || "";
} else {
if(variable.resultList) {
resultList = variable.resultList;
}
params = variable.params;
}
return {
@@ -203,24 +192,22 @@ Widget.prototype.getVariable = function(name,options) {
/*
Maps actual parameters onto formal parameters, returning an array of {name:,value:} objects
formalParams - Array of {name:,default:} (default value is optional)
actualParams - Array of string values or {name:,value:,multiValue} (name and multiValue is optional)
actualParams - Array of string values or {name:,value:} (name is optional)
*/
Widget.prototype.resolveVariableParameters = function(formalParams,actualParams) {
formalParams = formalParams || [];
actualParams = actualParams || [];
var nextAnonParameter = 0, // Next candidate anonymous parameter in macro call
paramInfo, paramValue, paramMultiValue,
paramInfo, paramValue,
results = [];
// Step through each of the parameters in the macro definition
for(var p=0; p<formalParams.length; p++) {
// Check if we've got a macro call parameter with the same name
paramInfo = formalParams[p];
paramValue = undefined;
paramMultiValue = undefined;
for(var m=0; m<actualParams.length; m++) {
if(typeof actualParams[m] !== "string" && actualParams[m].name === paramInfo.name) {
paramValue = actualParams[m].value;
paramMultiValue = actualParams[m].multiValue || [paramValue]
}
}
// If not, use the next available anonymous macro call parameter
@@ -230,13 +217,11 @@ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams)
if(paramValue === undefined && nextAnonParameter < actualParams.length) {
var param = actualParams[nextAnonParameter++];
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
paramValue = paramValue || paramInfo["default"] || "";
paramMultiValue = paramMultiValue || [paramValue];
// Store the parameter name and value
results.push({name: paramInfo.name, value: paramValue, multiValue: paramMultiValue});
results.push({name: paramInfo.name, value: paramValue});
}
return results;
};
@@ -325,7 +310,7 @@ Widget.prototype.getStateQualifier = function(name) {
};
/*
Make a fake widget with specified variables, suitable for variable lookup in filters. Each variable can be a string or an array of strings
Make a fake widget with specified variables, suitable for variable lookup in filters
*/
Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
var self = this,
@@ -333,12 +318,7 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
return {
getVariable: function(name,opts) {
if($tw.utils.hop(variables,name)) {
var value = variables[name];
if($tw.utils.isArray(value)) {
return value[0];
} else {
return value;
}
return variables[name];
} else {
opts = opts || {};
opts.variables = variables;
@@ -347,18 +327,9 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
},
getVariableInfo: function(name,opts) {
if($tw.utils.hop(variables,name)) {
var value = variables[name];
if($tw.utils.isArray(value)) {
return {
text: value[0],
resultList: value
};
} else {
return {
text: value,
resultList: [value]
};
}
return {
text: variables[name]
};
} else {
opts = opts || {};
opts.variables = $tw.utils.extend({},variables,opts.variables);
@@ -395,45 +366,20 @@ Widget.prototype.computeAttributes = function(options) {
return changedAttributes;
};
/*
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 || {};
Widget.prototype.computeAttribute = function(attribute) {
var self = this,
value;
if(attribute.type === "filtered") {
value = this.wiki.filterTiddlers(attribute.filter,this);
if(!options.asList) {
value = value[0] || "";
}
value = this.wiki.filterTiddlers(attribute.filter,this)[0] || "";
} else if(attribute.type === "indirect") {
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler"));
if(value && options.asList) {
value = [value];
}
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler")) || "";
} else if(attribute.type === "macro") {
var variableInfo = this.getVariableInfo(attribute.value.name,{params: attribute.value.params});
if(options.asList) {
value = variableInfo.resultList;
} else {
value = variableInfo.text;
}
value = variableInfo.text;
} else if(attribute.type === "substituted") {
value = this.wiki.getSubstitutedText(attribute.rawValue,this) || "";
if(options.asList) {
value = [value];
}
} else { // String attribute
value = attribute.value;
if(options.asList) {
if(value === undefined) {
value = [];
} else {
value = [value];
}
}
}
return value;
};

View File

@@ -200,7 +200,7 @@ exports.generateNewTitle = function(baseTitle,options) {
c = (parseInt(options.startCount,10) > 0) ? parseInt(options.startCount,10) : 0,
prefix = (typeof(options.prefix) === "string") ? options.prefix : " ";
if(template) {
if (template) {
// "count" is important to avoid an endless loop in while(...)!!
template = (/\$count:?(\d+)?\$/i.test(template)) ? template : template + "$count$";
// .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)+""});
}
} else {
if(c > 0) {
if (c > 0) {
title = baseTitle + prefix + c;
}
while(this.tiddlerExists(title) || this.isShadowTiddler(title) || this.findDraft(title)) {
@@ -369,16 +369,31 @@ Sort an array of tiddler titles by a specified field
isDescending: true if the sort should be descending
isCaseSensitive: true if the sort should consider upper and lower case letters to be different
*/
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric,locale) {
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) {
var self = this;
if(sortField === "title") {
if(!isNumeric && !isAlphaNumeric) {
const sorter = new Intl.Collator(locale, { sensitivity: isCaseSensitive ? "variant" : "accent" });
if(isDescending) {
titles.sort((a,b) => sorter.compare(b, a));
if(isCaseSensitive) {
if(isDescending) {
titles.sort(function(a,b) {
return b.localeCompare(a);
});
} else {
titles.sort(function(a,b) {
return a.localeCompare(b);
});
}
} else {
titles.sort((a,b) => sorter.compare(a, b));
}
if(isDescending) {
titles.sort(function(a,b) {
return b.toLowerCase().localeCompare(a.toLowerCase());
});
} else {
titles.sort(function(a,b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
}
}
} else {
titles.sort(function(a,b) {
var x,y;
@@ -399,8 +414,14 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
}
}
}
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
if(isAlphaNumeric) {
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
}
if(!isCaseSensitive) {
a = a.toLowerCase();
b = b.toLowerCase();
}
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
});
}
} else {
@@ -442,8 +463,14 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
}
a = String(a);
b = String(b);
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
if(isAlphaNumeric) {
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
}
if(!isCaseSensitive) {
a = a.toLowerCase();
b = b.toLowerCase();
}
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
});
}
};
@@ -505,7 +532,7 @@ exports.getTiddlerLinks = function(title) {
return self.extractLinks(parser.tree);
}
return [];
}).slice(0);
});
};
/*
@@ -524,9 +551,8 @@ exports.getTiddlerBacklinks = function(targetTitle) {
backlinks.push(title);
}
});
return backlinks;
}
return backlinks.slice(0);
return backlinks;
};
@@ -552,7 +578,7 @@ exports.extractTranscludes = function(parseTreeRoot, title) {
}
}
} else if(parseTreeNode.attributes.tiddler) {
if(parseTreeNode.attributes.tiddler.type === "string") {
if (parseTreeNode.attributes.tiddler.type === "string") {
// Old transclude widget usage
value = parseTreeNode.attributes.tiddler.value;
}
@@ -592,7 +618,7 @@ exports.getTiddlerTranscludes = function(title) {
return self.extractTranscludes(parser.tree,title);
}
return [];
}).slice(0);
});
};
/*
@@ -604,9 +630,9 @@ exports.getTiddlerBacktranscludes = function(targetTitle) {
backtranscludes = backIndexer && backIndexer.subIndexers.transclude.lookup(targetTitle);
if(!backtranscludes) {
return [];
backtranscludes = [];
}
return backtranscludes.slice(0);
return backtranscludes;
};
/*
@@ -615,7 +641,7 @@ Return a hashmap of tiddler titles that are referenced but not defined. Each val
exports.getMissingTitles = function() {
var self = this,
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) {
var links = self.getTiddlerLinks(title);
$tw.utils.each(links,function(link) {
@@ -657,7 +683,7 @@ exports.getTiddlersWithTag = function(tag) {
return self.sortByList(tagmap[tag],tag);
});
}
return results.slice(0);
return results;
};
/*
@@ -708,7 +734,7 @@ exports.findListingsOfTiddler = function(targetTitle,fieldName) {
for(var i = 0; i < list.length; i++) {
var listItem = list[i],
listing = listings[listItem] || [];
if(listing.indexOf(title) === -1) {
if (listing.indexOf(title) === -1) {
listing.push(title);
}
listings[listItem] = listing;
@@ -717,7 +743,7 @@ exports.findListingsOfTiddler = function(targetTitle,fieldName) {
});
return listings;
});
return (listings[targetTitle] || []).slice(0);
return listings[targetTitle] || [];
};
/*
@@ -756,7 +782,7 @@ exports.sortByList = function(array,listTitle) {
}
}
// If a new position is specified, let's move it
if(newPos !== -1) {
if (newPos !== -1) {
// get its current Pos, and make sure
// sure that it's _actually_ in the list
// and that it would _actually_ move
@@ -1033,7 +1059,7 @@ Options include:
exports.parseText = function(type,text,options) {
text = text || "";
options = options || {};
var Parser = $tw.utils.getParser(type,options);
var Parser = $tw.utils.getParser(type,options)
// Return the parser instance
return new Parser(type,text,{
parseAsInline: options.parseAsInline,
@@ -1052,11 +1078,11 @@ exports.parseTiddler = function(title,options) {
tiddler = this.getTiddler(title),
self = this;
return tiddler ? this.getCacheForTiddler(title,cacheType,function() {
if(tiddler.hasField("_canonical_uri")) {
options._canonical_uri = tiddler.fields._canonical_uri;
}
return self.parseText(tiddler.fields.type,tiddler.fields.text,options);
}) : null;
if(tiddler.hasField("_canonical_uri")) {
options._canonical_uri = tiddler.fields._canonical_uri;
}
return self.parseText(tiddler.fields.type,tiddler.fields.text,options);
}) : null;
};
exports.parseTextReference = function(title,field,index,options) {
@@ -1112,7 +1138,7 @@ exports.getTextReferenceParserInfo = function(title,field,index,options) {
parserInfo.parserType = null;
}
return parserInfo;
};
}
/*
Parse a block of text of a specified MIME type
@@ -1138,7 +1164,7 @@ exports.getSubstitutedText = function(text,widget,options) {
});
// Substitute any variable references with their values
return output.replace(/\$\((.+?)\)\$/g, function(match,varname) {
return widget.getVariable(varname,{defaultValue: ""});
return widget.getVariable(varname,{defaultValue: ""})
});
};
@@ -1216,7 +1242,7 @@ exports.makeTranscludeWidget = function(title,options) {
name: "recursionMarker",
type: "string",
value: options.recursionMarker || "yes"
},
},
tiddler: {
name: "tiddler",
type: "string",
@@ -1359,7 +1385,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 = [];
if(options.field) {
if($tw.utils.isArray(options.field)) {
@@ -1492,7 +1518,7 @@ exports.checkTiddlerText = function(title,targetText,options) {
targetText = targetText.toLowerCase();
}
return text === targetText;
};
}
/*
Execute an action string without an associated context widget
@@ -1616,7 +1642,7 @@ exports.findDraft = function(targetTitle) {
}
});
return draftTitle;
};
}
/*
Check whether the specified draft tiddler has been modified.
@@ -1643,7 +1669,7 @@ historyTitle: title of history tiddler (defaults to $:/HistoryList)
exports.addToHistory = function(title,fromPageRect,historyTitle) {
var story = new $tw.Story({wiki: this, historyTitle: historyTitle});
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!")
};
/*
@@ -1656,7 +1682,7 @@ options: see story.js
exports.addToStory = function(title,fromTitle,storyTitle,options) {
var story = new $tw.Story({wiki: this, storyTitle: storyTitle});
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!")
};
/*

View File

@@ -1,7 +1,7 @@
title: $:/core/templates/tiddlywiki5-external-js.html
<$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>
`{{$:/core/templates/MOTW.html}}`<html lang="`<$text text={{{ [{$:/language}get[name]] }}}/>`">
<head>

View File

@@ -49,27 +49,6 @@ title: $:/core/ui/ImportListing
\end
\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">
<table class="tc-import-table">
<tbody>

View File

@@ -1,7 +1,7 @@
title: $:/core/ui/PageTemplate/alerts
tags: $:/tags/PageTemplate
<div class="tc-alerts" role="region" aria-label={{$:/language/Alerts}}>
<div class="tc-alerts" role="region" aria-label="Alerts">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Alert]!is[draft]]" template="$:/core/ui/AlertTemplate" storyview="pop"/>

View File

@@ -15,7 +15,7 @@ caption: {{$:/language/SideBar/Open/Caption}}
\define droppable-item(button)
\whitespace trim
<$droppable actions=<<drop-actions>> enable=<<tv-enable-drag-and-drop>> tag="div">
<$droppable actions=<<drop-actions>> enable=<<tv-allow-drag-and-drop>> tag="div">
<<placeholder>>
<div>
$button$

View File

@@ -2,7 +2,7 @@ title: $:/core/ui/TiddlerInfo
\whitespace trim
<div style="position:relative;">
<div class="tc-tiddler-controls tc-tiddler-info-controls">
<div class="tc-tiddler-controls" style="position:absolute;right:0;">
<$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">
{{$:/core/images/close-button}}

View File

@@ -11,13 +11,9 @@ tags: $:/tags/ViewTemplate
storyview="pop"
variable="listItem"
>
<$let condition={{{ [<listItem>get[condition]] }}}>
<%if [<condition>!is[blank]] :and[<currentTiddler>subfilter<condition>limit[1]] :else[<condition>is[blank]then[true]] %>
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
<$transclude tiddler=<<listItem>>/>
</$set>
<%endif%>
</$let>
<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
<$transclude tiddler=<<listItem>>/>
</$set>
</$list>
</span>
<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>

View File

@@ -41,8 +41,6 @@ Drag this link to copy this tool to another wiki
</$wikify>
\end capture-item-wikified
\function get.shadow.source() [shadowsource[]]
\procedure capture-wiki-info(tempWikiInfo)
<$transclude $variable="capture-item-wikified" label="TiddlyWiki Version" value="<<version>>"/>
<$transclude $variable="capture-item" label="Current palette" value={{$:/palette}}/>
@@ -66,7 +64,6 @@ 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="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="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
\procedure template-header()

View File

@@ -1,39 +0,0 @@
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

View File

@@ -13,6 +13,56 @@ tags: $:/tags/Macro
\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)
<$macrocall $name="makedatauri" type={{{ [<title>get[type]] }}} text={{{ [<title>get[text]] }}} _canonical_uri={{{ [<title>get[_canonical_uri]] }}}/>
\end

View File

@@ -1,43 +0,0 @@
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

View File

@@ -22,7 +22,7 @@ tags: $:/tags/Macro
<$action-listops $tiddler=<<targetTiddler>> $field=<<targetField>> $subfilter="+[insertbefore<actionTiddler>,<currentTiddler>]"/>
\end
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate, displayField:"caption")
\define list-links-draggable(tiddler,field:"list",emptyMessage,type:"ul",subtype:"li",class:"",itemTemplate)
\whitespace trim
<$set name="_tiddler" value="""$tiddler$""" emptyValue=<<currentTiddler>> >
<$let field-reference={{{ [<_tiddler>] "!!" [[$field$]] +[join[]] }}}
@@ -42,7 +42,7 @@ tags: $:/tags/Macro
<$transclude tiddler="""$itemTemplate$""">
<$link to={{!!title}}>
<$let tv-wikilinks="no">
<$transclude field=<<__displayField__>>>
<$transclude field="caption">
<$view field="title"/>
</$transclude>
</$let>
@@ -92,7 +92,7 @@ tags: $:/tags/Macro
</$set>
\end
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"",displayField:"title")
\define list-tagged-draggable(tag,subFilter,emptyMessage,itemTemplate,elementTag:"div",storyview:"")
\whitespace trim
<span class="tc-tagged-draggable-list">
<$set name="tag" value=<<__tag__>>>
@@ -110,11 +110,7 @@ tags: $:/tags/Macro
<$genesis $type=<<__elementTag__>>>
<$transclude tiddler="""$itemTemplate$""">
<$link to={{!!title}}>
<$let tv-wikilinks="no">
<$transclude field=<<__displayField__>>>
<$view field="title"/>
</$transclude>
</$let>
<$view field="title"/>
</$link>
</$transclude>
</$genesis>

View File

@@ -9,9 +9,8 @@ code-body: yes
setTo=<<currentTab>>
default=<<__default__>>
selectedClass="tc-tab-selected"
selectedAria="aria-selected"
tooltip={{!!tooltip}}
role="tab"
role="switch"
data-tab-title=<<currentTab>>
>
<$tiddler tiddler=<<save-currentTiddler>>>
@@ -58,12 +57,12 @@ code-body: yes
\whitespace trim
<$qualify title=<<__state__>> name="qualifiedState">
<$let tabsState={{{ [<__explicitState__>minlength[1]] ~[<qualifiedState>] }}}>
<div class={{{ [[tc-tab-set]addsuffix[ ]addsuffix<__class__>] }}} role="tablist">
<div class={{{ [[tc-tab-set]addsuffix[ ]addsuffix<__class__>] }}}>
<div class={{{ [[tc-tab-buttons]addsuffix[ ]addsuffix<__class__>] }}}>
<<tabs-tab-list>>
</div>
<div class={{{ [[tc-tab-divider]addsuffix[ ]addsuffix<__class__>] }}}/>
<div class={{{ [[tc-tab-content]addsuffix[ ]addsuffix<__class__>] }}} role="tabpanel">
<div class={{{ [[tc-tab-content]addsuffix[ ]addsuffix<__class__>] }}}>
<<tabs-tab-body>>
</div>
</div>

View File

@@ -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 -->
<!-- This could probably be optimized / removed if we would use different temp-tiddlers
(future improvement because keeping track is complex for humans)
(future improvement because keeping track is comlex for humans)
-->
\procedure delete-tag-state-tiddlers()
<$action-deletetiddler $filter="[<newTagNameTiddler>] [<storeTitle>] [<tagSelectionState>]"/>
@@ -111,7 +111,6 @@ The second ESC tries to close the "draft tiddler"
refreshTitle=<<refreshTitle>>
selectionStateTitle=<<tagSelectionState>>
inputAcceptActions=<<add-tag-actions>>
inputAcceptVariantActions=<<save-tiddler-actions>>
inputCancelActions=<<clear-tags-actions>>
tag="input"
placeholder={{$:/language/EditTemplate/Tags/Add/Placeholder}}

View File

@@ -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.
See the demo at https://github.com/Jermolene/TiddlyWiki5DemoApp
See the demo at https://github.com/TiddlyWiki/TiddlyWiki5DemoApp

View File

@@ -0,0 +1,17 @@
caption: savetiddlers
color: #4DB6AC
community-author: Buggyj
created: 20171109171935039
delivery: Browser Extension
description: Extension pour les navigateurs Chrome et Firefox
fr-title:
method: save
modified: 20220402105820520
tags: Chrome Firefox Saving [[Other Resources]] plugins
title: "savetiddlers" Extension for Chrome and Firefox by buggyj
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
Une extension pour Google Chrome et Mozilla Firefox qui fluidifie l'utilisation de [[l'enregistreur HTML5 par défaut|Saving with the HTML5 fallback saver]] de <<tw>>, et le rend presque aussi convivial que ~TiddlyFox une fois configurée.
https://github.com/buggyj/savetiddlers

View File

@@ -1,17 +0,0 @@
caption: savetiddlers
color: #4DB6AC
community-author: buggyj
created: 20171109171935039
delivery: Browser Extension
description: Extension pour les navigateur Firefox
fr-title:
method: save
modified: 20250809092435788
tags: Firefox Saving [[Other Resources]] plugins
title: savetiddlers: Extension for Firefox by buggyj
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
Une extension Mozilla Firefox qui fluidifie l'utilisation de [[l'enregistreur HTML5 par défaut|Saving with the HTML5 fallback saver]] de <<tw>>, et le rend presque aussi convivial que [[TiddlyFox]] une fois configurée.
{{!!url}}

View File

@@ -1,12 +1,13 @@
created: 20240313100515958
modified: 20251214111324789
original-modified: 20251023154747366
modified: 20241222104855231
original-modified: 20240313103959789
tags: Editions
title: TiddlyWiki Docs PR Maker
ja-title: TiddlyWikiドキュメントPRメーカー
''~TiddlyWikiドキュメントPRメーカー''は、ドキュメントへの貢献と改善を支援するために設計された、tiddlywiki.comの特別エディションです。
https://edit.tiddlywiki.com
[[@saqimtiaz|https://github.com/saqimtiaz/]]が作成した''~TiddlyWikiドキュメントPRメーカー''は、ドキュメントへの貢献と改善を支援するために設計された、tiddlywiki.comの特別エディションです。
https://saqimtiaz.github.io/tw5-docs-pr-maker/
ドキュメントに加えられたすべての変更は、GitHubに簡単に送信できます。 -- プルリクエストは自動的に作成されるため、エディションの名前は"PRメーカー"になります。

View File

@@ -1,6 +1,6 @@
created: 20231005205623086
modified: 20251208113045167
original-modified: 20250807100434131
modified: 20241226114558500
original-modified: 20241115193649399
tags: About
title: TiddlyWiki Archive
ja-title: TiddlyWikiアーカイブ
@@ -10,7 +10,7 @@ ja-title: TiddlyWikiアーカイブ
5.1.10 5.1.11 5.1.12 5.1.13 5.1.14 5.1.15 5.1.16 5.1.17 5.1.18 5.1.19
5.1.20 5.1.21 5.1.22 5.1.23
5.2.0 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7
5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.3.7 5.3.8
5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6
\end
TiddlyWikiの古いバージョンは[[アーカイブ|https://github.com/TiddlyWiki/tiddlywiki.com-gh-pages/tree/master/archive]]で入手できます:

View File

@@ -1,13 +1,31 @@
created: 20150412191004348
modified: 20251208113458455
original-modified: 20251022153208584
modified:
original-modified: 20240925114810504
tags: Community Reference
title: Developers
ja-title: 開発者
type: text/vnd.tiddlywiki
! [[GitHubの統計|https://github.com/TiddlyWiki/TiddlyWiki5/graphs/contributors]]
開発者がTiddlyWikiについて学び、開発について議論し、貢献するためのリソースがあります。
> [img[https://repobeats.axiom.co/api/embed/b92b1b363e2b5f26837ae573a60d39b4248b50a0.svg]]
* [[tiddlywiki.com/dev|https://tiddlywiki.com/dev]]は公式の開発者ドキュメントです
* [[GitHubでの開発|https://github.com/TiddlyWiki/TiddlyWiki5]]に参加する
* [[GitHubディスカッション|https://github.com/TiddlyWiki/TiddlyWiki5/discussions]]はQ&Aとオープンな形式のディスカッションです
* [[GitHubイシュー|https://github.com/TiddlyWiki/TiddlyWiki5/issues]]は、バグレポートを作成し、具体的で実現可能な新しいアイデアを提案するためのものです
* プロジェクトに貢献する方法についてのガイドラインについては、[[貢献|Contributing]]を参照してください
* 古い~TiddlyWikiDevGoogleグループは閉鎖され、[[TiddlyWikiトーク|https://talk.tiddlywiki.org/]]と[[GitHubディスカッション|https://github.com/TiddlyWiki/TiddlyWiki5/discussions]]に代わりました
** 有用なアーカイブとして残っています: https://groups.google.com/group/TiddlyWikiDev
*** 強化されたグループ検索機能は[[mail-archive.com|https://www.mail-archive.com/tiddlywikidev@googlegroups.com/]]で利用できます
* https://gitter.im/TiddlyWiki/public でチャットしてください(開発ルームは近日公開予定)
! Twitter
* 最新ニュースは[[Twitterで@TiddlyWiki|http://twitter.com/#!/TiddlyWiki]]をフォローしてください

View File

@@ -1,14 +1,88 @@
created: 20140908114400000
modified: 20251208115007037
original-modified: 20251122174540932
modified: 20241225112134741
original-modified: 20241016125145988
tags: About
title: History of TiddlyWiki
ja-title: TiddlyWikiの歴史
type: text/vnd.tiddlywiki
~TiddlyWikiの歴史をまとめています。このプロジェクトは現在進行中です。寄稿や思い出話など、ぜひお寄せください。
! ~TiddlyWikiの20年
~TiddlyWikiの20周年を祝うために、いくつかのライブストリームを開催しました。録画はここで視聴できます:
* 2024年9月19日 - https://youtube.com/live/z9slx92TyrU
* 2024年9月20日 - https://youtube.com/live/puFdN-FgOjg
* 2024年9月21日 - https://youtube.com/live/0SjsHvwjHGE
* 2024年9月22日 - https://youtube.com/live/oD7Jtq2D4lg
GitHubでは、TiddlyWikiの貢献者に記念日の感想を[[聞いて|https://github.com/TiddlyWiki/TiddlyWiki5/discussions/7983]]お祝いしました。興味深く思慮深い回答がいくつか寄せられました。たとえば、[[@FND|https://github.com/FND]]からの回答は次の通りです:
> TiddlyWikiは、私のキャリアだけでなく、価値観にも計り知れないほどの永続的な影響を与えました。今日に至るまで、私はTiddlyWikiから学んだ[[基本的なコンセプト|https://prepitaph.org/articles/creative-privacy/]] - その多くは、他では忘れられたり無視されたりしています - を頻繁に参照しています。このバックグラウンドがあることで、技術的な複雑さを崇拝したり、テクノロジーの世界に人間が存在することを思い出したりする場合でも、この業界で仕事をする上で自分の方向性を保つことができます。
> TiddlyWikiとは、人々のことです。このコミュニティや、Jeremyがその周りに築いたグループと交流し、そこから学ぶことができたのは、私にとって計り知れない特権でした。また、この特権がまったくの偶然によって私に与えられたものだということを思い出すのにも役立ちます。この恩返しをしていきたいと思います。
~TiddlyWikiを特集した最近のポッドキャスト:
* 2016年のチェンジログ ポッドキャスト - https://changelog.com/podcast/196 ~TiddlyWikiの背景について議論しています
* 2021年のFloss Weeklyの録画 - https://twit.tv/shows/floss-weekly/episodes/620
! TiddlyWikiの起源
遡ること1997年に、同僚が私に[[Ward Cunningham のオリジナル wiki|http://c2.com/cgi/wiki]]を紹介してくれました。これほど強力なものがわずか700行のPerlに収まることに感銘を受け、セキュリティとパーミッションの根本的な再考に魅了されました。他の多くの開発者と同様に、私もあらゆる機会を利用してさまざまなWikiを試し、仕事での使用法を模索しました
私にとってWikiの魅力は、印刷物中心のドキュメントやEメールの一般的なパラダイムを最終的に破壊する可能性があるという感覚でした
人々がWikiを使用する様子を数年間観察した結果、パワーユーザーは複数のブラウザタブで複数のWikiページを同時に開く機能を多用しており、ページの比較やレビュー、ページ間でのテキストのコピー、未読ページの一種のキューとして用いることが容易になっていることに気づきました
一度に複数のページを操作するこの機能がWikiをリファクタリングする機能の中心であると感じました。また、愛情を込めてリファクタリングされたWikiはより便利になる傾向があると一般に認められています。それでも、標準のWikiユーザーインターフェイスは常に、単一ページを一度に表示し操作すること専用にデザインされてきました
2004年4月にGMailを見たとき、すべての考えがまとまりました。GMailは、Ajaxを巧みに使用して個々のメールをスレッド化された会話に融合させました。
このアイデアをさらに探求するために、HTMLとJavaScriptを試し始めました。私にはどちらの経験もなく、以前の活動で、いくつかの静的ページと単純なASPサイトをまとめただけでした。これらのクライアント側テクロジーについて理解するのは大変でした。他の皆さんと同じように、私もWebプログラミングの非互換性と矛盾がどれほど恐ろしいものであるかを知り、愕然としました
! TiddlyWikiのラウンチ
そうして、2004年9月に、私は原始的な[[TiddlyWikiの最初のバージョン|https://classic.tiddlywiki.com/firstversion.html]]をリリースしました。これは、アイデアを実証するための最小のもので、シンプルで自己完結型の静的な48KB HTMLファイルでした
TiddlyWikiの最初のバージョンをこの方法で作成することの欠点は、編集に使用するのが完全に非現実的になることでした。'変更を保存'をクリックすると、ファイルシステムにHTMLページを書き込むために、保存されるデータを示すウィンドウがポップアップ表示されるだけでした
初期のフィードバックの多くは、TiddlyWikiは優れているが、変更を適切に保存できればさらに便利になるというものでした。ブラウザで実行されているHTMLファイルがローカルファイルシステムに変更を保存することは不可能であることはわかっていると思っていたので、少しイライラしました
数か月以内に、TiddlyWikiがブラウザに変更を保存できるようにする実験的なFirefox拡張機能を目にしました。コードを調べてみると、ファイルシステムへの書き込みに使用されていたAPIは、`file://` URI経由でロードされている場合に限り、実際には通常のHTMLファイルで利用できることがわかりました
私はFirefoxコードをTiddlyWikiのコアに適合させ、すぐにInternet Explorerにも同様の機能を追加しました(MicrosoftがInternet Explorerとともに配布した古い[[ActiveX|https://en.wikipedia.org/wiki/ActiveX]]コントロールを利用しています)
! TiddlyWikiの成長
TiddlyWikiの成長における大きなマイルストーンは、Nathan Bowersによる"GTDTiddlyWiki"の作成でした。彼はバニラのTiddlyWiki製品を採用し、一般的なGetting Things Done方法論を使用してタスクをトラックするという特定のアプリケーションに適応させました。GTDTiddlyWikiはすぐに人気を博し、[[LifeHacker|https://lifehacker.com/]]などのWebサイトで熱狂的に歓迎されました
その後数年間にわたって、TiddlyWikiの人気は高まり続け、新しい機能や能力も獲得しました。1年以内に、私はTiddlyWikiでオーダーメイドの開発作業を行うことで自活できるようになり、特にWikiパイオニアである[[SocialText|https://en.wikipedia.org/wiki/Socialtext]]と協力して変更をオンラインサーバと同期する機能に取り組みました
! BTの獲得
2007年5月に、[[BT]]は私のコンサルティング会社である[[Osmosoft]]を買収しました。従業員が1人で、収益がほんの少ししかない会社を買収するというのは、異例の決断でした。[[Osmosoft]]は、コミュニティの将来を保証するために私がTiddlyWikiの知的財産をUnaMesaに譲渡したため、TiddlyWikiの知的財産さえ所有していませんでした
[[BT]]の動機は、コミュニティベースのエコシステムを理解することでした。私は"オープンソースイノベーション責任者"として組織に加わり、オープンソースガバナンスの責任を負い、オープンソースコミュニティへの参加方法に関するアドバイスと専門知識を提供しました
! [[Osmosoft]]とTiddlySpace
私はBTに[[Osmosoft]]という名前でチームを作りました。私たちの目的は、オープンソースのメリットを広め、他のチームが実際にそのメリットを実感できるよう支援することでした。また、Webの使用全般、特にWeb標準の使用を普及する必要があることもわかりました
私たちのアプローチは、話すことよりも見せることに重点を置くことでした。私たちはTiddlyWikiコミュニティと協力してエコシステムを拡張し、BT用の多数の内部システムを構築しました(TiddlyWikiに基づくものもあれば、そうでないものもあります)
TiddlyWikiコミュニティへの[[Osmosoft]]の主な貢献は、TiddlyWebとTiddlySpaceの作成でした。TiddlyWebは、Tiddlerのための堅牢なインターネット規模のサーバであり、TiddlerのTiddlyWikiビューを構成することもできました。TiddlySpaceは、TiddlyWebをより直接的に使用可能な形式にパッケージ化する試みでした
! BTを離れる
2011年の終わりまでに、私はBTという企業の枠外でTiddlyWikiの可能性を実現するのがより適切な立場にあると感じるようになりました。そうして、私は退職して独立した開発者として働き始め、主にTiddlyWiki5という形でTiddlyWikiを新しくリブートすることに取り組みました
! TiddlyWiki5の開発
私は2011年11月からTiddlyWikiの新しいリリースに取り組みました。プログラマーとして、すでに書いたものの"バージョン 2.0"に取り組むことは非常に魅力的な提案です。これは、要件が完全に理解され、目的の機能をサポートするために必要なアーキテクチャの進化に集中できることを意味します
! 将来
TiddlyWiki5がついに"ベータ"ステータスを脱した今、私の希望は、それが長く存続することです。HTML5とNode.jsの標準機能のみを使用しているため、今後何年にもわたって完全に動作しない理由はありません。私の目標は、少なくとも25年は続けることです
//Jeremy Ruston, 2014年9月20日//
* [[TiddlyWiki物語|The Story of TiddlyWiki]] [[@Jermolene]]によるTiddlyWikiの物語、その起源と進化に関する個人的な記録
* https://github.com/TiddlyWiki/LaunchArchive 2004年のTiddlyWiki立ち上げ時からのブログとツイート
* [[TiddlyWiki記念日|TiddlyWiki Anniversaries]] TiddlyWikiの主要な記念日のお祝いイベントの記録
* [[フィルタシンタックスの歴史|Filter Syntax History]] TiddlyWiki5におけるフィルタシンタックスの進化の簡単な歴史

View File

@@ -1,71 +0,0 @@
title: The Story of TiddlyWiki
ja-title: TiddlyWiki物語
tags: [[History of TiddlyWiki]]
modifier: Jeremy Ruston
created: 20140908114400000
modified: 20251215111120830
original-modified: 20250730154331065
これは、2004年9月20日の最初のリリース以来のTiddlyWikiの起源と進化のストーリーについての個人的な記録です。
! TiddlyWikiの起源
遡ること1997年に、同僚が私に[[Ward Cunningham のオリジナル wiki|http://c2.com/cgi/wiki]]を紹介してくれました。これほど強力なものがわずか700行のPerlに収まることに感銘を受け、セキュリティとパーミッションの根本的な再考に魅了されました。他の多くの開発者と同様に、私もあらゆる機会を利用してさまざまなWikiを試し、仕事での使用法を模索しました
私にとってWikiの魅力は、印刷物中心のドキュメントやEメールの一般的なパラダイムを最終的に破壊する可能性があるという感覚でした
人々がWikiを使用する様子を数年間観察した結果、パワーユーザーは複数のブラウザタブで複数のWikiページを同時に開く機能を多用しており、ページの比較やレビュー、ページ間でのテキストのコピー、未読ページの一種のキューとして用いることが容易になっていることに気づきました
一度に複数のページを操作するこの機能がWikiをリファクタリングする機能の中心であると感じました。また、愛情を込めてリファクタリングされたWikiはより便利になる傾向があると一般に認められています。それでも、標準のWikiユーザーインターフェイスは常に、単一ページを一度に表示し操作すること専用にデザインされてきました
2004年4月にGMailを見たとき、すべての考えがまとまりました。GMailは、Ajaxを巧みに使用して個々のメールをスレッド化された会話に融合させました。
このアイデアをさらに探求するために、HTMLとJavaScriptを試し始めました。私にはどちらの経験もなく、以前の活動で、いくつかの静的ページと単純なASPサイトをまとめただけでした。これらのクライアント側テクロジーについて理解するのは大変でした。他の皆さんと同じように、私もWebプログラミングの非互換性と矛盾がどれほど恐ろしいものであるかを知り、愕然としました
! TiddlyWikiのラウンチ
そうして、2004年9月に、私は原始的な[[TiddlyWikiの最初のバージョン|https://classic.tiddlywiki.com/firstversion.html]]をリリースしました。これは、アイデアを実証するための最小のもので、シンプルで自己完結型の静的な48KB HTMLファイルでした
TiddlyWikiの最初のバージョンをこの方法で作成することの欠点は、編集に使用するのが完全に非現実的になることでした。'変更を保存'をクリックすると、ファイルシステムにHTMLページを書き込むために、保存されるデータを示すウィンドウがポップアップ表示されるだけでした
初期のフィードバックの多くは、TiddlyWikiは優れているが、変更を適切に保存できればさらに便利になるというものでした。ブラウザで実行されているHTMLファイルがローカルファイルシステムに変更を保存することは不可能であることはわかっていると思っていたので、少しイライラしました
数か月以内に、TiddlyWikiがブラウザに変更を保存できるようにする実験的なFirefox拡張機能を目にしました。コードを調べてみると、ファイルシステムへの書き込みに使用されていたAPIは、`file://` URI経由でロードされている場合に限り、実際には通常のHTMLファイルで利用できることがわかりました
私はFirefoxコードをTiddlyWikiのコアに適合させ、すぐにInternet Explorerにも同様の機能を追加しました(MicrosoftがInternet Explorerとともに配布した古い[[ActiveX|https://en.wikipedia.org/wiki/ActiveX]]コントロールを利用しています)
! TiddlyWikiの成長
TiddlyWikiの成長における大きなマイルストーンは、Nathan Bowersによる"GTDTiddlyWiki"の作成でした。彼はバニラのTiddlyWiki製品を採用し、一般的なGetting Things Done方法論を使用してタスクをトラックするという特定のアプリケーションに適応させました。GTDTiddlyWikiはすぐに人気を博し、[[LifeHacker|https://lifehacker.com/]]などのWebサイトで熱狂的に歓迎されました
その後数年間にわたって、TiddlyWikiの人気は高まり続け、新しい機能や能力も獲得しました。1年以内に、私はTiddlyWikiでオーダーメイドの開発作業を行うことで自活できるようになり、特にWikiパイオニアである[[SocialText|https://en.wikipedia.org/wiki/Socialtext]]と協力して変更をオンラインサーバと同期する機能に取り組みました
! BTの獲得
2007年5月に、[[BT]]は私のコンサルティング会社である[[Osmosoft]]を買収しました。従業員が1人で、収益がほんの少ししかない会社を買収するというのは、異例の決断でした。[[Osmosoft]]は、コミュニティの将来を保証するために私がTiddlyWikiの知的財産をUnaMesaに譲渡したため、TiddlyWikiの知的財産さえ所有していませんでした
[[BT]]の動機は、コミュニティベースのエコシステムを理解することでした。私は"オープンソースイノベーション責任者"として組織に加わり、オープンソースガバナンスの責任を負い、オープンソースコミュニティへの参加方法に関するアドバイスと専門知識を提供しました
! [[Osmosoft]]とTiddlySpace
私はBTに[[Osmosoft]]という名前でチームを作りました。私たちの目的は、オープンソースのメリットを広め、他のチームが実際にそのメリットを実感できるよう支援することでした。また、Webの使用全般、特にWeb標準の使用を普及する必要があることもわかりました
私たちのアプローチは、話すことよりも見せることに重点を置くことでした。私たちはTiddlyWikiコミュニティと協力してエコシステムを拡張し、BT用の多数の内部システムを構築しました(TiddlyWikiに基づくものもあれば、そうでないものもあります)
TiddlyWikiコミュニティへの[[Osmosoft]]の主な貢献は、TiddlyWebとTiddlySpaceの作成でした。TiddlyWebは、Tiddlerのための堅牢なインターネット規模のサーバであり、TiddlerのTiddlyWikiビューを構成することもできました。TiddlySpaceは、TiddlyWebをより直接的に使用可能な形式にパッケージ化する試みでした
! BTを離れる
2011年の終わりまでに、私はBTという企業の枠外でTiddlyWikiの可能性を実現するのがより適切な立場にあると感じるようになりました。そうして、私は退職して独立した開発者として働き始め、主にTiddlyWiki5という形でTiddlyWikiを新しくリブートすることに取り組みました
! TiddlyWiki5の開発
私は2011年11月からTiddlyWikiの新しいリリースに取り組みました。プログラマーとして、すでに書いたものの"バージョン 2.0"に取り組むことは非常に魅力的な提案です。これは、要件が完全に理解され、目的の機能をサポートするために必要なアーキテクチャの進化に集中できることを意味します
! 将来
2014年、 TiddlyWiki5を初めてリリースした直後に、私は次のように書きました:
> TiddlyWiki5がついに"ベータ"ステータスを脱した今、私の希望は、それが長く存続することです。HTML5とNode.jsの標準機能のみを使用しているため、今後何年にもわたって完全に動作しない理由はありません。私の目標は、少なくとも25年は続けることです
これを書いている時点で、TiddlyWiki5は目標の44%を達成しています。コミュニティの皆様のご支援と熱意により、このプロジェクトは今後も発展し、進化していくと確信しています。

View File

@@ -1,33 +0,0 @@
title: TiddlyWiki Anniversaries
ja-title: TiddlyWiki記念日
tags: [[History of TiddlyWiki]]
created: 20250730154331065
modified: 20251215105745893
original-modified: 20250730154331065
! ~TiddlyWikiの20周年
~TiddlyWikiの20周年を祝うために、いくつかのライブストリームを開催しました。録画はここで視聴できます:
* 2024年9月19日 - https://youtube.com/live/z9slx92TyrU
* 2024年9月20日 - https://youtube.com/live/puFdN-FgOjg
* 2024年9月21日 - https://youtube.com/live/0SjsHvwjHGE
* 2024年9月22日 - https://youtube.com/live/oD7Jtq2D4lg
GitHubでは、TiddlyWikiの貢献者に記念日の感想を[[聞いて|https://github.com/TiddlyWiki/TiddlyWiki5/discussions/7983]]お祝いしました。興味深く思慮深い回答がいくつか寄せられました。たとえば、[[@FND|https://github.com/FND]]からの回答は次の通りです:
> TiddlyWikiは、私のキャリアだけでなく、価値観にも計り知れないほどの永続的な影響を与えました。今日に至るまで、私はTiddlyWikiから学んだ[[基本的なコンセプト|https://prepitaph.org/articles/creative-privacy/]] - その多くは、他では忘れられたり無視されたりしています - を頻繁に参照しています。このバックグラウンドがあることで、技術的な複雑さを崇拝したり、テクノロジーの世界に人間が存在することを思い出したりする場合でも、この業界で仕事をする上で自分の方向性を保つことができます。
> TiddlyWikiとは、人々のことです。このコミュニティや、Jeremyがその周りに築いたグループと交流し、そこから学ぶことができたのは、私にとって計り知れない特権でした。また、この特権がまったくの偶然によって私に与えられたものだということを思い出すのにも役立ちます。この恩返しをしていきたいと思います。
~TiddlyWikiを特集した最近のポッドキャスト:
* 2016年のチェンジログ ポッドキャスト - https://changelog.com/podcast/196 ~TiddlyWikiの背景について議論しています
* 2021年のFloss Weeklyの録画 - https://twit.tv/shows/floss-weekly/episodes/620
! ~TiddlyWikiの10周年
2014年9月20日に行われた、TiddlyWikiの10周年を祝うライブストリームはここで視聴できます:
https://www.youtube.com/watch?v=f_02ZV0J9NY

View File

@@ -1,11 +1,13 @@
created: 20130909151600000
modified: 20251210110939585
original-modified: 20250909171928024
modified: 20241002113817654
original-modified: 20210322152237662
tags: TableOfContents Welcome
title: Community
ja-title: コミュニティ
type: text/vnd.tiddlywiki
TiddlyWikiコミュニティは、TiddlyWikiをより良くするために協力し、お互いにベストを尽せるよう支援する熱心なユーザーと開発者のグループです。
<<.tip "最新の有益なリンクが[[コミュニティリンク収集|Community Links Aggregator]]に集められています。">>
<<tabs "[[TiddlyWiki Project]] [[TiddlyWiki People]] Forums" "TiddlyWiki Project">>
すべての関連リンクがこれらのエントリに書かれると、メインのtiddlywiki.comサイトからは削除されます。
<<tabs "Forums Latest Tutorials [[Community Editions]] [[Community Plugins]] [[Community Themes]] [[Community Palettes]] [[Other Resources]] Examples Articles Meetups" "Latest">>

View File

@@ -1,9 +1,9 @@
color: #808
created: 20241009150445080
icon: $:/core/images/link
list: TalkTiddlyWiki [[TiddlyWiki on YouTube]] [[TiddlyWiki on Reddit]] [[TiddlyWiki on Discord]] [[TiddlyWiki on GitHub]] [[TiddlyWiki on Mastodon]] [[TiddlyWiki on Open Collective]]
modified: 20251210112417726
original-modified: 20241115170824144
list: TalkTiddlyWiki [[TiddlyWiki on YouTube]] [[TiddlyWiki on Reddit]] [[TiddlyWiki on Discord]] [[TiddlyWiki on GitHub]] [[TiddlyWiki on Mastodon]] [[TiddlyWiki on Twitter]] [[TiddlyWiki on Gitter]] [[TiddlyWiki on Open Collective]]
modified: 20241010114936568
original-modified: 20241009150453139
tags: Welcome
title: TiddlyWiki on the Web
ja-title: ウェブ上のTiddlyWiki

View File

@@ -0,0 +1,18 @@
caption: savetiddlers
color: #4DB6AC
community-author: Buggyj
created: 20171109171935039
delivery: Browser Extension
description: ChromeとFirefoxのブラウザ拡張機能
method: save
modified: 20241014110546647
original-modified: 20210106151027189
tags: Chrome Firefox Saving [[Other Resources]] plugins
title: "savetiddlers" Extension for Chrome and Firefox by buggyj
ja-title: buggyjによるChromeとFirefoxの"savetiddlers"拡張機能
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
Google ChromeとMozilla Firefoxの拡張機能で、TiddlyWikiの組み込み[[HTML5セーバー|Saving with the HTML5 saver]]による使いにくさの一部を解消し、正しく設定すればTiddlyFoxとほぼ同じくらい簡単に使用できるようになります。
https://github.com/buggyj/savetiddlers

View File

@@ -1,18 +0,0 @@
caption: savetiddlers
color: #4DB6AC
community-author: buggyj
created: 20171109171935039
delivery: Browser Extension
description: Firefoxのブラウザ拡張機能
method: save
modified: 20250809092435788
original-modified: 20250809092435788
tags: Firefox Saving [[Other Resources]] plugins
title: savetiddlers: Extension for Firefox by buggyj
ja-title: buggyjによるFirefoxの"savetiddlers"拡張機能
type: text/vnd.tiddlywiki
url: https://github.com/buggyj/savetiddlers
Mozilla Firefoxの拡張機能で、TiddlyWikiの組み込み[[HTML5セーバー|Saving with the HTML5 saver]]による使いにくさの一部を解消し、正しく設定すれば[[TiddlyFox]]とほぼ同じくらい簡単に使用できるようになります。
{{!!url}}

View File

@@ -1,6 +1,6 @@
created: 20140610213500000
modified: 20251212111127961
original-modified: 20250217154855572
modified: 20241209112247651
original-modified: 20241030132047048
tags: Concepts Features
title: ExternalImages
ja-title: 外部画像
@@ -25,28 +25,22 @@ TiddlyWikiの外部画像は、画像データすべてを埋め込むのでは
参照される外部画像を含む''images''フォルダーを伴うWikiの静的HTMLファイルバージョンを作成するには、次の手順を使用します:
# 通常の方法でTiddlyWikiFoldersに画像Tiddlerを作成します
# 画像を別ファイルとして保存します (慣例により、''/images''という名前のサブフォルダに保存します)
# 画像を別ファイルとして保存します (慣例により、''images''という名前のサブフォルダに保存します)
# ''_canonical_uri''フィールドを追加して画像Tiddlerを外部化します
# メインのHTMLファイルを保存します
画像ファイルは外部化する前に保存する必要があることに注意してください。外部化すると、Wikiストアのメモリ内コピーの''text''フィールドが破壊され、保存の試みが失敗します。
!! 外部画像の構成
たとえば、''tiddlywiki.info''ファイル内に、''externalimages''ビルドターゲットを作成します:
たとえば、''tw5.com'' Wikiの''externalimages''ビルドターゲットを参照してください:
```
"build": {
"externalimages": [
--save [is[image]] images
--setfield [is[image]] _canonical_uri $:/core/templates/canonical-uri-external-image text/plain
--setfield [is[image]] text "" text/plain
--render $:/core/save/all externalimages.html text/plain
]
}
--save [is[image]] images
--setfield [is[image]] _canonical_uri $:/core/templates/canonical-uri-external-image text/plain
--setfield [is[image]] text "" text/plain
--render $:/core/save/all externalimages.html text/plain
```
!! 画像Tiddlerの外部化
!! 個別の画像ファイルを保存する
次の`--save`コマンド ([[Saveコマンド|SaveCommand]]を参照)を使用すると、Wikiの画像を''images''サブフォルダーに保存できます:
@@ -54,6 +48,8 @@ TiddlyWikiの外部画像は、画像データすべてを埋め込むのでは
--save [is[image]] images
```
!! 画像Tiddlerの外部化
2つの`--setfield`コマンドが使用されています: 最初のコマンドは、''_canonical_uri''フィールドをTiddlerのタイトルから派生したURIに設定し、2番目のコマンドはtextフィールドをクリアします。
```
@@ -71,20 +67,6 @@ TiddlyWikiの外部画像は、画像データすべてを埋め込むのでは
これらの操作により、Wikiストア内のTiddlerが変更されるため、後続のコマンド操作に影響する可能性があることに注意してください。
!! 外部画像をビルドするためのNode.jsコマンド
次のコマンドは、`myWiki/output`フォルダー内に外部画像を作成します。
```
tiddlywiki myWiki --build externalimages
```
Windowsでは、次のコマンドを実行すると、[[tw5.comエディション|https://github.com/TiddlyWiki/TiddlyWiki5/blob/master/editions/tw5.com/tiddlywiki.info#L26]]の一部である外部画像が作成されます。ファイルは出力ディレクトリに作成されます。
```
tiddlywiki .\editions\tw5.com --build index
```
! 外部画像の使用について
URIフィールドを別の画像を指すように変更しない限り、ブラウザで外部画像を直接編集することはできません。

View File

@@ -1,6 +1,6 @@
created: 20150124182127000
modified: 20251213102731461
original-modified: 20250731101041336
modified: 20250222110925130
original-modified: 20230710074414361
tags: [[Filter Run]]
title: Filter Step
ja-title: フィルタステップ
@@ -13,10 +13,10 @@ type: text/vnd.tiddlywiki
<$railroad text="""
\start none
\end none
["!"]
[:"!"]
( / "省略の場合のデフォルト: title" /|:
( :[[<"オペレータ">|"Filter Operators"]] )
[ {":" [: [[<"サフィックス">|"Filter Operators"]] ] }] )
( - | :[[<"オペレータ">|"Filter Operators"]] )
{ [:":" [[<"サフィックス">|"Filter Operators"]] ] } )
{ [[<"パラメータ">|"Filter Parameter"]] + "," }
"""/>

View File

@@ -1,8 +1,8 @@
color: #880
created: 20241009150347613
icon: $:/core/images/help
modified: 20251213103718012
original-modified: 20241115170824144
modified: 20241010114029686
original-modified: 20241009150430229
tags: Welcome
title: Find Out More
ja-title: さらに詳しく

View File

@@ -1,41 +1,19 @@
created: 20130822170200000
icon: $:/core/icon
list: [[A Gentle Guide to TiddlyWiki]] [[Discover TiddlyWiki]] [[Some of the things you can do with TiddlyWiki]] [[Ten reasons to switch to TiddlyWiki]] Examples [[What happened to the original TiddlyWiki?]]
modified: 20251213104120189
original-modified: 20250807084952911
modified: 20241010112232871
original-modified: 20241009150333146
tags: Welcome
title: HelloThere
ja-title: こんにちは
type: text/vnd.tiddlywiki
<h2
style="
background: red;
padding: 0.5em;
color: white;
font-weight: bold;
text-align: center;
border-radius: 0.5em;
box-shadow: 0 1px 3px 0 #d4d4d5, 0 0 0 1px #d4d4d5;
background-image: linear-gradient(90deg, rgb(34, 132, 224), rgb(95, 174, 248), rgb(34, 132, 224));
">
メモを有効活用する
</h2>
<h2
class="tc-hero-heading"
style="
text-align: center;
">
TiddlyWikiへようこそ。 TiddlyWikiは複雑な情報を[[収集|Creating and editing tiddlers]]し、[[整理|Structuring TiddlyWiki]]し、[[共有|Sharing your tiddlers with others]]するためのユニークな[[非線形|Philosophy of Tiddlers]]ノートブックです
</h2>
!!.tc-hero-heading ''TiddlyWikiへようこそ。 TiddlyWikiは複雑な情報を[[収集|Creating and editing tiddlers]]し、[[整理|Structuring TiddlyWiki]]し、[[共有|Sharing your tiddlers with others]]するためのユニークな[[非線形|Philosophy of Tiddlers]]ノートブックです。''
[[ToDo リスト|TaskManagementExample]]を管理したり、[[エッセイや小説|"TiddlyWiki for Scholars" by Alberto Molina]]を練ったり、結婚式を準備したりするために使えます。頭をよぎるすべての考えを記録し、柔軟で応答性の高いWebサイトを構築できます。
* ~TiddlyWikiはデータとコードを単一のHTMLファイルに保存し、インストールや外部依存を必要とせず、Webブラウザのみで動作します
* ~TiddlyWikiを使用すると、データの保存場所を選択でき、今日とったメモを今後数十年も[[使用できること|Future Proof]]が保証されます
* ~TiddlyWikiを使用すると、データの保存場所を選択でき、今日とったメモを今後数十年も[[使用できること|Future Proof]]が保証されます
* ~TiddlyWikiは、新しい機能を追加する多くのプラグインにより、無限にカスタマイズ、拡張可能です。
* ~TiddlyWikiは、新しい機能を追加する多くのプラグインにより、無限にカスタマイズ、拡張可能です
* ~TiddlyWikiは、大規模なユーザーコミュニティの一部である開発者集団の製品です
* ~TiddlyWikiは、大規模なユーザーコミュニティの一部である開発者集団の製品です

View File

@@ -1,7 +1,7 @@
color: #088
icon: $:/core/images/star-filled
modified: 20251214104051278
original-modified: 20241115170824144
modified: 20241010114508408
original-modified: 20241001141521924
tags: Welcome
title: Testimonials and Reviews
ja-title: 利用者の声とレビュー

View File

@@ -1,10 +1,8 @@
list: HelloThere [[Quick Start]] [[Find Out More]] [[TiddlyWiki on the Web]] [[Testimonials and Reviews]] GettingStarted Community
tags: TableOfContents
list-before:
title: Welcome
ja-title: ようこそ
type: text/vnd.tiddlywiki
<$transclude $tiddler="HelloThere"/>
''詳細については、トピックを選択してください:''
<div class="tc-table-of-contents"><<toc-selective-expandable "Welcome">></div>
<<list-links filter:"[tag<currentTiddler>]" >>

View File

@@ -2,8 +2,8 @@ color: #cc9
created: 20241009163451663
icon: $:/core/images/tip
list: GettingStarted [[Getting Started Video]] [[Find Out More]] [[TiddlyWiki on the Web]] [[Testimonials and Reviews]]
modified: 20251214103541254
original-modified: 20241115170824144
modified: 20241010112536263
original-modified: 20241009163521037
tags: Welcome
title: Quick Start
ja-title: クイックスタート

View File

@@ -1,9 +1,9 @@
created: 20240907042443909
modified: 20251214104453831
original-modified: 20241120225606237
modified: 20241116104031988
original-modified: 20240907042629405
tags: [[Hidden Settings]]
title: Hidden Setting: Default Tiddler Colour
ja-title: 隠し設定: TIddlerのデフォルト色
type: text/vnd.tiddlywiki
デフォルトのtag-tiddler色は、$:/config/DefaultTiddlerColourというTiddlerを作成し、CSSの色の値を含むことによって指定できます。詳細については、[[Tiddlerカラーカスケード|Tiddler Colour Cascade]]を参照してください
デフォルトのTiddler色は、$:/config/DefaultTiddlerColourというTiddlerを作成し、CSSの色の値を含むことによって指定できます。

View File

@@ -1,7 +1,7 @@
created: 20201228143125000
modified: 20251214105341696
original-modified: 20250302051857380
tags: OfficialPlugins [[Plugin Editions]]
modified: 20241222103744408
original-modified: 20201228143125000
tags: OfficialPlugins
title: Share Plugin
ja-title: シェアプラグイン
type: text/vnd.tiddlywiki
@@ -11,6 +11,4 @@ type: text/vnd.tiddlywiki
この実験的なプラグインは、URL経由でTiddlerを共有するためのツールを提供します。これには以下が含まれます:
* 起動時にブラウザのロケーションハッシュからTiddlerのグループをロードする機能
* TiddlerのグループからURLを作成するためのウィザードとテンプレート
デモは[ext[https://tiddlywiki.com/share|share]]を参照してください
* TiddlerのグループからURLを作成するためのウィザードとテンプレート

View File

@@ -1,12 +1,12 @@
created: 20130825160900000
modified: 20251214105948181
original-modified: 20241106165307259
modified: 20241110103519303
original-modified: 20160610083350724
tags: Features [[Working with TiddlyWiki]]
title: Encryption
ja-title: 暗号化
type: text/vnd.tiddlywiki
TiddlyWiki5を単一のHTMLファイルとして使用すると、[[Stanford JavaScript Crypto Library]]を使用してCCMモードのAES 128ビット暗号化でコンテンツを暗号化できます。
TiddlyWiki5を単一のHTMLファイルとして使用すると、[[Stanford JavaScript Crypto Library]]を使用してコンテンツを暗号化できます。
# サイドバーの''ツール''タブに切り替えて、南京錠アイコンのボタンを探します
# ボタンに<<.icon $:/core/images/unlocked-padlock>> ''パスワードの設定''と表示されている場合、現在のウィキは暗号化されていません。ボタンをクリックすると、以降の保存を暗号化するために使用されるパスワードの入力を求められます

View File

@@ -4,8 +4,7 @@ created: 20160216191710789
delivery: Protocol
description: SharePointなどの製品で利用できる標準Webプロトコル
method: save
modified: 20251214110658333
original-modified: 20220615155048712
modified: 20220615155048712
tags: Android Chrome Firefox [[Internet Explorer]] Linux Mac Opera PHP Safari Saving Windows iOS Edge
title: Saving via WebDAV
ja-title: WebDAV経由の保存

View File

@@ -1,6 +1,6 @@
created: 20140908163900000
modified: 20251214112408533
original-modified: 20230803052125981
modified: 20241016111248572
original-modified: 20201228143412000
tags: Learning
title: Sharing your tiddlers with others
ja-title: Tiddlerを他の人と共有する
@@ -12,7 +12,7 @@ type: text/vnd.tiddlywiki
* ~TiddlyWikiをオンラインで公開し、リンクを取得して他の人に送信、または、伝言できます:
** ~TiddlyWikiファイル全体のWebアドレスへのリンク
** 特定のTiddlerへの[[パーマリンク|PermaLinks]](<<.icon $:/core/images/permalink-button>>)
** 現在開いているすべてのTiddlerの[[パーマビュー|PermaLinks]](<<.icon $:/core/images/permaview-button>>)リンク
** 現在開いているすべてのTiddlerの[[パーマビュー|PermaViews]](<<.icon $:/core/images/permaview-button>>)リンク
* [[TiddlyWikiへのDropboxリンクを共有|Sharing a TiddlyWiki on Dropbox]]できます
* テキスト、静的HTML、カンマ区切り値(つまり、スプレッドシート互換)などのさまざまな形式で[[Tiddlerをエクスポート|How to export tiddlers]](<<.icon $:/core/images/export-button>>)できます
* また、~TiddlyWikiを他の人がアクセスできるようにするだけで、例えば、オンラインで公開して、そこから[[Tiddlerをインポート|Importing Tiddlers]]できるようにするだけで、Tiddlerを共有できます

View File

@@ -10,4 +10,4 @@ HelloThere
[[TiddlyWiki on the Web]]
[[Testimonials and Reviews]]
GettingStarted
Community
Community

View File

@@ -1,18 +0,0 @@
title: ElementMapping/Basic
description: Mapping one element to another
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<!-- Map <p> to <div>, adding the class my-class -->
\define tv-map-p() div
This is a paragraph
+
title: ExpectedResult
<div data-element-mapping-from="p">This is a paragraph</div>

View File

@@ -1,19 +0,0 @@
title: ElementMapping/BasicWithClass
description: Mapping one element to another with an added class
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<!-- Map <p> to <div>, adding the class my-class -->
\define tv-map-p() div
\define tv-map-p-class() my-class
This is a paragraph
+
title: ExpectedResult
<div class="my-class" data-element-mapping-from="p">This is a paragraph</div>

Some files were not shown because too many files have changed in this diff Show More