1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-02-19 16:39:50 +00:00

Compare commits

..

98 Commits

Author SHA1 Message Date
jeremy@jermolene.com
fb02f15972 Merge branch 'master' into tm-http-request-message 2023-06-12 15:29:39 +01:00
jeremy@jermolene.com
483ade1f16 Fix missing body 2023-06-12 15:29:09 +01:00
jeremy@jermolene.com
a12a9bd939 Fixes to browser storage plugin icon 2023-06-12 09:22:20 +01:00
jeremy@jermolene.com
ec7d248dcd Merge branch 'master' into tm-http-request-message 2023-06-11 12:21:22 +01:00
Carlo Colombo
6efd6dbf8b Update Jasmine website (#7533)
pivotal.github.io/jasmine website does not exists anymore,
replaced with the current Jasmine website
2023-06-11 10:36:02 +01:00
GameDungeon
578e883bdc Add Tabs To Settings (#7524)
* Move to Core

* List-Before

* Update core/ui/ControlPanel/Settings.tid

* Proper list-before
2023-06-11 10:28:52 +01:00
jeremy@jermolene.com
66212cd491 Refactor dependency on widget.getVariableInfo
Fixing https://talk.tiddlywiki.org/t/tw-v5-3-0-pre-problem-with-autocomplete-plugin/6958/9?u=jeremyruston
2023-06-11 09:46:05 +01:00
jeremy@jermolene.com
cc383e6d1e Refactor function evaluation code to avoid adding evaluateVariable method
Adding the new widget method was causing backwards compatibility issues. For example, see this discussion:

https://talk.tiddlywiki.org/t/tw-v5-3-0-pre-problem-with-autocomplete-plugin/6958
2023-06-10 08:58:04 +01:00
jeremy@jermolene.com
98e72558d0 Default site title no longer needs a tilde
Now that CamelCase linking is disabled by default
2023-06-09 08:35:42 +01:00
Jeremy Ruston
0095ea60d9 Switch off CamelCase linking by default (#7513)
* Disable camelcase by default

* New parse rule for ~CamelCase

For backwards compatibility with text that includes ~ to suppress camelcase links

* Enable CamelCase for main documentation wikis

Will take us a bit longer to convert all the links over

* Fix tests

* Release note update
2023-06-08 21:45:14 +01:00
Mario Pietsch
92f720901d Add missing data-tag-title attributes where needed (#7530)
* add missing data-tag-title assignments

* docs for data-tag-title

* fix typo in the docs

* rename file
2023-06-08 21:38:31 +01:00
jeremy@jermolene.com
7b9915b5c2 Update release note 2023-06-08 21:18:24 +01:00
jeremy@jermolene.com
8682beb717 Merge branch 'tiddlywiki-com' 2023-06-08 20:18:02 +01:00
jeremy@jermolene.com
cce23ac6cd Fix size of buttons in editor toolbar dropdowns
Fixes #7529
2023-06-08 08:32:56 +01:00
twMat
f141cbf8a5 Update WidgetMessage_ tm-close-all-windows.tid (#7525)
added caption. The problem can be seen in list 
https://tiddlywiki.com/#Messages
2023-06-07 15:26:47 +01:00
Bram Chen
88dc6eba96 Update chinese language files (#7514)
* Add chinese error messages for 'deserialize' operator
2023-06-03 18:00:37 +01:00
Saq Imtiaz
2221b8e08a Adds a deserialize filter operator (#7511)
* feat: added deserialize operator, tests and documentation

* fix: correct typo in lingo file

* fix: remove test that fails on node but succeeds in browser due to different availability of DOM deserializer
2023-06-03 14:33:10 +01:00
Mario Pietsch
d83d8e7245 Cover stand alone .from-version pill in a HTML block-element (#7512) 2023-06-03 14:27:59 +01:00
jeremy@jermolene.com
48b22abdaa Add a warning for tiddlywiki.info or plugin.info having json errors 2023-06-02 10:41:42 +01:00
jeremy@jermolene.com
a371ea0555 Minor fixes for introduction edition 2023-06-01 15:30:17 +01:00
jeremy@jermolene.com
68a7655396 Custom widgets and filter operator names must now contain a period
Fixes #7428
2023-06-01 08:06:28 +01:00
jeremy@jermolene.com
f19e74900e Merge branch 'tiddlywiki-com' 2023-05-29 12:45:59 +01:00
jeremy@jermolene.com
df323fe3c9 Simplify content shown for users without JavaScript
Saves 15% of the size of index.html

Fixes #7501
2023-05-29 12:45:41 +01:00
Tavin Cole
4e7a6ffc22 Add codemirror option to show trailing space (#7493)
* codemirror edit/trailingspace addon (default off)

* refactor as codemirror-trailingspace plugin

* copy cm-trailingspace styles from cm demo
2023-05-27 18:28:27 +02:00
Joshua Fontany
bc3a7d9826 Ignore visual studio files (#7499) 2023-05-27 18:26:37 +02:00
Arlen22
90f0ff8067 Polyfill is not needed, only globalCheck (#7492) 2023-05-27 18:24:25 +02:00
btheado
74e0619782 Protect codemirror.css from wikitext parsing, otherwise 'CodeMirror' is considered a wikilink (#7500) 2023-05-27 18:22:31 +02:00
Tavin Cole
86e5fbce5d Sign CLA (#7495) 2023-05-25 18:36:35 +02:00
twMat
fb79bebef4 Update Tiddler Colour Cascade.tid (updated PR) (#7491) 2023-05-24 22:03:10 +02:00
twMat
5d0043012a Update Edit Template Body Cascade.tid (#7484) 2023-05-24 18:35:17 +02:00
twMat
fec7e8791d Update View Template Title Cascade.tid (#7485) 2023-05-24 18:31:18 +02:00
twMat
f2c458a722 Update Field Editor Cascade.tid (#7486)
Co-authored-by: Jeremy Ruston <jeremy@jermolene.com>
2023-05-24 18:30:53 +02:00
twMat
86524aafbd Update Tiddler Icon Cascade.tid (#7487) 2023-05-24 18:29:10 +02:00
twMat
442e3f1e97 Update Field Editor Cascade.tid (#7488) 2023-05-24 18:26:53 +02:00
twMat
a9380655a0 Update Story Tiddler Template.tid (#7483)
improved phrasing (ref previous PR)
2023-05-24 11:57:19 +02:00
Bram Chen
9b59dff275 Update chinese language files (#7480)
* Update chinese help text for `authenticated-user-header`
2023-05-23 09:51:06 +02:00
lin onetwo
3f763775d6 Feat: decode url-encoded user name in authenticate request header to allow CJK username in header (#7471)
* fix: CJK in header has to be urlEncoded

* refactor: use $tw.utils.decodeURIComponentSafe

* docs: about chagne in this field

* docs: update

* docs: use less "field"
2023-05-22 12:25:51 +01:00
Mohammad Rahmani
9b78e871aa Update ParametersWidget and add Examples (#7464)
* Update ParametersWidget and add Examples

This PR updates the  ParametersWidget.tid and adds several examples

* Update Procedure and Parameters Pragma

This PR improve documentation for using parameters inside procedures

* Update Pragma_ _procedure.tid

A caution when use parameters inside procedures

* Resolved conversation

All comments by Jeremy were implemented.
2023-05-22 10:46:45 +01:00
Robin Munn
d4846bae6c Procedure definition example should not say macro (#7467)
The word "macro" appears in the text of the procedure definition
example, but it should be "procedure" instead.
2023-05-19 10:14:02 +01:00
Robin Munn
6941d079b8 Release notes for bugfix to checkbox date fields (#7466)
Add release notes for PR #7448
2023-05-19 10:13:43 +01:00
Mohammad Rahmani
e62f86a4c7 Update Procedure Definitions.tid (#7463)
Change macro to procedure!
2023-05-18 18:35:45 +01:00
jeremy@jermolene.com
8e132948b6 Fix crash when transcluding a lazily loaded tiddler as an attribute value
See bug report at https://talk.tiddlywiki.org/t/text-and-skinny-tiddler-and-echarts-oh-my/7044
2023-05-18 18:18:56 +01:00
jeremy@jermolene.com
6a12b15fac Remove #6699 from release note 2023-05-18 17:29:57 +01:00
jeremy@jermolene.com
990909c310 Revert "Feat: destroy() method for widgets to do custom cleanup (#6699)"
This reverts commit 474b73bdbe.
2023-05-18 17:27:05 +01:00
jeremy@jermolene.com
8ad08b0cd4 Fix diff-text widget crash with empty/missing attributes
Fixes #7462
2023-05-18 12:47:40 +01:00
Jeremy Ruston
a4da53ef6c Make newline after parameters pragma be optional
Fixes #7456
2023-05-16 09:41:58 +01:00
twMat
2e377b1f48 Simplify link widget in sidebar "open" tab (#7454)
simplified linkwidget use
2023-05-15 11:04:28 +01:00
Jeremy Ruston
70ee30fdf3 Add fillignore attribute to transclude widget to fix visible transclusion (#7451)
* slotignore attribute for transclude widget to fix visible transclusion

Fixes #7449

* Remove unneeded depth attribute

No longer needed

* Replace "slotignore" by "fillignore"
2023-05-14 21:25:35 +01:00
jeremy@jermolene.com
d5a7425458 Merge branch 'tiddlywiki-com' 2023-05-14 16:26:02 +01:00
Robin Munn
fb10b1ee91 Checkbox widget should not affect date fields (#7448)
* Checkbox widget should not affect date fields

If a date field like `created` or `modified` is passed as the listField
attribute of the checkbox widget, it will be left unchanged and actions
on the checkbox widget will *not* fire.

Includes unit tests to ensure that the "created" and "modified" fields
will not be touched by checkboxes and will continue to be Date objects.

* Replace const with var in checkbox tests
2023-05-11 18:28:44 +01:00
Jeremy Ruston
576d476a21 Merge branch 'master' of https://Jermolene@github.com/Jermolene/TiddlyWiki5.git 2023-05-11 16:26:52 +01:00
Jeremy Ruston
8aa0db59a3 Transclude widget should use fallback content if variable is missing or blank
Fixes #7424
2023-05-11 16:26:18 +01:00
btheado
9d6784f262 Add $slot widget examples and document the $depth parameter (#7446)
* Added $slot widget examples and documented the $depth parameter

* Fixed quotes and added named parameter
2023-05-11 15:09:16 +01:00
Mario Pietsch
61e2ad4286 Update thisTiddler Variable.tid (#7447)
Changing the caption of thisTiddler.tid to `caption: thisTiddler`
2023-05-11 14:20:53 +01:00
Mateusz Wilczek
db6b4f17e8 Improve translink macro, fixes 4877 (#7425)
* Improve translink macro

Changes:
- Change styles to adapt colours to the current palette, instead of hard-coded white inside black box with grey borders.
- Simplify the design to a single div (inspired by the Community links on tiddlywiki.com), instead of two nested contrasting divs.

Comments:
- I found pre-border and pre-background to be the most consistently readable across the default palettes (better than relying on e.g. tiddler-border, tiddler-background, page-background, code-border, code-background). Cupertino Dark, Gruvbox Dark, Nord, Solar Flare, Spartan Day, Spartan Night, Spartan Day, and Twilight have same or very similar pre-border and pre-background colours, so if the macro is nested (translinking a tiddler that contains a translink), the inner frames are not distinguishable, but I think it's an acceptable edge case.
- Padding is defined separately for block and inline modes of the macro to make it appear consistent.

* Update translink macro

Change the `<h1>` styling so that it is only applied to the transcluded tiddler's title and not to any potential `<h1>` in its text.

* Update translink macro

Change the class-constructing filter so that the empty message is displayed with consistent padding in block mode.

* Update translink.tid

* Add styles for translink macro to vanilla/base.tid

Split `pre` element styling, to allow part of it be reused with `.tc-pre-border` (used by translink macro).
Add `.tc-big-bold` class under Other utility classes (used by translink macro).

* Update base.tid

Add `.tc-big-bold` class under Other utility classes (used by translink macro).

* Update translink.tid

Update `tc-pre-border` class name to match the one in vanilla/base.tid

* Update translink.tid

Simplify by always wrapping transclusion in `<p>` element (adjusts padding when inline mode or tiddler missing).

* Update translink.tid

Localise missing tiddler message (`$:/language/MissingTiddler/Hint`)

* Update vanilla/base.tid

- Modify class `tc-pre-background`, so that it can be applied to elements other than `pre`. The styling of `pre` remains unchanged, it is only split into two parts, for one part to be reused in the `tc-pre-background` class (used e.g. in translink macro).
- Add `tc-big-v-gap` and `tc-big-bold` in the *Other utility classes* section (used e.g. in translink macro).

* Update translink.tid

Improve styling to depend only on classes specified in vanilla/base.tid

* Update base.tid

Update class `tc-translink` and CSS selectors to make styling the translink macro easier

* Update translink.tid

Change the classes of elements, so that changing the style is possible by modifying the stylesheet only

* Update base.tid

Add selectors to support new inline mode in translink macro

* Update translink.tid

Change behaviour of the inline mode, now the whole macro is inline, not just the transcluded text.

* Update base.tid

Fix padding of tc-translink class to account for multiline inline content.

* Update base.tid

Remove pseudo-element parentheses from inline translink macro

* Update translink.tid

Add parentheses around inline macro
2023-05-10 21:57:15 +01:00
Mateusz Wilczek
2ab28cc2b8 Add documentation on translink macro (#7426)
* Update Using Excise.tid

Rephrase the last paragraph (note).
Fix some minor formatting.

* Update WidgetMessage_ tm-edit-text-operation.tid

Add link to `translink Macro`

* Create TranslinkMacro.tid

* Create translink.tid
2023-05-10 16:38:58 +01:00
Mohammad Rahmani
1af4324370 Update thisTiddler Variable (Examples) for using unique parameter n in .example macro (#7434)
Address issue in https://github.com/Jermolene/TiddlyWiki5/pull/7433#discussion_r1186744704
2023-05-09 18:54:01 +01:00
jeremy@jermolene.com
3da0a9431c Introduce $:/tags/Global tag
And also $:/tags/Global/View and $:/tags/Global/View/Body
2023-05-09 15:46:54 +01:00
jeremy@jermolene.com
1f35b945a5 Fix comment typo 2023-05-09 14:32:03 +01:00
jeremy@jermolene.com
5124cbc776 Correct build version in build-site.sh 2023-05-09 14:31:52 +01:00
jeremy@jermolene.com
9f1eab175d Fix transclusion refresh
Fixes #7441
2023-05-09 14:31:36 +01:00
Carmine T. Guida
8f4b22110c Added a comma (#7438) 2023-05-07 22:45:34 +01:00
Carmine T. Guida
8ad35a9411 Signing the CLA (#7437) 2023-05-07 18:07:06 +01:00
Mario Pietsch
18d7d3d8c0 Improve the wording for the core-plugin in the upgrader-editioin (#6878) 2023-05-07 17:47:13 +01:00
jeremy@jermolene.com
3518e257c0 Tweak release note 2023-05-06 19:26:42 +01:00
Mohammad Rahmani
fe716dd58f thisTiddler description and examples improved (#7433) 2023-05-06 18:57:22 +01:00
jeremy@jermolene.com
e2fe681b50 Update release note 2023-05-06 17:33:19 +01:00
Mohammad Rahmani
36ac142110 Correct the caption for Procedure Call tiddler (#7432) 2023-05-06 15:35:03 +01:00
GameDungeon
e66e791944 Correct handling of pasting tiddlers (#7215)
* First Pass Implementation

* Fix Check

* Fix Style

* Update drag-drop interop example to support copy tiddlers to clipboard

---------

Co-authored-by: jeremy@jermolene.com <jeremy@jermolene.com>
2023-05-06 14:02:16 +01:00
lin onetwo
474b73bdbe Feat: destroy() method for widgets to do custom cleanup (#6699)
* feat: inform child widget to do some custom cleanup

* fix: type

* refactor: restore old removeChildDomNodes

* refactor: make destroy() a separate method

* refactor: make destroy call removeChildDomNodes

* refactor: call destroy instead of removeChildDomNodes in each core widgets

* fix: refreshSelf does not mean destroy

* refactor: use old var insteadof const

* docs: about subclass
2023-05-06 12:19:11 +01:00
Arlen22
2b95daf59b Change evalSandboxed to use only one context for all modules (#4624)
* Run modules in one new context

* Fix polyfill running on require

* Add code to check for global assignments

* Allow globals in separate context

This lets the caller request a separate context which may be polluted.

* Jasmine needs to pollute the global

* Formatting

* Add polyfill and cleanup code

* Convert to ES5

* One bug fix

* Some formatting

* Remove console.log line!

* Cleanup

* revert css-escape-polyfill.js to hopefully remove it from the PR

* Remove JSDOC directives
2023-05-06 12:11:18 +01:00
Jeremy Ruston
2bfefe3880 Parameterise core icons (#7413)
* Parameterise all the icons

* Improve splash screen macro for rendering icons

* Add new example from @kookma
2023-05-06 12:08:46 +01:00
Jeremy Ruston
96f97f237a Remove "direction" CSS property from framed version of editor (#7409) 2023-05-06 12:08:20 +01:00
Mario Pietsch
9cdb38d800 Linkcatcher should pass through event objects (#7401) 2023-05-06 12:07:55 +01:00
donmor
4e96a012f6 Add missing extensions for audio/mpeg (#7378)
Add missing extensions for audio/mpeg
2023-05-06 11:55:41 +01:00
yaisog
e92e125697 Add the querySelectorSafe() function and replace querySelector() usage (#7380)
* Initial commit

* Correct the over-estimation of my abilities

* Add fallback and move code to dom.js

* Use new function for tm-focus-selector

* Replace other uses of querySelector*

* Undo rash replacements of querySelector()
2023-05-06 11:54:54 +01:00
yaisog
6820d45bf0 Improve the StoryTiddlerTemplate fallback (#7332)
* Initial commit

* Update StoryTiddlerTemplate.tid

* Extend cascades hint to help in case of problems

* Remove note about debugging from docs

I think that this brief note is more confusing than anything else

---------

Co-authored-by: jeremy@jermolene.com <jeremy@jermolene.com>
2023-05-06 11:53:58 +01:00
yaisog
d6533b9ee1 Add the timestamp suffix to the format operator (#7292)
* Create timestamp.js

Taken verbatim from @ericshulman.

* Add description of the timestamp suffix

* Add an example for timestamp use

I also snuck it a couple of cosmetic corrections, because I was too lazy to open a new PR. 😢

* Correct example 4 to use the right date formats

* Correct description of the default date format

* Add a test for the timestamp suffix

* Add more format:timestamp tests

* Drop invalid input

* Update version tag in docs

---------

Co-authored-by: jeremy@jermolene.com <jeremy@jermolene.com>
2023-05-06 11:44:22 +01:00
btheado
3ee5f10362 BrowserStoragePlugin: Do not save shadow tiddlers to local storage (#7365)
If a tiddler is only a shadow tiddler, then do not save it
to local storage. Otherwise when installing a plugin, each
individual tiddler will be expanded and saved individually.
In order to uninstall such a plugin, the plugin tiddler and
each tiddler needs to be deleted.

This can be prevented by including a run like `-[is[shadow]!is[tiddler]]`
in the save filter, but that has the side effect of preventing
overwritten shadow tiddlers from being deleted from local storage.
2023-05-06 11:41:22 +01:00
Jeremy Ruston
a6ced74a13 Introduce "thisTiddler" variable (#7182)
* Initial Commit

* Change of mind: Do not blank thisTiddler within macros

* Revert previous implementation

* Somewhat simpler implementation

* Add docs

* Add docs version tag
2023-05-06 11:40:22 +01:00
Mario Pietsch
b61aef27d7 External-js file naming adjusted. import docs form tw5.com. make extrnal-js more visible (#7361)
* external-js file naming adjusted. import docs form tw5.com. make external-js more visible

* add comment about doc usage in server-external-js edition

* add changes suggested by cdruan

* change modifed date to start vercel rebuild process
2023-05-06 11:37:05 +01:00
jeremy@jermolene.com
a1b706a945 Remove dynannotate plugin fro tw5.com edition
It was added temporarily to make #7260 easier to work on
2023-05-06 11:36:36 +01:00
yaisog
2340d48844 Add additional searchModes to Dynannotate (#7260)
* Add searchModes: literal, some and words

* Add additional search modes

Description of selection tracker config tiddlers was also changed.

* Update simple.tid

* Improve View Template examples

Transcludes a sample tiddler for demonstration instead of the dynannotate view template code.
Adds an example for usage with $genesis to add state tiddler controlled per-tiddler highlights.

* Make search highlights not case sensitive

* Remove created and modified fields

* Add another example text (Searching in Tiddlywiki)

* Add dynannotate for vercel deployment

This should probably not be merged...

* Create LegacySelectionTracker.tid

* Create SelectionTracker.tid

* Revert putting the SelectionTracker config titles in code blocks

* Replace inline styles with CSS class

* Add class for view template examples

Class name is tc-dynannotate-example-frame.

* Remove some <br> line breaks.

* Remove first example transclusion and fix some tab spacing

* Add class to override control panel table layout

* Add class to settings table

* More tab shenanigans

Great Scott!

* Add explanatory comment to example macro

* Change defaults to match widget behavior

* Make previous macro comment more concise

* Change example to transclude CP tiddler

$:/core/ui/ControlPanel/TiddlerFields

* Delete unnecessary example tiddler
2023-05-06 11:30:21 +01:00
Michelle Saad
4e641f4fc0 Add 'filepath' source attribute to tiddlywiki.files (#7253)
* Add 'filepath' source attribute to tiddlywiki.files

Adds a new source attribute to facilitate importing subdirectories with
the `searchSubdirectories` attribute.

The `filepath` atttribute is like `filename` except it includes the full
pathname relative to the directory path. Consequently it only works with
`directories` sections (not `tiddlers`).

* Add `subdirectories` source attribute to tiddlywiki.files

Adds another new source attribute to facilitate importing subdirectories
with the `searchSubdirectories` attribute.

The `subdirectories` source attribute is only usable with `directories`
sections (not `tiddlers`). It resolves to an array containing all the
directories in the file's path relative to the directory path. Eg, if
the directory path is `files`, `{ source: 'subdirectories' }` for a file
in  `files/images/photos` would resolve to `['images', 'photos'].

This commit also adds an example to the "tiddlywiki.files Files"
documentation tiddler that demonstrates using the `filepath` and
`subdirectories` source attributes to import and auto-tag image files
as external-image tiddlers.
2023-05-06 11:26:40 +01:00
Mohammad Rahmani
17f18daa89 Docs: Fix typo in “Procedure Calls.tid” (#7429)
fix typo in procedure call
2023-05-05 18:47:03 +01:00
jeremy@jermolene.com
a927de5b78 Merge branch 'master' into tm-http-request-message 2023-05-04 09:11:25 +01:00
jeremy@jermolene.com
b2aeea0393 Merge branch 'tiddlywiki-com' 2023-05-04 09:11:14 +01:00
jeremy@jermolene.com
09e626e8ab Further fixes to cancelling outstanding HTTP requests 2023-05-03 08:51:55 +01:00
jeremy@jermolene.com
cc7b857d71 Fix crash when cancelling more than one HTTP request
Thanks @saqimtiaz
2023-05-03 08:30:58 +01:00
Jeremy Ruston
53715bd3fd Fix typo
Thanks @btheado

Co-authored-by: btheado <brian.theado@gmail.com>
2023-05-02 21:32:00 +01:00
jeremy@jermolene.com
f798bf5611 Add a network activity button
Click it to cancel outstanding requests
2023-05-02 17:07:16 +01:00
jeremy@jermolene.com
fc22df908d Make the number of outstanding HTTP requests available in a state tiddler 2023-05-02 11:37:37 +01:00
jeremy@jermolene.com
be1882dd4c Add support for cancelling HTTP requests 2023-05-01 17:46:04 +01:00
jeremy@jermolene.com
0adc0518a6 HttpClient object shouldn't need to know about events 2023-05-01 17:04:35 +01:00
Mario Pietsch
48b7b5d294 Fix a typo in example (#7423)
fix a typo in example
2023-05-01 12:53:26 +01:00
jeremy@jermolene.com
585c7339de Initial Commit 2023-04-29 17:16:14 +01:00
jeremy@jermolene.com
1cac177211 Fix pragma procedure docs
See #7412 - thanks @kookma
2023-04-23 10:29:15 +01:00
jeremy@jermolene.com
6da74c6104 Docs: Xememex implementation clarification 2023-04-18 22:52:17 +01:00
179 changed files with 2050 additions and 565 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
.DS_Store
.c9/
.vs/
.vscode/
tmp/
output/

View File

@@ -5,7 +5,7 @@
# Default to the current version number for building the plugin library
if [ -z "$TW5_BUILD_VERSION" ]; then
TW5_BUILD_VERSION=v5.2.8
TW5_BUILD_VERSION=v5.3.0
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"

View File

@@ -569,10 +569,23 @@ $tw.utils.getTypeEncoding = function(ext) {
return typeInfo ? typeInfo.encoding : "utf8";
};
var globalCheck =[
" Object.defineProperty(Object.prototype, '__temp__', {",
" get: function () { return this; },",
" configurable: true",
" });",
" if(Object.keys(__temp__).length){",
" console.log(Object.keys(__temp__));",
" delete Object.prototype.__temp__;",
" throw \"Global assignment is not allowed within modules on node.\";",
" }",
" delete Object.prototype.__temp__;",
].join('\n');
/*
Run code globally with specified context variables in scope
*/
$tw.utils.evalGlobal = function(code,context,filename) {
$tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
var contextCopy = $tw.utils.extend(Object.create(null),context);
// Get the context variables as a pair of arrays of names and values
var contextNames = [], contextValues = [];
@@ -581,25 +594,38 @@ $tw.utils.evalGlobal = function(code,context,filename) {
contextValues.push(value);
});
// Add the code prologue and epilogue
code = "(function(" + contextNames.join(",") + ") {(function(){\n" + code + "\n;})();\nreturn exports;\n})\n";
code = [
"(function(" + contextNames.join(",") + ") {",
" (function(){\n" + code + "\n;})();",
(!$tw.browser && sandbox && !allowGlobals) ? globalCheck : "",
" return exports;\n",
"})"
].join("\n");
// Compile the code into a function
var fn;
if($tw.browser) {
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
} else {
fn = vm.runInThisContext(code,filename);
if(sandbox){
fn = vm.runInContext(code,sandbox,filename)
} else {
fn = vm.runInThisContext(code,filename);
}
}
// Call the function and return the exports
return fn.apply(null,contextValues);
};
$tw.utils.sandbox = !$tw.browser ? vm.createContext({}) : undefined;
/*
Run code in a sandbox with only the specified context variables in scope
*/
$tw.utils.evalSandboxed = $tw.browser ? $tw.utils.evalGlobal : function(code,context,filename) {
var sandbox = $tw.utils.extend(Object.create(null),context);
vm.runInNewContext(code,sandbox,filename);
return sandbox.exports;
$tw.utils.evalSandboxed = $tw.browser ? $tw.utils.evalGlobal : function(code,context,filename,allowGlobals) {
return $tw.utils.evalGlobal(
code,context,filename,
allowGlobals ? vm.createContext({}) : $tw.utils.sandbox,
allowGlobals
);
};
/*
@@ -1920,7 +1946,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
// Read the specification
var filesInfo = $tw.utils.parseJSONSafe(fs.readFileSync(filepath + path.sep + "tiddlywiki.files","utf8"));
// Helper to process a file
var processFile = function(filename,isTiddlerFile,fields,isEditableFile) {
var processFile = function(filename,isTiddlerFile,fields,isEditableFile,rootPath) {
var extInfo = $tw.config.fileExtensionInfo[path.extname(filename)],
type = (extInfo || {}).type || fields.type || "text/plain",
typeInfo = $tw.config.contentTypeInfo[type] || {},
@@ -1941,6 +1967,12 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
} else {
var value = tiddler[name];
switch(fieldInfo.source) {
case "subdirectories":
value = path.relative(rootPath, filename).split('/').slice(0, -1);
break;
case "filepath":
value = path.relative(rootPath, filename);
break;
case "filename":
value = path.basename(filename);
break;
@@ -2023,7 +2055,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
var thisPath = path.relative(filepath, files[t]),
filename = path.basename(thisPath);
if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) {
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile);
processFile(thisPath,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile,dirSpec.path);
}
}
} else {
@@ -2048,7 +2080,11 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
console.log("Warning: missing plugin.info file in " + filepath);
return null;
}
var pluginInfo = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"));
var pluginInfo = $tw.utils.parseJSONSafe(fs.readFileSync(infoPath,"utf8"),function() {return null;});
if(!pluginInfo) {
console.log("warning: invalid JSON in plugin.info file at " + infoPath);
pluginInfo = {};
}
// Read the plugin files
var pluginFiles = $tw.loadTiddlersFromPath(filepath,excludeRegExp);
// Save the plugin tiddlers into the plugin info
@@ -2165,7 +2201,11 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
pluginFields;
// Bail if we don't have a wiki info file
if(fs.existsSync(wikiInfoPath)) {
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath,"utf8"));
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath,"utf8"),function() {return null;});
if(!wikiInfo) {
console.log("warning: invalid JSON in tiddlywiki.info file at " + wikiInfoPath);
wikiInfo = {};
}
} else {
return null;
}
@@ -2408,7 +2448,7 @@ $tw.boot.initStartup = function(options) {
$tw.utils.registerFileType("video/webm","base64",".webm");
$tw.utils.registerFileType("video/mp4","base64",".mp4");
$tw.utils.registerFileType("audio/mp3","base64",".mp3");
$tw.utils.registerFileType("audio/mpeg","base64");
$tw.utils.registerFileType("audio/mpeg","base64",[".mp3",".m2a",".mp2",".mpa",".mpg",".mpga"]);
$tw.utils.registerFileType("text/markdown","utf8",[".md",".markdown"],{deserializerType:"text/x-markdown"});
$tw.utils.registerFileType("text/x-markdown","utf8",[".md",".markdown"]);
$tw.utils.registerFileType("application/enex+xml","utf8",".enex");

View File

@@ -3,7 +3,7 @@ title: $:/Acknowledgements
TiddlyWiki incorporates code from these fine OpenSource projects:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
And media from these projects:

View File

@@ -0,0 +1,11 @@
title: $:/core/images/network-activity
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-network-activity tc-image-button" viewBox="0 0 128 128"><g class={{{ [{$:/state/http-requests}match[0]then[]else[tc-network-activity-background]] }}}>
<$list filter="[{$:/state/http-requests}match[0]]" variable="ignore">
<path d="M64.043 45.153a4.002 4.002 0 0 1 4.367 2.21l.084.188 30.403 73.4a4 4 0 0 1-7.307 3.25l-.084-.188-3.103-7.49-8.898 8.899a3.985 3.985 0 0 1-2.624 1.166l-.205.005a3.987 3.987 0 0 1-2.828-1.171l-9.849-9.848-9.847 9.848a3.985 3.985 0 0 1-2.624 1.166l-.204.005a3.987 3.987 0 0 1-2.829-1.171l-8.899-8.9-3.102 7.491a4 4 0 1 1-7.391-3.062l30.403-73.4a4.001 4.001 0 0 1 4.495-2.39l.042-.008Zm13.636 56.74-8.023 8.024 7.02 7.019 8.023-8.022-7.02-7.02Zm-27.353.008-7.019 7.019 8.016 8.016 7.019-7.02-8.016-8.015Zm13.68-13.68-8.023 8.023 8.016 8.016 8.023-8.023-8.016-8.016Zm-8.971-8.971-4.687 11.315 8.001-8.001-3.314-3.314Zm17.933.009-3.305 3.305 7.979 7.979-4.674-11.284ZM64 57.607l-5.666 13.68c.096.072.188.15.278.232l.133.126 5.261 5.262 5.262-5.262c.128-.127.261-.244.4-.35L64 57.607Zm0-34.69a8 8 0 1 1 0 16 8 8 0 0 1 0-16Z"/>
</$list>
<$list filter="[{$:/state/http-requests}!match[0]]" variable="ignore">
<path d="M109.395.952a4.002 4.002 0 0 1 3.787 2.708C117.529 11.62 120 20.753 120 30.462c0 15.186-6.044 28.96-15.858 39.047a4 4 0 1 1-6.47-4.626l-.12-.094C106.466 56.074 112 43.914 112 30.462c0-8.492-2.205-16.469-6.074-23.39l.054-.036a4 4 0 0 1 3.415-6.084Zm-90.762 0a4 4 0 0 1 3.072 6.562l.093.06A47.786 47.786 0 0 0 16 30.463c0 13.315 5.42 25.363 14.176 34.058l-.01.007a4 4 0 1 1-6.312 4.863l-.063.05C14.017 59.359 8 45.613 8 30.462c0-9.77 2.502-18.956 6.9-26.952A4.002 4.002 0 0 1 18.634.952Z"/><path d="M64.043 44.698a4.002 4.002 0 0 1 4.367 2.21l.084.188 30.403 73.4a4 4 0 0 1-7.307 3.25l-.084-.188-3.103-7.49-8.898 8.9a3.985 3.985 0 0 1-2.624 1.166l-.205.005a3.987 3.987 0 0 1-2.828-1.172l-9.849-9.848-9.847 9.848a3.985 3.985 0 0 1-2.624 1.167l-.204.005a3.987 3.987 0 0 1-2.829-1.172l-8.899-8.899-3.102 7.49a4 4 0 0 1-7.391-3.061l30.403-73.4a4.001 4.001 0 0 1 4.495-2.39l.042-.009ZM77.68 101.44l-8.023 8.023 7.02 7.019 8.023-8.022-7.02-7.02Zm-27.353.007-7.019 7.019 8.016 8.016 7.019-7.019-8.016-8.016Zm13.68-13.68-8.023 8.023 8.016 8.016 8.023-8.023-8.016-8.016Zm-8.971-8.971L50.348 90.11l8.001-8.001-3.314-3.314Zm17.933.009-3.305 3.305 7.979 7.979-4.674-11.284ZM64 57.152l-5.666 13.68c.096.073.188.15.278.232l.133.127 5.261 5.261 5.262-5.261c.128-.128.261-.244.4-.351L64 57.152ZM38.503 1.058a4 4 0 0 1 2.7 6.952l.17-.175C35.582 13.625 32 21.625 32 30.462c0 8.838 3.582 16.838 9.374 22.629a4 4 0 0 1-5.659 5.658l-.01.01C28.473 51.52 24 41.526 24 30.485 24 19.567 28.374 9.67 35.466 2.453a3.995 3.995 0 0 1 3.037-1.395ZM89.369.952c1.14 0 2.17.478 2.899 1.244l.005-.006C99.518 9.43 104 19.434 104 30.485c0 10.826-4.3 20.648-11.287 27.85a4 4 0 1 1-6.054-5.213l-.032-.032C92.418 47.299 96 39.299 96 30.462c0-8.73-3.496-16.643-9.164-22.416A4 4 0 0 1 89.368.952Zm-39.282 11.14a4 4 0 0 1 2.59 7.048l.01.009A15.95 15.95 0 0 0 48 30.462a15.95 15.95 0 0 0 4.687 11.315l-.01.01a4 4 0 1 1-5.82 5.47l.173.177A23.925 23.925 0 0 1 40 30.462a23.925 23.925 0 0 1 7.03-16.97l.01.01a3.991 3.991 0 0 1 3.047-1.41Zm27.895.07a3.99 3.99 0 0 1 2.984 1.336l.006-.005A23.925 23.925 0 0 1 88 30.463a23.92 23.92 0 0 1-6.707 16.642l-.3.305a4 4 0 1 1-5.679-5.632v-.002A15.95 15.95 0 0 0 80 30.462a15.95 15.95 0 0 0-4.685-11.312 4.012 4.012 0 0 1-1.333-2.987 4 4 0 0 1 4-4ZM64 22.463a8 8 0 1 1 0 16 8 8 0 0 1 0-16Z"/>
</$list>
</g></svg>

View File

@@ -67,6 +67,8 @@ More/Caption: more
More/Hint: More actions
NewHere/Caption: new here
NewHere/Hint: Create a new tiddler tagged with this one
NetworkActivity/Caption: network activity
NetworkActivity/Hint: Cancel all network activity
NewJournal/Caption: new journal
NewJournal/Hint: Create a new journal tiddler
NewJournalHere/Caption: new journal here

View File

@@ -18,7 +18,7 @@ All parameters are optional with safe defaults, and can be specified in any orde
* ''anon-username'' - the username for signing edits for anonymous users
* ''username'' - optional username for basic authentication
* ''password'' - optional password for basic authentication
* ''authenticated-user-header'' - optional name of header to be used for trusted authentication
* ''authenticated-user-header'' - optional name of request header to be used for trusted authentication.
* ''readers'' - comma-separated list of principals allowed to read from this wiki
* ''writers'' - comma-separated list of principals allowed to write to this wiki
* ''csrf-disable'' - set to "yes" to disable CSRF checks (defaults to "no")

View File

@@ -25,6 +25,8 @@ Encryption/RepeatPassword: Repeat password
Encryption/PasswordNoMatch: Passwords do not match
Encryption/SetPassword: Set password
Error/Caption: Error
Error/DeserializeOperator/MissingOperand: Filter Error: Missing operand for 'deserialize' operator
Error/DeserializeOperator/UnknownDeserializer: Filter Error: Unknown deserializer provided as operand for the 'deserialize' operator
Error/Filter: Filter error
Error/FilterSyntax: Syntax error in filter expression
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run

View File

@@ -1,3 +1,3 @@
title: $:/SiteTitle
My ~TiddlyWiki
My TiddlyWiki

View File

@@ -118,6 +118,8 @@ FramedEngine.prototype.copyStyles = function() {
this.domNode.style.margin = "0";
// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour
this.domNode.style["-webkit-text-fill-color"] = "currentcolor";
// Ensure we don't force text direction to LTR
this.domNode.style.removeProperty("direction");
};
/*

View File

@@ -12,6 +12,8 @@ Adds tiddler filtering methods to the $tw.Wiki object.
/*global $tw: false */
"use strict";
var widgetClass = require("$:/core/modules/widgets/widget.js").widget;
/* Maximum permitted filter recursion depth */
var MAX_FILTER_DEPTH = 300;
@@ -269,7 +271,7 @@ exports.compileFilter = function(filterString) {
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
} else if(operand.variable) {
var varTree = $tw.utils.parseFilterVariable(operand.text);
operand.value = widget.evaluateVariable(varTree.name,{params: varTree.params, source: source})[0] || "";
operand.value = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source})[0] || "";
} else {
operand.value = operand.text;
}

View File

@@ -0,0 +1,39 @@
/*\
title: $:/core/modules/filters/deserialize.js
type: application/javascript
module-type: filteroperator
Filter operator for deserializing string data into JSON representing tiddlers
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports["deserialize"] = function(source,operator,options) {
var results = [],
deserializer;
if(operator.operand) {
// Get the deserializer identified by the operand
deserializer = $tw.Wiki.tiddlerDeserializerModules[operator.operand];
if(deserializer) {
source(function(tiddler,title) {
var tiddlers;
try {
tiddlers = deserializer(title);
} catch(e) {
// Return an empty array if we could not extract any tiddlers
tiddlers = [];
}
results.push(JSON.stringify(tiddlers));
});
} else {
return [$tw.language.getString("Error/DeserializeOperator/UnknownDeserializer")];
}
} else {
return [$tw.language.getString("Error/DeserializeOperator/MissingOperand")];
}
return results;
}
})();

View File

@@ -0,0 +1,25 @@
/*\
title: $:/core/modules/filters/format/timestamp.js
type: application/javascript
module-type: formatfilteroperator
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.timestamp = function(source,operand,options) {
var results = [];
source(function(tiddler,title) {
if (title.match(/^-?\d+$/)) {
var value = new Date(Number(title));
results.push($tw.utils.formatDateString(value,operand || "[UTC]YYYY0MM0DD0hh0mm0ss0XXX"));
}
});
return results;
};
})();

View File

@@ -17,9 +17,13 @@ Export our filter function
*/
exports.function = function(source,operator,options) {
var functionName = operator.operands[0],
variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(functionName);
params = [];
$tw.utils.each(operator.operands.slice(1),function(param) {
params.push({value: param});
});
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(functionName,{params: params, source: source});
if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
return options.widget.evaluateVariable(functionName,{params: operator.operands.slice(1), source: source});
return variableInfo.resultList ? variableInfo.resultList : [variableInfo.text];
}
// Return the input list if the function wasn't found
var results = [];

View File

@@ -21,10 +21,14 @@ Export our filter function
*/
exports["[unknown]"] = function(source,operator,options) {
// Check for a user defined filter operator
if(operator.operator.charAt(0) === ".") {
var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(operator.operator);
if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
var list = options.widget.evaluateVariable(operator.operator,{params: operator.operands, source: source});
if(operator.operator.indexOf(".") !== -1) {
var params = [];
$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) {
var list = variableInfo.resultList ? variableInfo.resultList : [variableInfo.text];
if(operator.prefix === "!") {
var results = [];
source(function(tiddler,title) {

View File

@@ -78,7 +78,7 @@ exports.parseTag = function(source,pos,options) {
orderedAttributes: []
};
// Define our regexps
var reTagName = /([a-zA-Z0-9\-\$]+)/g;
var reTagName = /([a-zA-Z0-9\-\$\.]+)/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a less than sign
@@ -138,7 +138,7 @@ exports.parseTag = function(source,pos,options) {
exports.findNextTag = function(source,pos,options) {
// A regexp for finding candidate HTML tags
var reLookahead = /<([a-zA-Z\-\$]+)/g;
var reLookahead = /<([a-zA-Z\-\$\.]+)/g;
// Find the next candidate
reLookahead.lastIndex = pos;
var match = reLookahead.exec(source);

View File

@@ -26,7 +26,7 @@ Instantiate parse rule
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /^\\parameters\s*\(([^)]*)\)\s*\r?\n/mg;
this.matchRegExp = /^\\parameters\s*\(([^)]*)\)(\s*\r?\n)?/mg;
};
/*

View File

@@ -0,0 +1,40 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/wikilinkprefix.js
type: application/javascript
module-type: wikirule
Wiki text inline rule for suppressed wiki links. For example:
```
~SuppressedLink
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "wikilinkprefix";
exports.types = {inline: true};
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = new RegExp($tw.config.textPrimitives.unWikiLink + $tw.config.textPrimitives.wikiLink,"mg");
};
/*
Parse the most recent match
*/
exports.parse = function() {
// Get the details of the match
var linkText = this.match[0];
// Move past the wikilink
this.parser.pos = this.matchRegExp.lastIndex;
// Return the link without unwikilink character as plain text
return [{type: "text", text: linkText.substr(1)}];
};
})();

View File

@@ -37,7 +37,7 @@ HeaderAuthenticator.prototype.authenticateRequest = function(request,response,st
return false;
} else {
// authenticatedUsername will be undefined for anonymous users
state.authenticatedUsername = username;
state.authenticatedUsername = $tw.utils.decodeURIComponentSafe(username);
return true;
}
};

View File

@@ -20,6 +20,38 @@ exports.before = ["story"];
exports.synchronous = true;
exports.startup = function() {
// Install the HTTP client event handler
$tw.httpClient = new $tw.utils.HttpClient();
var getPropertiesWithPrefix = function(properties,prefix) {
var result = Object.create(null);
$tw.utils.each(properties,function(value,name) {
if(name.indexOf(prefix) === 0) {
result[name.substring(prefix.length)] = properties[name];
}
});
return result;
};
$tw.rootWidget.addEventListener("tm-http-request",function(event) {
var params = event.paramObject || {};
$tw.httpClient.initiateHttpRequest({
wiki: event.widget.wiki,
url: params.url,
method: params.method,
body: params.body,
oncompletion: params.oncompletion,
onprogress: params.onprogress,
bindStatus: params["bind-status"],
bindProgress: params["bind-progress"],
variables: getPropertiesWithPrefix(params,"var-"),
headers: getPropertiesWithPrefix(params,"header-"),
passwordHeaders: getPropertiesWithPrefix(params,"password-header-"),
queryStrings: getPropertiesWithPrefix(params,"query-"),
passwordQueryStrings: getPropertiesWithPrefix(params,"password-query-")
});
});
$tw.rootWidget.addEventListener("tm-http-cancel-all-requests",function(event) {
$tw.httpClient.cancelAllHttpRequests();
});
// Install the modal message mechanism
$tw.modal = new $tw.utils.Modal($tw.wiki);
$tw.rootWidget.addEventListener("tm-modal",function(event) {
@@ -41,12 +73,8 @@ exports.startup = function() {
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
var selector = event.param || "",
element,
doc = event.event && event.event.target ? event.event.target.ownerDocument : document;
try {
element = doc.querySelector(selector);
} catch(e) {
console.log("Error in selector: ",selector)
}
baseElement = event.event && event.event.target ? event.event.target.ownerDocument : document;
element = $tw.utils.querySelectorSafe(selector,baseElement);
if(element && element.focus) {
element.focus(event.paramObject);
}

View File

@@ -129,7 +129,7 @@ function findTitleDomNode(widget,targetClass) {
targetClass = targetClass || "tc-title";
var domNode = widget.findFirstDomNode();
if(domNode && domNode.querySelector) {
return domNode.querySelector("." + targetClass);
return $tw.utils.querySelectorSafe("." + targetClass,domNode);
}
return null;
}

View File

@@ -365,5 +365,25 @@ exports.collectDOMVariables = function(selectedNode,domNode,event) {
return variables;
};
/*
Make sure the CSS selector is not invalid
*/
exports.querySelectorSafe = function(selector,baseElement) {
baseElement = baseElement || document;
try {
return baseElement.querySelector(selector);
} catch(e) {
console.log("Invalid selector: ",selector);
}
};
exports.querySelectorAllSafe = function(selector,baseElement) {
baseElement = baseElement || document;
try {
return baseElement.querySelectorAll(selector);
} catch(e) {
console.log("Invalid selector: ",selector);
}
};
})();

View File

@@ -159,7 +159,7 @@ exports.importDataTransfer = function(dataTransfer,fallbackTitle,callback) {
if(!$tw.browser.isIE || importDataTypes[t].IECompatible) {
// Get the data
var dataType = importDataTypes[t];
var data = dataTransfer.getData(dataType.type);
var data = dataTransfer.getData(dataType.type);
// Import the tiddlers in the data
if(data !== "" && data !== null) {
if($tw.log.IMPORT) {
@@ -173,6 +173,36 @@ exports.importDataTransfer = function(dataTransfer,fallbackTitle,callback) {
}
};
exports.importPaste = function(item,fallbackTitle,callback) {
// Try each provided data type in turn
for(var t=0; t<importDataTypes.length; t++) {
if(item.type === importDataTypes[t].type) {
// Get the data
var dataType = importDataTypes[t];
item.getAsString(function(data){
if($tw.log.IMPORT) {
console.log("Importing data type '" + dataType.type + "', data: '" + data + "'")
}
var tiddlerFields = dataType.toTiddlerFieldsArray(data,fallbackTitle);
callback(tiddlerFields);
});
return;
}
}
};
exports.itemHasValidDataType = function(item) {
for(var t=0; t<importDataTypes.length; t++) {
if(!$tw.browser.isIE || importDataTypes[t].IECompatible) {
if(item.type === importDataTypes[t].type) {
return true;
}
}
}
return false;
}
var importDataTypes = [
{type: "text/vnd.tiddler", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
return parseJSONTiddlers(data,fallbackTitle);
@@ -205,7 +235,13 @@ var importDataTypes = [
return [{title: fallbackTitle, text: data}];
}},
{type: "text/uri-list", IECompatible: false, toTiddlerFieldsArray: function(data,fallbackTitle) {
return [{title: fallbackTitle, text: data}];
// Check for tiddler data URI
var match = $tw.utils.decodeURIComponentSafe(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
if(match) {
return parseJSONTiddlers(match[1],fallbackTitle);
} else {
return [{title: fallbackTitle, text: data}]; // As URL string
}
}}
];

View File

@@ -3,7 +3,7 @@ title: $:/core/modules/utils/dom/http.js
type: application/javascript
module-type: utils
Browser HTTP support
HTTP support
\*/
(function(){
@@ -13,11 +13,204 @@ Browser HTTP support
"use strict";
/*
A quick and dirty HTTP function; to be refactored later. Options are:
Manage tm-http-request events. Options include:
wiki: Reference to the wiki to be used for state tiddler tracking
stateTrackerTitle: Title of tiddler to be used for state tiddler tracking
*/
function HttpClient(options) {
options = options || {};
this.nextId = 1;
this.wiki = options.wiki || $tw.wiki;
this.stateTrackerTitle = options.stateTrackerTitle || "$:/state/http-requests";
this.requests = []; // Array of {id: string,request: HttpClientRequest}
this.updateRequestTracker();
}
/*
Return the index into this.requests[] corresponding to a given ID. Returns null if not found
*/
HttpClient.prototype.getRequestIndex = function(targetId) {
var targetIndex = null;
$tw.utils.each(this.requests,function(requestInfo,index) {
if(requestInfo.id === targetId) {
targetIndex = index;
}
});
return targetIndex;
};
/*
Update the state tiddler that is tracking the outstanding requests
*/
HttpClient.prototype.updateRequestTracker = function() {
this.wiki.addTiddler({title: this.stateTrackerTitle, text: "" + this.requests.length});
};
HttpClient.prototype.initiateHttpRequest = function(options) {
var self = this,
id = this.nextId,
request = new HttpClientRequest(options);
this.nextId += 1;
this.requests.push({id: id, request: request});
this.updateRequestTracker();
request.send(function(err) {
var targetIndex = self.getRequestIndex(id);
if(targetIndex !== null) {
self.requests.splice(targetIndex,1);
self.updateRequestTracker();
}
});
return id;
};
HttpClient.prototype.cancelAllHttpRequests = function() {
var self = this;
if(this.requests.length > 0) {
for(var t=this.requests.length - 1; t--; t>=0) {
var requestInfo = this.requests[t];
requestInfo.request.cancel();
}
}
this.requests = [];
this.updateRequestTracker();
};
HttpClient.prototype.cancelHttpRequest = function(targetId) {
var targetIndex = this.getRequestIndex(targetId);
if(targetIndex !== null) {
this.requests[targetIndex].request.cancel();
this.requests.splice(targetIndex,1);
this.updateRequestTracker();
}
};
/*
Initiate an HTTP request. Options:
wiki: wiki to be used for executing action strings
url: URL for request
method: method eg GET, POST
body: text of request body
oncompletion: action string to be invoked on completion
onprogress: action string to be invoked on progress updates
bindStatus: optional title of tiddler to which status ("pending", "complete", "error") should be written
bindProgress: optional title of tiddler to which the progress of the request (0 to 100) should be bound
variables: hashmap of variable name to string value passed to action strings
headers: hashmap of header name to header value to be sent with the request
passwordHeaders: hashmap of header name to password store name to be sent with the request
queryStrings: hashmap of query string parameter name to parameter value to be sent with the request
passwordQueryStrings: hashmap of query string parameter name to password store name to be sent with the request
*/
function HttpClientRequest(options) {
var self = this;
console.log("Initiating an HTTP request",options)
this.wiki = options.wiki;
this.completionActions = options.oncompletion;
this.progressActions = options.onprogress;
this.bindStatus = options["bind-status"];
this.bindProgress = options["bind-progress"];
this.method = options.method || "GET";
this.body = options.body || "";
this.variables = options.variables;
var url = options.url;
$tw.utils.each(options.queryStrings,function(value,name) {
url = $tw.utils.setQueryStringParameter(url,name,value);
});
$tw.utils.each(options.passwordQueryStrings,function(value,name) {
url = $tw.utils.setQueryStringParameter(url,name,$tw.utils.getPassword(value) || "");
});
this.url = url;
this.requestHeaders = {};
$tw.utils.each(options.headers,function(value,name) {
self.requestHeaders[name] = value;
});
$tw.utils.each(options.passwordHeaders,function(value,name) {
self.requestHeaders[name] = $tw.utils.getPassword(value) || "";
});
}
HttpClientRequest.prototype.send = function(callback) {
var self = this,
setBinding = function(title,text) {
if(title) {
this.wiki.addTiddler(new $tw.Tiddler({title: title, text: text}));
}
};
if(this.url) {
setBinding(this.bindStatus,"pending");
setBinding(this.bindProgress,"0");
// Set the request tracker tiddler
var requestTrackerTitle = this.wiki.generateNewTitle("$:/temp/HttpRequest");
this.wiki.addTiddler({
title: requestTrackerTitle,
tags: "$:/tags/HttpRequest",
text: JSON.stringify({
url: this.url,
type: this.method,
status: "inprogress",
headers: this.requestHeaders,
data: this.body
})
});
this.xhr = $tw.utils.httpRequest({
url: this.url,
type: this.method,
headers: this.requestHeaders,
data: this.body,
callback: function(err,data,xhr) {
var hasSucceeded = xhr.status >= 200 && xhr.status < 300,
completionCode = hasSucceeded ? "complete" : "error",
headers = {};
$tw.utils.each(xhr.getAllResponseHeaders().split("\r\n"),function(line) {
var pos = line.indexOf(":");
if(pos !== -1) {
headers[line.substr(0,pos)] = line.substr(pos + 1).trim();
}
});
setBinding(self.bindStatus,completionCode);
setBinding(self.bindProgress,"100");
var resultVariables = {
status: xhr.status.toString(),
statusText: xhr.statusText,
error: (err || "").toString(),
data: (data || "").toString(),
headers: JSON.stringify(headers)
};
self.wiki.addTiddler(new $tw.Tiddler(self.wiki.getTiddler(requestTrackerTitle),{
status: completionCode,
}));
self.wiki.invokeActionString(self.completionActions,undefined,$tw.utils.extend({},self.variables,resultVariables),{parentWidget: $tw.rootWidget});
callback(hasSucceeded ? null : xhr.statusText);
// console.log("Back!",err,data,xhr);
},
progress: function(lengthComputable,loaded,total) {
if(lengthComputable) {
setBinding(self.bindProgress,"" + Math.floor((loaded/total) * 100))
}
self.wiki.invokeActionString(self.progressActions,undefined,{
lengthComputable: lengthComputable ? "yes" : "no",
loaded: loaded,
total: total
},{parentWidget: $tw.rootWidget});
}
});
}
};
HttpClientRequest.prototype.cancel = function() {
if(this.xhr) {
this.xhr.abort();
}
};
exports.HttpClient = HttpClient;
/*
Make an HTTP request. Options are:
url: URL to retrieve
headers: hashmap of headers to send
type: GET, PUT, POST etc
callback: function invoked with (err,data,xhr)
progress: optional function invoked with (lengthComputable,loaded,total)
returnProp: string name of the property to return as first argument of callback
*/
exports.httpRequest = function(options) {
@@ -83,8 +276,16 @@ exports.httpRequest = function(options) {
options.callback($tw.language.getString("Error/XMLHttpRequest") + ": " + this.status,null,this);
}
};
// Handle progress
if(options.progress) {
request.onprogress = function(event) {
console.log("Progress event",event)
options.progress(event.lengthComputable,event.loaded,event.total);
};
}
// Make the request
request.open(type,url,true);
// Headers
if(headers) {
$tw.utils.each(headers,function(header,headerTitle,object) {
request.setRequestHeader(headerTitle,header);
@@ -96,6 +297,7 @@ exports.httpRequest = function(options) {
if(!hasHeader("X-Requested-With") && !isSimpleRequest(type,headers)) {
request.setRequestHeader("X-Requested-With","TiddlyWiki");
}
// Send data
try {
request.send(data);
} catch(e) {
@@ -104,4 +306,19 @@ exports.httpRequest = function(options) {
return request;
};
exports.setQueryStringParameter = function(url,paramName,paramValue) {
var URL = $tw.browser ? window.URL : require("url").URL,
newUrl;
try {
newUrl = new URL(url);
} catch(e) {
}
if(newUrl && paramName) {
newUrl.searchParams.set(paramName,paramValue || "");
return newUrl.toString();
} else {
return url;
}
};
})();

View File

@@ -127,8 +127,8 @@ PageScroller.prototype.scrollIntoView = function(element,callback,options) {
};
PageScroller.prototype.scrollSelectorIntoView = function(baseElement,selector,callback,options) {
baseElement = baseElement || document.body;
var element = baseElement.querySelector(selector);
baseElement = baseElement || document;
var element = $tw.utils.querySelectorSafe(selector,baseElement);
if(element) {
this.scrollIntoView(element,callback,options);
}

View File

@@ -112,7 +112,7 @@ CheckboxWidget.prototype.getValue = function() {
var list;
if(this.checkboxListField) {
if($tw.utils.hop(tiddler.fields,this.checkboxListField)) {
list = tiddler.getFieldList(this.checkboxListField);
list = tiddler.getFieldList(this.checkboxListField) || [];
} else {
list = $tw.utils.parseStringArray(this.checkboxDefault || "") || [];
}
@@ -208,16 +208,20 @@ CheckboxWidget.prototype.handleChangeEvent = function(event) {
if(this.checkboxListField || this.checkboxListIndex) {
var fieldContents, listContents, oldPos, newPos;
if(this.checkboxListField) {
fieldContents = tiddler ? tiddler.fields[this.checkboxListField] : undefined;
fieldContents = (tiddler ? tiddler.fields[this.checkboxListField] : undefined) || [];
} else {
fieldContents = this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxListIndex);
}
if($tw.utils.isArray(fieldContents)) {
// Make a copy so we can modify it without changing original that's refrenced elsewhere
listContents = fieldContents.slice(0);
} else {
listContents = $tw.utils.parseStringArray(fieldContents) || [];
} else if(typeof fieldContents === "string") {
listContents = $tw.utils.parseStringArray(fieldContents);
// No need to copy since parseStringArray returns a fresh array, not refrenced elsewhere
} else {
// Field was neither an array nor a string; it's probably something that shouldn't become
// an array (such as a date field), so bail out *without* triggering actions
return;
}
oldPos = notValue ? listContents.indexOf(notValue) : -1;
newPos = value ? listContents.indexOf(value) : -1;

View File

@@ -39,7 +39,7 @@ DiffTextWidget.prototype.render = function(parent,nextSibling) {
this.execute();
// Create the diff
var dmpObject = new dmp.diff_match_patch(),
diffs = dmpObject.diff_main(this.getAttribute("source"),this.getAttribute("dest"));
diffs = dmpObject.diff_main(this.getAttribute("source",""),this.getAttribute("dest",""));
// Apply required cleanup
switch(this.getAttribute("cleanup","semantic")) {
case "none":

View File

@@ -271,6 +271,20 @@ DropZoneWidget.prototype.handlePasteEvent = function(event) {
callback: readFileCallback,
deserializer: this.dropzoneDeserializer
});
} else if(item.kind === "string" && !["text/html", "text/plain", "Text"].includes(item.type) && $tw.utils.itemHasValidDataType(item)) {
// Try to import the various data types we understand
var fallbackTitle = self.wiki.generateNewTitle("Untitled");
//Use the deserializer specified if any
if(this.dropzoneDeserializer) {
item.getAsString(function(str){
var tiddlerFields = self.wiki.deserializeTiddlers(null,str,{title: fallbackTitle},{deserializer:self.dropzoneDeserializer});
if(tiddlerFields && tiddlerFields.length) {
readFileCallback(tiddlerFields);
}
});
} else {
$tw.utils.importPaste(item,fallbackTitle,readFileCallback);
}
} else if(item.kind === "string") {
// Create tiddlers from string items
var tiddlerFields;

View File

@@ -92,12 +92,9 @@ LinkCatcherWidget.prototype.handleNavigateEvent = function(event) {
this.executingActions = false;
}
} else {
// This is a navigate event generated by the actions of this linkcatcher, so we don't trap it again, but just pass it to the parent
this.parentWidget.dispatchEvent({
type: "tm-navigate",
param: event.navigateTo,
navigateTo: event.navigateTo
});
// This is a navigate event generated by the actions of this linkcatcher,
// so we don't trap it again, but just pass it to the parent
this.parentWidget.dispatchEvent(event);
}
return false;
};

View File

@@ -51,7 +51,8 @@ MacroCallWidget.prototype.execute = function() {
var positionalName = 0,
parseTreeNodes = [{
type: "transclude",
isBlock: this.parseTreeNode.isBlock
isBlock: this.parseTreeNode.isBlock,
children: this.parseTreeNode.children
}];
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$variable",this.macroName);
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$type",this.parseType);

View File

@@ -119,8 +119,8 @@ ScrollableWidget.prototype.scrollIntoView = function(element,callback,options) {
};
ScrollableWidget.prototype.scrollSelectorIntoView = function(baseElement,selector,callback,options) {
baseElement = baseElement || document.body;
var element = baseElement.querySelector(selector);
baseElement = baseElement || document;
var element = $tw.utils.querySelectorSafe(selector,baseElement);
if(element) {
this.scrollIntoView(element,callback,options);
}

View File

@@ -48,7 +48,7 @@ SlotWidget.prototype.execute = function() {
var pointer = this.parentWidget,
depth = this.slotDepth;
while(pointer) {
if(pointer instanceof TranscludeWidget) {
if(pointer instanceof TranscludeWidget && pointer.hasVisibleSlots()) {
depth--;
if(depth <= 0) {
break;

View File

@@ -45,7 +45,7 @@ TranscludeWidget.prototype.execute = function() {
var target = this.getTransclusionTarget(),
parseTreeNodes = target.parseTreeNodes;
this.sourceText = target.text;
this.sourceType = target.type;
this.parserType = target.type;
this.parseAsInline = target.parseAsInline;
// Process the transclusion according to the output type
switch(this.transcludeOutput || "text/html") {
@@ -58,7 +58,7 @@ TranscludeWidget.prototype.execute = function() {
break;
default:
// text/plain
var plainText = this.wiki.renderText("text/plain",this.sourceType,this.sourceText,{parentWidget: this});
var plainText = this.wiki.renderText("text/plain",this.parserType,this.sourceText,{parentWidget: this});
parseTreeNodes = [{type: "text", text: plainText}];
break;
}
@@ -171,99 +171,86 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
}
var parser;
// Get the parse tree
if(this.transcludeVariable) {
// Transcluding a variable
var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}),
srcVariable = variableInfo && variableInfo.srcVariable;
if(srcVariable) {
if(srcVariable.isFunctionDefinition) {
// Function to return parameters by name or position
var fnGetParam = function(name,index) {
// Parameter names starting with dollar must be escaped to double dollars
if(name.charAt(0) === "$") {
name = "$" + name;
}
// Look for the parameter by name
if(self.hasAttribute(name)) {
return self.getAttribute(name);
// Look for the parameter by index
} else if(self.hasAttribute(index + "")) {
return self.getAttribute(index + "");
} else {
return undefined;
}
},
result = this.evaluateVariable(this.transcludeVariable,{params: fnGetParam})[0] || "";
parser = {
tree: [{
type: "text",
text: result
}],
source: result,
type: "text/vnd.tiddlywiki"
};
if(parseAsInline) {
parser.tree[0] = {
type: "text",
text: result
};
} else {
parser.tree[0] = {
type: "element",
tag: "p",
children: [{
if(this.hasAttribute("$variable")) {
if(this.transcludeVariable) {
// Transcluding a variable
var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}),
srcVariable = variableInfo && variableInfo.srcVariable;
if(variableInfo.text) {
if(srcVariable.isFunctionDefinition) {
// Function to return parameters by name or position
var result = (variableInfo.resultList ? variableInfo.resultList[0] : variableInfo.text) || "";
parser = {
tree: [{
type: "text",
text: result
}]
}
}
} else {
var cacheKey = (parseAsInline ? "inlineParser" : "blockParser") + (this.transcludeType || "");
if(variableInfo.isCacheable && srcVariable[cacheKey]) {
parser = srcVariable[cacheKey];
} else {
parser = this.wiki.parseText(this.transcludeType,variableInfo.text || "",{parseAsInline: parseAsInline, configTrimWhiteSpace: srcVariable.configTrimWhiteSpace});
if(variableInfo.isCacheable) {
srcVariable[cacheKey] = parser;
}
}
}
if(parser) {
// Add parameters widget for procedures and custom widgets
if(srcVariable.isProcedureDefinition || srcVariable.isWidgetDefinition) {
parser = {
tree: [
{
type: "parameters",
children: parser.tree
}
],
source: parser.source,
type: parser.type
}
$tw.utils.each(srcVariable.params,function(param) {
var name = param.name;
// Parameter names starting with dollar must be escaped to double dollars
if(name.charAt(0) === "$") {
name = "$" + name;
}],
source: result,
type: "text/vnd.tiddlywiki"
};
if(parseAsInline) {
parser.tree[0] = {
type: "text",
text: result
};
} else {
parser.tree[0] = {
type: "element",
tag: "p",
children: [{
type: "text",
text: result
}]
}
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],name,param["default"])
});
} else {
// For macros and ordinary variables, wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
parser = {
tree: [
{
type: "vars",
children: parser.tree
}
],
source: parser.source,
type: parser.type
}
$tw.utils.each(variableInfo.params,function(param) {
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],"__" + param.name + "__",param.value)
});
} else {
var cacheKey = (parseAsInline ? "inlineParser" : "blockParser") + (this.transcludeType || "");
if(variableInfo.isCacheable && srcVariable[cacheKey]) {
parser = srcVariable[cacheKey];
} else {
parser = this.wiki.parseText(this.transcludeType,variableInfo.text || "",{parseAsInline: parseAsInline, configTrimWhiteSpace: srcVariable.configTrimWhiteSpace});
if(variableInfo.isCacheable) {
srcVariable[cacheKey] = parser;
}
}
}
if(parser) {
// Add parameters widget for procedures and custom widgets
if(srcVariable.isProcedureDefinition || srcVariable.isWidgetDefinition) {
parser = {
tree: [
{
type: "parameters",
children: parser.tree
}
],
source: parser.source,
type: parser.type
}
$tw.utils.each(srcVariable.params,function(param) {
var name = param.name;
// Parameter names starting with dollar must be escaped to double dollars
if(name.charAt(0) === "$") {
name = "$" + name;
}
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],name,param["default"])
});
} else {
// For macros and ordinary variables, wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
parser = {
tree: [
{
type: "vars",
children: parser.tree
}
],
source: parser.source,
type: parser.type
}
$tw.utils.each(variableInfo.params,function(param) {
$tw.utils.addAttributeToParseTreeNode(parser.tree[0],"__" + param.name + "__",param.value)
});
}
}
}
}
@@ -279,6 +266,8 @@ TranscludeWidget.prototype.getTransclusionTarget = function() {
defaultType: this.transcludeType
});
}
// Set 'thisTiddler'
this.setVariable("thisTiddler",this.transcludeTitle);
// Return the parse tree
if(parser) {
return {
@@ -380,6 +369,13 @@ TranscludeWidget.prototype.getTransclusionSlotFill = function(name,defaultParseT
}
};
/*
Return whether this transclusion should be visible to the slot widget
*/
TranscludeWidget.prototype.hasVisibleSlots = function() {
return this.getAttribute("$fillignore","no") === "no";
}
/*
Compose a string comprising the title, field and/or index to identify this transclusion for recursion detection
*/

View File

@@ -112,14 +112,18 @@ Get the prevailing value of a context variable
name: name of variable
options: see below
Options include
params: array of {name:, value:} for each parameter
defaultValue: default value if the variable is not defined
source: optional source iterator for evaluating function invocations
allowSelfAssigned: if true, includes the current widget in the context chain instead of just the parent
Returns an object with the following fields:
params: array of {name:,value:} of parameters passed to wikitext variables
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
*/
Widget.prototype.getVariableInfo = function(name,options) {
options = options || {};
@@ -135,7 +139,8 @@ Widget.prototype.getVariableInfo = function(name,options) {
if(variable) {
var originalValue = variable.value,
value = originalValue,
params = [];
params = [],
resultList = [value];
// Only substitute parameter and variable references if this variable was defined with the \define pragma
if(variable.isMacroDefinition) {
params = self.resolveVariableParameters(variable.params,actualParams);
@@ -144,10 +149,28 @@ Widget.prototype.getVariableInfo = function(name,options) {
value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value);
});
value = self.substituteVariableReferences(value,options);
resultList = [value];
} else if(variable.isFunctionDefinition) {
// Function evaluations
params = self.resolveVariableParameters(variable.params,actualParams);
var variables = Object.create(null);
// Apply default parameter values
$tw.utils.each(variable.params,function(param,index) {
if(param["default"]) {
variables[param.name] = param["default"];
}
});
// Parameters are an array of {value:} or {name:, value:} pairs
$tw.utils.each(params,function(param) {
variables[param.name] = param.value;
});
resultList = this.wiki.filterTiddlers(value,this.makeFakeWidgetWithVariables(variables),options.source);
value = resultList[0] || "";
}
return {
text: value,
params: params,
resultList: resultList,
srcVariable: variable,
isCacheable: originalValue === value
};
@@ -159,6 +182,7 @@ Widget.prototype.getVariableInfo = function(name,options) {
}
return {
text: text,
resultList: [text],
srcVariable: {}
};
};
@@ -317,62 +341,11 @@ Widget.prototype.makeFakeWidgetWithVariables = function(variables) {
};
},
makeFakeWidgetWithVariables: self.makeFakeWidgetWithVariables,
evaluateVariable: self.evaluateVariable,
resolveVariableParameters: self.resolveVariableParameters,
wiki: self.wiki
};
};
/*
Evaluate a variable and associated actual parameters and result the resulting array.
The way that the variable is evaluated depends upon its type:
* Functions are evaluated as parameterised filter strings
* Macros are returned as plain text with substitution of parameters
* Procedures and widgets are returned as plain text
Options are:
params - the actual parameters may be one of:
* an array of values that may be an anonymous string value, or a {name:, value:} pair
* a hashmap of {name: value} pairs
* a function invoked with parameters (name,index) that returns a parameter value by name or position
source - iterator for source tiddlers
*/
Widget.prototype.evaluateVariable = function(name,options) {
options = options || {};
var params = options.params || [];
// Get the details of the variable (includes processing text substitution for macros
var variableInfo = this.getVariableInfo(name,{params: params,defaultValue: ""});
// Process function parameters
var variables = Object.create(null);
if(variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
// Apply default parameter values
$tw.utils.each(variableInfo.srcVariable.params,function(param,index) {
if(param["default"]) {
variables[param.name] = param["default"];
}
});
if($tw.utils.isArray(params)) {
// Parameters are an array of values or {name:, value:} pairs
$tw.utils.each(this.resolveVariableParameters(variableInfo.srcVariable.params,params),function(param) {
variables[param.name] = param.value;
});
} else if(typeof params === "function") {
// Parameters are passed via a function
$tw.utils.each(variableInfo.srcVariable.params,function(param,index) {
variables[param.name] = params(param.name,index) || param["default"] || "";
});
} else {
// Parameters are a hashmap
$tw.utils.each(params,function(value,name) {
variables[name] = value;
});
}
return this.wiki.filterTiddlers(variableInfo.text,this.makeFakeWidgetWithVariables(variables),options.source);
} else {
return [variableInfo.text];
}
};
/*
Compute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed.
Options include:
@@ -403,16 +376,10 @@ Widget.prototype.computeAttribute = function(attribute) {
if(attribute.type === "filtered") {
value = this.wiki.filterTiddlers(attribute.filter,this)[0] || "";
} else if(attribute.type === "indirect") {
value = this.wiki.getTextReference(attribute.textReference,"",this.getVariable("currentTiddler"));
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(variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
// It is a function definition. Go through each of the defined parameters, and make a variable with the value of the corresponding provided parameter
var paramArray = this.resolveVariableParameters(variableInfo.srcVariable.params,attribute.value.params);
value = this.evaluateVariable(attribute.value.name,{params: paramArray})[0] || "";
} else {
value = variableInfo.text;
}
value = variableInfo.text;
} else { // String attribute
value = attribute.value;
}
@@ -546,8 +513,8 @@ Widget.prototype.makeChildWidget = function(parseTreeNode,options) {
var variableDefinitionName = "$" + parseTreeNode.type;
if(this.variables[variableDefinitionName]) {
var isOverrideable = function() {
// Widget is overrideable if it has a double dollar user defined name, or if it is an existing JS widget and we're not in safe mode
return parseTreeNode.type.charAt(0) === "$" || (!!self.widgetClasses[parseTreeNode.type] && !$tw.safeMode);
// Widget is overrideable if its name contains a period, or if it is an existing JS widget and we're not in safe mode
return parseTreeNode.type.indexOf(".") !== -1 || (!!self.widgetClasses[parseTreeNode.type] && !$tw.safeMode);
};
if(!parseTreeNode.isNotRemappable && isOverrideable()) {
var variableInfo = this.getVariableInfo(variableDefinitionName,{allowSelfAssigned: true});
@@ -829,6 +796,20 @@ Widget.prototype.allowActionPropagation = function() {
return true;
};
/*
Evaluate a variable with parameters. This is a static convenience method that attempts to evaluate a variable as a function, returning an array of strings
*/
Widget.evaluateVariable = function(widget,name,options) {
var result;
if(widget.getVariableInfo) {
var variableInfo = widget.getVariableInfo(name,options);
result = variableInfo.resultList || [variableInfo.text];
} else {
result = [widget.getVariable(name)];
}
return result;
};
exports.widget = Widget;
})();

View File

@@ -1149,7 +1149,7 @@ exports.makeTranscludeWidget = function(title,options) {
if(options.importVariables) {
parseTreeImportVariables.attributes.filter.value = options.importVariables;
} else if(options.importPageMacros) {
parseTreeImportVariables.attributes.filter.value = "[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]";
parseTreeImportVariables.attributes.filter.value = this.getTiddlerText("$:/core/config/GlobalImportFilter");
}
parseTreeDiv.tree[0].children.push(parseTreeImportVariables);
parseTreeImportVariables.children.push(parseTreeTransclude);
@@ -1415,6 +1415,14 @@ exports.checkTiddlerText = function(title,targetText,options) {
return text === targetText;
}
/*
Execute an action string without an associated context widget
*/
exports.invokeActionString = function(actions,event,variables,options) {
var widget = this.makeWidget(null,{parentWidget: options.parentWidget});
widget.invokeActionString(actions,null,event,variables);
};
/*
Read an array of browser File objects, invoking callback(tiddlerFieldsArray) once they're all read
*/

View File

@@ -54,6 +54,7 @@ modal-footer-background: #f5f5f5
modal-footer-border: #dddddd
modal-header-border: #eeeeee
muted-foreground: #bbb
network-activity-foreground: #448844
notification-background: #ffffdd
notification-border: #999999
page-background: #f4f4f4

View File

@@ -3,5 +3,5 @@ title: $:/core/templates/exporters/StaticRiver/Content
\define renderContent()
{{{ $(exportFilter)$ ||$:/core/templates/static-tiddler}}}
\end
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
<<renderContent>>

View File

@@ -7,5 +7,5 @@ condition: [<count>compare:lte[1]]
\define renderContent()
{{{ $(exportFilter)$ +[limit[1]] ||$:/core/templates/tid-tiddler}}}
\end
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
<<renderContent>>

View File

@@ -1,11 +1,14 @@
title: $:/core/save/all-external-js
\whitespace trim
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
\define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
\end
<!-- Important: core library is provided by serving URI encoded $:/core/templates/tiddlywiki5.js -->
\define defaultCoreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}>
{{$:/core/templates/tiddlywiki5-external-js.html}}
</$let>

View File

@@ -1,7 +1,7 @@
title: $:/core/save/offline-external-js
\whitespace trim
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
\define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
\end

View File

@@ -1,6 +1,6 @@
title: $:/core/save/all
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
\define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
\end

View File

@@ -2,7 +2,7 @@ title: $:/core/templates/server/static.tiddler.html
\whitespace trim
\define tv-wikilink-template() $uri_encoded$
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

View File

@@ -4,7 +4,7 @@ title: $:/core/templates/single.tiddler.window
\define containerClasses()
tc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$
\end
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
<$vars
tv-config-toolbar-icons={{$:/config/Toolbar/Icons}}

View File

@@ -4,7 +4,7 @@ title: $:/core/templates/static.tiddler.html
\define tv-config-toolbar-icons() no
\define tv-config-toolbar-text() no
\define tv-config-toolbar-class() tc-btn-invisible
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
`<!doctype html>
<html>
<head>

View File

@@ -30,15 +30,15 @@ Block transclusions are shown in red, and inline transclusions are shown in gree
<!-- Look for a parameter starting with $ to determine if we are in legacy mode -->
<$list filter="[<@params>jsonindexes[]] :filter[<currentTiddler>prefix[$]] +[limit[1]]" variable="ignore" emptyMessage="""
<!-- Legacy mode: we render the transclusion without a dollar sign for recursionMarker and mode -->
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" recursionMarker="no" mode=<<mode>>>
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" recursionMarker="no" mode=<<mode>> $$fillignore="yes">
<!-- Reach back up to the grandparent transclusion to get the correct slot value -->
<$slot $name="ts-raw" $depth="2"/>
<$slot $name="ts-raw"/>
</$genesis>
""">
<!-- Non-legacy mode: we use dollar signs for the recursionMarker and mode -->
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" $$recursionMarker="no" $$mode=<<mode>>>
<$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget<currentTiddler>]" $$recursionMarker="no" $$mode=<<mode>> $$fillignore="yes">
<!-- Reach back up to the grandparent transclusion to get the correct slot fill value -->
<$slot $name="ts-raw" $depth="2"/>
<$slot $name="ts-raw"/>
</$genesis>
</$list>
</$genesis>

View File

@@ -211,7 +211,7 @@ $:/state/add-plugin-info/$(connectionTiddler)$/$(assetInfo)$
</div>
\end
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
\whitespace trim
<div>

View File

@@ -2,18 +2,6 @@ title: $:/core/ui/ControlPanel/Settings
tags: $:/tags/ControlPanel
caption: {{$:/language/ControlPanel/Settings/Caption}}
\define lingo-base() $:/language/ControlPanel/Settings/
<<lingo Hint>>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Settings]]">
<div style="border-top:1px solid #eee;">
!! <$link><$transclude field="caption"/></$link>
<$transclude/>
</div>
</$list>
<div class="tc-control-panel">
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/SettingsTab]!has[draft.of]]" default="$:/core/ui/ControlPanel/Settings/TiddlyWiki" explicitState="$:/state/tab--697582678"/>
</div>

View File

@@ -1,6 +1,7 @@
title: $:/core/ui/ControlPanel/Settings/TiddlyWiki
tags: $:/tags/ControlPanel/SettingsTab
caption: TiddlyWiki
list-before:
\define lingo-base() $:/language/ControlPanel/Settings/

View File

@@ -2,7 +2,7 @@ title: $:/core/ui/EditTemplate/body/preview/output
tags: $:/tags/EditPreview
caption: {{$:/language/EditTemplate/Body/Preview/Type/Output}}
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]] [all[shadows+tiddlers]tag[$:/tags/Macro/View/Body]!has[draft.of]]
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Macro/View/Body]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global/View]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global/View/Body]!is[draft]]
<$set name="tv-tiddler-preview" value="yes">
<$transclude tiddler={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/ViewTemplateBodyFilter]!is[draft]get[text]] :and[!is[blank]else[$:/core/ui/ViewTemplate/body/default]] }}} />

View File

@@ -14,8 +14,8 @@ color:$(foregroundColor)$;
\define tag-body-inner(colour,fallbackTarget,colourA,colourB,icon,tagField:"tags")
\whitespace trim
<$vars foregroundColor=<<contrastcolour target:"""$colour$""" fallbackTarget:"""$fallbackTarget$""" colourA:"""$colourA$""" colourB:"""$colourB$""">> backgroundColor="""$colour$""">
<span style=<<tag-styles>> class="tc-tag-label tc-tag-list-item tc-small-gap-right">
<$transclude tiddler="""$icon$"""/><$view field="title" format="text" />
<span style=<<tag-styles>> class="tc-tag-label tc-tag-list-item tc-small-gap-right" data-tag-title=<<currentTiddler>>>
<$transclude tiddler="""$icon$"""/><$view field="title" format="text"/>
<$button class="tc-btn-invisible tc-remove-tag-button" style=<<tag-styles>>><$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter="-[{!!title}]"/>{{$:/core/images/close-button}}</$button>
</span>
</$vars>

View File

@@ -0,0 +1,16 @@
title: $:/core/ui/Buttons/network-activity
tags: $:/tags/PageControls
caption: {{$:/core/images/network-activity}} {{$:/language/Buttons/NetworkActivity/Caption}}
description: {{$:/language/Buttons/NetworkActivity/Hint}}
\whitespace trim
<$button message="tm-http-cancel-all-requests" tooltip={{$:/language/Buttons/NetworkActivity/Hint}} aria-label={{$:/language/Buttons/NetworkActivity/Caption}} class=<<tv-config-toolbar-class>>>
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
{{$:/core/images/network-activity}}
</$list>
<$list filter="[<tv-config-toolbar-text>match[yes]]">
<span class="tc-btn-text">
<$text text={{$:/language/Buttons/NetworkActivity/Caption}}/>
</span>
</$list>
</$button>

View File

@@ -1,6 +1,6 @@
title: $:/core/ui/PageStylesheet
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
\whitespace trim
<$set name="currentTiddler" value={{$:/language}}>

View File

@@ -4,7 +4,7 @@ description: {{$:/language/PageTemplate/Description}}
icon: $:/core/images/layout-button
\whitespace trim
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
<$vars
tv-config-toolbar-icons={{$:/config/Toolbar/Icons}}

View File

@@ -26,7 +26,7 @@ $button$
<div class="tc-sidebar-tab-open">
<$list filter="[list<tv-story-list>]" history=<<tv-history-list>> storyview="pop">
<div class="tc-sidebar-tab-open-item">
<$macrocall $name="droppable-item" button="<$button message='tm-close-tiddler' tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class='tc-btn-invisible tc-btn-mini tc-small-gap-right'>{{$:/core/images/close-button}}</$button><$link to={{!!title}}><$view field='title'/></$link>"/>
<$macrocall $name="droppable-item" button="<$button message='tm-close-tiddler' tooltip={{$:/language/Buttons/Close/Hint}} aria-label={{$:/language/Buttons/Close/Caption}} class='tc-btn-invisible tc-btn-mini tc-small-gap-right'>{{$:/core/images/close-button}}</$button><$link/>"/>
</div>
</$list>
<$tiddler tiddler="">

View File

@@ -1,3 +1,3 @@
title: $:/core/ui/StoryTiddlerTemplate
<$transclude tiddler={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/StoryTiddlerTemplateFilter]!is[draft]get[text]] :and[!is[blank]else{$:/config/ui/ViewTemplate}] }}} />
<$transclude tiddler={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/StoryTiddlerTemplateFilter]!is[draft]get[text]] :and[has[title]else[$:/core/ui/ViewTemplate]] }}} />

View File

@@ -15,7 +15,7 @@ title: $:/core/ui/TagPickerTagTemplate
<<actions>>
<$set name="backgroundColor" value={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}>
<$wikify name="foregroundColor" text="""<$macrocall $name="contrastcolour" target=<<backgroundColor>> fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>>/>""">
<span class="tc-tag-label tc-btn-invisible" style=<<tag-pill-styles>>>
<span class="tc-tag-label tc-btn-invisible" style=<<tag-pill-styles>> data-tag-title=<<currentTiddler>> >
{{||$:/core/ui/TiddlerIcon}}<$view field="title" format="text"/>
</span>
</$wikify>

View File

@@ -5,10 +5,10 @@ title: $:/core/ui/ViewTemplate
$:/state/folded/$(currentTiddler)$
\end
\define cancel-delete-tiddler-actions(message) <$action-sendmessage $message="tm-$message$-tiddler"/>
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global/View]!is[draft]]
<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">>>
<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ [all[shadows+tiddlers]tag[$:/tags/ClassFilters/TiddlerTemplate]!is[draft]] :map:flat[subfilter{!!text}] tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}} role="article">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!is[draft]]" variable="listItem">
<$transclude tiddler=<<listItem>>/>
</$list>
</div>

View File

@@ -1,7 +1,7 @@
title: $:/core/ui/ViewTemplate/body
tags: $:/tags/ViewTemplate
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View/Body]!has[draft.of]]
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View/Body]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global/View/Body]!is[draft]]
<$reveal tag="div" class="tc-tiddler-body" type="nomatch" stateTitle=<<folded-state>> text="hide" retain="yes" animate="yes">

View File

@@ -0,0 +1,2 @@
title: $:/core/config/GlobalImportFilter
text: [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global]!is[draft]]

View File

@@ -13,6 +13,7 @@ core/ui/Buttons/language: hide
core/ui/Buttons/tag-manager: hide
core/ui/Buttons/manager: hide
core/ui/Buttons/more-page-actions: hide
core/ui/Buttons/network-activity: hide
core/ui/Buttons/new-journal: hide
core/ui/Buttons/new-image: hide
core/ui/Buttons/palette: hide

View File

@@ -1,3 +1,3 @@
title: $:/config/WikiParserRules/Inline/wikilink
enable
disable

View File

@@ -3,14 +3,26 @@ tags: $:/tags/Macro
\define translink(title,mode:"block")
\whitespace trim
<div style="border:1px solid #ccc; padding: 0.5em; background: black; foreground; white;">
<$list filter="[<__mode__>match[block]]">
<div class="tc-translink">
<div>
<$link to="""$title$""">
<$text text="""$title$"""/>
<h1><$text text="""$title$"""/></h1>
</$link>
<div style="border:1px solid #ccc; padding: 0.5em; background: white; foreground; black;">
<$transclude tiddler="""$title$""" mode="$mode$">
"<$text text="""$title$"""/>" is missing
<$transclude tiddler="""$title$""" mode="block">
<$set name="currentTiddler" value="""$title$"""><$transclude tiddler="$:/language/MissingTiddler/Hint"/></$set>
</$transclude>
</div>
</div>
</$list>
<$list filter="[<__mode__>match[inline]]">
<span class="tc-translink">
<$link to="""$title$""">
<$text text="""$title$"""/>
</$link>
&#32;(<$transclude tiddler="""$title$""" mode="inline">
<$set name="currentTiddler" value="""$title$"""><$transclude tiddler="$:/language/MissingTiddler/Hint"/></$set>
</$transclude>)
</span>
</$list>
\end

View File

@@ -1,2 +1,2 @@
title: $:/tags/PageControls
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/layout]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/layout]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/network-activity]] [[$:/core/ui/Buttons/more-page-actions]]

View File

@@ -2,7 +2,7 @@ modified: 20141013085608911
tags: Mechanisms
title: TestingMechanism
TiddlyWiki5 incorporates the Jasmine JavaScript testing framework (see http://pivotal.github.io/jasmine/). It allows the same tests to be run both in the browser and under Node.js.
TiddlyWiki5 incorporates the Jasmine JavaScript testing framework (see https://jasmine.github.io/). It allows the same tests to be run both in the browser and under Node.js.
! TiddlyWiki5 Testing Components

View File

@@ -15,6 +15,10 @@
<div id="draggable" draggable="true">
Drag me to a TiddlyWiki window
</div>
<button id="copy">
Click to copy two tiddlers to the clipboard
</button>
</body>
<script>
@@ -30,6 +34,18 @@
event.stopPropagation();
return false;
});
document.getElementById("copy").addEventListener("click",function(event) {
function listener(event) {
event.clipboardData.setData("URL","data:text/vnd.tiddler," + encodeURIComponent(JSON.stringify(tiddlerData)));
event.preventDefault();
}
document.addEventListener("copy",listener);
document.execCommand("copy");
document.removeEventListener("copy",listener);
});
</script>
</html>

View File

@@ -0,0 +1,3 @@
title: $:/config/WikiParserRules/Inline/wikilink
enable

View File

@@ -5,7 +5,7 @@ title: $:/core/ui/ViewTemplate
$:/state/folded/$(currentTiddler)$
\end
\define cancel-delete-tiddler-actions(message) <$action-sendmessage $message="tm-$message$-tiddler"/>
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global/View]!is[draft]]
<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">>>
<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}>
<$set name="state" value={{{ [[$:/state/viewtemplate/visibility/]addsuffix<currentTiddler>] }}}>

View File

@@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
TiddlyWiki incorpora código de los siguientes proyectos OpenSource:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
...y materiales de estos otros proyectos:

View File

@@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
TiddlyWiki intègre du code provenant de ces excellents projets OpenSource<<dp>>
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]]
Et des contenus provenenant de ces sources<<dp>>

View File

@@ -5,7 +5,7 @@ type: text/vnd.tiddlywiki
\define tv-wikilink-template() https://tiddlywiki.com/static/$uri_doubleencoded$.html
<$importvariables filter="[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]">
<$importvariables filter={{$:/core/config/GlobalImportFilter}}>
Bienvenue sur <<tw>>, un carnet de notes personnel web et non-linéaire que tout le monde peut utiliser et conserver, sans dépendre d'une quelconque entreprise.

View File

@@ -8,6 +8,6 @@ Tiddlers can contain formatted text:
Formatting is typed with special codes:
<$edit-text tiddler="FormattingDemoText" class="tc-edit-texteditor" minHeight="10px"/>
<$edit-text tiddler="FormattingDemoText" class="tc-edit-texteditor" minHeight="100px"/>
TiddlyWiki is not just for text. [[Images]] are first class citizens, too.

View File

@@ -49,14 +49,6 @@
],
"build": {
"index": [
"--rendertiddler","$:/core/save/all","index.html","text/plain"],
"favicon": [
"--savetiddler","$:/favicon.ico","favicon.ico",
"--savetiddler","$:/green_favicon.ico","static/favicon.ico"],
"static": [
"--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain",
"--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain",
"--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain",
"--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"]
"--rendertiddler","$:/core/save/all","index.html","text/plain"]
}
}

View File

@@ -1,19 +1,19 @@
caption: 5.3.0
created: 20230419103154368
modified: 20230419103154368
created: 20230506164543446
modified: 20230506164543446
tags: ReleaseNotes
title: Release 5.3.0
type: text/vnd.tiddlywiki
//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/master...parameterised-transclusions]]//
//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.2.7...master]]//
! About v5.3.0
! Overview of v5.3.0
This pre-release introduces a number of significant improvements and new features related to some of TiddlyWiki's most fundamental components: macros, widgets, operators and transclusion.
This release introduces a number of significant improvements and new features related to some of TiddlyWiki's most fundamental components: macros, widgets, operators and transclusion. v5.3.0 also contains several other bug fixes and improvements.
! Introduction to v5.3.0
! Introduction to Parameterised Transclusion, Procedures, Functions and Custom Widgets
The motivation of these changes is to fix one of ~TiddlyWiki 5's early design flaws: the reliance on macros using textual substitution as the primary way to modularise and reuse wikitext and filters.
<<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/6666">> The motivation of these changes is to fix one of ~TiddlyWiki 5's early design flaws: the reliance on macros using textual substitution as the primary way to modularise and reuse wikitext and filters.
Experience has shown that while macros are a good match for a small number of tasks, they are brittle and error prone for many common operations. See [[Macro Pitfalls]] for a discussion of the problems that accompany this approach. Over the years we have introduced mitigations for the worst problems but these have come at a cost of increased complexity.
@@ -30,9 +30,15 @@ These changes lay the groundwork for macros and related features to be deprecate
The new transclusion architecture is not by itself sufficient to enable us to fully deprecate macros yet. To handle the remaining use cases we propose a new backtick quoted attribute format that allows for the substitution of variable values. See https://github.com/Jermolene/TiddlyWiki5/issues/6663 for details.
! Defaulting to Disabling CamelCase Links
<<.link-badge-updated "https://github.com/Jermolene/TiddlyWiki5/pull/7513">> CamelCase linking is now disabled by default. (Note that this wiki has CamelCase linking explicitly enabled)
! Plugin Improvements
*
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7260">> Dynannotate pugin to support three additional search modes
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7365">> problem with [[BrowserStorage Plugin]] unnecessarily saving shadow tiddlers
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7493">> [[CodeMirror Plugin]] to add an option to make trailing spaces visible
! Translation improvement
@@ -54,15 +60,30 @@ Improvements to the following translations:
! Filter improvements
*
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7511"> new [[deserialize Operator]] for converting various textual representations of tiddlers into JSON data
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7292">> [[format Operator]] to support converting Unix timestamps to TiddlyWiki's native date format
! Hackability Improvements
*
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7413">> [[Core Icons]] to allow the size to be controlled with a parameter
** <<.warning """This change can cause problems with non-standard usage of the core icons where the text is directly rendered instead of being transcluded""">>
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7182">> new [[thisTiddler Variable]] that refers to the tiddler currently being rendered
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7332">> [[Story Tiddler Template Cascade]] handling to fall back to the default template if the output of the cascade is not valid
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7378">> missing file extensions for "audio/mpeg" files
! Bug Fixes
*
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7215">> importing tiddlers by pasting tiddler data
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7400">> unneeded 14px bottom border for textareas with autoheight enabled
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7380">> crashes when using an invalid CSS selector for [[WidgetMessage: tm-focus-selector]] and [[WidgetMessage: tm-scroll]]
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7401">> bug whereby scrolling occurs if the linkcatcher widget triggers an action-navigate and the $scroll attribute is set to "no"
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7409">> problem switching between LTR and RTL text
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/7448">> bug when checkbox widget's listField attribute was given the name of a date field (like <<.field created>> or <<.field modified>>)
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7529">> size of buttons in dropdown for editor "link" toolbar button
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/commit/8e132948b6bec623d81d300fbe6dc3a0307bcc6d">> crash when transcluding a lazily loaded tiddler as an attribute value
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/issues/7462">> DiffTextWidget crash with missing or empty attributes
* <<.link-badge-improved "https://github.com/Jermolene/TiddlyWiki5/pull/7448">> CheckboxWidget to avoid writing to date fields
! Developer Improvements
@@ -70,14 +91,36 @@ Improvements to the following translations:
! Node.js Improvements
*
* <<.link-badge-extended "https://github.com/Jermolene/TiddlyWiki5/pull/7471">> [[WebServer Parameter: authenticated-user-header]] to require URI encoding of authenticated username header, permitting non-ASCII characters in usernames
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/pull/7253">> support for `filepath` source attribute to [[tiddlywiki.files Files]]
* <<.link-badge-added "https://github.com/Jermolene/TiddlyWiki5/commit/48b22abdaab62c281c207127c66883b50898f9dd">> a warning message for JSON errors in [[tiddlywiki.info Files]] or [[plugin.info Files|PluginFolders]]
! Performance Improvements
*
* <<.link-badge-fixed "https://github.com/Jermolene/TiddlyWiki5/pull/4624">> module execution to reuse the same sandbox, saving memory and improving performance
! Acknowledgements
[[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki:
<<.contributors """
Arlen22
BramChen
btheado
donmor
flibbles
GameDungeon
JoshuaFontany
kookma
linonetwo
Marxsal
mateuszwilczek
michsa
muzimuzhi
pmario
rmunn
saqimtiaz
tavin
twMat
yaisog
""">>

View File

@@ -0,0 +1,3 @@
title: $:/config/WikiParserRules/Inline/wikilink
enable

View File

@@ -0,0 +1,7 @@
created: 20230314153132081
modified: 20230314153243008
title: $:/DefaultTiddlers
type: text/vnd.tiddlywiki
GettingStarted
[[Using the external JavaScript template]]

View File

@@ -0,0 +1,4 @@
title: $:/config/SaveWikiButton/Filename
type: text/vnd.tiddlywiki
external-<<version>>.html

View File

@@ -0,0 +1,8 @@
{
"tiddlers": [
{
"file": "../../../tw5.com/tiddlers/webserver/Using the external JavaScript template.tid",
"isTiddlerFile": true
}
]
}

View File

@@ -2,8 +2,7 @@
"description": "Client-server edition with external tiddlywiki.js",
"plugins": [
"tiddlywiki/tiddlyweb",
"tiddlywiki/filesystem",
"tiddlywiki/highlight"
"tiddlywiki/filesystem"
],
"themes": [
"tiddlywiki/vanilla",
@@ -13,7 +12,7 @@
"listen": [
"--listen","root-tiddler=$:/core/save/all-external-js","use-browser-cache=yes"],
"index": [
"--render","$:/core/save/offline-external-js","index.html","text/plain",
"--render","$:/core/save/offline-external-js","[[external-]addsuffix<version>addsuffix[.html]]","text/plain",
"--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffix<version>addsuffix[.js]]","text/plain"],
"static": [
"--render","$:/core/templates/static.template.html","static.html","text/plain",

View File

@@ -0,0 +1,8 @@
title: dezerializer test data case 6
type: application/json
[
{"created":"20230601125557184","text":"Before you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\n\n","title":"GettingStarted","modified":"20230601125601619"},
{"created":"20230601125507054","text":"Welcome to \"TiddlyWiki\".\n\nThis is a test tiddler.","tags":"","title":"Hello There \"Welcome\"","modified":"20230601125551144"},
{"title":"TiddlyWiki","created":"20130822170700000","modified":"20170127221451610","tags":"Concepts","type":"text/vnd.tiddlywiki","text":"~TiddlyWiki is a rich, interactive tool for manipulating complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors.\n\n~TiddlyWiki is designed to fit around your brain, helping you deal with the things that won't fit."}
]

View File

@@ -0,0 +1,29 @@
title: ThisTiddler/Simple
description: Simple usage of thisTiddler variable
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
\import Macro
\define print-this-tiddler()
<$text text=<<thisTiddler>>/>
\end
(<$text text=<<thisTiddler>>/>)
(<<print-this-tiddler>>)
(<<imported-print-this-tiddler>>)
+
title: Macro
\define imported-print-this-tiddler()
<$text text=<<thisTiddler>>/>
\end
+
title: ExpectedResult
<p>(Output)</p><p>(Output)</p><p>(Output)</p>

View File

@@ -12,15 +12,15 @@ title: Output
title: Actions
\whitespace trim
<!-- Define the <$$action-mywidget> widget by defining a transcludable variable with that name -->
\widget $$action-mywidget(one:'Jaguar')
<!-- Define the <$action.mywidget> widget by defining a transcludable variable with that name -->
\widget $action.mywidget(one:'Jaguar')
\whitespace trim
<$action-setfield $tiddler="Result" $field="text" $value=<<one>>/>
\end
<$$action-mywidget one="Dingo">
<$action.mywidget one="Dingo">
Crocodile
</$$action-mywidget>
</$action.mywidget>
+
title: ExpectedResult

View File

@@ -12,21 +12,21 @@ title: Output
title: TiddlerOne
\whitespace trim
<!-- Define the <$$mywidget> widget by defining a transcludable variable with that name -->
\widget $$mywidget(one:'Jaguar')
<!-- Define the <$my.widget> widget by defining a transcludable variable with that name -->
\widget $my.widget(one:'Jaguar')
\whitespace trim
<$text text=<<one>>/>
<$slot $name="ts-raw">
Whale
</$slot>
\end
<$$mywidget one="Dingo">
<$my.widget one="Dingo">
Crocodile
</$$mywidget>
<$$mywidget one="BumbleBee">
</$my.widget>
<$my.widget one="BumbleBee">
Squirrel
</$$mywidget>
<$$mywidget/>
</$my.widget>
<$my.widget/>
+
title: ExpectedResult

View File

@@ -6,13 +6,13 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
\widget $$mywidget()
\widget $my.widget()
<$slot $name=ts-raw>the body is empty</$slot>
\end
#<$$mywidget/>
#<$$mywidget></$$mywidget>
#<$$mywidget>the body is not empty</$$mywidget>
#<$my.widget/>
#<$my.widget></$my.widget>
#<$my.widget>the body is not empty</$my.widget>
+
title: ExpectedResult

View File

@@ -6,21 +6,21 @@ tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
\widget $$mywidget(one:'Jaguar')
\widget $my.widget(one:'Jaguar')
\whitespace trim
<$text text=<<one>>/>
<$slot $name="ts-stuff">
Whale
</$slot>
\end
<$$mywidget one="Dingo">
<$my.widget one="Dingo">
<$fill $name="ts-stuff">
Crocodile
</$fill>
</$$mywidget>
<$$mywidget one="BumbleBee">
</$my.widget>
<$my.widget one="BumbleBee">
Squirrel
</$$mywidget>
</$my.widget>
+
title: ExpectedResult

View File

@@ -12,17 +12,17 @@ title: Output
title: TiddlerOne
\whitespace trim
<!-- Redefine the <$$mywidget> widget by defining a transcludable variable with that name -->
\widget $$mywidget($variable:'Jaguar')
<!-- Redefine the <$my.widget> widget by defining a transcludable variable with that name -->
\widget $my.widget($variable:'Jaguar')
\whitespace trim
<$text text=<<$variable>>/>
<$slot $name="ts-raw">
Whale
</$slot>
\end
<$$mywidget $variable="Dingo">
<$my.widget $variable="Dingo">
Crocodile
</$$mywidget>
</$my.widget>
+
title: ExpectedResult

View File

@@ -0,0 +1,40 @@
title: Transclude/Macro/Missing
description: Transcluding a missing or blank variable
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\whitespace trim
<$macrocall $name="missingmacro">
Fallback content
</$macrocall>
<$transclude $variable="missingmacro">
Fallback content
</$transclude>
<$macrocall $name="">
Fallback content
</$macrocall>
<$transclude $variable="">
Fallback content
</$transclude>
<$let emptyVariable="">
<$macrocall $name="emptyVariable">
Fallback content
</$macrocall>
<$transclude $variable="emptyVariable">
Fallback content
</$transclude>
</$let>
+
title: ExpectedResult
<p>Fallback content</p><p>Fallback content</p><p>Fallback content</p><p>Fallback content</p><p>Fallback content</p><p>Fallback content</p>

View File

@@ -56,7 +56,7 @@ Tests the checkbox widget thoroughly.
* Test data for checkbox widget tests
*/
const fieldModeTests = [
var fieldModeTests = [
{
testName: "field mode checked",
tiddlers: [{title: "TiddlerOne", text: "Jolly Old World", expand: "yes"}],
@@ -95,16 +95,16 @@ Tests the checkbox widget thoroughly.
},
];
const indexModeTests = fieldModeTests.map(data => {
const newData = {...data};
const newName = data.testName.replace('field mode', 'index mode');
const newTiddlers = data.tiddlers.map(tiddler => {
var indexModeTests = fieldModeTests.map(data => {
var newData = {...data};
var newName = data.testName.replace('field mode', 'index mode');
var newTiddlers = data.tiddlers.map(tiddler => {
return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\nexpand: ${tiddler.expand}\ntwo: b`}
});
const newWidgetText = data.widgetText.replace("field='expand'", "index='expand'");
const newChange = {};
for (const key of Object.keys(data.expectedChange)) {
const oldChange = data.expectedChange[key];
var newWidgetText = data.widgetText.replace("field='expand'", "index='expand'");
var newChange = {};
for (var key of Object.keys(data.expectedChange)) {
var oldChange = data.expectedChange[key];
if (oldChange.expand) {
newChange[key] = { text: `one: a\nexpand: ${oldChange.expand}\ntwo: b` }
} else {
@@ -119,7 +119,26 @@ Tests the checkbox widget thoroughly.
return newData;
});
const listModeTests = [
var listModeTestsForDateFields = [
{
testName: "list mode created date field",
tiddlers: [{title: "Colors", created: "201304152222", modified: "202301022222"}],
widgetText: "<$checkbox tiddler='Colors' listField='created' checked='green' />",
startsOutChecked: false,
finalValue: false,
expectedChange: { "Colors": { created: new Date("2013-04-15T22:22:00Z")}} // created field should *not* be touched by a listField checkbox
},
{
testName: "list mode modified date field",
tiddlers: [{title: "Colors", created: "201304152222", modified: "202301022222"}],
widgetText: "<$checkbox tiddler='Colors' listField='modified' checked='green' />",
startsOutChecked: false,
finalValue: false,
expectedChange: { "Colors": { modified: new Date("2023-01-02T22:22:00Z")}} // modified field should *not* be touched by a listField checkbox
},
]
var listModeTests = [
{
testName: "list mode add",
tiddlers: [{title: "Colors", colors: "orange yellow"}],
@@ -235,11 +254,11 @@ Tests the checkbox widget thoroughly.
];
// https://github.com/Jermolene/TiddlyWiki5/issues/6871
const listModeTestsWithListField = (
var listModeTestsWithListField = (
listModeTests
.filter(data => data.widgetText.includes("listField='colors'"))
.map(data => {
const newData = {
var newData = {
...data,
tiddlers: data.tiddlers.map(tiddler => ({...tiddler, list: tiddler.colors, colors: undefined})),
widgetText: data.widgetText.replace("listField='colors'", "listField='list'"),
@@ -250,11 +269,11 @@ Tests the checkbox widget thoroughly.
return newData;
})
);
const listModeTestsWithTagsField = (
var listModeTestsWithTagsField = (
listModeTests
.filter(data => data.widgetText.includes("listField='colors'"))
.map(data => {
const newData = {
var newData = {
...data,
tiddlers: data.tiddlers.map(tiddler => ({...tiddler, tags: tiddler.colors, colors: undefined})),
widgetText: data.widgetText.replace("listField='colors'", "listField='tags'"),
@@ -266,20 +285,20 @@ Tests the checkbox widget thoroughly.
})
);
const indexListModeTests = listModeTests.map(data => {
const newData = {...data};
const newName = data.testName.replace('list mode', 'index list mode');
const newTiddlers = data.tiddlers.map(tiddler => {
var indexListModeTests = listModeTests.map(data => {
var newData = {...data};
var newName = data.testName.replace('list mode', 'index list mode');
var newTiddlers = data.tiddlers.map(tiddler => {
if (tiddler.hasOwnProperty('colors')) {
return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\ncolors: ${tiddler.colors}\ntwo: b`}
} else if (tiddler.hasOwnProperty('someField')) {
return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\nsomeField: ${tiddler.someField}\ntwo: b`}
}
});
const newWidgetText = data.widgetText.replace("listField='colors'", "listIndex='colors'").replace(/\$field/g, '$index').replace("listField='someField'", "listIndex='someField'");
const newChange = {};
for (const key of Object.keys(data.expectedChange)) {
const oldChange = data.expectedChange[key];
var newWidgetText = data.widgetText.replace("listField='colors'", "listIndex='colors'").replace(/\$field/g, '$index').replace("listField='someField'", "listIndex='someField'");
var newChange = {};
for (var key of Object.keys(data.expectedChange)) {
var oldChange = data.expectedChange[key];
if (oldChange.colors) {
newChange[key] = { text: `one: a\ncolors: ${oldChange.colors}\ntwo: b` }
} else if (oldChange.someField !== undefined) {
@@ -296,7 +315,7 @@ Tests the checkbox widget thoroughly.
return newData;
});
const filterModeTests = [
var filterModeTests = [
{
testName: "filter mode false -> true",
tiddlers: [{title: "Colors", colors: "red orange yellow"}],
@@ -482,9 +501,10 @@ Tests the checkbox widget thoroughly.
},
];
const checkboxTestData = fieldModeTests.concat(
var checkboxTestData = fieldModeTests.concat(
indexModeTests,
listModeTests,
listModeTestsForDateFields,
listModeTestsWithListField,
listModeTestsWithTagsField,
indexListModeTests,
@@ -494,7 +514,7 @@ Tests the checkbox widget thoroughly.
/*
* Checkbox widget tests using the test data above
*/
for (const data of checkboxTestData) {
for (var data of checkboxTestData) {
it('checkbox widget test: ' + data.testName, function() {
// Setup
@@ -505,7 +525,7 @@ Tests the checkbox widget thoroughly.
// Check initial state
const widget = findNodeOfType('checkbox', widgetNode);
var widget = findNodeOfType('checkbox', widgetNode);
// Verify that the widget is or is not checked as expected
expect(widget.getValue()).toBe(data.startsOutChecked);
@@ -519,16 +539,16 @@ Tests the checkbox widget thoroughly.
widget.handleChangeEvent(null);
// Check state again: in most tests, checkbox should be inverse of what it was
const finalValue = data.hasOwnProperty('finalValue') ? data.finalValue : !data.startsOutChecked;
var finalValue = data.hasOwnProperty('finalValue') ? data.finalValue : !data.startsOutChecked;
expect(widget.getValue()).toBe(finalValue);
// Check that tiddler(s) has/have gone through expected change(s)
for (const key of Object.keys(data.expectedChange)) {
const tiddler = wiki.getTiddler(key);
const change = data.expectedChange[key];
for (const fieldName of Object.keys(change)) {
const expectedValue = change[fieldName];
const fieldValue = tiddler.fields[fieldName];
for (var key of Object.keys(data.expectedChange)) {
var tiddler = wiki.getTiddler(key);
var change = data.expectedChange[key];
for (var fieldName of Object.keys(change)) {
var expectedValue = change[fieldName];
var fieldValue = tiddler.fields[fieldName];
expect(fieldValue).toEqual(expectedValue);
}
}

View File

@@ -0,0 +1,44 @@
/*\
title: test-deserialize-operator.js
type: application/javascript
tags: [[$:/tags/test-spec]]
Tests deserialize[] filter operator with various core deserializers
\*/
(function(){
/* jslint node: true, browser: true */
/* eslint-env node, browser, jasmine */
/* eslint no-mixed-spaces-and-tabs: ["error", "smart-tabs"]*/
/* global $tw, require */
"use strict";
describe("deserialize operator tests", function() {
it("should support the deserialize[] operator", function() {
//Unknown deserializer as operand
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[unknown/deserializer]]")).toEqual([$tw.language.getString("Error/DeserializeOperator/UnknownDeserializer")]);
//Missing operand
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[]]")).toEqual([$tw.language.getString("Error/DeserializeOperator/MissingOperand")]);
//Deserialize TiddlyWiki file
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[text/html]]")).toEqual(['[{"type":"text/vnd.tiddlywiki","text":"Abacus","title":"Hello \\"There\\""},{"title":"Hello \\"There\\"","text":"Calculator"}]']);
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 5}deserialize[text/html]]")).toEqual(['[{"type":"text/vnd.tiddlywiki","text":"Abacus","title":"Hello \\"There\\""},{"title":"Hello \\"There\\"","text":"Calculator"},{"title":"Hello \\"There\\"","text":"Protractor"}]']);
// Deserialize JSON payload containing tiddlers
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 6}deserialize[application/json]]")).toEqual( [ `[{"created":"20230601125557184","text":"Before you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\\n\\n","title":"GettingStarted","modified":"20230601125601619"},{"created":"20230601125507054","text":"Welcome to \\"TiddlyWiki\\".\\n\\nThis is a test tiddler.","tags":"","title":"Hello There \\"Welcome\\"","modified":"20230601125551144"},{"title":"TiddlyWiki","created":"20130822170700000","modified":"20170127221451610","tags":"Concepts","type":"text/vnd.tiddlywiki","text":"~TiddlyWiki is a rich, interactive tool for manipulating complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors.\\n\\n~TiddlyWiki is designed to fit around your brain, helping you deal with the things that won't fit."}]` ]);
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 6}deserialize[application/json]jsonindexes[]] :map[{dezerializer test data case 6}jsonget<currentTiddler>,[title]]")).toEqual([ 'GettingStarted', 'Hello There "Welcome"', 'TiddlyWiki' ]);
//Deserialize TiddlyWiki file with an mismatched deserializer
expect($tw.wiki.filterTiddlers("[{dezerializer test data case 5}deserialize[application/json]]")).toEqual([jasmine.stringMatching('JSON error')]);
});
});
})();

View File

@@ -99,14 +99,14 @@ Tests the filtering mechanism.
},
"TiddlerSix": {
title: "TiddlerSix",
text: "Missing inaction from TiddlerOne",
text: "Missing inaction from [[TiddlerOne]]",
filter: "[[one]] [[a a]] [subfilter{hasList!!list}]",
tags: []
},
"TiddlerSeventh": {
title: "TiddlerSeventh",
text: "",
list: "TiddlerOne [[Tiddler Three]] [[a fourth tiddler]] MissingTiddler",
list: "[[TiddlerOne]] [[Tiddler Three]] [[a fourth tiddler]] [[MissingTiddler]]",
tags: ["one"]
},
"Tiddler8": {
@@ -144,7 +144,7 @@ Tests the filtering mechanism.
modified: "201304152211"
},{
title: "Tiddler Three",
text: "The speed of sound in light\n\nThere is no TiddlerZero but TiddlerSix",
text: "The speed of sound in light\n\nThere is no [[TiddlerZero]] but [[TiddlerSix]]",
tags: ["one","two"],
cost: "56",
value: "80",
@@ -252,9 +252,9 @@ Tests the filtering mechanism.
});
it("should handle the lookup operator", function() {
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler],[text]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler],[text]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],8,Tidd");
expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler],[tags]]").join(",")).toBe(",one,one");
});
@@ -990,10 +990,10 @@ Tests the filtering mechanism.
expect(wiki.filterTiddlers("[!sortsub:number<sort1>]",anchorWidget).join(",")).toBe("filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,has filter,TiddlerOne,hasList,one");
expect(wiki.filterTiddlers("[sortsub:string<sort1>]",anchorWidget).join(",")).toBe("has filter,TiddlerOne,$:/TiddlerTwo,Tiddler Three,$:/ShadowPlugin,a fourth tiddler,filter regexp test,one,hasList");
expect(wiki.filterTiddlers("[!sortsub:string<sort1>]",anchorWidget).join(",")).toBe("hasList,one,filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,has filter,TiddlerOne");
expect(wiki.filterTiddlers("[sortsub:number<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test,$:/ShadowPlugin");
expect(wiki.filterTiddlers("[!sortsub:number<sort2>]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[sortsub:string<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test");
expect(wiki.filterTiddlers("[!sortsub:string<sort2>]",anchorWidget).join(",")).toBe("filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[sortsub:number<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,a fourth tiddler,$:/TiddlerTwo,Tiddler Three,filter regexp test,$:/ShadowPlugin");
expect(wiki.filterTiddlers("[!sortsub:number<sort2>]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,Tiddler Three,$:/TiddlerTwo,a fourth tiddler,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[sortsub:string<sort2>]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,$:/TiddlerTwo,Tiddler Three,filter regexp test");
expect(wiki.filterTiddlers("[!sortsub:string<sort2>]",anchorWidget).join(",")).toBe("filter regexp test,Tiddler Three,$:/TiddlerTwo,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one");
expect(wiki.filterTiddlers("[[TiddlerOne]] [[$:/TiddlerTwo]] [[Tiddler Three]] [[a fourth tiddler]] +[!sortsub:number<sort3>]",anchorWidget).join(",")).toBe("$:/TiddlerTwo,Tiddler Three,TiddlerOne,a fourth tiddler");
expect(wiki.filterTiddlers("a1 a10 a2 a3 b10 b3 b1 c9 c11 c1 +[sortsub:alphanumeric<sort4>]",anchorWidget).join(",")).toBe("a1,a2,a3,a10,b1,b3,b10,c1,c9,c11");
// #7155. The order of the output is the same as the input when an undefined variable is used in the subfitler
@@ -1060,6 +1060,9 @@ Tests the filtering mechanism.
expect(wiki.filterTiddlers("[[Hello There]] [[GettingStarted]] +[format:titlelist[]]").join(" ")).toBe("[[Hello There]] GettingStarted");
expect(wiki.filterTiddlers("[title[Hello There]] +[format:titlelist[]]").join(" ")).toBe("[[Hello There]]");
expect(wiki.filterTiddlers("[title[HelloThere]] +[format:titlelist[]]").join(" ")).toBe("HelloThere");
expect(wiki.filterTiddlers("0 +[format:timestamp[]]").join(",")).toBe("19700101000000000");
expect(wiki.filterTiddlers("1603188514443 +[format:timestamp[]]").join(",")).toBe("20201020100834443");
expect(wiki.filterTiddlers("void +[format:timestamp[]]").join(",")).toBe("");
});
it("should handle the deserializers operator", function() {

View File

@@ -45,16 +45,6 @@ describe("WikiText tests", function() {
it("should support attributes specified as macro invocations", function() {
expect(wiki.renderTiddler("text/html","TiddlerFour")).toBe("<p><a class=\"tc-tiddlylink tc-tiddlylink-missing\" href=\"#This%20is%20my%20%27%27amazingly%27%27%20groovy%20macro%21\">This is a link</a></p>");
});
it("should identify wikiwords to automatically link", function() {
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No wikilinks here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","One WikiLink here").indexOf("<a") !== -1).toBe(true);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No Wiki-Link here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No Wiki×Link here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No Wiki÷Link here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No xWikiLink here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No -WikiLink here").indexOf("<a") !== -1).toBe(false);
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No _WikiLink here").indexOf("<a") !== -1).toBe(false);
});
it("handles style wikitext notation", function() {
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","@@.myclass\n!header\n@@")).toBe("<h1 class=\"myclass\">header</h1>");
expect(wiki.renderText("text/html","text/vnd-tiddlywiki","@@.myclass\n<div>\n\nContent</div>\n@@")).toBe("<div class=\"myclass\"><p>Content</p></div>");

View File

@@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
The edit template body cascade is a [[cascade|Cascades]] used by the default edit template to choose the template for displaying the tiddler body.
The core edit template body cascade can be found in $:/core/ui/EditTemplate/body
The default edit template body cascade consists of:
# If the tiddler has the field ''_canonical_uri'' then use the template $:/core/ui/EditTemplate/body/canonical-uri to display the remote URL
@@ -13,4 +15,4 @@ The default edit template body cascade consists of:
You can see the current settings for the view template body cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Edit Template Body'' tab.
<<list-links "[tag[Edit Template Body Cascade]]">>
<<list-links "[tag[Edit Template Body Cascade]]">>

View File

@@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
The field editor cascade is a [[cascade|Cascades]] used to choose a template for rendering the field editor within the [[EditTemplate|$:/core/ui/EditTemplate/fields]].
The core field editor cascade can be found in $:/core/ui/EditTemplate/fields
The default field editor cascade only contains one element:
# Use the tiddler $:/core/ui/EditTemplate/fieldEditor/default to render the field
@@ -14,4 +16,4 @@ See [[Customizing EditTemplate field rendering]] for more details.
You can see the current settings for the field editor cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Field Editor'' tab.
<<list-links "[tag[Tiddler Field Editor Cascade]]">>
<<list-links "[tag[Tiddler Field Editor Cascade]]">>

View File

@@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
"Story tiddler template" refers to the template used to display a tiddler within the story river.
The core story tiddler template can be found in $:/core/ui/StoryTiddlerTemplate
The [[Story Tiddler Template Cascade]] is used to choose the template to be used for a particular tiddler. By default, the edit template is used for tiddlers in draft mode, and the view template used otherwise.
See also:

View File

@@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
The tiddler colour cascade is a [[cascade|Cascades]] used to choose which colour should be used for a particular tiddler.
Core tiddler colour cascades can be found in $:/core/macros/tag, $:/core/ui/Components/tag-link, $:/core/ui/EditTemplate/tags, $:/core/ui/TagPickerTagTemplate, $:/core/ui/TagTemplate and $:/core/ui/ViewTemplate/title
The default tiddler colour cascade consists of:
# If the tiddler has a ''color'' field, use the value as the colour
@@ -13,4 +15,4 @@ The default tiddler colour cascade consists of:
You can see the current settings for the tiddler colour cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Tiddler Colour'' tab.
<<list-links "[tag[Tiddler Colour Cascade]]">>
<<list-links "[tag[Tiddler Colour Cascade]]">>

View File

@@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
The tiddler icon cascade is a [[cascade|Cascades]] used to choose which icon should be used for a particular tiddler.
The core tiddler icon cascade can be found in $:/core/ui/TiddlerIcon
The default tiddler icon cascade consists of:
# If the tiddler has an ''icon'' field, use the value as the title of the icon tiddler
@@ -13,4 +15,4 @@ The default tiddler icon cascade consists of:
You can see the current settings for the tiddler icon cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Tiddler Icon'' tab.
<<list-links "[tag[Tiddler Icon Cascade]]">>
<<list-links "[tag[Tiddler Icon Cascade]]">>

View File

@@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki
The view template title cascade is a [[cascade|Cascades]] used by the default view template to choose the template for displaying the tiddler title.
The core view template title cascade can be found in $:/core/ui/ViewTemplate/title
The default view template title cascade consists of:
# If the tiddler title starts with `$:/` then use the template $:/core/ui/ViewTemplate/title/system which causes the `$:/` prefix to be displayed in pale text
@@ -13,4 +15,4 @@ The default view template title cascade consists of:
You can see the current settings for the view template title cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''View Template Title'' tab.
<<list-links "[tag[View Template Title Cascade]]">>
<<list-links "[tag[View Template Title Cascade]]">>

View File

@@ -45,7 +45,7 @@ Special tags assign special behaviour or appearance to all of the tiddlers to wh
For example:
* $:/tags/Macro causes the macros defined in a tiddler to be available globally
* $:/tags/Global causes the definitions in a tiddler to be available globally
* $:/tags/Stylesheet causes the tiddler to be interpreted as a CSS stylesheet
* $:/tags/SideBar causes the tiddler to be displayed as a sidebar tab

View File

@@ -5,7 +5,7 @@ modified: 20230410105035569
<span style="float:right;">[img width=340 [Xememex Logo]]</span>
Xememex is a multiuser TiddlyWiki from [[Federatial]]. It allows large groups of people to work together on intertwingled wikis that can share content.
Xememex is a multiuser TiddlyWiki from [[Federatial]]. It allows large groups of people to work together on intertwingled wikis that can share content. It is implemented as a serverless application on Amazon Web Services.
The largest customer implementation has hundreds of online wikis with thousands of users. See https://manuals.annafreud.org/

View File

@@ -36,7 +36,7 @@ The initial startup actions are useful for customising TiddlyWiki according to e
Note that global macros are not available within initial startup action tiddlers by default. If you need to access them then you'll need to explicitly include them with an [[Pragma: \import]] at the top of the tiddler:
```
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
```
!! Post-Render Startup Actions

View File

@@ -0,0 +1,26 @@
caption: deserialize
created: 20230601195749377
from-version: 5.3.0
modified: 20230602105513132
op-input: a selection of strings
op-output: JSON representations of tiddlers extracted from input titles.
op-parameter: the deserializer module to be used to extract tiddlers from the input
op-purpose: extract JSON representation of tiddlers from the input strings
tags: [[Filter Operators]] [[Special Operators]]
title: deserialize Operator
type: text/vnd.tiddlywiki
<<.tip "Deserializer modules parse text in various formats into their JSON representation as tiddlers. You can see the deserializers available in a wiki using the [[deserializers operator|deserializers Operator]].">>
|!Deserializer |!Description |
|(DOM)|Extracts tiddlers from a DOM node, should not be used with the <<.op deserialize[]>> operator |
|application/javascript|Parses a JavaScript module as a tiddler extracting fields from the header comment|
|application/json|Parses [[JSON|JSON in TiddlyWiki]] into tiddlers|
|application/x-tiddler|Parses the [[.tid file format|TiddlerFiles]] as a tiddler|
|application/x-tiddler-html-div|Parses the [[<DIV>.tiddler file format|TiddlerFiles]] as a tiddler|
|application/x-tiddlers|Parses the [[MultiTiddlerFile format|MultiTiddlerFiles]] as tiddlers|
|text/css|Parses CSS as a tiddler extracting fields from the header comment|
|text/html|Parses an HTML file into tiddlers. Supports ~TiddlyWiki Classic HTML files, ~TiddlyWiki5 HTML files and ordinary HTML files|
|text/plain|Parses plain text as a tiddler|
<<.operator-examples "deserialize">>

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