1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-22 10:54:46 +00:00

Compare commits

...

604 Commits

Author SHA1 Message Date
jeremy@jermolene.com
8816efa737 Restore standard sitetitle 2023-04-19 11:51:32 +01:00
jeremy@jermolene.com
093274f0fa Remove custom CI step for this branch 2023-04-19 11:51:21 +01:00
jeremy@jermolene.com
3b3879df03 Update 5.3.0 release note 2023-04-19 11:35:25 +01:00
jeremy@jermolene.com
55e38eb89a Update modification times of doc tiddlers
So that they are at the top of the recent tab
2023-04-19 11:32:34 +01:00
jeremy@jermolene.com
b91872bed1 Merge branch 'master' into parameterised-transclusions 2023-04-18 10:48:39 +01:00
jeremy@jermolene.com
5e329b1da1 Merge branch 'tiddlywiki-com' 2023-04-17 10:21:41 +01:00
jeremy@jermolene.com
31de1527f3 Docs: Fix tag on Tiddlyhost tiddler
Thanks @pmario https://github.com/Jermolene/TiddlyWiki5/pull/7399#issuecomment-1510920662
2023-04-17 09:49:50 +01:00
jeremy@jermolene.com
f41051b621 Merge branch 'master' into parameterised-transclusions 2023-04-12 17:11:38 +01:00
jeremy@jermolene.com
23b5b7f7d9 Merge branch 'tiddlywiki-com' 2023-04-12 15:19:17 +01:00
jeremy@jermolene.com
be67b0714c Add a community link to Open Collective 2023-04-12 14:25:56 +01:00
Jeremy Ruston
d3ef198842 Remove the 14px adjustment to textarea autoheight (#7400) 2023-04-12 11:18:17 +01:00
jeremy@jermolene.com
b1c295230d Fix clean.sh
It was missing the output of the `zh-Hans` edition previously
2023-04-10 21:03:26 +01:00
jeremy@jermolene.com
3689171198 Merge branch 'master' into parameterised-transclusions 2023-04-10 16:07:54 +01:00
jeremy@jermolene.com
bffe538982 Merge branch 'tiddlywiki-com' 2023-04-10 16:06:52 +01:00
Jeremy Ruston
caac9bee92 Docs: Fixed PR for getting started tweaks (#7399)
* Cherry picked from getting-started-tweaks-feb-2023

* Update tiddler modified dates
2023-04-10 15:52:10 +01:00
Yukai Chou
36d766081d Fix typos in Saving to a Git service.tid (#7396)
* Fix typos in `Saving to a Git service.tid`

* Sign the CLA
2023-04-07 13:39:12 +01:00
jeremy@jermolene.com
54548babc8 Mastodon verification link 2023-04-07 12:33:07 +01:00
jeremy@jermolene.com
a2cbb6f992 Merge branch 'master' into parameterised-transclusions 2023-04-06 16:11:54 +01:00
jeremy@jermolene.com
dccce5878c Merge branch 'tiddlywiki-com' 2023-04-06 16:11:44 +01:00
jeremy@jermolene.com
5b271bb4f4 Fix nonstandard initialisation code for fill/parameter/slot widgets 2023-04-06 08:50:47 +01:00
yaisog
bfcb386343 Restructure and optimize CheckboxWidget docs (#7362)
* Restructure and optimize `CheckboxWidget` docs

* Minor improvements

* Use new tab macros and some reformatting

* Fix bug in widget-attr-link tooltip

* Minor layout tweaks

* First try at a Widget Documentation Style Guide

* Add new tabs-related macros to overview

* Update CSS, add tm-scroll and rename macros

* Avoid RSoE with tm-scroll, improve CSS for tab-links

* Handle doc-tab-links within tab tiddlers better

* Reflect macro name changes in their docs

* Update Widget Doc Style Guide
2023-04-04 18:00:04 +01:00
Marxsal
f7c3ac4c54 Add save mechanism TiddlyStow (#7389)
* Add save mechanism TiddlyStow

* Add save mechanism TiddlyStow (incl url)
2023-04-03 20:20:32 +01:00
jeremy@jermolene.com
bb2dea2414 Remove 5.2.8 release note 2023-04-02 14:42:39 +01:00
jeremy@jermolene.com
7ba666bd53 Merge branch 'master' into parameterised-transclusions 2023-04-02 14:00:47 +01:00
jeremy@jermolene.com
2a19c60e20 Merge branch 'tiddlywiki-com' 2023-04-02 14:00:19 +01:00
Mohammad Rahmani
c28dbd0025 Update regexp.tid (#7382)
The list-links by default show caption of listed tiddlers instead of their title. So in the example here

```
<$macrocall
$name="wikitext-example-without-html"
src="""<$set name="digit-pattern" value="[0-9]{2}">
<<list-links "[regexp:title<digit-pattern>]" field:"title">>
</$set>"""/>
```

you need to use field:"title" to see the correct results visually.
2023-03-28 10:23:02 +02:00
Mohammad Rahmani
29c2260457 Update ListMacro.tid (#7381)
The field input parameter was corrected
2023-03-28 10:22:32 +02:00
Saq Imtiaz
d7c89de11d Update docs for TiddlerTemplate classes (#7377)
* Update docs for TiddlerTemplate classes

* Update SystemTag_ $__tags_ClassFilters_TiddlerTemplate.tid
2023-03-26 18:03:02 +01:00
jeremy@jermolene.com
e0ff54a04e Preparation for v5.2.8 2023-03-26 12:56:40 +01:00
jeremy@jermolene.com
042f3c59ad Merge branch 'tiddlywiki-com' 2023-03-26 12:54:10 +01:00
jeremy@jermolene.com
07960f1527 Update relesase banner for v5.2.8 2023-03-26 09:28:26 +01:00
jeremy@jermolene.com
5cdffd6943 Missed release date for v5.2.7 2023-03-26 09:05:06 +01:00
jeremy@jermolene.com
ee0a32c8f1 Version number update for 5.2.7 2023-03-26 08:50:15 +01:00
jeremy@jermolene.com
4bb3d2ba34 Preparing for the release of v5.2.7 2023-03-26 08:49:40 +01:00
jeremy@jermolene.com
e7c0ad484b Merge branch 'tiddlywiki-com' 2023-03-26 08:45:04 +01:00
jeremy@jermolene.com
cff3db6eaa Merge branch 'master' into parameterised-transclusions 2023-03-26 08:29:41 +01:00
yaisog
e82053609b Tweak some examples for get and getindex (#7376) 2023-03-25 17:56:12 +00:00
jeremy@jermolene.com
7926af8541 Updated release banner for v5.2.7 2023-03-25 07:52:44 +00:00
Cameron Fischer
bcca4eca81 Fixed issue with trailing newlines in macrodefs (#7371) 2023-03-23 22:37:35 +00:00
jeremy@jermolene.com
8c98fc4ab1 Merge branch 'master' into parameterised-transclusions 2023-03-21 08:08:18 +00:00
jeremy@jermolene.com
925ff202a0 Preparing for v5.2.7 2023-03-20 19:01:54 +00:00
jeremy@jermolene.com
97bc9039e6 Version number update for 5.2.6 2023-03-20 18:51:07 +00:00
jeremy@jermolene.com
e6149e7e29 Update readme for v5.2.6 2023-03-20 18:50:30 +00:00
jeremy@jermolene.com
e47f038d2a Preparing for release of v5.2.6 2023-03-20 18:48:56 +00:00
jeremy@jermolene.com
2789bc8ef6 Update release note to add banner competition information 2023-03-20 18:44:43 +00:00
jeremy@jermolene.com
3a2831870b Remove peace symbol from new release banner
Our code of conduct declares that TiddlyWiki does not espouse any political statements.
2023-03-20 18:32:59 +00:00
jeremy@jermolene.com
4cddfa228b New release banner for v5.2.6
See competition at https://talk.tiddlywiki.org/t/vote-for-the-tiddlywiki-banner-v5-2-6/6469
2023-03-20 18:28:07 +00:00
jeremy@jermolene.com
da1825e6c5 Update release note 2023-03-20 15:10:38 +00:00
jeremy@jermolene.com
4ae2d8422b Revert to original icon for "dirty" version of save wiki icon
This restores the circle-in-a-circle image first introduced in #7232
2023-03-20 14:58:33 +00:00
jeremy@jermolene.com
e2cc32aa75 Merge branch 'master' into parameterised-transclusions 2023-03-18 16:04:20 +00:00
jeremy@jermolene.com
c9e1b91099 Simplify save wiki button dirty state
Thanks to Thomas_Chuffart at https://talk.tiddlywiki.org/t/now-is-the-time-to-help-with-testing-the-tiddlywiki-v5-2-6-prerelease/6405/66

Addendum to #7232
2023-03-18 16:02:55 +00:00
jeremy@jermolene.com
95f987544c Update save wiki "dirty" state icon
See https://talk.tiddlywiki.org/t/now-is-the-time-to-help-with-testing-the-tiddlywiki-v5-2-6-prerelease/6405/60

Addendum to #7232
2023-03-14 14:50:52 +00:00
jeremy@jermolene.com
308e207a67 Remove reference to #7297 from release note 2023-03-12 17:03:19 +00:00
jeremy@jermolene.com
aa5a6627e6 Revert "Use sticky flag to improve regexp search performance (#7297)"
This reverts commit e313857822.
2023-03-12 17:02:16 +00:00
Mario Pietsch
6f038e362e External-js: fix index.html overwrites external wiki (#7356) 2023-03-12 16:49:15 +00:00
jeremy@jermolene.com
f9751f19b6 Merge branch 'master' into parameterised-transclusions 2023-03-12 16:19:30 +00:00
jeremy@jermolene.com
95a9c0bd54 Merge branch 'tiddlywiki-com' 2023-03-12 16:19:22 +00:00
jeremy@jermolene.com
0a20c08107 Fix Typo
Thanks @timp
2023-03-12 15:49:37 +00:00
jeremy@jermolene.com
964993f879 New-here: Fix unwanted double braces around tags specified in $:/config/NewTiddler/Tags
Fixes #7354
2023-03-11 11:13:35 +00:00
yaisog
e6175227b2 Add another example for the get operator (#7351) 2023-03-10 15:57:51 +00:00
jeremy@jermolene.com
f247686970 Remove "const" accidentally included in #7290
See #7350
2023-03-10 12:32:52 +00:00
jeremy@jermolene.com
589813f233 Improved fix for #7270 2023-03-10 09:41:36 +00:00
jeremy@jermolene.com
007b759421 Undefined variables in let widget: Revert fix for #7270
Reverts 8c378e0d24 and adds a test
2023-03-10 09:41:18 +00:00
jeremy@jermolene.com
2a2939f4eb Merge branch 'master' into parameterised-transclusions 2023-03-10 09:10:27 +00:00
yaisog
714587cdfc Improve documentation for get and getindex - Update descriptions and examples (#7349) 2023-03-10 08:48:28 +00:00
Michelle Saad
d8c2ab3baf Sign CLA (#7342) 2023-03-08 18:16:48 +00:00
jeremy@jermolene.com
b16d695386 Update release note 2023-03-08 08:53:02 +00:00
yaisog
2bac676ac4 Docs: Align description with example (#7339) 2023-03-07 21:51:52 +00:00
Mario Pietsch
ba01d06962 German Translation: fix some typos and add missing tiddlers (#7337) 2023-03-07 08:56:41 +00:00
yaisog
6732d96f78 Add a description and examples for "strict" results from getindex (#7333)
* Add a description and examples for "strict" results

* Add another example

* Amend description of output with suffix "index"
2023-03-06 16:14:08 +00:00
Mario Pietsch
416a2fae7a Add syntax docs to railroad plugin (#7334) 2023-03-06 16:12:26 +00:00
jeremy@jermolene.com
f417bdb742 Merge branch 'master' into parameterised-transclusions 2023-03-06 09:06:41 +00:00
jeremy@jermolene.com
2ce14ac8f9 Remove erroneously committed storylist tiddler 2023-03-05 18:05:25 +00:00
jeremy@jermolene.com
3764ca4760 Update release note 2023-03-05 17:59:32 +00:00
jeremy@jermolene.com
3f478f5689 Naming tweak to #6047
@linonetwo I realised on review that we refer to boot.files as the "tiddler file info"
2023-03-05 17:40:04 +00:00
cdruan
f9604c40d3 Add wikiparser.js dependency (#7330) 2023-03-05 10:34:41 +00:00
Jeremy Ruston
11ffc83493 Introduce new levenshtein, makepatches, applypatches operators (#7290)
* Initial Commit

* Fix crash with invalid patches

See https://github.com/Jermolene/TiddlyWiki5/pull/7290#issuecomment-1453155311

Thanks @yaisog

* Add words and lines options to makepatches (#7326)

* Prevent infinite loop for single-word texts (#7327)

* Add docs and examples for the new operators (#7328)

* Create makepatches Operator.tid

* Improve wording

* Doc and examples for the new operators

---------

Co-authored-by: yaisog <m@rcuswinter.de>
2023-03-04 21:16:26 +00:00
jeremy@jermolene.com
f343198353 Merge branch 'tiddlywiki-com' 2023-03-04 20:42:22 +00:00
yaisog
1946f173a9 Update ActionListopsWidget documentation including notes on de-duplication (#7301)
* Changed headings under Content

Made them H2 and changed the wording a bit.

* Move the list of filters to another tiddler

There is a tiddler for Extended Listops Filters, and the list should go there, so that the Widget tiddler does not get too overcrowded.

* Rework comparison to ActionSetFieldWidget

* Add notes on de-duplication

* Update link to Extended Listops Filters

* Updated link to Extended Listops Filters

* Update link to Extended Listops Filters

Duh. This was the most important one.

* Remove repeated links to widgets within one section

* Re-create original tiddler with a redirect notice

* Excised the examples into a separate tiddler

Also created an "examples" subdirectory under tw5.com/tiddlers/widgets.
2023-03-04 11:48:14 +00:00
hffqyd
7d7ac662a2 Saving via a Minimal Web Server (#7315)
A standalone mini web server enables support tiddlywiki as well as upload files/images, for use like `[img[images/uploaded.jpg]]`.
2023-03-03 22:02:15 +00:00
hffqyd
3627ad1d28 Signing the CLA (#7316) 2023-03-03 21:58:13 +00:00
Mario Pietsch
b16ed6629d Docs: Improve Formatting in Wikitext (#7320)
* improve Formatting in Wikitext

* formatting add more info about semantic meaning

* back to 1 tiddler Formatting in Wikitext

* single backtics are used for code - fix typo
2023-03-03 21:57:21 +00:00
lin onetwo
d14e775b90 Allow deleteTiddler to not modify fs (#6047)
* feat: allow deleteTiddler to not modify fs

* refactor: add new function that merely delete file in cache, and let old func calls it

* fix: self is undefined
2023-03-03 21:56:40 +00:00
Mario Pietsch
d4b10605c3 improve WikiText docs add a Markdown tiddler (#7319)
* improve WikiText docs add a Markdown tiddler

* remove Elements heading as requested
2023-03-03 21:51:01 +00:00
Mario Pietsch
7f1064d14b Add dollar sign to HTML entities (#7323) 2023-03-03 21:34:30 +00:00
Mario Pietsch
867d647839 Move fourcolumns CSS class as multicolumns to tw5-styles for reuse (#7318) 2023-03-03 21:25:12 +00:00
Mario Pietsch
8c39c9e911 Docs: Add HTML Entities to WikiText info (#7321) 2023-03-03 20:25:28 +00:00
Bram Chen
c0ce53e3ea Update chinese language files (#7310)
* Add chinese translation for the text of `Error/ZoominTextNode` in Misc.multids
2023-03-02 08:40:11 +00:00
Maurycy Zarzycki
3a9f848ea0 Report ZoomIn issues when using tiddler template that starts with a text node (#7007)
* add alert when zoomin error occurs plus protection to avoid TW getting stuck when it happens

* Reverted additional logging and made the zoomin just silently and safely ignore the issue
2023-03-01 16:18:41 +00:00
jeremy@jermolene.com
ea055f2ba5 Merge branch 'master' into parameterised-transclusions 2023-02-28 08:45:56 +00:00
Saq Imtiaz
5bce35d90b Fix: add twEditor attribute to paste events handled by codemirror (#7281) 2023-02-28 08:35:15 +00:00
lin onetwo
8d39ce95eb FieldIndexer performance: use isShadowTiddler instead of allTitles (#7299)
* feat: use `isShadowTiddler` insteadof `allTitles`

* fix: use `tiddlerExists` instead
2023-02-27 17:32:20 +00:00
Jeremy Ruston
e313857822 Use sticky flag to improve regexp search performance (#7297) 2023-02-27 15:12:07 +00:00
Maurycy Zarzycki
ce988f909a Add PL translations to strings introduce in 7b7063a7b2 (#7300) 2023-02-27 15:03:03 +00:00
yaisog
ba2c9f44b0 Make some cosmetic changes to the DateFormat and Date Fields documentation (#7295)
* Add description of field date format

* Add description of field date format and improvements

Due to the re-creation of the PR all changes to this file got mushed together.
2023-02-27 09:24:36 +00:00
btheado
6479c26b59 Removes datauri triggered save instructions modal (#7296)
* Do not trigger a save instructions modal when viewing through data uri

* Removed all instances of the no longer used SaveInstructions tiddler
2023-02-26 21:42:10 +00:00
Jeremy Ruston
2271f6885a Add focusSelectFromStart/focusSelectFromEnd attributes to <$edit-text> widget (#7222)
* Initial commit

* WIP

* Align implementation with @yaisog's suggestion

See https://github.com/Jermolene/TiddlyWiki5/pull/7222#issuecomment-1410194593

* Commit missing from 3262b8d77d

Thanks @pmario

* Fix version number

Thanks @yaisog

* Add two examples for text selection (#7286)

---------

Co-authored-by: yaisog <m@rcuswinter.de>
2023-02-25 18:25:46 +00:00
jeremy@jermolene.com
8c378e0d24 Let widget should specify a default value for variables
Fixes #7270
2023-02-25 13:41:13 +00:00
andrigamerita
925ce2b505 Add meta viewport to StaticRiver (#6953)
StaticRiver HTML didn't feature a <meta name="viewport" line, which made single-page full wiki static exports look bad on mobile.
2023-02-24 16:51:30 +00:00
andrigamerita
cf25dae8a7 Signing the CLA (#7287) 2023-02-24 16:50:49 +00:00
cdruan
eb8f4d66b9 Markdown Plugin: Handle non-string attr values in tw_image() (#7284) 2023-02-24 15:41:29 +00:00
jeremy@jermolene.com
ef03a4a5df Markdown Plugin: Default to recognising TiddlyWiki-format links
Fixes #7275
2023-02-24 09:51:45 +00:00
jeremy@jermolene.com
51a4d39c19 Refresh text editors when the palette changes
Fixes #7276
2023-02-23 10:13:13 +00:00
Mateusz Wilczek
55124b4ee6 Improve documentation of WikiText formatting (#7272)
* Improve 'Formatting in WikiText.tid'

Add highlight formatting example.
Simplify code formatting example to be single line without nested list.
Improve bold, italic, and underscore formatting examples to be consistent with others.

* Improve 'Styles and Classes in WikiText.tid'

Add more examples, including the default highlight styling when no style or class is defined, as introduced in #6877
2023-02-17 19:14:21 +01:00
Mateusz Wilczek
fb99d3050e Sign the CLA (#7271)
Mateusz Wilczek, @mateuszwilczek, 2023/02/16
2023-02-17 10:09:45 +01:00
btheado
95dc56d850 Fix importTitle and autoOpenOnImport in the tm-import-tiddler message (#7243)
* Add initial tm-import-tiddler test

* Add failing test for tm-import-tiddlers importTitle #7234

* Add failing test for tm-import-tiddlers autoOpenOnImport #7234

* Use event.paramObject instead of event to access tm-import-tiddlers options. Fixes #7234.

* Added a clarifying comment

* Allow mixing tm-import-tiddler params in both event and event.paramObject

* Added import test using tv-auto-open-on-import variable

* Removed stray punctuation
2023-02-11 09:15:44 +00:00
Jeremy Ruston
77b418004a Zoomin: Avoid using broken tc-storyview-zoomin-tiddler class (#7252)
* First commit

Fixes #7247

* Revert to setting the faulty tc-storyview-zoomin-tiddler class for backwards compatibility
2023-02-10 21:27:20 +00:00
jeremy@jermolene.com
0d1667c467 Merge branch 'master' into parameterised-transclusions 2023-02-10 16:04:08 +00:00
Cameron Fischer
028dfe39b7 Fixed issue where $genesis didn't pass isBlock (#7230)
* Fixed issue where $genesis didn't pass isBlock

* Added $mode attribute for genesis

* Added documentation for $mode attribute
2023-02-10 10:17:32 +00:00
jeremy@jermolene.com
81f5141166 Dynannotate: Don't crash when used in the fake DOM
Fixes #7258
2023-02-10 09:00:52 +00:00
TonyM
8567c48be8 Update BrowseWidget.tid (#7231)
* Update BrowseWidget.tid

Made sure all references to use of the `<$browse>` widget were changed to `<$browse/>`

Which possibly caused this problem, now closed https://github.com/Jermolene/TiddlyWiki5/issues/7223

If not closed other widgets may work

* To documentation standard

Replaced `The content of the `<$browse>` widget is ignored.`
`The content of the <<.wid BrowseWidget>> widget is ignored.`
To restore documentation standards as per   @Jermolene
2023-02-03 19:25:23 +00:00
jeremy@jermolene.com
3da3318396 Node.js: Prefer .tid format when a _canonical_uri field present
Fixes #7238
2023-02-03 19:22:43 +00:00
jeremy@jermolene.com
89fd8871b6 Add encodebase64/decodebase64 operators
Proposed by @ericshulman
2023-02-02 09:55:54 +00:00
jeremy@jermolene.com
f249b79e81 Fix edit toolbar button classes
Appears to have been broken at least as far back as v5.1.10
2023-02-01 19:04:46 +00:00
jeremy@jermolene.com
86569e5ade Merge branch 'master' into parameterised-transclusions 2023-01-30 21:43:00 +00:00
jeremy@jermolene.com
524cee1489 XLSX plugin: Add support for numeric fields 2023-01-30 21:42:44 +00:00
jeremy@jermolene.com
1dea0a03b8 Merge branch 'master' into parameterised-transclusions 2023-01-30 09:43:54 +00:00
jeremy@jermolene.com
93abe5e3a6 xlsx-utils plugin: Update to latest version of xlsx.js 2023-01-30 09:43:18 +00:00
jeremy@jermolene.com
c0bca18cab Dynannotate: Fix searchCaseSensitive default in docs
Fixes #7245
2023-01-29 16:43:01 +00:00
Jeremy Ruston
d70b6a7d6c Make save wiki button be accessible to users without colour vision (#7232)
* Make save wiki button be accessible to users without colour vision

* Make the dynamic button be a separate button

For backwards compatibility
2023-01-28 09:51:25 +00:00
jeremy@jermolene.com
6404d5652e Minor tweaks for fe2c677ac4 2023-01-27 20:49:34 +00:00
fkmiec
fe2c677ac4 Docs for #7169 - update readme tiddlers for TiddlyWebAdaptor and BrowserStorage plugins (#7240)
* Update readme to reflect optional use of browser storage with tiddlyweb sync adapter

* Fix typos in readme
2023-01-27 20:39:13 +00:00
Mario Pietsch
3faadd69c0 Fix #7227 control panel parser rule checkbox text spacing (#7228) 2023-01-23 22:20:35 +00:00
jeremy@jermolene.com
4e5c957e97 Further fix to whitespace handling in $tw.utils.stringifyList
Fixes typo in 3d0ec5b1bd

See 3d0ec5b1bd (commitcomment-97804850)
2023-01-23 19:36:13 +00:00
jeremy@jermolene.com
3d0ec5b1bd Fix handling of whitespace in $tw.utils.stringifyList
Fixes #7226
2023-01-23 17:16:51 +00:00
jeremy@jermolene.com
59895db097 Merge branch 'master' into parameterised-transclusions 2023-01-23 16:36:56 +00:00
jeremy@jermolene.com
683414f51e Fix positional parameters in widget.evaluateVariable()
This should clear up the remaining anomalies in #7009, let me know how you get on @btheado
2023-01-23 16:34:08 +00:00
Mario Pietsch
fb8e5d1417 Improve readability of the editor save-button (#7225) 2023-01-23 13:23:25 +00:00
Mario Pietsch
2426cc668d Fix #7220 whitespace issue with editor save button (#7224) 2023-01-23 13:22:27 +00:00
jeremy@jermolene.com
34afe4e143 Refactor function invocation
* Introduce new widget helper function to evaluate variables.Functions are evaluated as parameterised filter strings, macros as text with textual substitution of parameters and variables, and procedures and widgets as plain text
* Refactor the function operator and unknown operator to use the new helper
* Use the new helper to evaluate variables within filter strings, thus fixing a bug whereby functions called in such a way were being returned as plain text instead of being evaluated
* Refactor the transclude widget to use the new helper
* Update tests
2023-01-21 22:07:34 +00:00
jeremy@jermolene.com
d4ab427ceb Refactor wikified function tests 2023-01-21 21:04:43 +00:00
jeremy@jermolene.com
a62d7f1b0d Merge branch 'master' into parameterised-transclusions 2023-01-21 20:45:21 +00:00
jeremy@jermolene.com
75a399a389 Add contributors to release note 2023-01-21 17:14:17 +00:00
jeremy@jermolene.com
4c4399c32d Merge branch 'master' of github.com:Jermolene/TiddlyWiki5 2023-01-21 13:57:36 +00:00
jeremy@jermolene.com
194df33de3 Update release note 2023-01-21 13:57:14 +00:00
Télumire
6718f82b4c Small gap fix for the updated toc macro (alternative to tc-tiny-gap-left) (#7219) 2023-01-20 10:15:35 +00:00
jeremy@jermolene.com
8ef6d78bef Filesystemadaptor: Use json format for tiddlers with fieldnames containing hash
Fixes #7144
2023-01-19 21:16:46 +00:00
Mario Pietsch
e6189078ff Make tag-picker and keyboard-driven-input macros human readable (#7118)
* make tag-picker and keyboard-driven-input macros human readable

* fix indentation as requested
2023-01-19 20:44:00 +00:00
Cameron Fischer
c20c35c0a6 Fully committing core to the $genesis widget (#7129) 2023-01-19 17:48:23 +00:00
cdruan
51cbf83c23 Fix data-tiddler field duplications in server snapshots (#7130) 2023-01-19 17:47:49 +00:00
Télumire
1441138d5c Correction of the toc and toc-body macro (#7121)
* correction of the toc and toc-body macro: tiddler without toc-link field can now be overriden + nested the macros

* reverted macro nesting

.. to be able to override the toc-body macro

* reverted tabs to spaces
2023-01-19 17:46:50 +00:00
Jeremy Ruston
a5894946de Extend encodeuricomponent to process additional characters (#7128)
* First commit

* Fix version number in docs

* Add code comment
2023-01-19 17:45:54 +00:00
Matthias Bilger
a3a1eceb4a Use iframe to embed PDF (#7102)
`<iframe>` is kind of preferred over `<embed>` and widely supported.
2023-01-19 17:01:53 +00:00
cdruan
aa8f7f77d6 External.js: Allow boot code to remain as tiddlers in tiddlywikicore.js (#7210)
* Allow boot code to remain as tiddlers

* Sync up with tiddlywiki5.html

* Add \whitespace trim

* Add download-full-wiki button

* Simplify ExportTiddlyWikiCore code

No longer needs the if-boot-code-is-missing part of the code.

* Replace space btw icon and button text with CSS
2023-01-19 16:52:12 +00:00
jeremy@jermolene.com
5d650e87dd Remove savers for Beaker Browser now it is archived
See https://github.com/beakerbrowser/beaker/blob/master/archive-notice.md
2023-01-19 16:45:30 +00:00
jeremy@jermolene.com
67a8f7aeba Merge branch 'tiddlywiki-com' 2023-01-19 16:44:09 +00:00
jeremy@jermolene.com
485bf19c3c Remove docs references to Beaker Browser now it is archived
See https://github.com/beakerbrowser/beaker/blob/master/archive-notice.md
2023-01-19 16:43:48 +00:00
jeremy@jermolene.com
586d44f6ce Allow missing tiddlers to be deleted (ie closed)
Fixes #7217
2023-01-18 16:50:58 +00:00
jeremy@jermolene.com
66cf779abb Merge branch 'master' into parameterised-transclusions 2023-01-18 09:05:48 +00:00
jeremy@jermolene.com
18c790152f Merge branch 'master' of github.com:Jermolene/TiddlyWiki5 2023-01-17 23:14:15 +00:00
jeremy@jermolene.com
9541f3c283 Clean up build errors 2023-01-17 23:13:58 +00:00
GameDungeon
5aa5fc72b1 Gamedungeon Sign CLA (#7216) 2023-01-17 22:16:09 +00:00
fkmiec
005dfdadf0 Automatic sync of tiddler changes in browser storage when sync connection is re-established (#7169)
* Add automatic sync of tiddler changes in browswer-storage on restoration of server connection in tiddlywebadaptor

* Fix issue with new tiddlers not being synced.

* Fix issue with new tiddlers not being synced.

* Added logging

* Modified browser-storage plugin. Refactored into utility class.

* Modified browser-storage plugin. Refactored into utility class.

* Fix: browser storage config tiddler created on load only if not already exists

* Fix: Removed extra indent in util.js
2023-01-17 22:12:18 +00:00
Mario Pietsch
af1cc56c0c [DOC] Improve ActionCreateTiddlerWidget documentation (#7202)
* [DOC] Improve ActionCreateTiddlerWidget documentation

* action-createtitddler improve docs as requested
2023-01-17 17:29:08 +00:00
jeremy@jermolene.com
5bf60cd26f Remove some contractions that have crept in
They do not belong in technical documentation
2023-01-17 16:56:52 +00:00
jeremy@jermolene.com
4546828541 Genesis widget rewording 2023-01-17 16:56:25 +00:00
jeremy@jermolene.com
1a69fb7e5c Merge branch 'tiddlywiki-com' 2023-01-17 16:48:26 +00:00
Mario Pietsch
db88eed88f Improve docs for genesis-widget (#7174)
* Improve docs for genesis-widget

* improve wording

* use <<.attr macro instead of <<.param
2023-01-17 16:45:51 +00:00
jeremy@jermolene.com
81002f9f30 Merge branch 'master' into parameterised-transclusions 2023-01-17 16:40:47 +00:00
Mario Pietsch
c51816e826 Fix pasting of multiple types at once (#6622)
* wip fix dropzone closure variable problem

* just a new commit to autocreate at test wiki
2023-01-17 15:02:57 +00:00
Mario Pietsch
e41511c652 make core/ui/MoreSideBar/Tags look nice in the story river (#7212) 2023-01-17 14:57:49 +00:00
jeremy@jermolene.com
8f7441f296 Share plugin: Further fixes to c39ef398bf
See https://talk.tiddlywiki.org/t/revived-share-plugin/5887/14

Thanks @btheado
2023-01-17 14:34:06 +00:00
jeremy@jermolene.com
c8d99c8aad Merge branch 'tiddlywiki-com' 2023-01-17 12:32:04 +00:00
yaisog
166f68cc15 Improve \parsermode documentation (#7214) 2023-01-17 12:31:07 +00:00
jeremy@jermolene.com
fecb7edca4 Fix typo in messagecatcher widget
I think this was a copy-paste error, but would appreciate other eyes on this...
2023-01-16 19:34:02 +00:00
jeremy@jermolene.com
7632a3317a Merge branch 'tiddlywiki-com' 2023-01-16 19:21:07 +00:00
jeremy@jermolene.com
0039c2134b Use correct image for Mastodon link 2023-01-16 14:05:36 +00:00
jeremy@jermolene.com
34643a4279 Add icon to default page layout and show in switcher
Thanks @linonetwo

Fixes #7197
2023-01-16 13:21:40 +00:00
twMat
4d040d2499 Docs: Update is.tid (#7213)
Ref [discussion](https://talk.tiddlywiki.org/t/filter-q-is-tiddler-or-shadow-how/5888)
2023-01-16 12:56:51 +00:00
jeremy@jermolene.com
c0615e20ec Revert "Fix table overflow for small screens (#7010)"
This reverts commit 2db886793e.
2023-01-15 20:22:52 +00:00
jeremy@jermolene.com
c39ef398bf Share plugin: decode the URI component before checking for the leading hash sign
Should compensate for the mangling we get from Discourse – see https://talk.tiddlywiki.org/t/revived-share-plugin/5887
2023-01-15 18:55:36 +00:00
jeremy@jermolene.com
02d28c100b Merge branch 'tiddlywiki-com' 2023-01-15 18:46:46 +00:00
Pippo Peppo
dc225da1ff Update italian language file (#7209)
* Update italian language file

* Update italian language file
2023-01-14 16:55:40 +00:00
jeremy@jermolene.com
aeec6aee23 Docs typo 2023-01-14 14:56:49 +00:00
jeremy@jermolene.com
f9efbd93b1 Docs: Fix ordering of badges 2023-01-14 14:31:37 +00:00
jeremy@jermolene.com
b7c420393c Add a "NEW" banner to the newsletter badge 2023-01-14 14:11:19 +00:00
jeremy@jermolene.com
9574506a89 Image for TiddlyWiki newsletter badge 2023-01-14 14:09:05 +00:00
jeremy@jermolene.com
13c0f3c5e2 TiddlyWiki Newsletter badge 2023-01-14 14:06:03 +00:00
jeremy@jermolene.com
301a0ecec7 Docs: Remove another stray camelcase link 2023-01-14 14:00:25 +00:00
jeremy@jermolene.com
917975b464 Avoid unnecessary full stop 2023-01-14 13:49:36 +00:00
jeremy@jermolene.com
c9691bdb27 Docs: Remove camelcase wikification for newsletter badge 2023-01-14 13:47:16 +00:00
jeremy@jermolene.com
5ea9743cd5 Add TiddlyWiki Newsletter badge 2023-01-14 13:39:25 +00:00
cdruan
0c328a1696 Revamp markdown plugin (#6528)
* Rename markdown to markdown-legacy

* Change how default renderWikiTextPragma value is displayed

To prevent out-of-sync, dynamically display the default value of
renderWikiTextPragma from the shadow tiddler instead of hard coding
the text in the "usage.tid".

* Repackage remarkable-based markdown plugin as markdown-legacy

- Rename plugin title to $:/plugins/tiddlywiki/markdown-legacy

- Add support for "text/markdown" MIME type and set that as the default
  when creating new markdown tiddlers

* Create new markdown plugin

* add support to text/markdown MIME type

* remove linkify and linkNewWindow config options

- linkify feature should be controlled by "extlink" TW parser rule;
  enabling markdown's linkify option will interfere with parsing

- remove the possibility to open external links in the same tab/window
  to match TW's behavior

* Ignore latex-parser wikirule in rednerWikiTextPragma

* Prevent camel-case link text from generating a link

* Update editions/markdowndemo

* Produce better parse tree

* Improve markdown/tiddlywiki integration

- widget block should not interrupt paragraph
- ignore tw-syntax links inside markdown-syntax links
- remove repeated renderWikiTextPragma parsing
- more efficient findNextMatch when examining tw rules

* Update user docs

* Replace includes() with indexOf() for legacy browsers
2023-01-14 09:49:04 +00:00
btheado
b5134951e5 Allow attribute override in innerwiki widget (#7176) 2023-01-13 10:48:51 +00:00
btheado
6e10918a28 Fixes share plugin stale url and prevents wikification of generated json (#7207)
* Use tv-action-refresh-policy to ensure generated share url is up-to-date

* Use 'text/raw' output to prevent generated json from being wikified
2023-01-12 23:36:21 +00:00
Wincent Balin
0ee53bbc01 Use British English (#7180)
Fixed some typos too.
2023-01-12 20:59:34 +00:00
btheado
a52da67563 Use decodeURIComponent in share plugin rawmarkup (#7204) 2023-01-12 18:24:32 +00:00
Mohammad Rahmani
494ee984f8 Update Macro Definitions in WikiText.tid (#7201)
Ref: https://talk.tiddlywiki.org/t/requesting-macro-massage-willing-to-donate-50-to-tw/5833/17

Add explanation for single line nested macro
2023-01-11 18:57:21 +00:00
jeremy@jermolene.com
923f9084f8 New test missed off a45349cc99 2023-01-11 09:15:40 +00:00
jeremy@jermolene.com
a45349cc99 Fix detection of empty transclusions
See https://talk.tiddlywiki.org/t/exploring-default-tiddler-links-hackability-in-v5-3-0/5745/25?u=jeremyruston
2023-01-11 08:57:54 +00:00
Marxsal
9c70ee34d4 Update community resources TiddlyResearch and Drift (#7198) 2023-01-10 22:18:32 +00:00
Bram Chen
c7612ff4ce Update chinese language files (#7195)
* Added documentation for more core fields
2023-01-09 09:36:07 +00:00
TonyM
51acc24b0a Remove the tag to itself on the "Open collective" tiddler (#7187)
Remove [[Open Collective]] from the tags of itself.

This breaks the heirachy of the TOC and produces an entry that will not open its own list see HelloThere > Open Collective
2023-01-08 13:20:17 +00:00
yaisog
c5ce1d78a2 Update cla-individual.md (#7189) 2023-01-08 13:18:53 +00:00
Saq Imtiaz
dd6e00687b Adds support for indenting pragmas with whitespace (#7185)
* feat: first pass at allowing pragmas to be indented

* Added documentation
2023-01-08 13:17:01 +00:00
Cameron Fischer
7b7063a7b2 Added documentation for neglected core fields (#7191) 2023-01-08 13:13:04 +00:00
jeremy@jermolene.com
7a4a8bd3f6 Rename test 2023-01-07 09:41:39 +00:00
jeremy@jermolene.com
4f96465141 Merge branch 'master' into parameterised-transclusions 2023-01-07 09:34:11 +00:00
jeremy@jermolene.com
f3ebb258f7 Remove obsolete content from v5.2.6 release note
Should have been included in 44de7918ab
2023-01-05 11:21:02 +00:00
Scott Sauyet
67beafe359 Add Scott Sauyet (CrossEye) to the CLA (#7181) 2023-01-05 08:22:46 +00:00
jeremy@jermolene.com
8ca0bf10e4 Lazy loading a tiddler should trigger a sync
Fixes #7138
2023-01-03 14:28:48 +00:00
btheado
6f9cf20e77 Fixes reduce, filter, and sortsub operators undefined variable exception (#7156)
* Added failing tests for #7155

* Pass getVariable options through to the widget method. Fixes #7155

* Whitespace fix

* Added tests to verify macro parameters work inside filter, reduce, and sortsub operators
2023-01-03 13:48:20 +00:00
Pippo Peppo
fb8df29948 Fix and enhance italian translation (#7173)
* Fixed and enhanced italian translation

* Fixed and enhanced italian translation

* Delete type: text/vnd.tiddlywiki

* Delete type: text/vnd.tiddlywiki

* Update and rename application%2Fjavascript.tid to application_javascript.tid

* Update and rename application%2Fjson.tid to application_json.tid

* Update and rename application%2Fx-tiddler-dictionary.tid to application_x_tiddler_dictionary.tid

* Update and rename image%2Fgif.tid to image_gif.tid

* Update and rename image%2Fjpeg.tid to image_jpeg.tid

* Update and rename image%2Fpng.tid to image_png.tid

* Update and rename image%2Fsvg%2Bxml.tid to image_svg_xml.tid

* Update and rename image%2Fx-icon.tid to image_x-icon.tid

* Update and rename text%2Fcss.tid to text_css.tid

* Update and rename text%2Fhtml.tid to text_html.tid

* Update and rename text%2Fplain.tid to text_plain.tid

* Update and rename text%2Fvnd.tiddlywiki.tid to text_vnd.tiddlywiki.tid

* Update and rename text%2Fx-tiddlywiki.tid to text_x-tiddlywiki.tid

* Fixed and enhanced italian translation

* Fixed and enhanced italian translation

* Changed en-GB to ''en-GB''

* Fixed and enhanced italian translation

* Fixed and enhanced italian translation

* Fixed and enhanced italian translation

* Fixed and enhanced italian translation

* Update NewJournal.multids

* Create NewJournalTags.tid

* Delete Advanced/Matches

* Update SideBar.multids

* Fixed and enhanced italian translation

* Fixed and enhanced italian translation
2023-01-03 10:17:10 +00:00
Pippo Peppo
b33b41e1fc Signing the CLA (#7172) 2023-01-03 10:16:42 +00:00
jeremy@jermolene.com
04810667e6 It's 2023 2023-01-02 15:47:24 +00:00
jeremy@jermolene.com
50971db392 Italian translation update
Thanks Pippo Peppo

See https://talk.tiddlywiki.org/t/italian-it-it-translation-update/5680
2023-01-01 18:58:23 +00:00
fkmiec
d57abcbb23 Signing the CLA (#7168) 2023-01-01 18:21:36 +00:00
Nick Bell
8a2fad2499 Using stamp - docs (#7165)
* Using stamp - docs

* Moved from-version pill

* Changed tag-pill to tag

* Corrected the right tag-pill

Oops!
2023-01-01 18:15:09 +00:00
Nick Bell
666e2a795f Signing the CLA (#7164) 2023-01-01 18:12:50 +00:00
jeremy@jermolene.com
42a408146d Empty or missing type on genesis widget should not render an element/widget
Fixes #7153
2022-12-30 21:42:07 +00:00
Jeremy Ruston
bf8e1ca5b0 Fix options.tiddlerinfo is undefined on New Tiddler button click (#7162)
See https://talk.tiddlywiki.org/t/nodejs-wiki-typeerror-options-tiddlerinfo-is-undefined-on-new-tiddler-button-click/5583
2022-12-30 19:41:41 +00:00
jeremy@jermolene.com
3bdc18ab84 Fix json operators retrieving properties of strings and numbers
Fixes #7160
2022-12-30 15:28:34 +00:00
jeremy@jermolene.com
43214c1cc6 Docs: System tag doc tables should display description if caption is missing
Fixes #7161
2022-12-30 15:15:24 +00:00
jeremy@jermolene.com
0b39e47ce8 Browsers import MP3 files as audio/mpeg, not audio/mp3
Chrome changed in v81 to match Firefox and Safari - https://stackoverflow.com/questions/61363934/chrome-81-mimetype-change-to-file-upload-of-audio-mp3

Fixes #7157
2022-12-30 09:34:38 +00:00
cs8425
87c3e53299 Signing the CLA (#7159) 2022-12-30 09:15:18 +00:00
jeremy@jermolene.com
3a7a3d64c2 Docs: Update indexes operator to note that results are sorted
See https://talk.tiddlywiki.org/t/how-can-i-get-the-indexes-of-a-data-tiddler-in-the-order-they-are-given-there/3359
2022-12-29 09:43:18 +00:00
Mario Pietsch
c819b2d365 Changecount macro change the wording ... just a bit (#7146) 2022-12-24 16:00:30 +00:00
Mario Pietsch
119813529d changecount macro change the wording ... just a bit (#7147) 2022-12-24 15:59:48 +00:00
Mario Pietsch
9f69161709 Add ignore .github, .vscode to regexp (#7148) 2022-12-24 15:58:50 +00:00
Jeffrey Zhang
18d3ea9d14 Support obsidian external link (#7149) 2022-12-24 15:56:46 +00:00
Jeffrey Zhang
ae18c2e19b Signing the CLA (#7150) 2022-12-24 15:55:56 +00:00
jeremy@jermolene.com
95e6168839 Fix logout triggering 404 error
See https://talk.tiddlywiki.org/t/logout-error-xmlhttprequest-error-code-404/5590/5 for details

We can't POST to the logout endpoint without triggering authentication, so we report in advance whether logout is supported.
2022-12-24 12:13:01 +00:00
jeremy@jermolene.com
73507ca8b5 Release note typo 2022-12-24 10:30:34 +00:00
Mohammad Rahmani
4a6e3d4281 Convert Rendertiddler(s) Command in Sever TiddlyWIki.info (#7124)
* convert rendertiddler(s) in sever .info

* Conversion of rendertiddler(s) in tiddlywiki.info for editions/empty

Conversion of rendertiddler(s) in tiddlywiki.info for editions/empty

* Conversion of rendertiddler(s) in tiddlywiki.info for editions\server-external-js

Conversion of rendertiddler(s) in tiddlywiki.info for editions\server-external-js

* Convert Rendertiddler(s) in tiddlywiki.info in tw5.com, tw5.com-doc

Convert Rendertiddler(s) in tiddlywiki.info in tw5.com, tw5.com-doc

* Convert rendertiddler(s) editions\twitter-archivist\tiddlywiki.info

Convert rendertiddler(s) editions\twitter-archivist\tiddlywiki.info

* Convert rendertiddler(s) in editions\katexdemo\tiddlywiki.info

Convert rendertiddler(s) in editions\katexdemo\tiddlywiki.info

* Correct for extra space in editions\katexdemo\tiddlywiki.info

* Convert rendertiddler(s) editions\highlightdemo\tiddlywiki.info

* Convert rendertiddler(s) in editions\tw.org\tiddlywiki.info

Convert rendertiddler(s) in editions\tw.org\tiddlywiki.info
2022-12-23 22:42:25 +00:00
jeremy@jermolene.com
76e3a341da Merge branch 'master' into parameterised-transclusions 2022-12-21 17:26:10 +00:00
Wincent Balin
d217826375 Fix miscellaneous docs typos (#7143) 2022-12-21 10:07:14 +00:00
jeremy@jermolene.com
a5afed9384 Fix crash with illegal tag names for element widget
Fixes #7122
2022-12-20 17:31:51 +00:00
jeremy@jermolene.com
b37a356b5e Crash with <$genesis $type="" />
Fixes #7140
2022-12-20 16:45:29 +00:00
jeremy@jermolene.com
55d9a5e16d Preparing for v5.2.6 2022-12-19 18:52:03 +00:00
jeremy@jermolene.com
3bab996acd Version number update for 5.2.5 2022-12-19 18:47:55 +00:00
jeremy@jermolene.com
7e8380a8df Update readme.tid for github 2022-12-19 18:47:05 +00:00
jeremy@jermolene.com
44de7918ab Preparing for release of v5.2.5 2022-12-19 18:46:10 +00:00
jeremy@jermolene.com
5ee6af0632 Merge branch 'tiddlywiki-com' 2022-12-19 18:41:28 +00:00
jeremy@jermolene.com
ccf444c834 Release note updates 2022-12-19 17:25:52 +00:00
Wincent Balin
ecaa288fc5 Docs typo (#7137) 2022-12-19 15:49:05 +00:00
jeremy@jermolene.com
ceb6999dd6 Update release note 2022-12-19 08:56:18 +00:00
jeremy@jermolene.com
e51dd406b1 Revert global CSS changes from v5.2.4
Changes to style definitions for unclassed elements are being reverted because of backwards compatibility issues in the field. See #7126.
2022-12-19 08:46:26 +00:00
Wincent Balin
6ea61ac94f Signing the CLA (#7134) 2022-12-19 08:18:02 +00:00
Joe Bordes
caf01f10d6 i18n(ES) update with latest changes in master (#7127) 2022-12-17 14:00:57 +00:00
Mario Pietsch
1bd7924e1b Docs: "Saving with the HTML5 saver" improvements (#7109)
* "Saving with the HTML5 saver" improvements

* fix typos add platform tags

* reset modified date and fix minor typos
2022-12-17 08:22:27 +00:00
jeremy@jermolene.com
25b8f26073 Banner for v5.2.5
Daria has kindly reworked their v5.2.4 artwork for v5.2.5.
2022-12-16 17:41:59 +00:00
jeremy@jermolene.com
9160d81cc6 BibTex plugin: Fix obsolete comments 2022-12-16 17:41:05 +00:00
jeremy@jermolene.com
34bd0f0ae5 Merge branch 'master' into parameterised-transclusions 2022-12-13 17:31:51 +00:00
jeremy@jermolene.com
0b1a4f3a4d Fix release note typo 2022-12-13 17:30:52 +00:00
jeremy@jermolene.com
8d48964aca Preparing for v5.2.5 2022-12-13 16:42:40 +00:00
jeremy@jermolene.com
6cd2fc029d Version number update for 5.2.4 2022-12-13 16:35:26 +00:00
jeremy@jermolene.com
6235f29749 Preparing for release of v5.2.4 2022-12-13 16:34:14 +00:00
jeremy@jermolene.com
6385534638 Release note tweaks 2022-12-13 16:26:09 +00:00
jeremy@jermolene.com
ba3cba6170 Merge branch 'tiddlywiki-com' 2022-12-13 16:20:11 +00:00
Simon Baird
34c9e83bec Remove "Saving" tag from "Saving on TiddlySpot" (#7115)
The content is still there since there are links to it from various
places, but let's not have its card appear in the list of savers
shown in the "Saving" tiddler any more.

Removing just the "Saving" tag would have been sufficient, but I
think it makes sense to remove the other tags as well.
2022-12-13 12:26:14 +00:00
jeremy@jermolene.com
34ce7cacc3 Merge branch 'master' into parameterised-transclusions 2022-12-13 11:08:54 +00:00
jeremy@jermolene.com
ed9cc84fb2 Remove erroneous references to en-GB language plugin
en-GB is built into the core, and so does not have a separate language plugin
2022-12-13 09:36:10 +00:00
jeremy@jermolene.com
22bc826247 Merge branch 'tiddlywiki-com' 2022-12-12 08:51:52 +00:00
jeremy@jermolene.com
6e6efcafc9 Reword Grok TiddlyWiki card 2022-12-12 08:45:38 +00:00
jeremy@jermolene.com
3c81558d74 Add introduction message to "Saving" tiddler
Fixes #7095
2022-12-10 14:23:28 +00:00
Mario Pietsch
cc47bb0330 Improve readability for: Using the external JavaScript template (#7097)
* Improve readability for: Using the external JavaScript template

* remove the extra button
2022-12-10 14:10:54 +00:00
Jeremy Ruston
0ce5788747 Fixes for JSON operators (#7105) 2022-12-09 18:31:23 +00:00
jeremy@jermolene.com
1118de319e Update prerelease warning 2022-12-09 10:43:13 +00:00
jeremy@jermolene.com
c2d82ccb32 Update release note 2022-12-09 10:17:31 +00:00
Maurycy Zarzycki
a899aac92c Change first letter in two plugin-related buttons to be uppercase to be consistent with the button that appears earlier (#7103) 2022-12-08 13:48:45 +00:00
jeremy@jermolene.com
2bf9e97eb5 Merge branch 'master' into parameterised-transclusions 2022-12-08 08:29:56 +00:00
jeremy@jermolene.com
bef11fe6a2 Allow overriding the coreURL for the external JS builds
Fixes #7096
2022-12-07 22:02:58 +00:00
Mario Pietsch
17a1ae23eb Fix truncated search results on small screens (#7099) 2022-12-07 17:14:12 +00:00
jeremy@jermolene.com
9f867ad51e Dynannotate: Fix undefined class 2022-12-07 17:10:45 +00:00
jeremy@jermolene.com
be65819441 Docs note about nested macro definitions 2022-12-07 10:01:58 +00:00
jeremy@jermolene.com
5bb7168c02 Merge branch 'master' into parameterised-transclusions 2022-12-07 10:01:38 +00:00
jeremy@jermolene.com
28c1e6bfc3 Docs update for nested macro definitions
Suggested by @kookma in bcb3b06d60 (commitcomment-91922651) and bcb3b06d60 (commitcomment-91922974)
2022-12-07 09:43:39 +00:00
Mario Pietsch
2db886793e Fix table overflow for small screens (#7010)
* fix table overflow for small screens

* add PRE word-break for Chrome and Safari on mobile

* remove comment, since it looks better for all browsers now

* add 1 space to trigger the new automatic build

* change small screen settings only for tiddler frame
2022-12-06 16:36:26 +00:00
jeremy@jermolene.com
8d050e0e69 Merge branch 'tiddlywiki-com' 2022-12-06 15:36:04 +00:00
jeremy@jermolene.com
e77006de63 Update links to Open Collective 2022-12-05 22:44:35 +00:00
FlashSystems
80442b7f7f Fix for bug #7054 (#7092)
* Fix Bug #7054: Reuse of $:/core/ui/EditTemplate/fields broken

This fixes Bug #7054 by creating a new variable
`safeNewFieldValueTiddlerPrefix` that is always set to a valid,
temporary prefix. This variable is used within `$action-deletetiddler`.
If the passed `newFieldValueTiddlerPrefix` variable is empty a new
prefix will be generated by the same logic that creates the original
`newFieldValueTiddlerPrefix` variable.

To be even more defensive, the prefix-filter was prepended with another
prefix filter that limits matches to `$:/temp/NewFieldValue`. This
prevents a bogus but non empty value in `newFieldValueTiddlerPrefix`
to delete arbitrary tiddlers.

* Add a default for `newFieldValueTiddlerPrefix`

This fixes a problem that was identified while fixing bug #7054. If the
tiddler `$:/core/ui/EditTemplate/fields` is transcluded directly and
`newFieldValueTiddlerPrefix` is not set, it will be generated. This
makes sure that this value is defined. It can not be redefined
unconditionally because if this tiddler is transcluded from
`EditTemplate.tid` these two tiddlers must agree on the same prefix
because the clean-up is duplicated between `EditTemplate.tid` and
`fields.tid`.

This would make `safeNewFieldValueTiddlerPrefix` obsolete, but I leave
it in there to make the macros safe and prevent any problems if the
`newFieldValueTiddlerPrefix` is unset by a later change.
2022-12-05 22:05:20 +00:00
Mario Pietsch
10bb3ba09d German Translation Update (#7093) 2022-12-05 22:04:52 +00:00
jeremy@jermolene.com
31f4c1f6af Merge branch 'master' into parameterised-transclusions 2022-12-05 17:21:33 +00:00
Maurycy Zarzycki
58013ba435 Another bundle of Polish translations (#7090)
* add Polish transaltions introduced in 272ba6a4b7

* Polish translations to changes introduced in a93a499684 and 0db987da60
2022-12-05 16:30:40 +00:00
Bram Chen
ee7bde58a2 Add chinese translations for the new layout switcher page control button (#7089) 2022-12-05 07:38:59 +00:00
Télumire
229159fea7 Correction of zindex for tc-card-ribbon-wrapper (new ribbon) (#7088) 2022-12-04 23:29:36 +00:00
Télumire
a311e5ebac correction of the z-index for the card ribbon wrapper (#7087) 2022-12-04 22:09:06 +00:00
jeremy@jermolene.com
9ff479ce87 Merge branch 'tiddlywiki-com' 2022-12-04 21:23:08 +00:00
jeremy@jermolene.com
77053cfe13 Update release note 2022-12-04 21:20:14 +00:00
jeremy@jermolene.com
1bd58db944 Add missing docs for commands command 2022-12-04 21:14:30 +00:00
jeremy@jermolene.com
4be0c17dd0 Fix HelloThere thumbnail for latest version to work in prerelease 2022-12-04 21:00:31 +00:00
jeremy@jermolene.com
595da5f9f6 Page control button for page layout should be hidden by default 2022-12-04 20:01:17 +00:00
jeremy@jermolene.com
ff674b9117 Merge branch 'tiddlywiki-com' 2022-12-04 19:57:22 +00:00
jeremy@jermolene.com
38dce175d6 Add Funding and Marketplace material, and refresh HelloThere 2022-12-04 17:58:16 +00:00
jeremy@jermolene.com
1ab9f457b4 Fix description of emergency tiddler expert
Confusing that it was using the same wording as the HTML5 fallback saver
2022-12-04 17:57:18 +00:00
jeremy@jermolene.com
1eddb52de5 Remove obsolete HelloThere badges 2022-12-04 17:55:52 +00:00
jeremy@jermolene.com
52fd6ce9c2 Remove creator field from docs tiddlers
By convention we don't attribute authors to tiddlers on tiddlywiki.com
2022-12-04 17:55:00 +00:00
jeremy@jermolene.com
62308792c8 Layout switcher page control button should be hidden by default 2022-12-04 16:26:52 +00:00
lin onetwo
272ba6a4b7 Add layout switcher page control button (#7076)
* feat: add layout switcher page control button

* feat: use icon from https://morosanuae.github.io/tw-icons/

$:/images/tabler-icons/layout

* fix: trigger switcher

* feat: beautify button icon

* fix: caption

* feat: group palette theme and layout buttons together

* fix: review

* fix: style issue
2022-12-04 16:25:13 +00:00
jeremy@jermolene.com
90449c9458 Fix modified data for "Installing TiddlyWiki on Node.js" 2022-12-04 16:06:37 +00:00
Bram Chen
5b8f36a594 Add chinese help texts for commands command (#7085) 2022-12-04 12:44:31 +00:00
jeremy@jermolene.com
acc7224758 Ensure unfold indicator is always visible
Fixes #7084
2022-12-04 11:19:54 +00:00
jeremy@jermolene.com
0db987da60 Minor tweaks for #7073 2022-12-04 11:03:51 +00:00
Carlo Colombo
a93a499684 Add commands command to run commands returned from a filter (#7073) 2022-12-04 10:59:59 +00:00
jeremy@jermolene.com
2c33502a4a Exclude drafts from the advanced search filter dropdown
Fixes #7083
2022-12-03 17:53:42 +00:00
lin onetwo
451a3454b5 Optionally allow click outside to close modals (#7072)
* feat: option to allow click on modalBackdrop to close modal

* feat: allow switcher modals closable

* feat: allow use caption field as modal title

* refactor: make maskClosable a variable

* fix: use "true"

* fix: code style

* docs: add description about maskClosable

* fix: convention is to have double quotes for strings in the TW core

* refactor: using a "mask-closable" field on the modal tiddlers instead of as a message parameter

* docs: move to modal tid

* Update WidgetMessage_ tm-modal.tid
2022-12-03 17:26:44 +00:00
Mohammad Rahmani
45a7eb1c03 Add new focus attribute to $select widget (#7081)
* Add focus attribute to $select widget

This address https://github.com/Jermolene/TiddlyWiki5/issues/7070

* Update SelectWidget.tid

Update the documentation for $select widget to include the new attribute: focus
2022-12-03 08:22:21 +00:00
jeremy@jermolene.com
d03da6085b Merge branch 'tiddlywiki-com' 2022-12-02 09:58:32 +00:00
Carlo Colombo
fa4dc2a4e9 Signing the CLA (#7074) 2022-12-01 21:26:08 +00:00
FlashSystems
3918e59cc1 Fixed PR to fix popup position if popup is triggered from within an offsetParent element (#7013)
* Fix popup location for tables

This commit introduces the `popupAbsCoords` option to the $button widget
and implements an absolut coordinate format.

Coordinates for popups are stored in the format `(x,y,w,h)`. These
coordinates are relative to the offset parent of the element that
defines the popup.

This commits adds a second format `@(x,y,w,h)`. Coordinates specified in
this format a relative to the pages root element.

The `popupAbsCoords` option of the $button widget enables the use of
this coordinates.

* Unify the declaration of the RegEx for parsing the popup-position

The regular expression was declared in three locations with the same
content. This commit supplies a new function `parseCoordinates` in
`popup.js`. This function returns the parsed coordinates and understands
the classic/absolute coordinates.

This function is used in `reveal.js` and `action-popup.js` to parse the
coordinates.

* Add documentation for coordinate systems

* Consolidate creating coordinate strings

The Popup object now contains a `buildCoordinates` method that can be
used to build coordinate strings. It takes an "enum" for the coordinate-
system to use. This makes everything easily extensible and prevents the
use of magic values.

* Add tests for `parseCoordinates` and `buildCoordinates`

* Add `tv-popup-abs-coords` to `collectDOMVariables`

This will make the absolute coordinates available for the
`DraggableWidget` and the `EventCatcherWidget`.

* Add documentation for the `tv-popup-abs-coords`

... to the `DraggableWidget` and the `EventCatcherWidget`.

* Fix crash when generating a static version of the TW

The Popup class is not initialized in `startup.js` if `$tw.browser` is
not true. After having consolidated the facilities for parsing
coordinate strings into `popup.js` this breaks because the static build
needs to parse coordinate stings even if no Popup module is initialized.
This commit solves this problem by making `readPopupState`,
`parseCoordinates` and `buildCoordinates` static methods of `popup.js`.
It also adds a comment to these functions to show that these can be called
safely even if the Popup-Class is not initialized.
2022-12-01 21:16:44 +00:00
lin onetwo
f7ccba4c25 Add "code" and "key" to propogateKeydownEvent's cloneEvent (#7071)
* feat: add key

* feat: add code
2022-11-30 10:17:10 +00:00
Mario Pietsch
319d7fbe9c Add hidden option to make "More" sidebar tabs be horizontal (#7063)
* make more sidebar tabs configurable vertical or horizontal

* more sidebar tabs orientation German translation

* remove language specific texts for more-horizontal setting

* Add More -> tabs horizontal setting to Hidden Settings
2022-11-30 09:57:14 +00:00
Guang Li
67c8f29160 more localized translation (#7069) 2022-11-29 22:57:13 +00:00
Cameron Fischer
856aca2f92 Linked-List refactor (#6056)
* Added failing linked-list test for #7059

* Fixed linked-list remove bug #7059

* Added failing linked-list test for #7059

* Switched LinkedList to use Map

* Removed this.last from LinkedList

* Removed this.first from LinkedList

* Switching to deleting old LinkedList entries

* LinkedList rewritten to be better

* Using null as LinkList ends to reduce hashing

* Using adhoc map... cause it's better than ECMA6 Map

* compliance with TiddlyWiki coding conventions

* Made link-list tests confirm the prev links

Co-authored-by: btheado <brian.theado@gmail.com>
2022-11-27 17:48:08 +00:00
jeremy@jermolene.com
b802b0cb09 Merge branch 'master' into parameterised-transclusions 2022-11-27 13:56:33 +00:00
jeremy@jermolene.com
34a20463c7 Update release note 2022-11-27 13:55:22 +00:00
jeremy@jermolene.com
56f13133d8 Missed off preparation for v5.2.4 2022-11-27 13:35:56 +00:00
jeremy@jermolene.com
b5e4b21707 Merge branch 'master' into parameterised-transclusions 2022-11-27 12:40:51 +00:00
Marxsal
684673cbff TiddlyBucket - Save to AWS or Google Storage (#7066) 2022-11-27 08:48:41 +00:00
btheado
bea1a6b14f Fix issue with linked list remove (#7065)
* Added failing linked-list test for #7059

* Fixed linked-list remove bug #7059
2022-11-26 15:05:10 +00:00
jeremy@jermolene.com
32a033bb50 Fix advanced search keyboard shortcut navigation
Fixes #7008
2022-11-26 11:22:24 +00:00
Mario Pietsch
97f7db169a Allow the big download button to be defined using the colour palette values (#7064) 2022-11-26 11:15:47 +00:00
jeremy@jermolene.com
850a4dd351 Correct colour for Mastodon icon 2022-11-25 17:59:11 +00:00
jeremy@jermolene.com
d707e6f825 Add Mastodon icon 2022-11-25 15:28:12 +00:00
jeremy@jermolene.com
5c378855ab Merge branch 'tiddlywiki-com' 2022-11-25 15:27:42 +00:00
jeremy@jermolene.com
ebc1f7e4ce Add link to official Mastodon account 2022-11-25 15:14:15 +00:00
Maurycy Zarzycki
2fcbf3b521 Update documentation to fix a mistake with format used by created and modified (#7060) 2022-11-24 18:43:51 +00:00
jeremy@jermolene.com
00927d2e13 Add parsermode pragma
Fixes #7058
2022-11-23 22:35:32 +00:00
Mario Pietsch
882e040e62 Refactor import preview to not use a hidden table row (#7057) 2022-11-23 21:53:21 +00:00
jeremy@jermolene.com
026739e2e0 Revert "Revert "add table utility classes and some docs how to use them. fix problem with control-panel basics tab shown in story river (#7039)""
See https://github.com/Jermolene/TiddlyWiki5/pull/7057#issue-1461608206

This reverts commit fba9efcf4a.
2022-11-23 21:52:36 +00:00
jeremy@jermolene.com
52592a4dbc Add support for named end markers for procedures, functions and widgets 2022-11-23 16:30:20 +00:00
jeremy@jermolene.com
b78f8769a9 Docs: move tiddlers to correct directory 2022-11-23 16:27:39 +00:00
jeremy@jermolene.com
39d88bf156 Docs: Update \define pragma to cover named ends 2022-11-23 09:02:39 +00:00
jeremy@jermolene.com
778b8dec7f Merge branch 'master' into parameterised-transclusions 2022-11-23 09:01:42 +00:00
jeremy@jermolene.com
fba9efcf4a Revert "add table utility classes and some docs how to use them. fix problem with control-panel basics tab shown in story river (#7039)"
See #7056

This reverts commit b8a30091ee.
2022-11-23 08:28:06 +00:00
jeremy@jermolene.com
acfea3a212 New release banner credits 2022-11-22 21:10:36 +00:00
jeremy@jermolene.com
0dc30086e9 Update new release banner 2022-11-22 21:08:41 +00:00
Jeremy Ruston
cb0d0cfa6d Support nested macro definitions (#7004)
* First commit

* Switched to \end <name> instead of all those repeated backslashes

Thanks @kookma. See https://github.com/Jermolene/TiddlyWiki5/pull/7004#issuecomment-1286429236

* Docs update
2022-11-22 17:10:37 +00:00
jeremy@jermolene.com
45958db074 Merge branch 'master' into parameterised-transclusions 2022-11-22 16:29:45 +00:00
Maurycy Zarzycki
d32d559f93 Add Timestamp to DateFormat (#7043)
* add Timestamp to DateFormat

* improve TIMESTAMP documentation
2022-11-21 16:13:34 +00:00
Cameron Fischer
8ead7e0624 Jasmine command (#6944) 2022-11-20 17:54:18 +00:00
Maurycy Zarzycki
4f7b10e055 CSV parser improvements (#7042) 2022-11-20 17:51:01 +00:00
Mario Pietsch
b8a30091ee add table utility classes and some docs how to use them. fix problem with control-panel basics tab shown in story river (#7039) 2022-11-20 17:48:10 +00:00
Maurycy Zarzycki
6955f14c3c add a hidden config to disable Syncer logging to the console (#7049) 2022-11-20 17:26:14 +00:00
Maurycy Zarzycki
994c5a2970 fix incorrect quote characters used in a code example (#7035) 2022-11-19 22:23:36 +00:00
Maurycy Zarzycki
ea150029f5 add a lot of small language tweaks and fixes to Polish translation (#7045) 2022-11-19 22:13:35 +00:00
Talha Mansoor
c663d2ba00 Sort completed tasks by 'modified' instead of 'created' field (#7047) 2022-11-19 22:13:02 +00:00
Talha Mansoor
39e8c8b125 Fix modified timestamp (#7046) 2022-11-19 22:11:46 +00:00
jeremy@jermolene.com
3713ee4fa9 Update release note 2022-11-16 17:27:10 +00:00
jeremy@jermolene.com
846edbfaa4 Merge branch 'master' into parameterised-transclusions 2022-11-16 08:27:00 +00:00
jeremy@jermolene.com
a99f934371 Fix build-site.sh hang with #6588 2022-11-16 08:26:35 +00:00
jeremy@jermolene.com
63803fd99d Merge branch 'tiddlywiki-com' 2022-11-15 19:50:44 +00:00
jeremy@jermolene.com
79ec96cb59 Remove old link 2022-11-15 17:58:50 +00:00
jeremy@jermolene.com
419b3b3534 Twitter Archivist: Update todo list 2022-11-15 17:12:54 +00:00
jeremy@jermolene.com
4e3566745e Merge branch 'master' into parameterised-transclusions 2022-11-15 11:46:04 +00:00
jeremy@jermolene.com
368963def0 Revert "Allow $:/core/ui/ControlPanel/Basics to work in the story river + some docs about utility classes (#6912)"
This reverts commit 10cb585dae.
2022-11-15 11:41:55 +00:00
jeremy@jermolene.com
830ffe64de Twitter Archivist: Add note about browser import only working on Chrome 2022-11-15 11:13:02 +00:00
jeremy@jermolene.com
70930e16b2 Merge branch 'master' into parameterised-transclusions 2022-11-15 10:39:29 +00:00
jeremy@jermolene.com
1483195cd5 Merge branch 'tiddlywiki-com' 2022-11-15 10:39:05 +00:00
Mario Pietsch
9b9ff1e843 Extend pluginlibrary edition with a minimal test server (#6588)
* pluginlibrary - minimal test server

* changes suggested by Jeremy

* use tmp instead of the files directory

* new tmp-route

* rename edition to test-pluginlibrary

* fix .gitignore

* remove StoryList tiddler

* improve GettingStarted text

* rename edtion test-pluginlibrary back to pluginlibrary

* remove 2 tiddlers that shouldn't be there
2022-11-15 08:18:58 +00:00
Mario Pietsch
ea3503e30c Allow users to overwrite TOC default icons (#6913)
* Allow users to overwrite TOC default icons

* Fix docs as requested
2022-11-14 22:04:30 +00:00
Mario Pietsch
5e116d2a57 Add data-tags and data-tiddler-title attributes to preview area (#6939) 2022-11-14 17:48:00 +00:00
Mario Pietsch
aa5183a08e Add indentation to $:/TagManager (#6923) 2022-11-14 17:42:17 +00:00
Mario Pietsch
10cb585dae Allow $:/core/ui/ControlPanel/Basics to work in the story river + some docs about utility classes (#6912)
* allow $:/core/ui/ControlPanel/Basics to work in the story river + some docs about utility classes

* apply changes suggested by twMat

* fix some typos and change the base padding for tables

* fix a typo and remove whitespace

* remove TODO in base CSS
2022-11-14 17:36:01 +00:00
Mario Pietsch
029203dbc0 Move the version number to the top of the upgrader (#6881)
* Move the version number to the top of the upgrader

* change header to be clearer

* Move Upgrade Wizard to the top
2022-11-14 17:31:30 +00:00
Mario Pietsch
832868ecae Allow user defined setting for retain-story-order button in ControlPanel (#6863)
* allow user defined setting for retain-story-order button in ControlPanel

* improve hidden setting wording

* adjust all languages with new "ControlPanel DefaultTiddlers BottomHint

* fix typos and snippet filename
2022-11-14 17:30:13 +00:00
Mario Pietsch
7f48b6c6ce Make timeline macro more customisable (#5947)
* make the timeline-macro more customizable

* changed comment as requested
2022-11-14 17:11:26 +00:00
TonyM
b263ee3c80 Update SystemTag_ $__tags_Filter.tid (#7019)
said seach not search in two places description and body
2022-11-14 17:05:16 +00:00
Jeremy Ruston
b097d2ec48 Fix typo in SystemTag_ $__tags_ClassFilters_TiddlerTemplate.tid
Thanks @twMat
2022-11-14 16:58:50 +00:00
Jeremy Ruston
ef779c11e8 Fix Node.js installation instructions for Arch Linux
Fixes #7027
2022-11-14 11:52:38 +00:00
jeremy@jermolene.com
06520c8994 Wikify hashtags 2022-11-14 08:51:18 +00:00
jeremy@jermolene.com
710e51fe04 Twitter Archivist: Fix off by one error in af6c017086 2022-11-13 19:11:56 +00:00
jeremy@jermolene.com
af6c017086 Twitter Archivist: Expand t.co URLs in tweets 2022-11-13 19:05:09 +00:00
jeremy@jermolene.com
34353f4065 Twitter Archivist: Fix display of tweet author
Also:

* Cleaner user interface
* Added data model spec
* Added todo list
* Icons for archives
2022-11-13 11:18:47 +00:00
Jeremy Ruston
fedc23d73c Introduce Twitter Archivist Plugin 2022-11-12 17:09:31 +00:00
jeremy@jermolene.com
344110e289 Rearrange ordering of MP4 extension so that it defaults to video not audio
Previously using the --load command to import an MP4 file would cause it to be recognised as autio/mp4 instead of video/mp4
2022-11-09 13:56:28 +00:00
Xavier Cazin
72f06581b6 More consistency in fr-FR captions for cascade examples in ControlPanel (#7025) 2022-11-08 18:09:42 +00:00
tw-FRed
ae12e8fb69 Help Plugin: Update links to community resources (#7023)
* Promote Talk TiddlyWiki
* Change link to GG to https
2022-11-05 17:44:41 +00:00
jeremy@jermolene.com
149d6c2d73 Docs: clarify function operator invocation
See discussion at https://github.com/Jermolene/TiddlyWiki5/issues/6991#issuecomment-1301703599
2022-11-05 10:13:35 +00:00
jeremy@jermolene.com
e8148ff978 Missed off 965bd090a9
Thanks @pmario @saqimtiaz
2022-11-05 09:41:43 +00:00
jeremy@jermolene.com
965bd090a9 list-links macro: add "field" parameter
See https://talk.tiddlywiki.org/t/choosing-what-field-to-show-with-list-links/5039?u=jeremyruston
2022-11-05 09:10:31 +00:00
Cameron Fischer
3be9b13814 Fix for #4767: lazy-loading deletes tiddler bodies (#7014) 2022-11-02 17:26:08 +00:00
jeremy@jermolene.com
478b585a8c Merge branch 'master' into parameterised-transclusions 2022-11-02 08:21:17 +00:00
jeremy@jermolene.com
62f26d6630 Improve genesis widget examples 2022-11-01 10:07:54 +00:00
jeremy@jermolene.com
8fe2f6086d Update release notes credits 2022-11-01 09:48:08 +00:00
jeremy@jermolene.com
30af537b91 Update release note 2022-11-01 09:45:08 +00:00
jeremy@jermolene.com
f54ecc23f3 Fix wikification of tiddler titles in advanced search filter dropdown
Closes #7017

Thanks @ericshulman
2022-10-31 12:03:47 +00:00
jeremy@jermolene.com
9029588b2c Merge branch 'master' into parameterised-transclusions 2022-10-30 21:21:48 +00:00
jeremy@jermolene.com
67dd3f06bf Merge branch 'tiddlywiki-com' 2022-10-30 21:21:40 +00:00
jeremy@jermolene.com
38ac1e4bfd Merge branch 'master' into parameterised-transclusions 2022-10-30 21:21:21 +00:00
jeremy@jermolene.com
e7caa0c739 Docs typo
Thanks @twMat
2022-10-30 21:17:55 +00:00
btheado
6af3eb539b Adds a javascript widget tutorial to the dev tiddlywiki edition (#7016)
* Initial widget tutorials extracted from https://btheado.github.io/tw-widget-tutorial/

* Fixes for refresh behavior change
2022-10-30 16:10:12 +00:00
Saq Imtiaz
3f55f827a6 Extend page template with filter assigned classes (#6976)
* Extend page template with filter assigned classes

* feat: added dynamic class support for tiddler templates and documentation
2022-10-28 12:58:58 +01:00
jeremy@jermolene.com
9f42007899 Filter run prefixes should use widget.makeFakeWidgetWithVariables 2022-10-25 14:13:38 +01:00
jeremy@jermolene.com
b9d27e9fd5 Revert "Fix popup position if popup is triggered from within an offsetParent element (#6887)"
This reverts commit 5b85786f73.
2022-10-22 13:22:15 +01:00
FlashSystems
5b85786f73 Fix popup position if popup is triggered from within an offsetParent element (#6887)
* Fix popup location for tables

This commit introduces the `popupAbsCoords` option to the $button widget
and implements an absolut coordinate format.

Coordinates for popups are stored in the format `(x,y,w,h)`. These
coordinates are relative to the offset parent of the element that
defines the popup.

This commits adds a second format `@(x,y,w,h)`. Coordinates specified in
this format a relative to the pages root element.

The `popupAbsCoords` option of the $button widget enables the use of
this coordinates.

* Unify the declaration of the RegEx for parsing the popup-position

The regular expression was declared in three locations with the same
content. This commit supplies a new function `parseCoordinates` in
`popup.js`. This function returns the parsed coordinates and understands
the classic/absolute coordinates.

This function is used in `reveal.js` and `action-popup.js` to parse the
coordinates.

* Add documentation for coordinate systems

* Consolidate creating coordinate strings

The Popup object now contains a `buildCoordinates` method that can be
used to build coordinate strings. It takes an "enum" for the coordinate-
system to use. This makes everything easily extensible and prevents the
use of magic values.

* Add tests for `parseCoordinates` and `buildCoordinates`

* Add `tv-popup-abs-coords` to `collectDOMVariables`

This will make the absolute coordinates available for the
`DraggableWidget` and the `EventCatcherWidget`.

* Add documentation for the `tv-popup-abs-coords`

... to the `DraggableWidget` and the `EventCatcherWidget`.
2022-10-22 13:13:39 +01:00
jeremy@jermolene.com
b426724f35 Fix macrocall refresh issue
It turns out that this.transcludeTitle is always truthy, even if we are transcluding a variable

Fixes #7001
2022-10-20 15:08:05 +01:00
jeremy@jermolene.com
ffc2594fef Add parenthesis to the visible transclusion definition
Parenthesis were made mandatory in 5194b24108

Fixes #6998
2022-10-19 15:35:43 +01:00
jeremy@jermolene.com
c171c441f5 Update release note 2022-10-19 09:42:41 +01:00
jeremy@jermolene.com
33de634606 Adjust modified times of docs tiddlers to make them easier to find 2022-10-19 09:15:38 +01:00
jeremy@jermolene.com
120b93c242 New test for undefined parameters 2022-10-19 08:37:27 +01:00
jeremy@jermolene.com
14e0a271d4 New New Release Banner 2022-10-19 08:37:04 +01:00
jeremy@jermolene.com
bc375c04b9 Temporary new release banner for v5.3.0 2022-10-19 08:14:29 +01:00
jeremy@jermolene.com
55c7eea52d Add release note etc for 5.3.0 2022-10-18 17:40:13 +01:00
jeremy@jermolene.com
45f1cf6cff Attempt to build this branch with CI 2022-10-18 17:27:47 +01:00
jeremy@jermolene.com
32710ef9e6 Merge branch 'master' into parameterised-transclusions 2022-10-18 17:23:57 +01:00
Rob Hoelz
24dbf69180 Fix [is[variable]] operator doesn't work for "fake" variables #6303 (#6996)
* Add tests for [is[variable]] and "faked" variables

See GH #6303

* Make is[variable] and variables[] operators resilient to fake widgets

Co-authored-by: jeremy@jermolene.com <jeremy@jermolene.com>
2022-10-18 17:08:04 +01:00
jeremy@jermolene.com
7b408c7adf Update release note 2022-10-17 16:50:54 +01:00
jeremy@jermolene.com
c19d6d6328 Merge branch 'tiddlywiki-com' 2022-10-17 12:22:06 +01:00
jeremy@jermolene.com
941c09fae2 ScrollableWidget example shouldn't iterate through all tiddlers 2022-10-17 12:21:34 +01:00
jeremy@jermolene.com
5194b24108 Parameter parenthesis should be mandatory in function/procedure/widget definitions
See https://github.com/Jermolene/TiddlyWiki5/pull/6666#issuecomment-1280404387
2022-10-17 08:31:07 +01:00
jeremy@jermolene.com
b531984f50 Restore "Add default settings for styled inline SPANs (#6877)"
This reverts commit 6f98edd6bd.
2022-10-16 17:28:36 +01:00
jeremy@jermolene.com
8f079e2d45 Fix handling of orderedattributes when adding classes/styles
Fixes issue referred to in https://github.com/Jermolene/TiddlyWiki5/pull/6877#issuecomment-1277590200
2022-10-16 17:27:46 +01:00
Maurycy Zarzycki
cfd894e6fb allow select widget class to update if it uses a filter and is output changes (#6987)
* allow select widget class to update if it uses a filter and the filter output changes

* rewrite code to be more idiomatic + updates local property
2022-10-15 12:26:21 +01:00
jeremy@jermolene.com
3a4589dc79 Transcluding functions: fix missing parameters passed as undefined
Thanks @btheado – see https://github.com/Jermolene/TiddlyWiki5/pull/6666#issuecomment-1276187372
2022-10-12 17:15:39 +01:00
Rob Hoelz
91327c1af0 Use deprecated macro for deprecated commands (#6973)
This just brings the documentation for these commands more inline with
other deprecations, plus offers a link to the recommended alternative
as well as the explanation for deprecation
2022-10-10 16:49:20 +01:00
jeremy@jermolene.com
76bc3a7358 Docs typo
https://github.com/Jermolene/TiddlyWiki5/pull/6666#discussion_r990811220

Thanks @btheado
2022-10-09 17:48:24 +01:00
jeremy@jermolene.com
85a203bcf2 Revert modified date of docs that have only had minor tweaks 2022-10-09 17:43:38 +01:00
jeremy@jermolene.com
c25129584c Docs updates 2022-10-09 17:34:22 +01:00
jeremy@jermolene.com
1c73460ecc Fix doc file locations 2022-10-09 13:56:36 +01:00
jeremy@jermolene.com
ef93fc29bf More docs updates 2022-10-09 13:54:33 +01:00
jeremy@jermolene.com
9d4aa47356 Clarify/simplify some tests 2022-10-09 13:54:08 +01:00
jeremy@jermolene.com
6f98edd6bd Revert "Add default settings for styled inline SPANs (#6877)" because of failed tests
This reverts commit 23e0eeb556.
2022-10-07 18:43:09 +01:00
Mario Pietsch
23e0eeb556 Add default settings for styled inline SPANs (#6877)
* add default settings for styled inline SPANs

* change color names in palettes and vanilla-base

* change parser behaviour if custom class is used

* tc-inline-style will only be set if no other custom setting is appliead

* Add tests for inline-styles

* add one more test

* remove space after if
2022-10-07 18:05:49 +01:00
Maurycy Zarzycki
f33c7e2aef Allow global keyboard shortcuts to override all other shortcuts by providing a special field (#6735)
* allow global keyboard shortcuts to override all other shortcuts by providing a special field

* rework the global shortcuts taking priority

* replace bool option with options object in KeyboardManager's keydown handler

* update keyboard shortcut documentation to add information about the new priority setting

* add support for priority global keyboard shortcuts to code mirror

* update the feature's docs to point out it was/will be introduced in 5.2.4

* rollback unnecessary change
2022-10-07 17:31:04 +01:00
jeremy@jermolene.com
12a87840fd Merge branch 'master' into parameterised-transclusions 2022-10-07 16:57:54 +01:00
jeremy@jermolene.com
fc586481a9 Merge branch 'tiddlywiki-com' 2022-10-07 16:57:34 +01:00
jeremy@jermolene.com
09179d2f62 Deprecated macro: update text 2022-10-07 16:57:19 +01:00
jeremy@jermolene.com
dcbff82460 Docs updates 2022-10-07 16:56:21 +01:00
jeremy@jermolene.com
6be996a858 Docs update 2022-10-06 21:37:14 +01:00
jeremy@jermolene.com
bf41e08c2f Revert change to setwidget docs 2022-10-06 10:30:40 +01:00
jeremy@jermolene.com
d6ff38095b Docs: Fix typo 2022-10-06 10:25:14 +01:00
Maurycy Zarzycki
3bbbe77471 Update Polish translations (#6975)
* add polish translations to changes introduced in two commits:

 * ca762ab7a6
 * a453121e96

* add polish translations to changes introduced in d7b9e6fb02

* add polish translations to changes introduced in 0b1fc8e574
2022-10-05 15:40:23 +01:00
Maurycy Zarzycki
5657dfec0e Add VScode user settings directory to git ignore (#6974) 2022-10-05 14:51:11 +01:00
jeremy@jermolene.com
9641345b92 Docs updates 2022-10-03 14:40:27 +01:00
jeremy@jermolene.com
93100a1c8f Remove support for conditional definitions
It was introduced for use cases associated with the global mechanism that was dropped in e3d13696c8
2022-10-03 14:39:45 +01:00
Bram Chen
31ab6dce77 Update chinese language files (#6972)
* Revise the footer and subtitle texts in Fields.multids
2022-10-03 09:45:30 +01:00
jeremy@jermolene.com
4007610d52 Prefer "modal" over "wizard" in the core
See https://github.com/Jermolene/TiddlyWiki5/discussions/6965#discussioncomment-3754315
2022-10-02 18:59:05 +01:00
jeremy@jermolene.com
fb34df84ed New image shortcut should not add journal tags
Fixes #6968
2022-10-02 18:55:26 +01:00
twMat
79e2e317cf Update Styles and Classes in WikiText.tid (#6969)
Add tag to include this tiddler in the list in the tiddler

https://tiddlywiki.com/prerelease/#How%20to%20apply%20custom%20styles
2022-10-02 17:37:03 +01:00
jeremy@jermolene.com
36896c3db8 Use view template body when opening tiddler in new window 2022-10-02 17:22:48 +01:00
Joe Bordes
82de7c9b1a i18n(ES) update translation with latest master (#6971) 2022-10-02 14:19:26 +01:00
jeremy@jermolene.com
b6796863e8 Merge branch 'master' into parameterised-transclusions 2022-10-01 14:05:54 +01:00
jeremy@jermolene.com
1841b0fa4f Fix tests 2022-10-01 14:05:13 +01:00
jeremy@jermolene.com
0a309f4865 Merge branch 'master' into parameterised-transclusions 2022-10-01 10:18:34 +01:00
jeremy@jermolene.com
47f80339b2 Update transclude widget to use error widget
Missed off #6970
2022-10-01 10:15:14 +01:00
Jeremy Ruston
db6abb9703 Improve recursion detection for transclusion and filters (#6970) 2022-10-01 10:13:40 +01:00
jeremy@jermolene.com
668168dfea Some widget.js cleanups 2022-09-27 08:58:10 +01:00
jeremy@jermolene.com
502a1ab70d Merge branch 'master' into parameterised-transclusions 2022-09-27 08:56:58 +01:00
jeremy@jermolene.com
109edd1b76 Docs update 2022-09-24 15:09:12 +01:00
jeremy@jermolene.com
d950835e2f Docs clarification 2022-09-24 15:05:54 +01:00
jeremy@jermolene.com
a482f01352 Merge branch 'master' into parameterised-transclusions 2022-09-24 14:08:44 +01:00
jeremy@jermolene.com
e3d13696c8 Remove implementation of $:/globals/
Performance with this implementation is inherently poor because of the need to perform a wiki lookup for each child widget created.
2022-09-24 12:56:06 +01:00
jeremy@jermolene.com
1aba8a1f65 Slight optimisation to user defined widgets 2022-09-24 12:41:28 +01:00
jeremy@jermolene.com
fddaa9fdb1 Merge branch 'master' into parameterised-transclusions 2022-09-24 11:07:53 +01:00
jeremy@jermolene.com
0c88467111 Merge branch 'master' into parameterised-transclusions 2022-09-22 10:35:01 +01:00
jeremy@jermolene.com
c3589357bf Huge Documentation Update
Not quite finished, but definitely on the home stretch
2022-09-21 10:41:03 +01:00
jeremy@jermolene.com
0196844f17 Merge branch 'master' into parameterised-transclusions 2022-09-21 09:33:24 +01:00
jeremy@jermolene.com
6847906bea Docs typo 2022-09-16 16:33:04 +01:00
jeremy@jermolene.com
fe6186b1c1 Docs update 2022-09-16 16:07:58 +01:00
jeremy@jermolene.com
3090bb104e Fix visible transclude 2022-09-16 16:07:44 +01:00
jeremy@jermolene.com
8f9d5cabaa Missing tests for parameters widget 2022-09-16 16:07:32 +01:00
jeremy@jermolene.com
fa86631d2e Improve indentation
See https://github.com/Jermolene/TiddlyWiki5/pull/6666#discussion_r967655251
2022-09-13 16:29:09 +01:00
jeremy@jermolene.com
ef677c39c0 Docs tweaks 2022-09-11 10:57:35 +01:00
jeremy@jermolene.com
a3ba6f9370 Tests and docs for function operator 2022-09-11 10:49:02 +01:00
jeremy@jermolene.com
cc7b276787 Remove negation from function operator
This implementation was not useful.
2022-09-11 10:48:37 +01:00
jeremy@jermolene.com
68a1d61f33 Update function operator to return the input list if the function is missing 2022-09-11 10:48:05 +01:00
jeremy@jermolene.com
ecd467496d Add custom view template body for globals, and a new sidebar tab under "more"
And also a custom view template title that greys out the $:/global/ part of the title
2022-09-10 11:03:40 +01:00
jeremy@jermolene.com
580e33d30f Merge branch 'master' into parameterised-transclusions 2022-09-10 11:01:45 +01:00
jeremy@jermolene.com
977a133028 Tweak comments 2022-09-09 14:16:08 +01:00
jeremy@jermolene.com
7aba21c1be Docs updates 2022-09-09 14:15:56 +01:00
jeremy@jermolene.com
32a6b6bb90 Docs updates 2022-09-09 12:05:08 +01:00
jeremy@jermolene.com
b751f7e793 Parameters widget: protect against negative $depth 2022-09-09 12:04:50 +01:00
jeremy@jermolene.com
82b22523aa Rejig genesis widget to be easier to use 2022-09-09 10:37:39 +01:00
jeremy@jermolene.com
e3697e29bb When transcluding functions, pass an empty item list to the filter, and just return the first item 2022-09-09 10:22:06 +01:00
jeremy@jermolene.com
7b465888c8 Revert "WIP"
This reverts commit 8654dfc679.
2022-09-04 16:43:40 +01:00
jeremy@jermolene.com
8654dfc679 WIP 2022-09-04 16:41:25 +01:00
jeremy@jermolene.com
5c860ed39b Fix error in 25312b3e32 2022-09-04 16:26:47 +01:00
jeremy@jermolene.com
25312b3e32 Refactor filter recursion detection to avoid an unneeded wrapper function 2022-09-04 16:23:49 +01:00
jeremy@jermolene.com
11e0c66a4c Transcluded functions should operate on the entire store 2022-09-03 20:11:45 +01:00
jeremy@jermolene.com
a439cb58be Fix caching of parse variables/macros/procedures 2022-09-03 20:11:23 +01:00
jeremy@jermolene.com
966707ea1c More comments 2022-09-03 16:57:38 +01:00
jeremy@jermolene.com
1b08cd40bf Coding style tweak 2022-09-03 16:36:36 +01:00
jeremy@jermolene.com
00b6645c94 Disable overriding core widgets in safe mode 2022-09-03 12:58:10 +01:00
jeremy@jermolene.com
f6ee0cdf4c Add test to show that global widgets need not use the _parameters field 2022-09-03 12:57:45 +01:00
jeremy@jermolene.com
36058cba89 Merge branch 'master' into parameterised-transclusions 2022-09-03 10:55:29 +01:00
jeremy@jermolene.com
389330436d Revert changes to parse tree preview
This implementation requires #6666
2022-09-03 10:52:34 +01:00
jeremy@jermolene.com
15ea3ffa9a Remove tests related to obsolete changes to boot.js
Should have been part of 2f494ba152
2022-09-02 20:10:11 +01:00
jeremy@jermolene.com
bf4a187ee1 Fix inadvertent whitespace change 2022-09-02 20:05:24 +01:00
jeremy@jermolene.com
2f494ba152 Revert obsolete changes to boot.js 2022-09-02 20:03:33 +01:00
jeremy@jermolene.com
f0fa1af3a8 Merge branch 'master' into parameterised-transclusions 2022-09-02 18:17:32 +01:00
jeremy@jermolene.com
d852123f61 Tweak semantics of JSON operators to match #6932
This allows us to later bring in the optimisations without breaking backwards compatibility.
2022-09-02 17:14:50 +01:00
jeremy@jermolene.com
54e1083dd6 Merge branch 'master' into parameterised-transclusions 2022-09-01 09:00:57 +01:00
jeremy@jermolene.com
2b8b133d4a Merge branch 'master' into parameterised-transclusions 2022-08-17 18:11:21 +01:00
jeremy@jermolene.com
9317804464 FIx transcluding of functions
This first implementation concatenates the results of the filter (with no separator) and then wikifies the result.

The test in this commit is quite interesting...
2022-08-04 09:28:56 +01:00
jeremy@jermolene.com
6207ec4812 Merge branch 'master' into parameterised-transclusions 2022-08-02 17:49:28 +01:00
jeremy@jermolene.com
0366d6d7ba Merge branch 'master' into parameterised-transclusions 2022-07-21 10:11:23 +01:00
jeremy@jermolene.com
b1cf9f241e Merge branch 'master' into parameterised-transclusions 2022-07-21 10:10:49 +01:00
jeremy@jermolene.com
17c9bf7546 Protect against excessively recursive functions 2022-07-21 09:17:57 +01:00
jeremy@jermolene.com
745707fea3 Parameters widget: Be defensive about negative depths 2022-07-19 10:27:36 +01:00
jeremy@jermolene.com
d4e0eb193b Slot widget: be more defensive about negative depth values 2022-07-19 10:26:20 +01:00
jeremy@jermolene.com
a2182255cc Simplify the fill widget
We can rely on the default processing in the base class
2022-07-19 10:02:09 +01:00
jeremy@jermolene.com
7d90083d14 Docs: Transclude widget 2022-07-18 19:44:53 +01:00
jeremy@jermolene.com
30f7b37cba Make use of type attribute consistent 2022-07-18 19:44:37 +01:00
jeremy@jermolene.com
189fe428b7 Merge branch 'master' into parameterised-transclusions 2022-07-04 21:15:42 +01:00
jeremy@jermolene.com
945c9e619a Merge branch 'master' into parameterised-transclusions 2022-06-22 08:51:46 +01:00
jeremy@jermolene.com
6e1138e504 Merge branch 'master' into parameterised-transclusions 2022-06-17 16:40:54 +01:00
jeremy@jermolene.com
cdf5d7bd4a Fix new selection tracker to return relative coordinates 2022-06-16 17:00:20 +01:00
jeremy@jermolene.com
05d2c029a4 Merge branch 'master' into parameterised-transclusions 2022-06-14 08:34:47 +01:00
jeremy@jermolene.com
4e6efed58f Revert "Fix #6721"
This reverts commit b216579255 which was committed to the wrong branch
2022-06-14 08:34:42 +01:00
Jeremy Ruston
b216579255 Fix #6721 2022-06-13 15:43:28 +00:00
jeremy@jermolene.com
3e33d309ed Docs: format:json
Also tweak to the behaviour of format:json if the input string is not valid JSON
2022-06-11 17:29:20 +01:00
jeremy@jermolene.com
688c3bc5f6 Docs: JSON operators and tweaks to genesis widget 2022-06-11 15:22:43 +01:00
jeremy@jermolene.com
227079f3da Add format:json operator
I've been finding this useful for debugging, and it kind of goes with the JSON operators
2022-06-10 09:29:56 +01:00
jeremy@jermolene.com
79b20bdaa8 Fix up handling of slot/fill for custom widgets
Previously we were wrapping the body in an implicit `<$fill $name="ts-body">` widget
2022-06-09 18:02:47 +01:00
jeremy@jermolene.com
defe3e42e6 Adjust naming of transclusion metaparameter 2022-06-05 16:10:41 +01:00
jeremy@jermolene.com
7680280d87 Fix typo 2022-06-05 15:59:03 +01:00
jeremy@jermolene.com
542df63ccf Simplify metaparameters implementation 2022-06-03 11:21:32 +01:00
jeremy@jermolene.com
b57a6da548 Mark docs as v5.3.0 2022-06-03 09:22:19 +01:00
jeremy@jermolene.com
c42df2233a Make slot fill data available to transclusions
Allows transcluded content to dynamically process <$fill> widgets within the calling transclusion
2022-06-03 08:53:51 +01:00
jeremy@jermolene.com
139047b4f8 Typo from f513b403fe 2022-06-01 10:06:27 +01:00
jeremy@jermolene.com
f513b403fe Remove support for $:/tags/Global
It is not needed now that we have true global variables
2022-06-01 08:24:20 +01:00
jeremy@jermolene.com
613f4af20f Fix refreshing of global variables
Global variables access within attributes will automatically trigger a refresh if the attribute text changes, but that wasn't happening for transclusions.
2022-05-31 09:19:01 +01:00
jeremy@jermolene.com
006ae6e759 Refactor $parameters widget
The objective is to add a $depth attribute so that it is possible to reach up to retrieve the parameters of ancestor transclusions. However, doing so requires changing the encoding of parameter names so that it is not possible for a user parameter to clash with an attribute like $depth. So now we have to double up dollars on any attribute names seen by the parameters widget, just like with the transclude widget itself.
2022-05-31 09:03:20 +01:00
jeremy@jermolene.com
150266c731 Use underscores for new system fields for global variable tiddlers
For consistency with `_canonical_uri`; unlike many system fields, the behaviour of these fields is baked into the core JS code.
2022-05-30 18:38:25 +01:00
jeremy@jermolene.com
3af2cc2691 Introduce function operator for calling functions
Can invoke any functions, not just those start with a period. And can pass zero parameters (in contrast when invoked as a custom filter operator there's no way to omit the first parameter).
2022-05-30 18:05:54 +01:00
jeremy@jermolene.com
bd9d7c3d6a Clean up unknown filter 2022-05-30 18:04:37 +01:00
jeremy@jermolene.com
0c3f82855b Minor cleanups 2022-05-29 10:55:15 +01:00
jeremy@jermolene.com
8106ad390d Merge branch 'master' into parameterised-transclusions 2022-05-29 10:52:45 +01:00
jeremy@jermolene.com
9424e9d1f2 Cleaning up after f636349007 2022-05-28 17:32:09 +01:00
jeremy@jermolene.com
f803e00567 Test showing how to un-override a core widget 2022-05-28 16:58:20 +01:00
jeremy@jermolene.com
58f01c9a20 Fix tabs global so it doesn't crash when viewed directly 2022-05-28 13:50:08 +01:00
jeremy@jermolene.com
5d413d3e2d Change to ? for conditional definitions 2022-05-28 13:49:02 +01:00
jeremy@jermolene.com
0d78b3fa38 Convert the tabs macro into a global
So far it appears to be totally backwards compatible... In practice, I think maybe this and the conversion of the other macros should go into a separate subsequent PR.
2022-05-28 12:24:48 +01:00
jeremy@jermolene.com
f636349007 Introduce true global variables
The basic idea is that if we don't find a variable `foo` then we fallback to retrieving the value from the tiddler `$:/global/foo`, if it exists.

This allows us to replace the usual importvariables-based mechanism for global definitions, avoiding cluttering up the variable namespace with every macro.

In order to permit subprocedures to be overridden, we also introduce a mechanism for conditional definitions: preceding the word definition|procedure|function|widget with a + causes the definition only to occur if the specified variable doesn't already exist. In the next commit we'll apply this mechanism to the tabs macro
2022-05-28 12:23:50 +01:00
jeremy@jermolene.com
a2fbebf509 Add utility function for parsing macro parameter definitions 2022-05-27 18:37:42 +01:00
jeremy@jermolene.com
7fc65d0d1a Remove accidental commit 6cc99fcbe3 2022-05-27 08:36:31 +01:00
jeremy@jermolene.com
6f9f92fa69 Add support for $:/tags/Global 2022-05-26 21:11:53 +01:00
jeremy@jermolene.com
dec45f0fc3 Fix importvariables to work with setvariables as well as set (they are aliases) 2022-05-26 21:11:32 +01:00
jeremy@jermolene.com
45b7b4bc6d Make is[variable] and variables[] operators resilient to fake widgets 2022-05-26 08:23:54 +01:00
jeremy@jermolene.com
e2d45e176a Merge branch 'master' into parameterised-transclusions 2022-05-25 18:08:17 +01:00
jeremy@jermolene.com
0e08150028 Remove unneeded test tiddler 2022-05-25 18:04:32 +01:00
jeremy@jermolene.com
d59eec74a8 Merge branch 'master' into parameterised-transclusions 2022-05-25 15:23:20 +01:00
jeremy@jermolene.com
6cc99fcbe3 WIP 2022-05-25 15:15:17 +01:00
jeremy@jermolene.com
cbce4ebb7b Allow custom functions to be invoked as attributes 2022-05-23 20:18:54 +01:00
jeremy@jermolene.com
9e8d05f699 Require period prefix for custom filter operator functions
To ensure that custom filter operators cannot clash with future core operators.
2022-05-23 16:40:21 +01:00
jeremy@jermolene.com
3e09eacd20 Missed off 22e7ec2381 2022-05-23 16:32:19 +01:00
jeremy@jermolene.com
22e7ec2381 Procedures and widgets inherit whitespace trim setting from their definition 2022-05-23 15:30:33 +01:00
jeremy@jermolene.com
170c4b1799 Merge branch 'master' into parameterised-transclusions 2022-05-23 11:28:12 +01:00
jeremy@jermolene.com
d11893752c Experimental update of the parse-tree preview visualisation
An experiment to try out using the new JSON operators for rendering the JSON parse tree that we get back from the wikify widget.

As usual with these experiments, this one is going to require quite a lot more work to finish up:

* The formatting is via direct styles rather than classes
* The formatting for attributes and properties is not yet completed
* The same thing needs to also be done to the widget tree preview
2022-05-23 10:24:51 +01:00
jeremy@jermolene.com
ec1ec8ccd8 Fix invocation of JS macros 2022-05-21 16:31:34 +01:00
jeremy@jermolene.com
e50101322f Require $$ for custom widgets, and that overridden JS widgets must exist
See https://github.com/Jermolene/TiddlyWiki5/pull/6666#issuecomment-1133637763
2022-05-21 15:47:19 +01:00
jeremy@jermolene.com
bbd9e2f243 Rename <$value> widget to <$fill> 2022-05-13 09:18:25 +01:00
jeremy@jermolene.com
36cf50aa96 Use \widget for custom widget definitions, and remove need for angle brackets
Need to do some refactoring of all those isFunctionDefinition/isProcedureDefinition/isWidgetDefinition flags into a single property
2022-05-13 08:49:53 +01:00
jeremy@jermolene.com
904e30a0e2 Detect recursion by tracking widget tree depth
The old recursion marker approach was very slow, and didn't catch test cases like editions/test/tiddlers/tests/data/transclude/Recursion.tid
2022-05-12 16:26:33 +01:00
jeremy@jermolene.com
413dc86d05 Rename internal "unknown" filter operator so that users cannot invoke it 2022-05-11 14:52:25 +01:00
jeremy@jermolene.com
774459fa73 Transclude: replace paramNames/paramValues with more robust JSON payload
More details at https://github.com/Jermolene/TiddlyWiki5/pull/6666#issuecomment-1123719153
2022-05-11 13:51:11 +01:00
jeremy@jermolene.com
a827290332 Fix stringifying/parsing string arrays containing newlines
A very old bug.

Fixes the ActionListOpsWidget problem @btheado
2022-05-10 10:22:35 +01:00
jeremy@jermolene.com
0b11b499c2 Better backwards compatibility for legacy recursion marker
Fixes the problem with tag dropdowns @btheado
2022-05-10 10:21:56 +01:00
jeremy@jermolene.com
eef7d180a5 Remove obsolete code
Left over after refactoring
2022-05-10 10:21:19 +01:00
jeremy@jermolene.com
8e4c13382b Fix visible transclusion example 2022-05-10 08:10:32 +01:00
jeremy@jermolene.com
e092113f9f Switch to using \procedure to define new-style macros, and \function for custom filter operator functions
I now need to update the OP!
2022-05-09 18:00:09 +01:00
jeremy@jermolene.com
64448ae774 Make the macrocall widget delegate to the transclude widget 2022-05-08 20:48:33 +01:00
jeremy@jermolene.com
4f2f689ab9 Clarify that the recent changes allow functions to be invoked with the double bracket syntax
In other words, the transclude widget distinguishes between functions and macros and handles the parameters appropriately
2022-05-08 16:05:32 +01:00
jeremy@jermolene.com
e9630328f1 Extend transclude widget to work with old-style macros and use it for the macrocall shortcut syntax 2022-05-08 15:59:20 +01:00
jeremy@jermolene.com
9be05f6f38 Use consistent parse tree node property for params 2022-05-07 13:22:53 +01:00
jeremy@jermolene.com
2fe2d20ddf Genesis widget should pass raw attributes onto child widget...
...so that it can more efficiently handle refreshing itself.
2022-05-07 11:41:28 +01:00
jeremy@jermolene.com
c5b10d5c1d Add visible transclusions component and demo
Very useful to see transclusions explicitly

Makes a good demo of a super-complicated widget override.
2022-05-06 15:39:45 +01:00
jeremy@jermolene.com
e01dfa1507 Experimental support for custom filter operators
Just as we can define custom widgets we can also define custom parameterised filter operators
2022-05-06 15:01:17 +01:00
jeremy@jermolene.com
a9938a6c67 Improve recursion detection
While retaining backwards compatibility
2022-05-06 15:00:10 +01:00
jeremy@jermolene.com
7caaf82571 Fix variable retrieval bug with test harness 2022-05-06 10:32:20 +01:00
jeremy@jermolene.com
e5164113c4 Don't create variables with value undefined for missing parameters 2022-05-05 14:47:22 +01:00
jeremy@jermolene.com
7ead87bd29 Use enlist:raw to preserve duplicates 2022-05-05 11:34:30 +01:00
jeremy@jermolene.com
f56e316c86 Fix genesis widget example 2022-05-05 11:34:06 +01:00
jeremy@jermolene.com
ea51b8a3fe Merge branch 'master' into parameterised-transclusions 2022-05-05 08:30:48 +01:00
jeremy@jermolene.com
f307f00e32 Fixes to enable the transclude widget itself to be overridden
There are two big changes here:

Replace the previous "ts-wrapper" mechanism, which we had been using to redefine custom widgets inside their definitions to prevent recursive calls. Now we've got the genesis widget we can instead control recursion through a new "$remappable" attribute that allows the custom widget mechanism to be skipped.

We also extend the slot widget to allow a depth to be specified; it then reaches up by the indicated number of transclusion widgets to find the one from which it should retrieve the slot value.
2022-05-05 08:20:14 +01:00
jeremy@jermolene.com
35430d09ed Fix bug with empty strings ignored in $tw.utils.stringifyList/parseStringArray
I will pull this out into a separate PR. Fixing it doesn't cause problems for the core but I imagine it might cause issues for 3rd party code.
2022-05-05 08:16:20 +01:00
jeremy@jermolene.com
e99137f4cc Cache parse trees when transcluding variables 2022-05-03 17:59:45 +01:00
jeremy@jermolene.com
719a5614cb Change tiddler separator used in wikitext tests
Underscore looked ambiguous; I kept typing dashes by accident
2022-05-03 16:53:00 +01:00
jeremy@jermolene.com
56c2242e4e Introduce genesis widget for dynamically creating widgets
See the "RedefineLet" test for a contrived example of usage
2022-05-03 12:55:10 +01:00
jeremy@jermolene.com
e1df50d981 Fix parameter handling 2022-05-03 12:54:29 +01:00
jeremy@jermolene.com
c4743ebbec Fix importing of function definitions 2022-05-03 09:39:05 +01:00
jeremy@jermolene.com
8f69c27632 Reuse attribute objects when executing custom widgets 2022-05-03 09:38:41 +01:00
jeremy@jermolene.com
0163c04b7d Fix addAttributeToParseTreeNode handling of ordered attributes 2022-05-03 09:37:49 +01:00
jeremy@jermolene.com
2ea0374b55 Allow the let widget to create variables starting with $ 2022-05-03 08:44:33 +01:00
jeremy@jermolene.com
3000d3339c Remove extraneous code 2022-05-03 08:11:00 +01:00
jeremy@jermolene.com
a888cd57cd Unquoted parameters should not eat a succeeding comma
Fixes #6672
2022-05-02 13:49:41 +01:00
jeremy@jermolene.com
a10106a4a6 Fix crash when transcluding an undefined variable
Thanks @pmario

See https://github.com/Jermolene/TiddlyWiki5/pull/6666#issuecomment-1114692359
2022-05-02 11:15:18 +01:00
jeremy@jermolene.com
fbd0357cae Mustn't allow commas in parameter names 2022-05-02 11:04:32 +01:00
jeremy@jermolene.com
689a6c5b6a Rewrite some tests to use the shortcut syntaxes 2022-05-02 10:56:22 +01:00
jeremy@jermolene.com
ea7199600d Be as permissive as possible with parameter names
Previously restricted to upper and lower case, digits and dash and underscore
2022-05-02 10:56:09 +01:00
jeremy@jermolene.com
5f02cc49fd Add support for accessing function parameters as name/value pairs 2022-05-02 10:00:50 +01:00
jeremy@jermolene.com
bbc6661192 Remove erroneous "tag" property 2022-05-02 09:26:18 +01:00
jeremy@jermolene.com
8b867be8ef Add pragma rule for parameters declarations 2022-05-02 09:15:45 +01:00
jeremy@jermolene.com
99750d78b5 Allow brackets to be omitted for function definitions with no parameters 2022-04-30 13:06:28 +01:00
jeremy@jermolene.com
c9bd1b5274 Add wikitext shortcut for new-style function definitions 2022-04-30 12:44:26 +01:00
jeremy@jermolene.com
886c8620f5 Replace ubertransclude widget with transclude widget 2022-04-30 10:00:38 +01:00
jeremy@jermolene.com
aac2d6ccb0 Refactor ubertransclude functionality into transclude widget 2022-04-30 09:54:55 +01:00
jeremy@jermolene.com
c4991fff9e Refactor transclude widget before uberfying it 2022-04-30 09:30:25 +01:00
jeremy@jermolene.com
f78e1f6f7d Importvariables should skip parameters widgets 2022-04-29 22:36:07 +01:00
jeremy@jermolene.com
5bcf7b9edd Add support for shortcut syntax for positional transclusion parameters 2022-04-29 22:35:47 +01:00
jeremy@jermolene.com
89b7a3bd28 Ubertransclusion positional parameters should be based on name, not position 2022-04-29 16:28:03 +01:00
jeremy@jermolene.com
9713da5071 Add support for positional parameters 2022-04-26 21:55:43 +01:00
jeremy@jermolene.com
31c3abb7ab Add a definition for the value widget just so that it doesn't cause errors
Of course, it doesn't actually need to be a JS widget, it could be a wikitext widget...
2022-04-26 14:36:05 +01:00
jeremy@jermolene.com
a401732995 Use ts- prefix for system slot names 2022-04-26 14:27:28 +01:00
jeremy@jermolene.com
fae038dcbc Remove need to explicitly clear widget mapping variable when invoking overridden widget 2022-04-26 14:24:31 +01:00
jeremy@jermolene.com
35616a0b39 Don't worry about ordered attributes
The changes in 0bffae2108 mean that we don't need to explicitly maintain the ordered attributes
2022-04-26 14:05:56 +01:00
jeremy@jermolene.com
7299d4fd1d Merge branch 'master' into parameterised-transclusions 2022-04-26 14:03:03 +01:00
jeremy@jermolene.com
66d4b07f7e Add a test for custom action widgets 2022-04-26 13:05:44 +01:00
jeremy@jermolene.com
0e4e037bb7 Changed transclude widget in binary parser to ubertransclude 2022-04-26 13:05:31 +01:00
jeremy@jermolene.com
cd0617f033 Use the ubertransclude widget for the wikitext transclusion syntax 2022-04-26 12:45:05 +01:00
jeremy@jermolene.com
05b582a202 Fix and test missing target handling 2022-04-26 12:32:46 +01:00
jeremy@jermolene.com
54b48876f7 Fix test execution 2022-04-26 12:32:34 +01:00
jeremy@jermolene.com
21b10a225f Initial commit
Everything is draft.
2022-04-24 21:24:38 +01:00
890 changed files with 16334 additions and 15699 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,7 @@
.DS_Store
.c9/
.vscode/
tmp/
output/
node_modules/

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.3
TW5_BUILD_VERSION=v5.2.8
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
@@ -233,6 +233,15 @@ node $TW5_BUILD_TIDDLYWIKI \
--build index \
|| exit 1
# /editions/twitter-archivist/index.html Twitter Archivist edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/twitter-archivist \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/twitter-archivist/ \
--build index \
|| exit 1
######################################################
#
# Plugin demos
@@ -350,14 +359,14 @@ node $TW5_BUILD_TIDDLYWIKI \
# Delete any existing static content
rm $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
# /languages/de-AT/index.html Demo wiki with de-AT language
# /languages/de-AT/empty.html Empty wiki with de-AT language
@@ -450,7 +459,7 @@ node $TW5_BUILD_TIDDLYWIKI \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/library/$TW5_BUILD_VERSION \
--build \
--build library\
|| exit 1
# Delete the temporary build tiddler

View File

@@ -2,4 +2,4 @@
# Remove any output files
find . -regex "^./editions/[a-z0-9\.-]*/output/.*" -delete
find . -regex "^./editions/.*/output/.*" -delete

View File

@@ -9,6 +9,7 @@ node ./tiddlywiki.js \
--verbose \
--version \
--rendertiddler $:/core/save/all test.html text/plain \
--test \
|| exit 1
echo To run the tests in a browser, open "editions/test/output/test.html"

View File

@@ -313,7 +313,7 @@ $tw.utils.getLocationHash = function() {
var idx = href.indexOf('#');
if(idx === -1) {
return "#";
} else if(idx < href.length-1 && href[idx+1] === '#') {
} else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") {
// Special case: ignore location hash if it itself starts with a #
return "#";
} else {
@@ -375,7 +375,7 @@ $tw.utils.stringifyList = function(value) {
var result = new Array(value.length);
for(var t=0, l=value.length; t<l; t++) {
var entry = value[t] || "";
if(entry.indexOf(" ") !== -1) {
if(entry.match(/[^\S\xA0]/mg)) {
result[t] = "[[" + entry + "]]";
} else {
result[t] = entry;
@@ -1881,7 +1881,7 @@ A default set of files for TiddlyWiki to ignore during load.
This matches what NPM ignores, and adds "*.meta" to ignore tiddler
metadata files.
*/
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.github$|^\.vscode$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
/*
Load all the tiddlers recursively from a directory, including honouring `tiddlywiki.files` files for drawing in external files. Returns an array of {filepath:,type:,tiddlers: [{..fields...}],hasMetaFile:}. Note that no file information is returned for externally loaded tiddlers, just the `tiddlers` property.
@@ -2403,11 +2403,12 @@ $tw.boot.initStartup = function(options) {
$tw.utils.registerFileType("application/x-font-ttf","base64",".woff");
$tw.utils.registerFileType("application/font-woff2","base64",".woff2");
$tw.utils.registerFileType("audio/ogg","base64",".ogg");
$tw.utils.registerFileType("audio/mp4","base64",[".mp4",".m4a"]);
$tw.utils.registerFileType("video/ogg","base64",[".ogm",".ogv",".ogg"]);
$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/mp4","base64",[".mp4",".m4a"]);
$tw.utils.registerFileType("audio/mpeg","base64");
$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

@@ -4,7 +4,7 @@ type: text/plain
TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
Copyright (c) 2004-2007, Jeremy Ruston
Copyright (c) 2007-2022, UnaMesa Association
Copyright (c) 2007-2023, UnaMesa Association
All rights reserved.
Redistribution and use in source and binary forms, with or without

4
core/images/layout-button.tid Executable file
View File

@@ -0,0 +1,4 @@
title: $:/core/images/layout-button
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-layout-button tc-image-button" viewBox="0 0 24 24" stroke-width="1" stroke="none"><path d="M0 0h24v24H0z" fill="none"/><rect x="2" y="2" width="7" height="7" rx="2"/><rect x="2" y="13" width="7" height="9" rx="2"/><rect x="12" y="2" width="10" height="20" rx="2"/></svg>

6
core/images/mastodon.tid Normal file
View File

@@ -0,0 +1,6 @@
title: $:/core/images/mastodon
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-mastodon tc-image-button" viewBox="0 0 128 128">
<path d="M112.716,76.735C111.231,85.764 99.411,95.646 85.836,97.561C78.757,98.559 71.787,99.476 64.355,99.073C52.201,98.415 42.61,95.646 42.61,95.646C42.61,97.044 42.683,98.374 42.829,99.619C44.409,113.79 54.723,114.639 64.493,115.035C74.354,115.434 83.134,112.163 83.134,112.163L83.539,122.695C83.539,122.695 76.642,127.071 64.355,127.875C57.58,128.315 49.167,127.674 39.369,124.61C18.118,117.965 14.463,91.202 13.904,64.048C13.733,55.985 13.839,48.383 13.839,42.024C13.839,14.257 29.238,6.118 29.238,6.118C37.002,1.905 50.326,0.134 64.177,-0L64.517,-0C78.369,0.134 91.701,1.905 99.465,6.118C99.465,6.118 114.864,14.257 114.864,42.024C114.864,42.024 115.057,62.511 112.716,76.735ZM96.7,44.179C96.7,37.307 95.219,31.847 92.245,27.807C89.177,23.767 85.16,21.696 80.174,21.696C74.403,21.696 70.034,24.316 67.146,29.556L64.337,35.118L61.529,29.556C58.64,24.316 54.271,21.696 48.501,21.696C43.514,21.696 39.497,23.767 36.43,27.807C33.455,31.847 31.974,37.307 31.974,44.179L31.974,77.8L43.249,77.8L43.249,45.167C43.249,38.288 45.699,34.796 50.599,34.796C56.017,34.796 58.733,38.938 58.733,47.128L58.733,64.99L69.941,64.99L69.941,47.128C69.941,38.938 72.657,34.796 78.075,34.796C82.975,34.796 85.425,38.288 85.425,45.167L85.425,77.8L96.7,77.8L96.7,44.179Z"/>
</svg>

View File

@@ -0,0 +1,12 @@
title: $:/core/images/save-button-dynamic
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-save-button-dynamic tc-image-button" viewBox="0 0 128 128">
<g class="tc-image-save-button-dynamic-clean">
<path fill-rule="evenodd" d="M120.783 34.33c4.641 8.862 7.266 18.948 7.266 29.646 0 35.347-28.653 64-64 64-35.346 0-64-28.653-64-64 0-35.346 28.654-64 64-64 18.808 0 35.72 8.113 47.43 21.03l2.68-2.68c3.13-3.13 8.197-3.132 11.321-.008 3.118 3.118 3.121 8.193-.007 11.32l-4.69 4.691zm-12.058 12.058a47.876 47.876 0 013.324 17.588c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48c14.39 0 27.3 6.332 36.098 16.362L58.941 73.544 41.976 56.578c-3.127-3.127-8.201-3.123-11.32-.005-3.123 3.124-3.119 8.194.006 11.319l22.617 22.617a7.992 7.992 0 005.659 2.347c2.05 0 4.101-.783 5.667-2.349l44.12-44.12z"/>
</g>
<g class="tc-image-save-button-dynamic-dirty">
<path d="M64.856912,0 C100.203136,0 128.856912,28.653776 128.856912,64 C128.856912,99.346224 100.203136,128 64.856912,128 C29.510688,128 0.856911958,99.346224 0.856911958,64 C0.856911958,28.653776 29.510688,0 64.856912,0 Z M64.856912,16 C38.347244,16 16.856912,37.490332 16.856912,64 C16.856912,90.509668 38.347244,112 64.856912,112 C91.3665799,112 112.856912,90.509668 112.856912,64 C112.856912,37.490332 91.3665799,16 64.856912,16 Z"></path>
<circle cx="65" cy="64" r="32"></circle>
</g>
</svg>

View File

@@ -59,6 +59,8 @@ Home/Caption: home
Home/Hint: Open the default tiddlers
Language/Caption: language
Language/Hint: Choose the user interface language
LayoutSwitcher/Hint: Open layout switcher
LayoutSwitcher/Caption: layout
Manager/Caption: tiddler manager
Manager/Hint: Open tiddler manager
More/Caption: more

View File

@@ -7,7 +7,7 @@ Appearance/Hint: Ways to customise the appearance of your TiddlyWiki.
Basics/AnimDuration/Prompt: Animation duration
Basics/AutoFocus/Prompt: Default focus field for new tiddlers
Basics/Caption: Basics
Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to <$button set="$:/DefaultTiddlers" setTo="[list[$:/StoryList]]">retain story ordering</$button>
Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to {{retain story ordering||$:/snippets/retain-story-ordering-button}}
Basics/DefaultTiddlers/Prompt: Default tiddlers
Basics/DefaultTiddlers/TopHint: Choose which tiddlers are displayed at startup
Basics/Language/Prompt: Hello! Current language:
@@ -90,8 +90,8 @@ Plugins/Languages/Caption: Languages
Plugins/Languages/Hint: Language pack plugins
Plugins/NoInfoFound/Hint: No ''"<$text text=<<currentTab>>/>"'' found
Plugins/NotInstalled/Hint: This plugin is not currently installed
Plugins/OpenPluginLibrary: open plugin library
Plugins/ClosePluginLibrary: close plugin library
Plugins/OpenPluginLibrary: Open plugin library
Plugins/ClosePluginLibrary: Close plugin library
Plugins/PluginWillRequireReload: (requires reload)
Plugins/Plugins/Caption: Plugins
Plugins/Plugins/Hint: Plugins

View File

@@ -1,11 +1,13 @@
title: $:/language/Docs/Fields/
_canonical_uri: The full URI of an external image tiddler
author: Name of the author of a plugin
bag: The name of the bag from which a tiddler came
caption: The text to be displayed on a tab or button
code-body: The view template will display the tiddler as code if set to ''yes''
color: The CSS color value associated with a tiddler
component: The name of the component responsible for an [[alert tiddler|AlertMechanism]]
core-version: For a plugin, indicates what version of TiddlyWiki with which it is compatible
current-tiddler: Used to cache the top tiddler in a [[history list|HistoryMechanism]]
created: The date a tiddler was created
creator: The name of the person who created a tiddler
@@ -13,7 +15,7 @@ dependents: For a plugin, lists the dependent plugin titles
description: The descriptive text for a plugin, or a modal dialogue
draft.of: For draft tiddlers, contains the title of the tiddler of which this is a draft
draft.title: For draft tiddlers, contains the proposed new title of the tiddler
footer: The footer text for a wizard
footer: The footer text for a modal
hide-body: The view template will hide bodies of tiddlers if set to ''yes''
icon: The title of the tiddler containing the icon associated with a tiddler
library: Indicates that a tiddler should be saved as a JavaScript library if set to ''yes''
@@ -22,13 +24,15 @@ list-before: If set, the title of a tiddler before which this tiddler should be
list-after: If set, the title of the tiddler after which this tiddler should be added to the ordered list of tiddler titles, or at the end of the list if this field is present but empty
modified: The date and time at which a tiddler was last modified
modifier: The tiddler title associated with the person who last modified a tiddler
module-type: For javascript tiddlers, specifies what kind of module it is
name: The human readable name associated with a plugin tiddler
parent-plugin: For a plugin, specifies which plugin of which it is a sub-plugin
plugin-priority: A numerical value indicating the priority of a plugin tiddler
plugin-type: The type of plugin in a plugin tiddler
revision: The revision of the tiddler held at the server
released: Date of a TiddlyWiki release
source: The source URL associated with a tiddler
subtitle: The subtitle text for a wizard
subtitle: The subtitle text for a modal
tags: A list of tags associated with a tiddler
text: The body text of a tiddler
throttle.refresh: If present, throttles refreshes of this tiddler

View File

@@ -0,0 +1,18 @@
title: $:/language/Help/commands
description: Run commands returned from a filter
Sequentially run the command tokens returned from a filter
```
--commands <filter>
```
Examples
```
--commands "[enlist{$:/build-commands-as-text}]"
```
```
--commands "[{$:/build-commands-as-json}jsonindexes[]] :map[{$:/build-commands-as-json}jsonget<currentTiddler>]"
```

View File

@@ -40,6 +40,7 @@ Error/RetrievingSkinny: Error retrieving skinny tiddler list
Error/SavingToTWEdit: Error saving to TWEdit
Error/WhileSaving: Error while saving
Error/XMLHttpRequest: XMLHttpRequest error code
Error/ZoominTextNode: Story View Error: It appears you tried to interact with a tiddler that displays in a custom container. This is most likely caused by using `$:/tags/StoryTiddlerTemplateFilter` with a template that contains text or whitespace at the start. Please use the pragma `\whitespace trim` and ensure the whole contents of the tiddler is wrapped in a single HTML element. The text that caused this issue:
InternalJavaScriptError/Title: Internal JavaScript Error
InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser
LayoutSwitcher/Description: Open the layout switcher

View File

@@ -1,21 +0,0 @@
title: $:/language/Modals/SaveInstructions
subtitle: Save your work
footer: <$button message="tm-close-tiddler">Close</$button>
help: https://tiddlywiki.com/static/SavingChanges.html
Your changes to this wiki need to be saved as a ~TiddlyWiki HTML file.
!!! Desktop browsers
# Select ''Save As'' from the ''File'' menu
# Choose a filename and location
#* Some browsers also require you to explicitly specify the file saving format as ''Webpage, HTML only'' or similar
# Close this tab
!!! Smartphone browsers
# Create a bookmark to this page
#* If you've got iCloud or Google Sync set up then the bookmark will automatically sync to your desktop where you can open it and save it as above
# Close this tab
//If you open the bookmark again in Mobile Safari you will see this message again. If you want to go ahead and use the file, just click the ''close'' button below//

View File

@@ -0,0 +1,42 @@
/*\
title: $:/core/modules/commands/commands.js
type: application/javascript
module-type: command
Runs the commands returned from a filter
\*/
(function() {
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "commands",
synchronous: true
};
var Command = function(params, commander) {
this.params = params;
this.commander = commander;
};
Command.prototype.execute = function() {
// Parse the filter
var filter = this.params[0];
if(!filter) {
return "No filter specified";
}
var commands = this.commander.wiki.filterTiddlers(filter)
if(commands.length === 0) {
return "No tiddlers found for filter '" + filter + "'";
}
this.commander.addCommandTokens(commands);
return null;
};
exports.Command = Command;
})();

View File

@@ -57,7 +57,7 @@ Command.prototype.execute = function() {
exportPath = path.resolve(outputPath,macroPath + extension);
}
}
var finalPath = exportPath || path.resolve(pathname,encodeURIComponent(title) + extension);
var finalPath = exportPath || path.resolve(pathname,$tw.utils.encodeURIComponentExtended(title) + extension);
$tw.utils.createFileDirectories(finalPath);
fs.writeFileSync(finalPath,text,"utf8");
});

View File

@@ -65,7 +65,7 @@ Command.prototype.execute = function() {
$tw.utils.each(filteredPluginList,function(title) {
var tiddler = containerData.tiddlers[title];
// Save each JSON file and collect the skinny data
var pathname = path.resolve(self.commander.outputPath,basepath + encodeURIComponent(title) + ".json");
var pathname = path.resolve(self.commander.outputPath,basepath + $tw.utils.encodeURIComponentExtended(title) + ".json");
$tw.utils.createFileDirectories(pathname);
fs.writeFileSync(pathname,JSON.stringify(tiddler),"utf8");
// Collect the skinny list data

View File

@@ -45,7 +45,7 @@ Command.prototype.execute = function() {
var tiddler = self.commander.wiki.getTiddler(title),
type = tiddler.fields.type || "text/vnd.tiddlywiki",
contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"},
filename = path.resolve(pathname,encodeURIComponent(title));
filename = path.resolve(pathname,$tw.utils.encodeURIComponentExtended(title));
fs.writeFileSync(filename,tiddler.fields.text,contentTypeInfo.encoding);
});
return null;

View File

@@ -30,7 +30,7 @@ exports.textPrimitives.wikiLink = exports.textPrimitives.upperLetter + "+" +
exports.textPrimitives.upperLetter +
exports.textPrimitives.anyLetter + "*";
exports.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };
exports.htmlEntities = {quot:34, dollar:36, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 };
exports.htmlVoidElements = "area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(",");

View File

@@ -87,7 +87,7 @@ function FramedEngine(options) {
$tw.utils.addEventListeners(this.domNode,[
{name: "click",handlerObject: this,handlerMethod: "handleClickEvent"},
{name: "input",handlerObject: this,handlerMethod: "handleInputEvent"},
{name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"},
{name: "keydown",handlerObject: this,handlerMethod: "handleKeydownEvent"},
{name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"}
]);
// Add drag and drop event listeners if fileDrop is enabled
@@ -162,13 +162,13 @@ FramedEngine.prototype.fixHeight = function() {
if(this.widget.editAutoHeight) {
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
this.iframeNode.style.height = (newHeight + 14) + "px"; // +14 for the border on the textarea
this.iframeNode.style.height = newHeight + "px";
}
} else {
var fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,"400px"),10);
fixedHeight = Math.max(fixedHeight,20);
this.domNode.style.height = fixedHeight + "px";
this.iframeNode.style.height = (fixedHeight + 14) + "px";
this.iframeNode.style.height = fixedHeight + "px";
}
}
};
@@ -177,9 +177,11 @@ FramedEngine.prototype.fixHeight = function() {
Focus the engine node
*/
FramedEngine.prototype.focus = function() {
if(this.domNode.focus && this.domNode.select) {
if(this.domNode.focus) {
this.domNode.focus();
this.domNode.select();
}
if(this.domNode.select) {
$tw.utils.setSelectionByPosition(this.domNode,this.widget.editFocusSelectFromStart,this.widget.editFocusSelectFromEnd);
}
};
@@ -192,6 +194,17 @@ FramedEngine.prototype.handleFocusEvent = function(event) {
}
};
/*
Handle a keydown event
*/
FramedEngine.prototype.handleKeydownEvent = function(event) {
if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) {
return true;
}
return this.widget.handleKeydownEvent(event);
};
/*
Handle a click
*/

View File

@@ -119,10 +119,12 @@ SimpleEngine.prototype.fixHeight = function() {
/*
Focus the engine node
*/
SimpleEngine.prototype.focus = function() {
if(this.domNode.focus && this.domNode.select) {
SimpleEngine.prototype.focus = function() {
if(this.domNode.focus) {
this.domNode.focus();
this.domNode.select();
}
if(this.domNode.select) {
$tw.utils.setSelectionByPosition(this.domNode,this.widget.editFocusSelectFromStart,this.widget.editFocusSelectFromEnd);
}
};

View File

@@ -180,6 +180,8 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.editMinHeight = this.getAttribute("minHeight",DEFAULT_MIN_TEXT_AREA_HEIGHT);
this.editFocusPopup = this.getAttribute("focusPopup");
this.editFocus = this.getAttribute("focus");
this.editFocusSelectFromStart = $tw.utils.parseNumber(this.getAttribute("focusSelectFromStart","0"));
this.editFocusSelectFromEnd = $tw.utils.parseNumber(this.getAttribute("focusSelectFromEnd","0"));
this.editTabIndex = this.getAttribute("tabindex");
this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes";
this.editInputActions = this.getAttribute("inputActions");
@@ -218,7 +220,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled || changedAttributes.fileDrop) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
this.refreshSelf();
return true;
} else if (changedTiddlers[this.editRefreshTitle]) {
@@ -298,7 +300,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
Propogate keydown events to our container for the keyboard widgets benefit
*/
EditTextWidget.prototype.propogateKeydownEvent = function(event) {
var newEvent = this.cloneEvent(event,["keyCode","which","metaKey","ctrlKey","altKey","shiftKey"]);
var newEvent = this.cloneEvent(event,["keyCode","code","which","key","metaKey","ctrlKey","altKey","shiftKey"]);
return !this.parentDomNode.dispatchEvent(newEvent);
};

View File

@@ -25,20 +25,10 @@ exports.cascade = function(operationSubFunction,options) {
if(!filterFnList[index]) {
filterFnList[index] = options.wiki.compileFilter(filter);
}
var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler")
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
}
}
});
var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler","")
}));
if(output.length !== 0) {
result = output[0];
return false;

View File

@@ -19,23 +19,13 @@ exports.filter = function(operationSubFunction,options) {
var resultsToRemove = [],
index = 0;
results.each(function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"),
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
}
}
});
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler",""),
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length
}));
if(filtered.length === 0) {
resultsToRemove.push(title);
}

View File

@@ -21,23 +21,13 @@ exports.map = function(operationSubFunction,options) {
flatten = (suffixes[0] && suffixes[0][0] === "flat") ? true : false;
results.clear();
$tw.utils.each(inputTitles,function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"),
"index": "" + index,
"revIndex": "" + (inputTitles.length - 1 - index),
"length": "" + inputTitles.length
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
}
}
});
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler",""),
"index": "" + index,
"revIndex": "" + (inputTitles.length - 1 - index),
"length": "" + inputTitles.length
}));
if(filtered.length && flatten) {
$tw.utils.each(filtered,function(value) {
results.push(value);

View File

@@ -18,24 +18,14 @@ exports.reduce = function(operationSubFunction,options) {
var accumulator = "",
index = 0;
results.each(function(title) {
var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"),
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length,
"accumulator": "" + accumulator
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
}
}
});
var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"),
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length,
"accumulator": "" + accumulator
}));
if(list.length > 0) {
accumulator = "" + list[0];
}

View File

@@ -25,20 +25,10 @@ exports.sort = function(operationSubFunction,options) {
indexes = new Array(inputTitles.length),
compareFn;
results.each(function(title) {
var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name,opts) {
opts = opts || {};
opts.variables = {
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler")
};
if(name in opts.variables) {
return opts.variables[name];
} else {
return widget.getVariable(name,opts);
}
}
});
var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler")
}));
sortKeys.push(key[0] || "");
});
results.clear();

View File

@@ -12,6 +12,9 @@ Adds tiddler filtering methods to the $tw.Wiki object.
/*global $tw: false */
"use strict";
/* Maximum permitted filter recursion depth */
var MAX_FILTER_DEPTH = 300;
/*
Parses an operation (i.e. a run) within a filter string
operators: Array of array of operator nodes into which results should be inserted
@@ -252,19 +255,21 @@ exports.compileFilter = function(filterString) {
var operands = [],
operatorFunction;
if(!operator.operator) {
// Use the "title" operator if no operator is specified
operatorFunction = filterOperators.title;
} else if(!filterOperators[operator.operator]) {
operatorFunction = filterOperators.field;
// Unknown operators treated as "[unknown]" - at run time we can distinguish between a custom operator and falling back to the default "field" operator
operatorFunction = filterOperators["[unknown]"];
} else {
// Use the operator function
operatorFunction = filterOperators[operator.operator];
}
$tw.utils.each(operator.operands,function(operand) {
if(operand.indirect) {
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
} else if(operand.variable) {
var varTree = $tw.utils.parseFilterVariable(operand.text);
operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""});
operand.value = widget.evaluateVariable(varTree.name,{params: varTree.params, source: source})[0] || "";
} else {
operand.value = operand.text;
}
@@ -328,7 +333,7 @@ exports.compileFilter = function(filterString) {
})());
});
// Return a function that applies the operations to a source iterator of tiddler titles
var compiled = $tw.perf.measure("filter: " + filterString,function filterFunction(source,widget) {
var fnMeasured = $tw.perf.measure("filter: " + filterString,function filterFunction(source,widget) {
if(!source) {
source = self.each;
} else if(typeof source === "object") { // Array or hashmap
@@ -338,9 +343,15 @@ exports.compileFilter = function(filterString) {
widget = $tw.rootWidget;
}
var results = new $tw.utils.LinkedList();
$tw.utils.each(operationFunctions,function(operationFunction) {
operationFunction(results,source,widget);
});
self.filterRecursionCount = (self.filterRecursionCount || 0) + 1;
if(self.filterRecursionCount < MAX_FILTER_DEPTH) {
$tw.utils.each(operationFunctions,function(operationFunction) {
operationFunction(results,source,widget);
});
} else {
results.push("/**-- Excessive filter recursion --**/");
}
self.filterRecursionCount = self.filterRecursionCount - 1;
return results.toArray();
});
if(this.filterCacheCount >= 2000) {
@@ -350,9 +361,9 @@ exports.compileFilter = function(filterString) {
this.filterCache = Object.create(null);
this.filterCacheCount = 0;
}
this.filterCache[filterString] = compiled;
this.filterCache[filterString] = fnMeasured;
this.filterCacheCount++;
return compiled;
return fnMeasured;
};
})();

View File

@@ -16,6 +16,22 @@ Filter operator for applying decodeURIComponent() to each item.
Export our filter functions
*/
exports.decodebase64 = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.base64Decode(title));
});
return results;
};
exports.encodebase64 = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.base64Encode(title));
});
return results;
};
exports.decodeuricomponent = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
@@ -27,7 +43,7 @@ exports.decodeuricomponent = function(source,operator,options) {
exports.encodeuricomponent = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(encodeURIComponent(title));
results.push($tw.utils.encodeURIComponentExtended(title));
});
return results;
};

View File

@@ -20,18 +20,10 @@ exports.filter = function(source,operator,options) {
results = [],
target = operator.prefix !== "!";
source(function(tiddler,title) {
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
default:
return options.widget.getVariable(name);
}
}
});
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": options.widget.getVariable("currentTiddler","")
}));
if((list.length > 0) === target) {
results.push(title);
}

View File

@@ -0,0 +1,32 @@
/*\
title: $:/core/modules/filters/function.js
type: application/javascript
module-type: filteroperator
Filter operator returning those input titles that are returned from a function
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
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);
if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
return options.widget.evaluateVariable(functionName,{params: operator.operands.slice(1), source: source});
}
// Return the input list if the function wasn't found
var results = [];
source(function(tiddler,title) {
results.push(title);
});
return results;
};
})();

View File

@@ -19,13 +19,13 @@ exports.variable = function(source,prefix,options) {
var results = [];
if(prefix === "!") {
source(function(tiddler,title) {
if(!(title in options.widget.variables)) {
if(options.widget.getVariable(title) === undefined) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title in options.widget.variables) {
if(options.widget.getVariable(title) !== undefined) {
results.push(title);
}
});

View File

@@ -17,9 +17,23 @@ exports["jsonget"] = function(source,operator,options) {
source(function(tiddler,title) {
var data = $tw.utils.parseJSONSafe(title,title);
if(data) {
var item = getDataItemValueAsString(data,operator.operands);
var items = getDataItemValueAsStrings(data,operator.operands);
if(items !== undefined) {
results.push.apply(results,items);
}
}
});
return results;
};
exports["jsonextract"] = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
var data = $tw.utils.parseJSONSafe(title,title);
if(data) {
var item = getDataItem(data,operator.operands);
if(item !== undefined) {
results.push(item);
results.push(JSON.stringify(item));
}
}
});
@@ -31,9 +45,9 @@ exports["jsonindexes"] = function(source,operator,options) {
source(function(tiddler,title) {
var data = $tw.utils.parseJSONSafe(title,title);
if(data) {
var item = getDataItemKeysAsStrings(data,operator.operands);
if(item !== undefined) {
results.push.apply(results,item);
var items = getDataItemKeysAsStrings(data,operator.operands);
if(items !== undefined) {
results.push.apply(results,items);
}
}
});
@@ -57,11 +71,11 @@ exports["jsontype"] = function(source,operator,options) {
/*
Given a JSON data structure and an array of index strings, return an array of the string representation of the values at the end of the index chain, or "undefined" if any of the index strings are invalid
*/
function getDataItemValueAsString(data,indexes) {
function getDataItemValueAsStrings(data,indexes) {
// Get the item
var item = getDataItem(data,indexes);
// Return the item as a string
return convertDataItemValueToString(item);
// Return the item as a string list
return convertDataItemValueToStrings(item);
}
/*
@@ -77,15 +91,34 @@ function getDataItemKeysAsStrings(data,indexes) {
/*
Return an array of the string representation of the values of a data item, or "undefined" if the item is undefined
*/
function convertDataItemValueToString(item) {
function convertDataItemValueToStrings(item) {
// Return the item as a string
if(item === undefined) {
return item;
return undefined;
} else if(item === null) {
return ["null"]
} else if(typeof item === "object") {
var results = [],i,t;
if($tw.utils.isArray(item)) {
// Return all the items in arrays recursively
for(i=0; i<item.length; i++) {
t = convertDataItemValueToStrings(item[i])
if(t !== undefined) {
results.push.apply(results,t);
}
}
} else {
// Return all the values in objects recursively
$tw.utils.each(Object.keys(item).sort(),function(key) {
t = convertDataItemValueToStrings(item[key]);
if(t !== undefined) {
results.push.apply(results,t);
}
});
}
return results;
}
if(typeof item === "object") {
return JSON.stringify(item);
}
return item.toString();
return [item.toString()];
}
/*
@@ -143,7 +176,11 @@ function getDataItem(data,indexes) {
var item = data;
for(var i=0; i<indexes.length; i++) {
if(item !== undefined) {
item = item[indexes[i]];
if(item !== null && ["number","string","boolean"].indexOf(typeof item) === -1) {
item = item[indexes[i]];
} else {
item = undefined;
}
}
}
return item;

View File

@@ -26,26 +26,14 @@ exports.reduce = function(source,operator,options) {
accumulator = operator.operands[1] || "";
for(var index=0; index<results.length; index++) {
var title = results[index],
list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
case "accumulator":
return "" + accumulator;
case "index":
return "" + index;
case "revIndex":
return "" + (results.length - 1 - index);
case "length":
return "" + results.length;
default:
return options.widget.getVariable(name);
}
}
});
list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": options.widget.getVariable("currentTiddler"),
"accumulator": "" + accumulator,
"index": "" + index,
"revIndex": "" + (results.length - 1 - index),
"length": "" + results.length
}));
if(list.length > 0) {
accumulator = "" + list[0];
}

View File

@@ -25,18 +25,10 @@ exports.sortsub = function(source,operator,options) {
inputTitles.push(title);
var r = filterFn.call(options.wiki,function(iterator) {
iterator(options.wiki.getTiddler(title),title);
},{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
default:
return options.widget.getVariable(name);
}
}
});
},options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title,
"..currentTiddler": options.widget.getVariable("currentTiddler")
}));
sortKeys.push(r[0] || "");
});
// Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays

View File

@@ -74,6 +74,113 @@ exports.join = makeStringReducingOperator(
},null
);
var dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js");
exports.levenshtein = makeStringBinaryOperator(
function(a,b) {
var dmpObject = new dmp.diff_match_patch(),
diffs = dmpObject.diff_main(a,b);
return [dmpObject.diff_levenshtein(diffs) + ""];
}
);
// these two functions are adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs
function diffLineWordMode(text1,text2,mode) {
var dmpObject = new dmp.diff_match_patch();
var a = diffPartsToChars(text1,text2,mode);
var lineText1 = a.chars1;
var lineText2 = a.chars2;
var lineArray = a.lineArray;
var diffs = dmpObject.diff_main(lineText1,lineText2,false);
dmpObject.diff_charsToLines_(diffs,lineArray);
return diffs;
}
function diffPartsToChars(text1,text2,mode) {
var lineArray = [];
var lineHash = {};
lineArray[0] = '';
function diff_linesToPartsMunge_(text,mode) {
var chars = '';
var lineStart = 0;
var lineEnd = -1;
var lineArrayLength = lineArray.length,
regexpResult;
var searchRegexp = /\W+/g;
while(lineEnd < text.length - 1) {
if(mode === "words") {
regexpResult = searchRegexp.exec(text);
lineEnd = searchRegexp.lastIndex;
if(regexpResult === null) {
lineEnd = text.length;
}
lineEnd = --lineEnd;
} else {
lineEnd = text.indexOf('\n', lineStart);
if(lineEnd == -1) {
lineEnd = text.length - 1;
}
}
var line = text.substring(lineStart, lineEnd + 1);
if(lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : (lineHash[line] !== undefined)) {
chars += String.fromCharCode(lineHash[line]);
} else {
if (lineArrayLength == maxLines) {
line = text.substring(lineStart);
lineEnd = text.length;
}
chars += String.fromCharCode(lineArrayLength);
lineHash[line] = lineArrayLength;
lineArray[lineArrayLength++] = line;
}
lineStart = lineEnd + 1;
}
return chars;
}
var maxLines = 40000;
var chars1 = diff_linesToPartsMunge_(text1,mode);
maxLines = 65535;
var chars2 = diff_linesToPartsMunge_(text2,mode);
return {chars1: chars1, chars2: chars2, lineArray: lineArray};
};
exports.makepatches = function(source,operator,options) {
var dmpObject = new dmp.diff_match_patch(),
suffix = operator.suffix || "",
result = [];
source(function(tiddler,title) {
var diffs, patches;
if(suffix === "lines" || suffix === "words") {
diffs = diffLineWordMode(title,operator.operand,suffix);
patches = dmpObject.patch_make(title,diffs);
} else {
patches = dmpObject.patch_make(title,operator.operand);
}
Array.prototype.push.apply(result,[dmpObject.patch_toText(patches)]);
});
return result;
};
exports.applypatches = makeStringBinaryOperator(
function(a,b) {
var dmpObject = new dmp.diff_match_patch(),
patches;
try {
patches = dmpObject.patch_fromText(b);
} catch(e) {
}
if(patches) {
return [dmpObject.patch_apply(patches,a)[0]];
} else {
return [a];
}
}
);
function makeStringBinaryOperator(fnCalc) {
return function(source,operator,options) {
var result = [];
@@ -184,4 +291,4 @@ exports.charcode = function(source,operator,options) {
return [chars.join("")];
};
})();
})();

View File

@@ -0,0 +1,45 @@
/*\
title: $:/core/modules/filters/unknown.js
type: application/javascript
module-type: filteroperator
Filter operator for handling unknown filter operators.
Not intended to be used directly by end users, hence the square brackets around the name.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var fieldFilterOperatorFn = require("$:/core/modules/filters/field.js").field;
/*
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.prefix === "!") {
var results = [];
source(function(tiddler,title) {
if(list.indexOf(title) === -1) {
results.push(title);
}
});
return results;
} else {
return list;
}
}
}
// Otherwise, use the "field" operator
return fieldFilterOperatorFn(source,operator,options);
};
})();

View File

@@ -16,9 +16,15 @@ Filter operator for returning the names of the active variables
Export our filter function
*/
exports.variables = function(source,operator,options) {
var names = [];
for(var variable in options.widget.variables) {
names.push(variable);
var names = [],
widget = options.widget;
while(widget && !widget.hasOwnProperty("variables")) {
widget = widget.parentWidget;
}
if(widget && widget.variables) {
for(var variable in widget.variables) {
names.push(variable);
}
}
return names.sort();
};

View File

@@ -32,18 +32,18 @@ FieldIndexer.prototype.setMaxIndexedValueLength = function(length) {
FieldIndexer.prototype.addIndexMethods = function() {
var self = this;
// get all tiddlers, including those overwrite shadow tiddlers
this.wiki.each.byField = function(name,value) {
var titles = self.wiki.allTitles(),
lookup = self.lookup(name,value);
var lookup = self.lookup(name,value);
return lookup && lookup.filter(function(title) {
return titles.indexOf(title) !== -1;
return self.wiki.tiddlerExists(title)
});
};
// get shadow tiddlers, including shadow tiddlers that is overwritten
this.wiki.eachShadow.byField = function(name,value) {
var titles = self.wiki.allShadowTitles(),
lookup = self.lookup(name,value);
var lookup = self.lookup(name,value);
return lookup && lookup.filter(function(title) {
return titles.indexOf(title) !== -1;
return self.wiki.isShadowTiddler(title)
});
};
this.wiki.eachTiddlerPlusShadows.byField = function(name,value) {

View File

@@ -141,6 +141,7 @@ function KeyboardManager(options) {
this.shortcutKeysList = [], // Stores the shortcut-key descriptors
this.shortcutActionList = [], // Stores the corresponding action strings
this.shortcutParsedList = []; // Stores the parsed key descriptors
this.shortcutPriorityList = []; // Stores the parsed shortcut priority
this.lookupNames = ["shortcuts"];
this.lookupNames.push($tw.platform.isMac ? "shortcuts-mac" : "shortcuts-not-mac")
this.lookupNames.push($tw.platform.isWindows ? "shortcuts-windows" : "shortcuts-not-windows");
@@ -318,12 +319,23 @@ KeyboardManager.prototype.updateShortcutLists = function(tiddlerList) {
this.shortcutKeysList[i] = tiddlerFields.key !== undefined ? tiddlerFields.key : undefined;
this.shortcutActionList[i] = tiddlerFields.text;
this.shortcutParsedList[i] = this.shortcutKeysList[i] !== undefined ? this.parseKeyDescriptors(this.shortcutKeysList[i]) : undefined;
this.shortcutPriorityList[i] = tiddlerFields.priority === "yes" ? true : false;
}
};
KeyboardManager.prototype.handleKeydownEvent = function(event) {
/*
event: the keyboard event object
options:
onlyPriority: true if only priority global shortcuts should be invoked
*/
KeyboardManager.prototype.handleKeydownEvent = function(event, options) {
options = options || {};
var key, action;
for(var i=0; i<this.shortcutTiddlers.length; i++) {
if(options.onlyPriority && this.shortcutPriorityList[i] !== true) {
continue;
}
if(this.shortcutParsedList[i] !== undefined && this.checkKeyDescriptors(event,this.shortcutParsedList[i])) {
key = this.shortcutParsedList[i];
action = this.shortcutActionList[i];

View File

@@ -28,6 +28,8 @@ var AudioParser = function(type,text,options) {
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["audio/ogg"] = AudioParser;

View File

@@ -23,7 +23,7 @@ var BinaryParser = function(type,text,options) {
children: [{
type: "transclude",
attributes: {
tiddler: {type: "string", value: BINARY_WARNING_MESSAGE}
"$tiddler": {type: "string", value: BINARY_WARNING_MESSAGE}
}
}]
};
@@ -38,7 +38,7 @@ var BinaryParser = function(type,text,options) {
children: [{
type: "transclude",
attributes: {
tiddler: {type: "string", value: EXPORT_BUTTON_IMAGE}
"$tiddler": {type: "string", value: EXPORT_BUTTON_IMAGE}
}
}]
};
@@ -64,6 +64,8 @@ var BinaryParser = function(type,text,options) {
children: [warn, link]
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["application/octet-stream"] = BinaryParser;

View File

@@ -13,6 +13,11 @@ The CSV text parser processes CSV files into a table wrapped in a scrollable wid
"use strict";
var CsvParser = function(type,text,options) {
// Special handler for tab-delimited files
if (type === 'text/tab-delimited-values' && !options.separator) {
options.separator = "\t";
}
// Table framework
this.tree = [{
"type": "scrollable", "children": [{
@@ -24,30 +29,35 @@ var CsvParser = function(type,text,options) {
}]
}];
// Split the text into lines
var lines = text.split(/\r?\n/mg),
var lines = $tw.utils.parseCsvString(text, options),
tag = "th";
var maxColumns = 0;
$tw.utils.each(lines, function(columns) {
maxColumns = Math.max(columns.length, maxColumns);
});
for(var line=0; line<lines.length; line++) {
var lineText = lines[line];
if(lineText) {
var row = {
"type": "element", "tag": "tr", "children": []
};
var columns = lineText.split(",");
for(var column=0; column<columns.length; column++) {
row.children.push({
"type": "element", "tag": tag, "children": [{
"type": "text",
"text": columns[column]
}]
});
}
tag = "td";
this.tree[0].children[0].children[0].children.push(row);
var columns = lines[line];
var row = {
"type": "element", "tag": "tr", "children": []
};
for(var column=0; column<maxColumns; column++) {
row.children.push({
"type": "element", "tag": tag, "children": [{
"type": "text",
"text": columns[column] || ''
}]
});
}
tag = "td";
this.tree[0].children[0].children[0].children.push(row);
}
this.source = text;
this.type = type;
};
exports["text/csv"] = CsvParser;
exports["text/tab-delimited-values"] = CsvParser;
})();

View File

@@ -29,6 +29,8 @@ var HtmlParser = function(type,text,options) {
if($tw.wiki.getTiddlerText("$:/config/HtmlParser/DisableSandbox","no") !== "yes") {
this.tree[0].attributes.sandbox = {type: "string", value: $tw.wiki.getTiddlerText("$:/config/HtmlParser/SandboxTokens","")};
}
this.source = text;
this.type = type;
};
exports["text/html"] = HtmlParser;

View File

@@ -28,6 +28,8 @@ var ImageParser = function(type,text,options) {
}
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["image/svg+xml"] = ImageParser;

View File

@@ -123,6 +123,36 @@ exports.parseStringLiteral = function(source,pos) {
}
};
/*
Returns an array of {name:} with an optional "default" property. Options include:
requireParenthesis: require the parameter definition to be wrapped in parenthesis
*/
exports.parseParameterDefinition = function(paramString,options) {
options = options || {};
if(options.requireParenthesis) {
var parenMatch = /^\s*\((.*)\)\s*$/g.exec(paramString);
if(!parenMatch) {
return [];
}
paramString = parenMatch[1];
}
var params = [],
reParam = /\s*([^:),\s]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|([^,"'\s]+)))?/mg,
paramMatch = reParam.exec(paramString);
while(paramMatch) {
// Save the parameter details
var paramInfo = {name: paramMatch[1]},
defaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5];
if(defaultValue !== undefined) {
paramInfo["default"] = defaultValue;
}
params.push(paramInfo);
// Look for the next parameter
paramMatch = reParam.exec(paramString);
}
return params;
};
exports.parseMacroParameters = function(node,source,pos) {
// Process parameters
var parameter = $tw.utils.parseMacroParameter(source,pos);
@@ -175,7 +205,36 @@ exports.parseMacroParameter = function(source,pos) {
};
/*
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:}
Look for a macro invocation. Returns null if not found, or {type: "transclude", attributes:, start:, end:}
*/
exports.parseMacroInvocationAsTransclusion = function(source,pos) {
var node = $tw.utils.parseMacroInvocation(source,pos);
if(node) {
var positionalName = 0,
transclusion = {
type: "transclude",
start: node.start,
end: node.end
};
$tw.utils.addAttributeToParseTreeNode(transclusion,"$variable",node.name);
$tw.utils.each(node.params,function(param) {
var name = param.name;
if(name) {
if(name.charAt(0) === "$") {
name = "$" + name;
}
$tw.utils.addAttributeToParseTreeNode(transclusion,{name: name,type: "string", value: param.value, start: param.start, end: param.end});
} else {
$tw.utils.addAttributeToParseTreeNode(transclusion,{name: (positionalName++) + "",type: "string", value: param.value, start: param.start, end: param.end});
}
});
return transclusion;
}
return node;
};
/*
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, params:, start:, end:}
*/
exports.parseMacroInvocation = function(source,pos) {
var node = {

View File

@@ -15,7 +15,7 @@ The PDF parser embeds a PDF viewer
var ImageParser = function(type,text,options) {
var element = {
type: "element",
tag: "embed",
tag: "iframe",
attributes: {}
},
src;
@@ -25,6 +25,8 @@ var ImageParser = function(type,text,options) {
element.attributes.src = {type: "string", value: "data:application/pdf;base64," + text};
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["application/pdf"] = ImageParser;

View File

@@ -20,6 +20,8 @@ var TextParser = function(type,text,options) {
language: {type: "string", value: type}
}
}];
this.source = text;
this.type = type;
};
exports["text/plain"] = TextParser;

View File

@@ -28,6 +28,8 @@ var VideoParser = function(type,text,options) {
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
}
this.tree = [element];
this.source = text;
this.type = type;
};
exports["video/ogg"] = VideoParser;

View File

@@ -0,0 +1,97 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/fnprocdef.js
type: application/javascript
module-type: wikirule
Wiki pragma rule for function, procedure and widget definitions
```
\function name(param:defaultvalue,param2:defaultvalue)
definition text
\end
\procedure name(param:defaultvalue,param2:defaultvalue)
definition text
\end
\widget $mywidget(param:defaultvalue,param2:defaultvalue)
definition text
\end
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "fnprocdef";
exports.types = {pragma: true};
/*
Instantiate parse rule
*/
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /^\\(function|procedure|widget)\s+([^(\s]+)\((\s*([^)]*))?\)(\s*\r?\n)?/mg;
};
/*
Parse the most recent match
*/
exports.parse = function() {
// Move past the macro name and parameters
this.parser.pos = this.matchRegExp.lastIndex;
// Parse the parameters
var params = [];
if(this.match[3]) {
params = $tw.utils.parseParameterDefinition(this.match[4]);
}
// Is this a multiline definition?
var reEnd;
if(this.match[5]) {
// If so, the end of the body is marked with \end
reEnd = new RegExp("(\\r?\\n\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[2]) + ")?(?:$|\\r?\\n))","mg");
} else {
// Otherwise, the end of the definition is marked by the end of the line
reEnd = /($|\r?\n)/mg;
// Move past any whitespace
this.parser.pos = $tw.utils.skipWhiteSpace(this.parser.source,this.parser.pos);
}
// Find the end of the definition
reEnd.lastIndex = this.parser.pos;
var text,
endMatch = reEnd.exec(this.parser.source);
if(endMatch) {
text = this.parser.source.substring(this.parser.pos,endMatch.index);
this.parser.pos = endMatch.index + endMatch[0].length;
} else {
// We didn't find the end of the definition, so we'll make it blank
text = "";
}
// Save the macro definition
var parseTreeNodes = [{
type: "set",
attributes: {},
children: [],
params: params
}];
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[2]);
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text);
if(this.match[1] === "function") {
parseTreeNodes[0].isFunctionDefinition = true;
} else if(this.match[1] === "procedure") {
parseTreeNodes[0].isProcedureDefinition = true;
} else if(this.match[1] === "widget") {
parseTreeNodes[0].isWidgetDefinition = true;
}
if(this.parser.configTrimWhiteSpace) {
parseTreeNodes[0].configTrimWhiteSpace = true;
}
return parseTreeNodes;
};
})();

View File

@@ -93,9 +93,6 @@ exports.parseTag = function(source,pos,options) {
return null;
}
node.tag = token.match[1];
if(node.tag.slice(1).indexOf("$") !== -1) {
return null;
}
if(node.tag.charAt(0) === "$") {
node.type = node.tag.substr(1);
}

View File

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

View File

@@ -27,7 +27,7 @@ exports.findNextMatch = function(startPos) {
var nextStart = startPos;
// Try parsing at all possible macrocall openers until we match
while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) {
var nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
var nextCall = $tw.utils.parseMacroInvocationAsTransclusion(this.parser.source,nextStart);
if(nextCall) {
var c = this.parser.source.charAt(nextCall.end);
// Ensure EOL after parsed macro

View File

@@ -27,7 +27,7 @@ exports.findNextMatch = function(startPos) {
var nextStart = startPos;
// Try parsing at all possible macrocall openers until we match
while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) {
this.nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
this.nextCall = $tw.utils.parseMacroInvocationAsTransclusion(this.parser.source,nextStart);
if(this.nextCall) {
return nextStart;
}

View File

@@ -27,7 +27,7 @@ Instantiate parse rule
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /^\\define\s+([^(\s]+)\(\s*([^)]*)\)(\s*\r?\n)?/mg;
this.matchRegExp = /\\define\s+([^(\s]+)\(\s*([^)]*)\)(\s*\r?\n)?/mg;
};
/*
@@ -58,7 +58,7 @@ exports.parse = function() {
var reEnd;
if(this.match[3]) {
// If so, the end of the body is marked with \end
reEnd = /(\r?\n\\end[^\S\n\r]*(?:$|\r?\n))/mg;
reEnd = new RegExp("(\\r?\\n[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg");
} else {
// Otherwise, the end of the definition is marked by the end of the line
reEnd = /($|\r?\n)/mg;
@@ -77,16 +77,16 @@ exports.parse = function() {
text = "";
}
// Save the macro definition
return [{
var parseTreeNodes = [{
type: "set",
attributes: {
name: {type: "string", value: this.match[1]},
value: {type: "string", value: text}
},
attributes: {},
children: [],
params: params,
isMacroDefinition: true
}];
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]);
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text);
return parseTreeNodes;
};
})();

View File

@@ -0,0 +1,60 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/parameters.js
type: application/javascript
module-type: wikirule
Wiki pragma rule for parameter definitions
```
\parameters(param:defaultvalue,param2:defaultvalue)
definition text
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "parameters";
exports.types = {pragma: true};
/*
Instantiate parse rule
*/
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /^\\parameters\s*\(([^)]*)\)\s*\r?\n/mg;
};
/*
Parse the most recent match
*/
exports.parse = function() {
// Move past the macro name and parameters
this.parser.pos = this.matchRegExp.lastIndex;
// Parse the parameters
var params = $tw.utils.parseParameterDefinition(this.match[1]);
var attributes = Object.create(null),
orderedAttributes = [];
$tw.utils.each(params,function(param) {
var name = param.name;
// Parameter names starting with dollar must be escaped to double dollars for the parameters widget
if(name.charAt(0) === "$") {
name = "$" + name;
}
var attribute = {name: name, type: "string", value: param["default"] || ""};
attributes[name] = attribute;
orderedAttributes.push(attribute);
});
// Save the macro definition
return [{
type: "parameters",
attributes: attributes,
orderedAttributes: orderedAttributes
}];
};
})();

View File

@@ -0,0 +1,68 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/parsermode.js
type: application/javascript
module-type: wikirule
Wiki pragma rule for parser mode specifications
```
\parsermode block
\parsermode inline
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "parsermode";
exports.types = {pragma: true};
/*
Instantiate parse rule
*/
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\\parsermode[^\S\n]/mg;
};
/*
Parse the most recent match
*/
exports.parse = function() {
// Move past the pragma invocation
this.parser.pos = this.matchRegExp.lastIndex;
// Parse whitespace delimited tokens terminated by a line break
var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg,
parserMode = undefined;
reMatch.lastIndex = this.parser.pos;
var match = reMatch.exec(this.parser.source);
while(match && match.index === this.parser.pos) {
this.parser.pos = reMatch.lastIndex;
// Exit if we've got the line break
if(match[2]) {
break;
}
// Process the token
if(match[1]) {
parserMode = match[1];
}
// Match the next token
match = reMatch.exec(this.parser.source);
}
// Process the tokens
if(parserMode !== undefined) {
if(parserMode === "block") {
this.parser.parseAsInline = false;
} else if(parserMode === "inline") {
this.parser.parseAsInline = true;
}
}
// No parse tree nodes to return
return [];
};
})();

View File

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

View File

@@ -41,9 +41,6 @@ exports.parse = function() {
var node = {
type: "element",
tag: "span",
attributes: {
"class": {type: "string", value: "tc-inline-style"}
},
children: tree
};
if(classString) {
@@ -52,6 +49,9 @@ exports.parse = function() {
if(stylesString) {
$tw.utils.addAttributeToParseTreeNode(node,"style",stylesString);
}
if(!classString && !stylesString) {
$tw.utils.addClassToParseTreeNode(node,"tc-inline-style");
}
return [node];
};

View File

@@ -23,7 +23,7 @@ exports.types = {block: true};
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?\}\}(?:\r?\n|$)/mg;
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}(?:\r?\n|$)/mg;
};
exports.parse = function() {
@@ -31,13 +31,22 @@ exports.parse = function() {
this.parser.pos = this.matchRegExp.lastIndex;
// Get the match details
var template = $tw.utils.trim(this.match[2]),
textRef = $tw.utils.trim(this.match[1]);
textRef = $tw.utils.trim(this.match[1]),
params = this.match[3] ? this.match[3].split("|") : [];
// Prepare the transclude widget
var transcludeNode = {
type: "transclude",
attributes: {},
isBlock: true
};
$tw.utils.each(params,function(paramValue,index) {
var name = "" + index;
transcludeNode.attributes[name] = {
name: name,
type: "string",
value: paramValue
}
});
// Prepare the tiddler widget
var tr, targetTitle, targetField, targetIndex, tiddlerNode;
if(textRef) {
@@ -48,14 +57,14 @@ exports.parse = function() {
tiddlerNode = {
type: "tiddler",
attributes: {
tiddler: {type: "string", value: targetTitle}
tiddler: {name: "tiddler", type: "string", value: targetTitle}
},
isBlock: true,
children: [transcludeNode]
};
}
if(template) {
transcludeNode.attributes.tiddler = {type: "string", value: template};
transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: template};
if(textRef) {
return [tiddlerNode];
} else {
@@ -63,12 +72,12 @@ exports.parse = function() {
}
} else {
if(textRef) {
transcludeNode.attributes.tiddler = {type: "string", value: targetTitle};
transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: targetTitle};
if(targetField) {
transcludeNode.attributes.field = {type: "string", value: targetField};
transcludeNode.attributes["$field"] = {name: "$field", type: "string", value: targetField};
}
if(targetIndex) {
transcludeNode.attributes.index = {type: "string", value: targetIndex};
transcludeNode.attributes["$index"] = {name: "$index", type: "string", value: targetIndex};
}
return [tiddlerNode];
} else {

View File

@@ -23,7 +23,7 @@ exports.types = {inline: true};
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?\}\}/mg;
this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}/mg;
};
exports.parse = function() {
@@ -31,12 +31,21 @@ exports.parse = function() {
this.parser.pos = this.matchRegExp.lastIndex;
// Get the match details
var template = $tw.utils.trim(this.match[2]),
textRef = $tw.utils.trim(this.match[1]);
textRef = $tw.utils.trim(this.match[1]),
params = this.match[3] ? this.match[3].split("|") : [];
// Prepare the transclude widget
var transcludeNode = {
type: "transclude",
attributes: {}
};
$tw.utils.each(params,function(paramValue,index) {
var name = "" + index;
transcludeNode.attributes[name] = {
name: name,
type: "string",
value: paramValue
}
});
// Prepare the tiddler widget
var tr, targetTitle, targetField, targetIndex, tiddlerNode;
if(textRef) {
@@ -47,13 +56,13 @@ exports.parse = function() {
tiddlerNode = {
type: "tiddler",
attributes: {
tiddler: {type: "string", value: targetTitle}
tiddler: {name: "tiddler", type: "string", value: targetTitle}
},
children: [transcludeNode]
};
}
if(template) {
transcludeNode.attributes.tiddler = {type: "string", value: template};
transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: template};
if(textRef) {
return [tiddlerNode];
} else {
@@ -61,12 +70,12 @@ exports.parse = function() {
}
} else {
if(textRef) {
transcludeNode.attributes.tiddler = {type: "string", value: targetTitle};
transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: targetTitle};
if(targetField) {
transcludeNode.attributes.field = {type: "string", value: targetField};
transcludeNode.attributes["$field"] = {name: "$field", type: "string", value: targetField};
}
if(targetIndex) {
transcludeNode.attributes.index = {type: "string", value: targetIndex};
transcludeNode.attributes["$index"] = {name: "$index", type: "string", value: targetIndex};
}
return [tiddlerNode];
} else {

View File

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

View File

@@ -32,6 +32,7 @@ options: see below:
parseAsInline: true to parse text as inline instead of block
wiki: reference to wiki to use
_canonical_uri: optional URI of content if text is missing or empty
configTrimWhiteSpace: true to trim whitespace
*/
var WikiParser = function(type,text,options) {
this.wiki = options.wiki;
@@ -46,7 +47,9 @@ var WikiParser = function(type,text,options) {
this.source = text || "";
this.sourceLength = this.source.length;
// Flag for ignoring whitespace
this.configTrimWhiteSpace = false;
this.configTrimWhiteSpace = options.configTrimWhiteSpace !== undefined ? options.configTrimWhiteSpace : false;
// Parser mode
this.parseAsInline = options.parseAsInline;
// Set current parse position
this.pos = 0;
// Start with empty output
@@ -83,7 +86,7 @@ var WikiParser = function(type,text,options) {
// Parse any pragmas
var topBranch = this.parsePragmas();
// Parse the text into inline runs or blocks
if(options.parseAsInline) {
if(this.parseAsInline) {
topBranch.push.apply(topBranch,this.parseInlineRun());
} else {
topBranch.push.apply(topBranch,this.parseBlocks());

View File

@@ -1,64 +0,0 @@
/*\
title: $:/core/modules/savers/beaker.js
type: application/javascript
module-type: saver
Saves files using the Beaker browser's (https://beakerbrowser.com) Dat protocol (https://datproject.org/)
Compatible with beaker >= V0.7.2
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Set up the saver
*/
var BeakerSaver = function(wiki) {
this.wiki = wiki;
};
BeakerSaver.prototype.save = function(text,method,callback) {
var dat = new DatArchive("" + window.location),
pathname = ("" + window.location.pathname).split("#")[0];
dat.stat(pathname).then(function(value) {
if(value.isDirectory()) {
pathname = pathname + "/index.html";
}
dat.writeFile(pathname,text,"utf8").then(function(value) {
callback(null);
},function(reason) {
callback("Beaker Saver Write Error: " + reason);
});
},function(reason) {
callback("Beaker Saver Stat Error: " + reason);
});
return true;
};
/*
Information about this saver
*/
BeakerSaver.prototype.info = {
name: "beaker",
priority: 3000,
capabilities: ["save", "autosave"]
};
/*
Static method that returns true if this saver is capable of working
*/
exports.canSave = function(wiki) {
return !!window.DatArchive && location.protocol==="dat:";
};
/*
Create an instance of this saver
*/
exports.create = function(wiki) {
return new BeakerSaver(wiki);
};
})();

View File

@@ -1,64 +0,0 @@
/*\
title: $:/core/modules/savers/hyperdrive.js
type: application/javascript
module-type: saver
Saves files using the Hyperdrive Protocol (https://hypercore-protocol.org/#hyperdrive) Beaker browser beta-1.0 and later (https://beakerbrowser.com)
Compatible with beaker >= V1.0.0
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Set up the saver
*/
var HyperdriveSaver = function(wiki) {
this.wiki = wiki;
};
HyperdriveSaver.prototype.save = function(text,method,callback) {
var dat = beaker.hyperdrive.drive("" + window.location),
pathname = ("" + window.location.pathname).split("#")[0];
dat.stat(pathname).then(function(value) {
if(value.isDirectory()) {
pathname = pathname + "/index.html";
}
dat.writeFile(pathname,text,"utf8").then(function(value) {
callback(null);
},function(reason) {
callback("Hyperdrive Saver Write Error: " + reason);
});
},function(reason) {
callback("Hyperdrive Saver Stat Error: " + reason);
});
return true;
};
/*
Information about this saver
*/
HyperdriveSaver.prototype.info = {
name: "beaker-1.x",
priority: 3000,
capabilities: ["save", "autosave"]
};
/*
Static method that returns true if this saver is capable of working
*/
exports.canSave = function(wiki) {
return !!window.beaker && !!beaker.hyperdrive && location.protocol==="hyper:";
};
/*
Create an instance of this saver
*/
exports.create = function(wiki) {
return new HyperdriveSaver(wiki);
};
})();

View File

@@ -21,6 +21,7 @@ exports.handler = function(request,response,state) {
username: state.authenticatedUsername || state.server.get("anon-username") || "",
anonymous: !state.authenticatedUsername,
read_only: !state.server.isAuthorized("writers",state.authenticatedUsername),
logout_is_available: false,
space: {
recipe: "default"
},

View File

@@ -30,6 +30,16 @@ exports.handler = function(request,response,state) {
if(fields.revision) {
delete fields.revision;
}
// If this is a skinny tiddler, it means the client never got the full
// version of the tiddler to edit. So we must preserve whatever text
// already exists on the server, or else we'll inadvertently delete it.
if(fields._is_skinny !== undefined) {
var tiddler = state.wiki.getTiddler(title);
if(tiddler) {
fields.text = tiddler.fields.text;
}
delete fields._is_skinny;
}
state.wiki.addTiddler(new $tw.Tiddler(fields,{title: title}));
var changeCount = state.wiki.getChangeCount(title).toString();
response.writeHead(204, "OK",{

View File

@@ -87,13 +87,6 @@ exports.startup = function() {
}
});
}
// If we're being viewed on a data: URI then give instructions for how to save
if(document.location.protocol === "data:") {
$tw.rootWidget.dispatchEvent({
type: "tm-modal",
param: "$:/language/Modals/SaveInstructions"
});
}
};
})();

View File

@@ -121,7 +121,11 @@ exports.startup = function() {
});
// Set up the syncer object if we've got a syncadaptor
if($tw.syncadaptor) {
$tw.syncer = new $tw.Syncer({wiki: $tw.wiki, syncadaptor: $tw.syncadaptor});
$tw.syncer = new $tw.Syncer({
wiki: $tw.wiki,
syncadaptor: $tw.syncadaptor,
logging: $tw.wiki.getTiddlerText('$:/config/SyncLogging', "yes") === "yes"
});
}
// Setup the saver handler
$tw.saverHandler = new $tw.SaverHandler({

View File

@@ -17,6 +17,10 @@ var easing = "cubic-bezier(0.645, 0.045, 0.355, 1)"; // From http://easings.net/
var ZoominListView = function(listWidget) {
var self = this;
this.listWidget = listWidget;
this.textNodeLogger = new $tw.utils.Logger("zoomin story river view", {
enable: true,
colour: 'red'
});
// Get the index of the tiddler that is at the top of the history
var history = this.listWidget.wiki.getTiddlerDataCached(this.listWidget.historyTitle,[]),
targetTiddler;
@@ -48,7 +52,10 @@ ZoominListView.prototype.navigateTo = function(historyInfo) {
var listItemWidget = this.listWidget.children[listElementIndex],
targetElement = listItemWidget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!targetElement) {
return;
} else if (targetElement.nodeType === Node.TEXT_NODE) {
this.logTextNodeRoot(targetElement);
return;
}
// Make the new tiddler be position absolute and visible so that we can measure it
@@ -130,7 +137,10 @@ function findTitleDomNode(widget,targetClass) {
ZoominListView.prototype.insert = function(widget) {
var targetElement = widget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) {
if(!targetElement) {
return;
} else if (targetElement.nodeType === Node.TEXT_NODE) {
this.logTextNodeRoot(targetElement);
return;
}
// Make the newly inserted node position absolute and hidden
@@ -173,16 +183,21 @@ ZoominListView.prototype.remove = function(widget) {
var toWidgetDomNode = toWidget && toWidget.findFirstDomNode();
// Set up the tiddler we're moving back in
if(toWidgetDomNode) {
$tw.utils.addClass(toWidgetDomNode,"tc-storyview-zoomin-tiddler");
$tw.utils.setStyle(toWidgetDomNode,[
{display: "block"},
{transformOrigin: "50% 50%"},
{transform: "translateX(0px) translateY(0px) scale(10)"},
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", opacity " + duration + "ms " + easing},
{opacity: "0"},
{zIndex: "500"}
]);
this.currentTiddlerDomNode = toWidgetDomNode;
if (toWidgetDomNode.nodeType === Node.TEXT_NODE) {
this.logTextNodeRoot(toWidgetDomNode);
toWidgetDomNode = null;
} else {
$tw.utils.addClass(toWidgetDomNode,"tc-storyview-zoomin-tiddler");
$tw.utils.setStyle(toWidgetDomNode,[
{display: "block"},
{transformOrigin: "50% 50%"},
{transform: "translateX(0px) translateY(0px) scale(10)"},
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", opacity " + duration + "ms " + easing},
{opacity: "0"},
{zIndex: "500"}
]);
this.currentTiddlerDomNode = toWidgetDomNode;
}
}
// Animate them both
// Force layout
@@ -206,6 +221,10 @@ ZoominListView.prototype.remove = function(widget) {
return true; // Indicate that we'll delete the DOM node
};
ZoominListView.prototype.logTextNodeRoot = function(node) {
this.textNodeLogger.log($tw.language.getString("Error/ZoominTextNode") + " " + node.textContent);
};
exports.zoomin = ZoominListView;
})();

View File

@@ -402,6 +402,7 @@ Syncer.prototype.handleLazyLoadEvent = function(title) {
// Mark the tiddler as needing loading, and having already been lazily loaded
this.titlesToBeLoaded[title] = true;
this.titlesHaveBeenLazyLoaded[title] = true;
this.processTaskQueue();
}
}
};

View File

@@ -12,35 +12,113 @@ A barebones CSV parser
/*global $tw: false */
"use strict";
var QUOTE = '"';
var getCellInfo = function(text, start, length, SEPARATOR) {
var isCellQuoted = text.charAt(start) === QUOTE;
var cellStart = isCellQuoted ? start + 1 : start;
if (text.charAt(i) === SEPARATOR) {
return [cellStart, cellStart, false];
}
for (var i = cellStart; i < length; i++) {
var cellCharacter = text.charAt(i);
var isEOL = cellCharacter === "\n" || cellCharacter === "\r";
if (isEOL && !isCellQuoted) {
return [cellStart, i, false];
} else if (cellCharacter === SEPARATOR && !isCellQuoted) {
return [cellStart, i, false];
} else if (cellCharacter === QUOTE && isCellQuoted) {
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
if (nextCharacter !== QUOTE) {
return [cellStart, i, true];
} else {
i++;
}
}
}
return [cellStart, i, isCellQuoted];
}
exports.parseCsvString = function(text, options) {
if (!text) {
return [];
}
options = options || {};
var SEPARATOR = options.separator || ",",
length = text.length,
rows = [],
nextRow = [];
for (var i = 0; i < length; i++) {
var cellInfo = getCellInfo(text, i, length, SEPARATOR);
var cellText = text.substring(cellInfo[0], cellInfo[1]);
if (cellInfo[2]) {
cellText = cellText.replace(/""/g, '"');
cellInfo[1]++;
}
nextRow.push(cellText);
i = cellInfo[1];
var character = text.charAt(i);
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
if (character === "\r" || character === "\n") {
// Edge case for empty rows
if (nextRow.length === 1 && nextRow[0] === '') {
nextRow.length = 0;
}
rows.push(nextRow);
nextRow = [];
if (character === "\r") {
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
if (nextCharacter === "\n") {
i++;
}
}
}
}
// Special case if last cell in last row is an empty cell
if (text.charAt(length - 1) === SEPARATOR) {
nextRow.push("");
}
rows.push(nextRow);
return rows;
}
/*
Parse a CSV string with a header row and return an array of hashmaps.
*/
exports.parseCsvStringWithHeader = function(text,options) {
options = options || {};
var separator = options.separator || ",",
rows = text.split(/\r?\n/mg).map(function(row) {
return $tw.utils.trim(row);
}).filter(function(row) {
return row !== "";
});
if(rows.length < 1) {
return "Missing header row";
}
var headings = rows[0].split(separator),
results = [];
for(var row=1; row<rows.length; row++) {
var columns = rows[row].split(separator),
columnResult = Object.create(null);
if(columns.length !== headings.length) {
return "Malformed CSV row '" + rows[row] + "'";
var csv = $tw.utils.parseCsvString(text, options);
var headers = csv[0];
csv = csv.slice(1);
for (var i = 0; i < csv.length; i++) {
var row = csv[i];
var rowObject = Object.create(null);
for(var columnIndex=0; columnIndex<headers.length; columnIndex++) {
var columnName = headers[columnIndex];
if (columnName) {
rowObject[columnName] = $tw.utils.trim(row[columnIndex] || "");
}
}
for(var column=0; column<columns.length; column++) {
var columnName = headings[column];
columnResult[columnName] = $tw.utils.trim(columns[column] || "");
}
results.push(columnResult);
csv[i] = rowObject;
}
return results;
return csv;
}
})();

View File

@@ -12,6 +12,8 @@ Various static DOM-related utility functions.
/*global $tw: false */
"use strict";
var Popup = require("$:/core/modules/utils/dom/popup.js");
/*
Determines whether element 'a' contains element 'b'
Code thanks to John Resig, http://ejohn.org/blog/comparing-document-position/
@@ -26,6 +28,24 @@ exports.domMatchesSelector = function(node,selector) {
return node.matches ? node.matches(selector) : node.msMatchesSelector(selector);
};
/*
Select text in a an input or textarea (setSelectionRange crashes on certain input types)
*/
exports.setSelectionRangeSafe = function(node,start,end,direction) {
try {
node.setSelectionRange(start,end,direction);
} catch(e) {
node.select();
}
};
/*
Select the text in an input or textarea by position
*/
exports.setSelectionByPosition = function(node,selectFromStart,selectFromEnd) {
$tw.utils.setSelectionRangeSafe(node,selectFromStart,node.value.length - selectFromEnd);
};
exports.removeChildren = function(node) {
while(node.hasChildNodes()) {
node.removeChild(node.firstChild);
@@ -294,8 +314,21 @@ exports.collectDOMVariables = function(selectedNode,domNode,event) {
});
if(selectedNode.offsetLeft) {
// Add a variable with a popup coordinate string for the selected node
variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")";
// Add variables with a (relative and absolute) popup coordinate string for the selected node
var nodeRect = {
left: selectedNode.offsetLeft,
top: selectedNode.offsetTop,
width: selectedNode.offsetWidth,
height: selectedNode.offsetHeight
};
variables["tv-popup-coords"] = Popup.buildCoordinates(Popup.coordinatePrefix.csOffsetParent,nodeRect);
var absRect = $tw.utils.extend({}, nodeRect);
for (var currentNode = selectedNode.offsetParent; currentNode; currentNode = currentNode.offsetParent) {
absRect.left += currentNode.offsetLeft;
absRect.top += currentNode.offsetTop;
}
variables["tv-popup-abs-coords"] = Popup.buildCoordinates(Popup.coordinatePrefix.csAbsolute,absRect);
// Add variables for offset of selected node
variables["tv-selectednode-posx"] = selectedNode.offsetLeft.toString();

View File

@@ -26,6 +26,8 @@ Display a modal dialogue
options: see below
Options include:
downloadLink: Text of a big download link to include
event: widget event
variables: from event.paramObject
*/
Modal.prototype.display = function(title,options) {
options = options || {};
@@ -209,6 +211,10 @@ Modal.prototype.display = function(title,options) {
headerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
bodyWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
footerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
// Whether to close the modal dialog when the mask (area outside the modal) is clicked
if(tiddler.fields && (tiddler.fields["mask-closable"] === "yes" || tiddler.fields["mask-closable"] === "true")) {
modalBackdrop.addEventListener("click",closeHandler,false);
}
// Set the initial styles for the message
$tw.utils.setStyle(modalBackdrop,[
{opacity: "0"}

View File

@@ -22,6 +22,19 @@ var Popup = function(options) {
this.popups = []; // Array of {title:,wiki:,domNode:} objects
};
/*
Global regular expression for parsing the location of a popup.
This is also used by the Reveal widget.
*/
exports.popupLocationRegExp = /^(@?)\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/
/*
Objekt containing the available prefixes for coordinates build with the `buildCoordinates` function:
- csOffsetParent: Uses a coordinate system based on the offset parent (no prefix).
- csAbsolute: Use an absolute coordinate system (prefix "@").
*/
exports.coordinatePrefix = { csOffsetParent: "", csAbsolute: "@" }
/*
Trigger a popup open or closed. Parameters are in a hashmap:
title: title of the tiddler where the popup details are stored
@@ -136,8 +149,17 @@ Popup.prototype.show = function(options) {
height: options.domNode.offsetHeight
};
}
var popupRect = "(" + rect.left + "," + rect.top + "," +
rect.width + "," + rect.height + ")";
if(options.absolute && options.domNode) {
// Walk the offsetParent chain and add the position of the offsetParents to make
// the position absolute to the root node of the page.
var currentNode = options.domNode.offsetParent;
while(currentNode) {
rect.left += currentNode.offsetLeft;
rect.top += currentNode.offsetTop;
currentNode = currentNode.offsetParent;
}
}
var popupRect = exports.buildCoordinates(options.absolute?exports.coordinatePrefix.csAbsolute:exports.coordinatePrefix.csOffsetParent,rect);
if(options.noStateReference) {
options.wiki.setText(options.title,"text",undefined,popupRect);
} else {
@@ -172,13 +194,54 @@ Popup.prototype.cancel = function(level) {
};
/*
Returns true if the specified title and text identifies an active popup
Returns true if the specified title and text identifies an active popup.
This function is safe to call, even if the popup class was not initialized.
*/
Popup.prototype.readPopupState = function(text) {
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/;
return popupLocationRegExp.test(text);
exports.readPopupState = function(text) {
return exports.popupLocationRegExp.test(text);
};
/*
Parses a coordinate string in the format `(x,y,w,h)` or `@(x,y,z,h)` and returns
an object containing the position, width and height. The absolute-Mark is boolean
value that indicates the coordinate system of the coordinates. If they start with
an `@`, `absolute` is set to true and the coordinates are relative to the root
element. If the initial `@` is missing, they are relative to the offset parent
element and `absoute` is false.
This function is safe to call, even if the popup class was not initialized.
*/
exports.parseCoordinates = function(coordinates) {
var match = exports.popupLocationRegExp.exec(coordinates);
if(match) {
return {
absolute: (match[1] === "@"),
left: parseFloat(match[2]),
top: parseFloat(match[3]),
width: parseFloat(match[4]),
height: parseFloat(match[5])
};
} else {
return false;
}
}
/*
Builds a coordinate string from a coordinate system identifier and an object
containing the left, top, width and height values.
Use constants defined in coordinatePrefix to specify a coordinate system.
If one of the parameters is invalid for building a coordinate string `(0,0,0,0)`
will be returned.
This function is safe to call, even if the popup class was not initialized.
*/
exports.buildCoordinates = function(prefix,position) {
var coord = prefix + "(" + position.left + "," + position.top + "," + position.width + "," + position.height + ")";
if (exports.popupLocationRegExp.test(coord)) {
return coord;
} else {
return "(0,0,0,0)";
}
}
exports.Popup = Popup;
})();

View File

@@ -228,7 +228,7 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
hasUnsafeFields = hasUnsafeFields || /[\x00-\x1F]/mg.test(value);
hasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);
}
hasUnsafeFields = hasUnsafeFields || /:/mg.test(fieldName);
hasUnsafeFields = hasUnsafeFields || /:|#/mg.test(fieldName);
});
// Check for field values
if(hasUnsafeFields) {
@@ -238,7 +238,7 @@ exports.generateTiddlerFileInfo = function(tiddler,options) {
} else {
// Save as a .tid or a text/binary file plus a .meta file
var tiddlerType = tiddler.fields.type || "text/vnd.tiddlywiki";
if(tiddlerType === "text/vnd.tiddlywiki") {
if(tiddlerType === "text/vnd.tiddlywiki" || tiddler.hasField("_canonical_uri")) {
// Save as a .tid file
fileInfo.type = "application/x-tiddler";
fileInfo.hasMetaFile = false;
@@ -393,7 +393,7 @@ exports.generateTiddlerFilepath = function(title,options) {
} while(fs.existsSync(fullPath));
// If the last write failed with an error, or if path does not start with:
// the resolved options.directory, the resolved wikiPath directory, the wikiTiddlersPath directory,
// or the 'originalpath' directory, then encodeURIComponent() and resolve to tiddler directory.
// or the 'originalpath' directory, then $tw.utils.encodeURIComponentExtended() and resolve to tiddler directory.
var writePath = $tw.hooks.invokeHook("th-make-tiddler-path",fullPath,fullPath),
encode = (options.fileInfo || {writeError: false}).writeError == true;
if(!encode) {
@@ -403,7 +403,7 @@ exports.generateTiddlerFilepath = function(title,options) {
writePath.indexOf(path.resolve($tw.boot.wikiTiddlersPath,originalpath)) == 0 );
}
if(encode) {
writePath = path.resolve(directory,encodeURIComponent(fullPath));
writePath = path.resolve(directory,$tw.utils.encodeURIComponentExtended(fullPath));
}
// Return the full path to the file
return writePath;

View File

@@ -15,10 +15,11 @@ function LinkedList() {
LinkedList.prototype.clear = function() {
// LinkedList performs the duty of both the head and tail node
this.next = Object.create(null);
this.prev = Object.create(null);
this.first = undefined;
this.last = undefined;
this.next = new LLMap();
this.prev = new LLMap();
// Linked list head initially points to itself
this.next.set(null, null);
this.prev.set(null, null);
this.length = 0;
};
@@ -41,28 +42,29 @@ Push behaves like array.push and accepts multiple string arguments. But it also
accepts a single array argument too, to be consistent with its other methods.
*/
LinkedList.prototype.push = function(/* values */) {
var values = arguments;
var i, values = arguments;
if($tw.utils.isArray(values[0])) {
values = values[0];
}
for(var i = 0; i < values.length; i++) {
for(i = 0; i < values.length; i++) {
_assertString(values[i]);
}
for(var i = 0; i < values.length; i++) {
for(i = 0; i < values.length; i++) {
_linkToEnd(this,values[i]);
}
return this.length;
};
LinkedList.prototype.pushTop = function(value) {
var t;
if($tw.utils.isArray(value)) {
for (var t=0; t<value.length; t++) {
for (t=0; t<value.length; t++) {
_assertString(value[t]);
}
for(var t=0; t<value.length; t++) {
for(t=0; t<value.length; t++) {
_removeOne(this,value[t]);
}
for(var t=0; t<value.length; t++) {
for(t=0; t<value.length; t++) {
_linkToEnd(this,value[t]);
}
} else {
@@ -74,11 +76,11 @@ LinkedList.prototype.pushTop = function(value) {
LinkedList.prototype.each = function(callback) {
var visits = Object.create(null),
value = this.first;
while(value !== undefined) {
value = this.next.get(null);
while(value !== null) {
callback(value);
var next = this.next[value];
if(typeof next === "object") {
var next = this.next.get(value);
if(Array.isArray(next)) {
var i = visits[value] || 0;
visits[value] = i+1;
value = next[i];
@@ -105,91 +107,79 @@ LinkedList.prototype.makeTiddlerIterator = function(wiki) {
};
function _removeOne(list,value) {
var prevEntry = list.prev[value],
nextEntry = list.next[value],
var nextEntry = list.next.get(value);
if(nextEntry === undefined) {
return;
}
var prevEntry = list.prev.get(value),
prev = prevEntry,
next = nextEntry;
if(typeof nextEntry === "object") {
next = nextEntry,
ref;
if(Array.isArray(nextEntry)) {
next = nextEntry[0];
prev = prevEntry[0];
}
// Relink preceding element.
if(list.first === value) {
list.first = next
} else if(prev !== undefined) {
if(typeof list.next[prev] === "object") {
if(next === undefined) {
// Must have been last, and 'i' would be last element.
list.next[prev].pop();
} else {
var i = list.next[prev].indexOf(value);
list.next[prev][i] = next;
}
} else {
list.next[prev] = next;
}
ref = list.next.get(prev);
if(Array.isArray(ref)) {
var i = ref.indexOf(value);
ref[i] = next;
} else {
return;
list.next.set(prev,next);
}
// Now relink following element
// Check "next !== undefined" rather than "list.last === value" because
// we need to know if the FIRST value is the last in the list, not the last.
if(next !== undefined) {
if(typeof list.prev[next] === "object") {
if(prev === undefined) {
// Must have been first, and 'i' would be 0.
list.prev[next].shift();
} else {
var i = list.prev[next].indexOf(value);
list.prev[next][i] = prev;
}
} else {
list.prev[next] = prev;
}
ref = list.prev.get(next);
if(Array.isArray(ref)) {
var i = ref.indexOf(value);
ref[i] = prev;
} else {
list.last = prev;
list.prev.set(next,prev);
}
// Delink actual value. If it uses arrays, just remove first entries.
if(typeof nextEntry === "object") {
if(Array.isArray(nextEntry) && nextEntry.length > 1) {
nextEntry.shift();
prevEntry.shift();
} else {
list.next[value] = undefined;
list.prev[value] = undefined;
list.next.set(value,undefined);
list.prev.set(value,undefined);
}
list.length -= 1;
};
// Sticks the given node onto the end of the list.
function _linkToEnd(list,value) {
if(list.first === undefined) {
list.first = value;
var old = list.next.get(value);
var last = list.prev.get(null);
// Does it already exists?
if(old !== undefined) {
if(!Array.isArray(old)) {
old = [old];
list.next.set(value,old);
list.prev.set(value,[list.prev.get(value)]);
}
old.push(null);
list.prev.get(value).push(last);
} else {
// Does it already exists?
if(list.first === value || list.prev[value] !== undefined) {
if(typeof list.next[value] === "string") {
list.next[value] = [list.next[value]];
list.prev[value] = [list.prev[value]];
} else if(typeof list.next[value] === "undefined") {
// list.next[value] must be undefined.
// Special case. List already has 1 value. It's at the end.
list.next[value] = [];
list.prev[value] = [list.prev[value]];
}
list.prev[value].push(list.last);
// We do NOT append a new value onto "next" list. Iteration will
// figure out it must point to End-of-List on its own.
} else {
list.prev[value] = list.last;
}
// Make the old last point to this new one.
if(typeof list.next[list.last] === "object") {
list.next[list.last].push(value);
} else {
list.next[list.last] = value;
}
list.next.set(value,null);
list.prev.set(value,last);
}
// Make the old last point to this new one.
if(value !== last) {
var array = list.next.get(last);
if(Array.isArray(array)) {
array[array.length-1] = value;
} else {
list.next.set(last,value);
}
list.prev.set(null,value);
} else {
// Edge case, the pushed value was already the last value.
// The second-to-last nextPtr for that value must point to itself now.
var array = list.next.get(last);
array[array.length-2] = value;
}
list.last = value;
list.length += 1;
};
@@ -199,6 +189,20 @@ function _assertString(value) {
}
};
var LLMap = function() {
this.map = Object.create(null);
};
// Just a wrapper so our object map can also accept null.
LLMap.prototype = {
set: function(key,val) {
(key === null) ? (this.null = val) : (this.map[key] = val);
},
get: function(key) {
return (key === null) ? this.null : this.map[key];
}
};
exports.LinkedList = LinkedList;
})();

View File

@@ -65,10 +65,8 @@ exports.addClassToParseTreeNode = function(node,classString) {
// If the class attribute does not exist, we must create it first.
attribute = {name: "class", type: "string", value: ""};
node.attributes["class"] = attribute;
if(node.orderedAttributes) {
// If there are orderedAttributes, we've got to add them there too.
node.orderedAttributes.push(attribute);
}
node.orderedAttributes = node.orderedAttributes || [];
node.orderedAttributes.push(attribute);
}
if(attribute.type === "string") {
if(attribute.value !== "") {
@@ -88,10 +86,8 @@ exports.addStyleToParseTreeNode = function(node,name,value) {
if(!attribute) {
attribute = {name: "style", type: "string", value: ""};
node.attributes.style = attribute;
if(node.orderedAttributes) {
// If there are orderedAttributes, we've got to add them there too.
node.orderedAttributes.push(attribute);
}
node.orderedAttributes = node.orderedAttributes || [];
node.orderedAttributes.push(attribute);
}
if(attribute.type === "string") {
attribute.value += name + ":" + value + ";";

View File

@@ -354,6 +354,9 @@ exports.formatDateString = function(date,template) {
var result = "",
t = template,
matches = [
[/^TIMESTAMP/, function() {
return date.getTime();
}],
[/^0hh12/, function() {
return $tw.utils.pad($tw.utils.getHours12(date));
}],
@@ -682,9 +685,19 @@ exports.escapeRegExp = function(s) {
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&');
};
/*
Extended version of encodeURIComponent that encodes additional characters including
those that are illegal within filepaths on various platforms including Windows
*/
exports.encodeURIComponentExtended = function(s) {
return encodeURIComponent(s).replace(/[!'()*]/g,function(c) {
return "%" + c.charCodeAt(0).toString(16).toUpperCase();
});
};
// Checks whether a link target is external, i.e. not a tiddler title
exports.isLinkExternal = function(to) {
var externalRegExp = /^(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\s<>{}\[\]`|"\\^]+(?:\/|\b)/i;
var externalRegExp = /^(?:file|http|https|mailto|ftp|irc|news|obsidian|data|skype):[^\s<>{}\[\]`|"\\^]+(?:\/|\b)/i;
return externalRegExp.test(to);
};

View File

@@ -14,6 +14,8 @@ Action widget to trigger a popup.
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var Popup = require("$:/core/modules/utils/dom/popup.js");
var ActionPopupWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
@@ -57,20 +59,20 @@ Invoke the action associated with this widget
*/
ActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) {
// Trigger the popup
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
match = popupLocationRegExp.exec(this.actionCoords || "");
if(match) {
var coordinates = Popup.parseCoordinates(this.actionCoords || "");
if(coordinates) {
$tw.popup.triggerPopup({
domNode: null,
domNodeRect: {
left: parseFloat(match[1]),
top: parseFloat(match[2]),
width: parseFloat(match[3]),
height: parseFloat(match[4])
left: coordinates.left,
top: coordinates.top,
width: coordinates.width,
height: coordinates.height
},
title: this.actionState,
wiki: this.wiki,
floating: this.floating
floating: this.floating,
absolute: coordinates.absolute
});
} else {
$tw.popup.cancel(0);

View File

@@ -14,6 +14,8 @@ Button widget
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var Popup = require("$:/core/modules/utils/dom/popup.js");
var ButtonWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
@@ -147,7 +149,7 @@ ButtonWidget.prototype.isSelected = function() {
ButtonWidget.prototype.isPoppedUp = function() {
var tiddler = this.popupTitle ? this.wiki.getTiddler(this.popupTitle) : this.wiki.getTiddler(this.popup);
var result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false;
var result = tiddler && tiddler.fields.text ? Popup.readPopupState(tiddler.fields.text) : false;
return result;
};
@@ -173,6 +175,7 @@ ButtonWidget.prototype.triggerPopup = function(event) {
if(this.popupTitle) {
$tw.popup.triggerPopup({
domNode: this.domNodes[0],
absolute: (this.popupAbsCoords === "yes"),
title: this.popupTitle,
wiki: this.wiki,
noStateReference: true
@@ -180,6 +183,7 @@ ButtonWidget.prototype.triggerPopup = function(event) {
} else {
$tw.popup.triggerPopup({
domNode: this.domNodes[0],
absolute: (this.popupAbsCoords === "yes"),
title: this.popup,
wiki: this.wiki
});
@@ -223,6 +227,7 @@ ButtonWidget.prototype.execute = function() {
this.setField = this.getAttribute("setField");
this.setIndex = this.getAttribute("setIndex");
this.popupTitle = this.getAttribute("popupTitle");
this.popupAbsCoords = this.getAttribute("popupAbsCoords", "no");
this.tabIndex = this.getAttribute("tabindex");
this.isDisabled = this.getAttribute("disabled","no");
// Make child widgets
@@ -252,7 +257,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
*/
ButtonWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
this.refreshSelf();
return true;
} else if(changedAttributes["class"]) {

View File

@@ -232,12 +232,34 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
};
DropZoneWidget.prototype.handlePasteEvent = function(event) {
var self = this,
readFileCallback = function(tiddlerFieldsArray) {
var self = this;
var readFileCallback = function(tiddlerFieldsArray) {
self.readFileCallback(tiddlerFieldsArray);
};
var getItem = function(type) {
type = type || "text/plain";
return function(str) {
// Use the deserializer specified if any
if(self.dropzoneDeserializer) {
tiddlerFields = self.wiki.deserializeTiddlers(null,str,{title: self.wiki.generateNewTitle("Untitled " + type)},{deserializer:self.dropzoneDeserializer});
if(tiddlerFields && tiddlerFields.length) {
readFileCallback(tiddlerFields);
}
} else {
tiddlerFields = {
title: self.wiki.generateNewTitle("Untitled " + type),
text: str,
type: type
};
if($tw.log.IMPORT) {
console.log("Importing string '" + str + "', type: '" + type + "'");
}
readFileCallback([tiddlerFields]);
}
}
};
// Let the browser handle it if we're in a textarea or input box
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable) {
if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable && !event.twEditor) {
var self = this,
items = event.clipboardData.items;
// Enumerate the clipboard items
@@ -251,27 +273,10 @@ DropZoneWidget.prototype.handlePasteEvent = function(event) {
});
} else if(item.kind === "string") {
// Create tiddlers from string items
var tiddlerFields,
type = item.type;
item.getAsString(function(str) {
// Use the deserializer specified if any
if(self.dropzoneDeserializer) {
tiddlerFields = self.wiki.deserializeTiddlers(null,str,{title: self.wiki.generateNewTitle("Untitled")},{deserializer:self.dropzoneDeserializer});
if(tiddlerFields && tiddlerFields.length) {
readFileCallback(tiddlerFields);
}
} else {
tiddlerFields = {
title: self.wiki.generateNewTitle("Untitled"),
text: str,
type: type
};
if($tw.log.IMPORT) {
console.log("Importing string '" + str + "', type: '" + type + "'");
}
readFileCallback([tiddlerFields]);
}
});
var tiddlerFields;
// It's important to give getAsString a closure with the right type
// So it can be added to the import queue
item.getAsString(getItem(item.type));
}
}
// Tell the browser that we've handled the paste

View File

@@ -34,6 +34,10 @@ ElementWidget.prototype.render = function(parent,nextSibling) {
if($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) {
this.tag = "safe-" + this.tag;
}
// Restrict tag name to digits, letts and dashes
this.tag = this.tag.replace(/[^0-9a-zA-Z\-]/mg,"");
// Default to a span
this.tag = this.tag || "span";
// Adjust headings by the current base level
var headingLevel = ["h1","h2","h3","h4","h5","h6"].indexOf(this.tag);
if(headingLevel !== -1) {

View File

@@ -0,0 +1,63 @@
/*\
title: $:/core/modules/widgets/error.js
type: application/javascript
module-type: widget
Error widget
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var ErrorWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
ErrorWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
ErrorWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
var message = this.getAttribute("$message","Unknown error"),
domNode = this.document.createElement("span");
domNode.appendChild(this.document.createTextNode(message));
domNode.className = "tc-error";
parent.insertBefore(domNode,nextSibling);
this.domNodes.push(domNode);
};
/*
Compute the internal state of the widget
*/
ErrorWidget.prototype.execute = function() {
// Nothing to do for a text node
};
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
ErrorWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes["$message"]) {
this.refreshSelf();
return true;
} else {
return false;
}
};
exports.error = ErrorWidget;
})();

View File

@@ -0,0 +1,30 @@
/*\
title: $:/core/modules/widgets/fill.js
type: application/javascript
module-type: widget
Sub-widget used by the transclude widget for specifying values for slots within transcluded content. It doesn't do anything by itself because the transclude widget only ever deals with the parse tree nodes, and doesn't instantiate the widget itself
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var FillWidget = function(parseTreeNode,options) {
// Initialise
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
FillWidget.prototype = new Widget();
exports.fill = FillWidget;
})();

View File

@@ -42,10 +42,16 @@ Compute the internal state of the widget
GenesisWidget.prototype.execute = function() {
var self = this;
// Collect attributes
this.genesisType = this.getAttribute("$type","element");
this.genesisType = this.getAttribute("$type");
this.genesisRemappable = this.getAttribute("$remappable","yes") === "yes";
this.genesisNames = this.getAttribute("$names","");
this.genesisValues = this.getAttribute("$values","");
this.genesisIsBlock = this.getAttribute("$mode",this.parseTreeNode.isBlock && "block") === "block";
// Do not create a child widget if the $type attribute is missing or blank
if(!this.genesisType) {
this.makeChildWidgets(this.parseTreeNode.children);
return;
}
// Construct parse tree
var isElementWidget = this.genesisType.charAt(0) !== "$",
nodeType = isElementWidget ? "element" : this.genesisType.substr(1),
@@ -55,6 +61,7 @@ GenesisWidget.prototype.execute = function() {
tag: nodeTag,
attributes: {},
orderedAttributes: [],
isBlock: this.genesisIsBlock,
children: this.parseTreeNode.children || [],
isNotRemappable: !this.genesisRemappable
}];

View File

@@ -52,38 +52,44 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) {
var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true});
if(parser) {
var parseTreeNode = parser.tree[0];
while(parseTreeNode && parseTreeNode.type === "set") {
while(parseTreeNode && ["setvariable","set","parameters"].indexOf(parseTreeNode.type) !== -1) {
var node = {
type: "set",
attributes: parseTreeNode.attributes,
params: parseTreeNode.params,
isMacroDefinition: parseTreeNode.isMacroDefinition
isMacroDefinition: parseTreeNode.isMacroDefinition,
isFunctionDefinition: parseTreeNode.isFunctionDefinition,
isProcedureDefinition: parseTreeNode.isProcedureDefinition,
isWidgetDefinition: parseTreeNode.isWidgetDefinition,
configTrimWhiteSpace: parseTreeNode.configTrimWhiteSpace
};
if (parseTreeNode.isMacroDefinition) {
// Macro definitions can be folded into
// current widget instead of adding
// another link to the chain.
var widget = widgetPointer.makeChildWidget(node);
widget.computeAttributes();
widget.execute();
// We SHALLOW copy over all variables
// in widget. We can't use
// $tw.utils.assign, because that copies
// up the prototype chain, which we
// don't want.
$tw.utils.each(Object.keys(widget.variables), function(key) {
widgetPointer.variables[key] = widget.variables[key];
});
} else {
widgetPointer.children = [widgetPointer.makeChildWidget(node)];
// No more regenerating children for
// this widget. If it needs to refresh,
// it'll do so along with the the whole
// importvariable tree.
if (widgetPointer != this) {
widgetPointer.makeChildWidgets = function(){};
if(parseTreeNode.type === "set" || parseTreeNode.type === "setvariable") {
if(parseTreeNode.isMacroDefinition || parseTreeNode.isProcedureDefinition || parseTreeNode.isWidgetDefinition || parseTreeNode.isFunctionDefinition) {
// Macro definitions can be folded into
// current widget instead of adding
// another link to the chain.
var widget = widgetPointer.makeChildWidget(node);
widget.computeAttributes();
widget.execute();
// We SHALLOW copy over all variables
// in widget. We can't use
// $tw.utils.assign, because that copies
// up the prototype chain, which we
// don't want.
$tw.utils.each(Object.keys(widget.variables), function(key) {
widgetPointer.variables[key] = widget.variables[key];
});
} else {
widgetPointer.children = [widgetPointer.makeChildWidget(node)];
// No more regenerating children for
// this widget. If it needs to refresh,
// it'll do so along with the the whole
// importvariable tree.
if (widgetPointer != this) {
widgetPointer.makeChildWidgets = function(){};
}
widgetPointer = widgetPointer.children[0];
}
widgetPointer = widgetPointer.children[0];
}
parseTreeNode = parseTreeNode.children && parseTreeNode.children[0];
}

View File

@@ -53,6 +53,10 @@ KeyboardWidget.prototype.render = function(parent,nextSibling) {
};
KeyboardWidget.prototype.handleChangeEvent = function(event) {
if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) {
return true;
}
var keyInfo = $tw.keyboardManager.getMatchingKeyDescriptor(event,this.keyInfoArray);
if(keyInfo) {
var handled = this.invokeActions(this,event);

View File

@@ -53,7 +53,9 @@ LetWidget.prototype.computeAttributes = function() {
name = attribute.name;
// Now that it's prepped, we're allowed to look this variable up
// when defining later variables
self.currentValueFor[name] = value;
if(value !== undefined) {
self.currentValueFor[name] = value;
}
});
// Run through again, setting variables and looking for differences
$tw.utils.each(this.currentValueFor,function(value,name) {

View File

@@ -97,8 +97,8 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
// Expand the tv-wikilink-template variable to construct the href
var wikiLinkTemplateMacro = this.getVariable("tv-wikilink-template"),
wikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : "#$uri_encoded$";
wikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,"$uri_encoded$",encodeURIComponent(this.to));
wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$uri_doubleencoded$",encodeURIComponent(encodeURIComponent(this.to)));
wikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,"$uri_encoded$",$tw.utils.encodeURIComponentExtended(this.to));
wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$uri_doubleencoded$",$tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(this.to)));
}
// Override with the value of tv-get-export-link if defined
wikiLinkText = this.getVariable("tv-get-export-link",{params: [{name: "to",value: this.to}],defaultValue: wikiLinkText});

View File

@@ -37,7 +37,7 @@ MacroCallWidget.prototype.render = function(parent,nextSibling) {
Compute the internal state of the widget
*/
MacroCallWidget.prototype.execute = function() {
// Get the parse type if specified
this.macroName = this.parseTreeNode.name || this.getAttribute("$name"),
this.parseType = this.getAttribute("$type","text/vnd.tiddlywiki");
this.renderOutput = this.getAttribute("$output","text/html");
// Merge together the parameters specified in the parse tree with the specified attributes
@@ -47,49 +47,26 @@ MacroCallWidget.prototype.execute = function() {
params.push({name: name, value: attribute});
}
});
// Get the macro value
var macroName = this.parseTreeNode.name || this.getAttribute("$name"),
variableInfo = this.getVariableInfo(macroName,{params: params}),
text = variableInfo.text,
parseTreeNodes;
// Are we rendering to HTML?
if(this.renderOutput === "text/html") {
// If so we'll return the parsed macro
// Check if we've already cached parsing this macro
var mode = this.parseTreeNode.isBlock ? "blockParser" : "inlineParser",
parser;
if(variableInfo.srcVariable && variableInfo.srcVariable[mode]) {
parser = variableInfo.srcVariable[mode];
} else {
parser = this.wiki.parseText(this.parseType,text,
{parseAsInline: !this.parseTreeNode.isBlock});
if(variableInfo.isCacheable && variableInfo.srcVariable) {
variableInfo.srcVariable[mode] = parser;
}
}
var parseTreeNodes = parser ? parser.tree : [];
// Wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__"
var attributes = {};
$tw.utils.each(variableInfo.params,function(param) {
var name = "__" + param.name + "__";
attributes[name] = {
name: name,
type: "string",
value: param.value
};
});
// Make a transclude widget
var positionalName = 0,
parseTreeNodes = [{
type: "vars",
attributes: attributes,
children: parseTreeNodes
type: "transclude",
isBlock: this.parseTreeNode.isBlock
}];
} else if(this.renderOutput === "text/raw") {
parseTreeNodes = [{type: "text", text: text}];
} else {
// Otherwise, we'll render the text
var plainText = this.wiki.renderText("text/plain",this.parseType,text,{parentWidget: this});
parseTreeNodes = [{type: "text", text: plainText}];
}
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$variable",this.macroName);
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$type",this.parseType);
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$output",this.renderOutput);
$tw.utils.each(params,function(param) {
var name = param.name;
if(name) {
if(name.charAt(0) === "$") {
name = "$" + name;
}
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],name,param.value);
} else {
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],(positionalName++) + "",param.value);
}
});
// Construct the child widgets
this.makeChildWidgets(parseTreeNodes);
};

View File

@@ -82,7 +82,7 @@ MessageCatcherWidget.prototype.render = function(parent,nextSibling) {
}
});
// Render children
this.renderChildren(parent,null);
this.renderChildren(parent,nextSibling);
};
/*

View File

@@ -227,10 +227,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
originalTitle = tiddler ? tiddler.fields["draft.of"] : "",
originalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,
confirmationTitle,
win = event.event && event.event.view ? event.event.view : window;
if(!tiddler) {
return false;
}
win = event.event && event.event.view ? event.event.view : window;
// Check if the tiddler we're deleting is in draft mode
if(originalTitle) {
// If so, we'll prompt for confirmation referencing the original tiddler
@@ -240,7 +237,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
confirmationTitle = title;
}
// Seek confirmation
if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !win.confirm($tw.language.getString(
if(((originalTitle && this.wiki.getTiddler(originalTitle)) || (tiddler && ((tiddler.fields.text || "") !== ""))) && !win.confirm($tw.language.getString(
"ConfirmDeleteTiddler",
{variables:
{title: confirmationTitle}
@@ -257,8 +254,10 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
this.removeTitleFromStory(storyList,originalTitle);
}
// Invoke the hook function and delete this tiddler
$tw.hooks.invokeHook("th-deleting-tiddler",tiddler);
this.wiki.deleteTiddler(title);
if(tiddler) {
$tw.hooks.invokeHook("th-deleting-tiddler",tiddler);
this.wiki.deleteTiddler(title);
}
// Remove the closed tiddler from the story
this.removeTitleFromStory(storyList,title);
this.saveStoryList(storyList);
@@ -500,7 +499,8 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
// Get the tiddlers
var tiddlers = $tw.utils.parseJSONSafe(event.param,[]);
// Get the current $:/Import tiddler
var importTitle = event.importTitle ? event.importTitle : IMPORT_TITLE,
var paramObject = event.paramObject || {},
importTitle = event.importTitle || paramObject.importTitle || IMPORT_TITLE,
importTiddler = this.wiki.getTiddler(importTitle),
importData = this.wiki.getTiddlerData(importTitle,{}),
newFields = new Object({
@@ -541,7 +541,7 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
newFields.text = JSON.stringify(importData,null,$tw.config.preferences.jsonSpaces);
this.wiki.addTiddler(new $tw.Tiddler(importTiddler,newFields));
// Update the story and history details
var autoOpenOnImport = event.autoOpenOnImport ? event.autoOpenOnImport : this.getVariable("tv-auto-open-on-import");
var autoOpenOnImport = event.autoOpenOnImport || paramObject.autoOpenOnImport || this.getVariable("tv-auto-open-on-import");
if(autoOpenOnImport !== "no") {
var storyList = this.getStoryList(),
history = [];

View File

@@ -0,0 +1,96 @@
/*\
title: $:/core/modules/widgets/parameters.js
type: application/javascript
module-type: widget
Widget for definition of transclusion parameters
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget,
TranscludeWidget = require("$:/core/modules/widgets/transclude.js").transclude;
var ParametersWidget = function(parseTreeNode,options) {
// Initialise
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
ParametersWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
ParametersWidget.prototype.render = function(parent,nextSibling) {
// Call the constructor
Widget.call(this);
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
this.renderChildren(parent,nextSibling);
};
/*
Compute the internal state of the widget
*/
ParametersWidget.prototype.execute = function() {
var self = this;
this.parametersDepth = Math.max(parseInt(this.getAttribute("$depth","1"),10) || 1,1);
// Find the parent transclusions
var pointer = this.parentWidget,
depth = this.parametersDepth;
while(pointer) {
if(pointer instanceof TranscludeWidget) {
depth--;
if(depth <= 0) {
break;
}
}
pointer = pointer.parentWidget;
}
// Process each parameter
if(pointer instanceof TranscludeWidget) {
// Get the value for each defined parameter
$tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(self.parseTreeNode),function(attr,index) {
var name = attr.name;
// If the attribute name starts with $$ then reduce to a single dollar
if(name.substr(0,2) === "$$") {
name = name.substr(1);
}
var value = pointer.getTransclusionParameter(name,index,self.getAttribute(attr.name,""));
self.setVariable(name,value);
});
// Assign any metaparameters
$tw.utils.each(pointer.getTransclusionMetaParameters(),function(getValue,name) {
var variableName = self.getAttribute("$" + name);
if(variableName) {
self.setVariable(variableName,getValue(name));
}
});
}
// Construct the child widgets
this.makeChildWidgets();
};
/*
Refresh the widget by ensuring our attributes are up to date
*/
ParametersWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(Object.keys(changedAttributes).length) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports.parameters = ParametersWidget;
})();

View File

@@ -14,6 +14,8 @@ Reveal widget
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var Popup = require("$:/core/modules/utils/dom/popup.js");
var RevealWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
@@ -94,6 +96,13 @@ RevealWidget.prototype.positionPopup = function(domNode) {
left = Math.max(0,left);
top = Math.max(0,top);
}
if (this.popup.absolute) {
// Traverse the offsetParent chain and correct the offset to make it relative to the parent node.
for (var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) {
left -= offsetParentDomNode.offsetLeft;
top -= offsetParentDomNode.offsetTop;
}
}
domNode.style.left = left + "px";
domNode.style.top = top + "px";
};
@@ -183,19 +192,11 @@ RevealWidget.prototype.compareStateText = function(state) {
};
RevealWidget.prototype.readPopupState = function(state) {
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
match = popupLocationRegExp.exec(state);
this.popup = Popup.parseCoordinates(state);
// Check if the state matches the location regexp
if(match) {
if(this.popup) {
// If so, we're open
this.isOpen = true;
// Get the location
this.popup = {
left: parseFloat(match[1]),
top: parseFloat(match[2]),
width: parseFloat(match[3]),
height: parseFloat(match[4])
};
} else {
// If not, we're closed
this.isOpen = false;

View File

@@ -42,6 +42,9 @@ SelectWidget.prototype.render = function(parent,nextSibling) {
this.execute();
this.renderChildren(parent,nextSibling);
this.setSelectValue();
if(this.selectFocus == "yes") {
this.getSelectDomNode().focus();
}
$tw.utils.addEventListeners(this.getSelectDomNode(),[
{name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"}
]);
@@ -143,6 +146,7 @@ SelectWidget.prototype.execute = function() {
this.selectMultiple = this.getAttribute("multiple", false);
this.selectSize = this.getAttribute("size");
this.selectTooltip = this.getAttribute("tooltip");
this.selectFocus = this.getAttribute("focus");
// Make the child widgets
var selectNode = {
type: "element",
@@ -175,6 +179,11 @@ SelectWidget.prototype.refresh = function(changedTiddlers) {
return true;
// If the target tiddler value has changed, just update setting and refresh the children
} else {
if(changedAttributes.class) {
this.selectClass = this.getAttribute("class");
this.getSelectDomNode().setAttribute("class",this.selectClass);
}
var childrenRefreshed = this.refreshChildren(changedTiddlers);
if(changedTiddlers[this.selectTitle] || childrenRefreshed) {
this.setSelectValue();

View File

@@ -48,7 +48,17 @@ SetWidget.prototype.execute = function() {
this.setValue = this.getAttribute("value");
this.setEmptyValue = this.getAttribute("emptyValue");
// Set context variable
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition);
if(this.parseTreeNode.isMacroDefinition) {
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,true);
} else if(this.parseTreeNode.isFunctionDefinition) {
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isFunctionDefinition: true});
} else if(this.parseTreeNode.isProcedureDefinition) {
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isProcedureDefinition: true, configTrimWhiteSpace: this.parseTreeNode.configTrimWhiteSpace});
} else if(this.parseTreeNode.isWidgetDefinition) {
this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isWidgetDefinition: true, configTrimWhiteSpace: this.parseTreeNode.configTrimWhiteSpace});
} else {
this.setVariable(this.setName,this.getValue());
}
// Construct the child widgets
this.makeChildWidgets();
};

View File

@@ -0,0 +1,82 @@
/*\
title: $:/core/modules/widgets/slot.js
type: application/javascript
module-type: widget
Widget for definition of slots within transcluded content. The values provided by the translusion are passed to the slot.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget,
TranscludeWidget = require("$:/core/modules/widgets/transclude.js").transclude;
var SlotWidget = function(parseTreeNode,options) {
// Initialise
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
SlotWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
SlotWidget.prototype.render = function(parent,nextSibling) {
// Call the constructor
Widget.call(this);
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
this.renderChildren(parent,nextSibling);
};
/*
Compute the internal state of the widget
*/
SlotWidget.prototype.execute = function() {
var self = this;
this.slotName = this.getAttribute("$name");
this.slotDepth = parseInt(this.getAttribute("$depth","1"),10) || 1;
// Find the parent transclusions
var pointer = this.parentWidget,
depth = this.slotDepth;
while(pointer) {
if(pointer instanceof TranscludeWidget) {
depth--;
if(depth <= 0) {
break;
}
}
pointer = pointer.parentWidget;
}
var parseTreeNodes = [{type: "text", attributes: {text: {type: "string", value: "Missing slot reference!"}}}];
if(pointer instanceof TranscludeWidget) {
// Get the parse tree nodes comprising the slot contents
parseTreeNodes = pointer.getTransclusionSlotFill(this.slotName,this.parseTreeNode.children);
}
// Construct the child widgets
this.makeChildWidgets(parseTreeNodes);
};
/*
Refresh the widget by ensuring our attributes are up to date
*/
SlotWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes["$name"] || changedAttributes["$depth"]) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports.slot = SlotWidget;
})();

View File

@@ -37,48 +37,347 @@ TranscludeWidget.prototype.render = function(parent,nextSibling) {
Compute the internal state of the widget
*/
TranscludeWidget.prototype.execute = function() {
// Get our parameters
this.transcludeTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
this.transcludeSubTiddler = this.getAttribute("subtiddler");
this.transcludeField = this.getAttribute("field");
this.transcludeIndex = this.getAttribute("index");
this.transcludeMode = this.getAttribute("mode");
this.recursionMarker = this.getAttribute("recursionMarker","yes");
// Parse the text reference
// Get our attributes, string parameters, and slot values into properties of the widget object
this.collectAttributes();
this.collectStringParameters();
this.collectSlotFillParameters();
// Get the parse tree nodes that we are transcluding
var target = this.getTransclusionTarget(),
parseTreeNodes = target.parseTreeNodes;
this.sourceText = target.text;
this.sourceType = target.type;
this.parseAsInline = target.parseAsInline;
// Process the transclusion according to the output type
switch(this.transcludeOutput || "text/html") {
case "text/html":
// No further processing required
break;
case "text/raw":
// Just return the raw text
parseTreeNodes = [{type: "text", text: this.sourceText}];
break;
default:
// text/plain
var plainText = this.wiki.renderText("text/plain",this.sourceType,this.sourceText,{parentWidget: this});
parseTreeNodes = [{type: "text", text: plainText}];
break;
}
// Set the legacy transclusion context variables only if we're not transcluding a variable
if(!this.transcludeVariable) {
var recursionMarker = this.makeRecursionMarker();
this.setVariable("transclusion",recursionMarker);
}
// Construct the child widgets
this.makeChildWidgets(parseTreeNodes);
};
/*
Collect the attributes we need, in the process determining whether we're being used in legacy mode
*/
TranscludeWidget.prototype.collectAttributes = function() {
var self = this;
// Detect legacy mode
this.legacyMode = true;
$tw.utils.each(this.attributes,function(value,name) {
if(name.charAt(0) === "$") {
self.legacyMode = false;
}
});
// Get the attributes for the appropriate mode
if(this.legacyMode) {
this.transcludeTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
this.transcludeSubTiddler = this.getAttribute("subtiddler");
this.transcludeField = this.getAttribute("field");
this.transcludeIndex = this.getAttribute("index");
this.transcludeMode = this.getAttribute("mode");
this.recursionMarker = this.getAttribute("recursionMarker","yes");
} else {
this.transcludeVariable = this.getAttribute("$variable");
this.transcludeType = this.getAttribute("$type");
this.transcludeOutput = this.getAttribute("$output","text/html");
this.transcludeTitle = this.getAttribute("$tiddler",this.getVariable("currentTiddler"));
this.transcludeSubTiddler = this.getAttribute("$subtiddler");
this.transcludeField = this.getAttribute("$field");
this.transcludeIndex = this.getAttribute("$index");
this.transcludeMode = this.getAttribute("$mode");
this.recursionMarker = this.getAttribute("$recursionMarker","yes");
}
};
/*
Collect string parameters
*/
TranscludeWidget.prototype.collectStringParameters = function() {
var self = this;
this.stringParametersByName = Object.create(null);
if(!this.legacyMode) {
$tw.utils.each(this.attributes,function(value,name) {
if(name.charAt(0) === "$") {
if(name.charAt(1) === "$") {
// Attributes starting $$ represent parameters starting with a single $
name = name.slice(1);
} else {
// Attributes starting with a single $ are reserved for the widget
return;
}
}
self.stringParametersByName[name] = value;
});
}
};
/*
Collect slot value parameters
*/
TranscludeWidget.prototype.collectSlotFillParameters = function() {
var self = this;
this.slotFillParseTrees = Object.create(null);
if(this.legacyMode) {
this.slotFillParseTrees["ts-missing"] = this.parseTreeNode.children;
} else {
this.slotFillParseTrees["ts-raw"] = this.parseTreeNode.children;
var noFillWidgetsFound = true,
searchParseTreeNodes = function(nodes) {
$tw.utils.each(nodes,function(node) {
if(node.type === "fill") {
if(node.attributes["$name"] && node.attributes["$name"].type === "string") {
var slotValueName = node.attributes["$name"].value;
self.slotFillParseTrees[slotValueName] = node.children || [];
}
noFillWidgetsFound = false;
} else {
searchParseTreeNodes(node.children);
}
});
};
searchParseTreeNodes(this.parseTreeNode.children);
if(noFillWidgetsFound) {
this.slotFillParseTrees["ts-missing"] = this.parseTreeNode.children;
}
}
};
/*
Get transcluded parse tree nodes as an object {parser:,text:,type:}
*/
TranscludeWidget.prototype.getTransclusionTarget = function() {
var self = this;
// Determine whether we're being used in inline or block mode
var parseAsInline = !this.parseTreeNode.isBlock;
if(this.transcludeMode === "inline") {
parseAsInline = true;
} else if(this.transcludeMode === "block") {
parseAsInline = false;
}
var parser = this.wiki.parseTextReference(
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: [{
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;
}
$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 {
// Transcluding a text reference
parser = this.wiki.parseTextReference(
this.transcludeTitle,
this.transcludeField,
this.transcludeIndex,
{
parseAsInline: parseAsInline,
subTiddler: this.transcludeSubTiddler
}),
parseTreeNodes = parser ? parser.tree : this.parseTreeNode.children;
this.sourceText = parser ? parser.source : null;
this.parserType = parser? parser.type : null;
// Set context variables for recursion detection
var recursionMarker = this.makeRecursionMarker();
if(this.recursionMarker === "yes") {
this.setVariable("transclusion",recursionMarker);
subTiddler: this.transcludeSubTiddler,
defaultType: this.transcludeType
});
}
// Check for recursion
// Return the parse tree
if(parser) {
if(this.parentWidget && this.parentWidget.hasVariable("transclusion",recursionMarker)) {
parseTreeNodes = [{type: "element", tag: "span", attributes: {
"class": {type: "string", value: "tc-error"}
}, children: [
{type: "text", text: $tw.language.getString("Error/RecursiveTransclusion")}
]}];
return {
parser: parser,
parseTreeNodes: parser.tree,
parseAsInline: parseAsInline,
text: parser.source,
type: parser.type
};
} else {
// If there's no parse tree then return the missing slot value
return {
parser: null,
parseTreeNodes: (this.slotFillParseTrees["ts-missing"] || []),
parseAsInline: parseAsInline,
text: null,
type: null
};
}
};
/*
Fetch all the string parameters as an ordered array of {name:, value:} where the name is optional
*/
TranscludeWidget.prototype.getOrderedTransclusionParameters = function() {
var result = [];
// Collect the parameters
for(var name in this.stringParametersByName) {
var value = this.stringParametersByName[name];
result.push({name: name, value: value});
}
// Sort numerical parameter names first
result.sort(function(a,b) {
var aIsNumeric = !isNaN(a.name),
bIsNumeric = !isNaN(b.name);
if(aIsNumeric && bIsNumeric) {
return a.name - b.name;
} else if(aIsNumeric) {
return -1;
} else if(bIsNumeric) {
return 1;
} else {
return a.name === b.name ? 0 : (a.name < b.name ? -1 : 1);
}
});
// Remove names from numerical parameters
$tw.utils.each(result,function(param,index) {
if(!isNaN(param.name)) {
delete param.name;
}
});
return result;
};
/*
Fetch the value of a parameter
*/
TranscludeWidget.prototype.getTransclusionParameter = function(name,index,defaultValue) {
if(name in this.stringParametersByName) {
return this.stringParametersByName[name];
} else {
var name = "" + index;
if(name in this.stringParametersByName) {
return this.stringParametersByName[name];
}
}
// Construct the child widgets
this.makeChildWidgets(parseTreeNodes);
return defaultValue;
};
/*
Get one of the special parameters to be provided by the parameters widget
*/
TranscludeWidget.prototype.getTransclusionMetaParameters = function() {
var self = this;
return {
"parseMode": function() {
return self.parseAsInline ? "inline" : "block";
},
"parseTreeNodes": function() {
return JSON.stringify(self.parseTreeNode.children || []);
},
"slotFillParseTreeNodes": function() {
return JSON.stringify(self.slotFillParseTrees);
},
"params": function() {
return JSON.stringify(self.stringParametersByName);
}
};
};
/*
Fetch the value of a slot
*/
TranscludeWidget.prototype.getTransclusionSlotFill = function(name,defaultParseTreeNodes) {
if(name && this.slotFillParseTrees[name] && this.slotFillParseTrees[name].length > 0) {
return this.slotFillParseTrees[name];
} else {
return defaultParseTreeNodes || [];
}
};
/*
@@ -101,6 +400,7 @@ TranscludeWidget.prototype.makeRecursionMarker = function() {
};
TranscludeWidget.prototype.parserNeedsRefresh = function() {
// Doesn't need to consider transcluded variables because a parent variable can't change once a widget has been created
var parserInfo = this.wiki.getTextReferenceParserInfo(this.transcludeTitle,this.transcludeField,this.transcludeIndex,{subTiddler:this.transcludeSubTiddler});
return (this.sourceText === undefined || parserInfo.sourceText !== this.sourceText || parserInfo.parserType !== this.parserType)
};
@@ -110,7 +410,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
*/
TranscludeWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(($tw.utils.count(changedAttributes) > 0) || (changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) {
if(($tw.utils.count(changedAttributes) > 0) || (!this.transcludeVariable && changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) {
this.refreshSelf();
return true;
} else {

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