1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-02-20 08:59:50 +00:00

Compare commits

..

110 Commits

Author SHA1 Message Date
Jeremy Ruston
d8b0e041b6 Initial commit 2026-02-19 12:45:27 +00:00
Saq Imtiaz
08f2b8bdf4 Fixes variable enumeration in widgets (#9648)
* fix: variable enumeration in widgets

* fix: fakeWidget should have a variables property

* fix: don't use spread properties

* fix: resolve more embarassing bugs

* chore: tests and whitespace

* fix: simplify opts check
2026-02-19 11:14:19 +00:00
Jeremy Ruston
c305eb01eb Fix passing a filtered attribute as a MVV (#9663) 2026-02-19 12:11:39 +01:00
Jeremy Ruston
71462143bf Fix BackgroundActions example 2026-02-16 18:16:45 +00:00
Théophile Desmedt
909149a347 [fix] Remove overflow:hidden on the tiddler info pannel, allowing popups to escape the info pannel (#9660)
* [fix] Remove overflow:hidden on the tiddler info pannel, allowing popups to escape the pannel

* add change note
2026-02-15 18:57:48 +00:00
Mario Pietsch
a2543cfd4a 5.4.0 Update German translations (#9655)
* Update German translations

* Add change note

* Update languages/de-DE/Draft.multids

Co-authored-by: XLBilly <LeiYiXia29@outlook.com>

---------

Co-authored-by: XLBilly <LeiYiXia29@outlook.com>
2026-02-14 21:26:02 +01:00
Jeremy Ruston
b713d13c5a Accidentally committed with #9657 2026-02-13 17:39:12 +00:00
Jeremy Ruston
bb05bd8817 Improve Release Note Presentation (#9657)
* First pass

* UI Tweaks

* Add some colour (possibly too much)

* Corrections

* More tweaks

* Various change note fixes
2026-02-11 18:12:52 +00:00
Mario Pietsch
42a908e1c9 set arrow function parens to always (#9590) 2026-02-10 12:35:10 +01:00
Cameron Fischer
70689a6de4 keyboard-driven-input couldn't use slots well (#9649)
Now it can, at least now without strange and arbitary tweaks to the $depth attribute.
2026-02-10 12:30:08 +01:00
Jeremy Ruston
64ee20edd2 Further MVV fixes (#9645)
* Add ((var)) syntax for passing multi-valued variables through transclude pipeline

Introduce ((var)) attribute syntax to explicitly pass
MVVs to procedures and functions via $transclude, solving the limitation
where <<var>> always resolves to the first value only for backwards
compatibility. Also adds ((var||sep)) and (((filter||sep))) inline display
syntax for debugging MVV values, and multivalued defaults for parameter attributes

* Create pr-draft.md

* Revert "Create pr-draft.md"

This reverts commit dd116af41b.

* Update change note

* Fix linting errors
2026-02-10 12:16:20 +01:00
Théophile Desmedt
0177f09823 Implement translations and indentation fixes for Advanced Info tab (#9643)
* Implement translations and indentation fixes for Advanced Info tab

* update change note

* Update CascadeInfo hint for current tiddler context

Clarified hint for cascade info in TiddlerInfo.

* docs: update github-links in release note #9634
2026-02-08 11:50:12 +01:00
Jeremy Ruston
643cabf9c8 Additional docs for #9641 2026-02-06 16:33:29 +00:00
Jeremy Ruston
5cf3fcd843 Background actions and media query tracking (#9641)
* Initial commit cherry picked from #8702

* Initial docs from #8702

...which need to also be turned into a changenote

* Add changenote
2026-02-06 16:30:46 +00:00
Jeremy Ruston
67f13c585d Fix #9055 docs issue identified in https://github.com/TiddlyWiki/TiddlyWiki5/pull/9055#pullrequestreview-3732792103 2026-02-06 16:24:14 +00:00
Mario Pietsch
1bbb7fd53b Add start- and endactions to link-widget, list-links-draggable and list-tagged-draggable macros (#9621)
* Add start- endactions to link-widget + documentation

* Add start- endactions to list-links-draggable and list-tagged-draggable macros

* Add changenote

* Update docs with actionTiddler info
2026-02-06 14:23:42 +01:00
Saq Imtiaz
599933c34d Remove 'tiddlywiki/dom-to-image' dependency
Removed 'tiddlywiki/dom-to-image' from the tiddlywiki.info
2026-02-06 12:01:22 +01:00
Simon Huber
b1ccb82e0a Update body-toolbar-button - use value={{{ [subfilter{!!button-classes}] :and[join[ ]] }}} (#9585)
* Update body-toolbar-button - use `filter={{!!button-classes}}`

* Update body-toolbar-button.tid

* Create #9566 - button-classes.tid

* Update and rename #9566 - button-classes.tid to #9585 - button-classes.tid

* :and[join[ ]]

* Update how-to guide to mention button-classes
2026-02-06 11:50:43 +01:00
Mohammad Rahmani
ea648c7d15 Update StoryList.tid to Work in Different Layouts (#9094)
* Update StoryList.tid to Work in Different Layouts

See https://talk.tiddlywiki.org/t/stay-organized-by-using-multiple-desktops-in-tiddlywiki/12752/7

All PageTemplate elements are enclosed within that `$navigator` widget, so it should be possible to use those two variables in filters instead of hard-coding the values.

* Apply suggestion from @saqimtiaz

---------

Co-authored-by: Saq Imtiaz <saq.imtiaz@gmail.com>
2026-02-06 11:46:18 +01:00
Jeremy Ruston
a3a4e91751 New dom-to-image plugin for saving DOM nodes as an image (#8810)
* Add tm-save-dom-to-image message

* Temporarily include the geospatial plugin in the Netlify previews

* Scale should default to 1x

* Fix saving SVG images

* Add example of saving in SVG format

* Add library version number

* Document peculiarities of JPEG quality parameter

* Allow format="jpg" as well as the more technically correct "jpeg"

* Document what happens if the selector returns multiple DOM nodes

* Refactor image-to-dom to be a separate plugin

* Add support for oncompletion handler

* Remove ELS marker

Thanks @ericshulman
2026-02-06 10:42:40 +00:00
Mario Pietsch
c96d398712 remove empty.hta from tiddlywiki.info build targets (#9633) 2026-02-06 10:11:23 +00:00
Saq Imtiaz
821dcaf002 Ensures that getting variable info for a function doesnt pollute parent widget (#9639)
* fix: ensure getting variable info for a function doesnt pollute parent widget

* fix: makeFakeWidget should not pollute upstream
2026-02-06 11:10:47 +01:00
Jeremy Ruston
9247a87e11 Missing release note for #8810 2026-02-06 09:09:42 +00:00
Saq Imtiaz
bda54b0ad5 Adds pointer capture and disabling support to eventcatcher widget (#9609)
* feat: eventcatcher with pointer capture support

* fix: various cleanups and improvements

* chore: lint

* chore: lint

* docs: updated eventcatcher docs

* docs: added changenote

* feat: provide access to event properties via JSON blob

* fix: added updated utils file

* fix: guard against missing nodes and not element nodes
2026-02-06 09:16:34 +01:00
Théophile Desmedt
cd8b1faa74 UI: Show cascade filter details in Advanced info tab (#9634)
* UI: Show details on cascade filters in the "Advanced info" tab

* Update CascadeInfo.tid with new formatting

* Remove codeblock for conciseness

* Add change note for #9634

* Refactor CascadeInfo.tid for active filters

Improve filter logic and names of variable

* Change heading names

Updated the CascadeInfo.tid to change 'Active Filter Condition' to 'Active Cascade Filter' and adjusted the corresponding variables.
2026-02-05 19:47:15 +00:00
Saq Imtiaz
0673426f5a fix: remove fn wrappers and unneeded comments (#9637) 2026-02-05 17:06:32 +01:00
Saq Imtiaz
d376ada241 Adds a widget destroy method (#9097)
* feat: widget destroy method

* fix: revert to original implementation

* Invoke onDestroy method during widget destruction

Add custom cleanup method call in destroy process

* Update documentation for destroy method options

* Fix formatting in widget.js comments

* Refactor destroyChildren method for formatting

* Fix indentation in findNextSiblingDomNode method

* docs: added changenote

* chore: lint

* fix: remove deprecated utils method
2026-02-05 17:03:40 +01:00
Mario Pietsch
33b2f514fb Allow title, tags, text as focus for editing existing tiddlers (#9214)
* Allow title, tags, text as focus for editing existing tiddlers

* Add release note

* Update description field

* refresh select widget, it .default parameter is changed

* remove default variable, because it is not needed anymore. select widget refresh handling deals with it

* Undo select widget changes
2026-02-04 13:41:40 +01:00
Saq Imtiaz
46fe3ca988 Revert "Fix RSOE from filter operator errors (#9496)" (#9630)
This reverts commit 86c4770a28.
2026-02-04 12:53:14 +01:00
XLBilly
bf7c0b575c Fix side effects of PR 9316 (#9568)
* Fix color transition not working

* Fix plugin install button

* Fix remove tag button

* Update change note
2026-02-04 12:43:40 +01:00
XLBilly
b236373064 Intergrate tiddlywiki palette colors and settings to custom CSS properties (#9333)
* Expose tiddlywiki palette colors and settings to custom CSS properties

* Rename & use --tc prefix

* Add colors and CSS  settings

* Make CSS settings properties' name readable

* Add all CSS settings

* Add all palette colors

* Remove macrocallblock rule

* Indent with tabs

* Use --tc-color prefix

* Update docs

* Use --tpc prefix

* Add change note

* Simplify palette color rules with list widget

* Update docs

* Hardcode custom properties

* Update docs

* Remove cascades

* Update docs

* Add more docs

* Update docs

* Update docs

* Add --tp-animation-duration

* Update change note
The previous example actually doesn't work at all

* Update docs about limits of CSS variables
2026-02-04 11:37:04 +00:00
Mario Pietsch
d15398fc09 Simple TOC level parameter (#9612)
* Add toc level parameter

* Update TOC documentation

* Add toc level release note

* Update releasenote number and GH links

* Update releasenote number and GH links
2026-02-04 11:26:31 +00:00
Jeremy Ruston
6bc77cf3e2 Dynamic parameters for macro/procedure/function calls (#9055)
* Initial commit

The idea is to extend the macro call syntax to accept dynamic parameter values (ie thing:{{more}} etc). Eventually, this will work in all the contexts in which the double angle bracket syntax is valid.

This initial commit gets the tests passing, but doesn't yet activate the new functionality.

* Test for standalone macro calls with dynamic parameters

* Parse attribute macros with the new parser

This fixes the tests

* Test for attribute macros

* Add some examples

* Tweak examples

* Fix test

* Temporarily disable a broken serializer test

* Fix/dynamic macro calls test (#9459)

* Revert "Temporarily disable a broken serializer test"

This reverts commit b3144300ee.

* restore synamic parameter parse result

* lint

* lint

* remove duplicate

* Update core/modules/parsers/parseutils.js

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update editions/test/tiddlers/tests/data/serialize/DynamicWidgetAttribute.tid

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update editions/test/tiddlers/tests/data/serialize/DynamicWidgetAttribute.tid

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: mixed qouted and unquoted

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix unneeded diff

* Minor docs update

* Genuflecting to the linter

* Remove debug logging

* Add change note

* Allow single closing square brackets within double square brackets quoted strings

* Only allow new style parameter values if the separator is an equals sign

* On reflection, new style values should not be allowed for anonymous parameters

Backwards compatibility

* Docs updates

* Docs updates

---------

Co-authored-by: lin onetwo <linonetwo012@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-04 11:24:06 +00:00
XLBilly
dc764b3a4a Replace fill rules in tw5.com edition (#9624) 2026-02-04 11:22:32 +00:00
XLBilly
9c09841eda Make draft title translatable (#8891)
* Make draft title translatable

* Update change note

* Improve number handling
Now generates "Draft of '...' 2" instead of "Draft 2 of '...'"

* Improve whitespace handling
We no longer needs to add whitespace in languages. We now handle it in javascript.

* Update language naming

* Update zh-Hans translation

* Update change note

* Refactor logic to make it less complex
Since we don't need to care about draft numbers, we can have two different templates for draft title with and without attribution. No need to trim the string now.
Also, we can reuse the getSubstitutedText method

* Update translators edition

* fixup! Update translators edition

* Switch to transclude and variable mechanism

* Adapt translators to the new mechanism

* Update change note

* Further simplify the logic
$tw.language.getString can already wikify translatable strings. No need for this.renderText
2026-02-04 11:21:54 +00:00
Cameron Fischer
9d5be2e9f8 Recurse exception handling to better handle '{{}}' in place of recently installed fix (#9548)
* Introduced preliminary idea for infinite recurse exception

* Better handling of infinite recursion

But it could be better still...

* the TransclusionError is a proper error

Moved the magic number to be on the error's class. Not sure if that's
a great idea.

* Fixed minor minor issue that came up in conflict

The minor fix to the jasmine regexp that escaped a '+' somehow
broke some random test.

* Removing patch fix for recursion errors

* Fixed issue where buttton and other widgets don't clean up

* Added release notes for #9548

* Update test-widget.js

If I don't fix those indentations, the entire TW codebase will explode or soemthing.

* Update test-widget.js

These lint problems are wasting my time.

* Fixed all core widgets to not leak when renderChildren fails

* Updated release notes to reflect what I'm actually fixing

* Update test-widget.js

Added warning not to use for-of loop for defining tests. The iterating variable needs to have its own method scope, or it risks being the same value for all tests.
2026-02-04 11:21:16 +00:00
lin onetwo
486d3bd326 Fix sitemap plugin can't provide xml content type in GET route (#9203)
* Update get-tiddler-html.js

* Create #9203.tid
2026-02-04 11:19:56 +00:00
XLBilly
196683915c Replace window.eval with Function (#9611)
* Replace window.eval with Function

* Add back comment
2026-02-04 11:17:10 +00:00
yaisog
42a3928960 Refactor code for EditTemplate fields (#9582)
* Refactored fields.tid

* Add changenote

* Optimize indentation and remove unneeded variable

* Consolidate some variables, procedures and functions

* Streamlined conditional and reveal structures

* Eliminate the fieldmangler widget

* Add tc-edit-field-exists to new field name input if applicable

* Call save-tiddler-actions on Ctrl-Enter in name input field
2026-02-04 11:13:53 +00:00
Saq Imtiaz
2e76cc08a1 Extends image widget with support for data-attributes and on load actions (#9050)
* feat: support for data-attributes and on load actions

* feat: support for data-attributes and on load actions

* fix: typo

* fix: simplify variable assignment

* docs: added changenote
2026-02-04 11:12:58 +00:00
Saq Imtiaz
891e4fcb2b Fixes a regression in correctly evaluating default param values for functions (#9614)
* Fix: bug in multivalue default params

* Enhance release notes for version 5.4.0

Updated GitHub links and contributors for release notes.

* Add FunctionDefaultValues test for default parameters

* Update function default values in FunctionDefaultValues.tid

* Update #8972.tid

* fix: correctly resolve default values for functions

* Update #8972.tid
2026-02-04 11:12:42 +00:00
Saq Imtiaz
f6fd5ff261 Fixes bug in correctly resolving functions in text substitutions (#9598)
* fix: correctly resolve functions in text substitutions

* docs: added changenote

* fix: remove commented code
2026-02-04 11:12:16 +00:00
XLBilly
526aaa3db8 Bump katex to newest version (#9626)
* Bump katex to newest version

* Update fonts
Also migrate to woff2

* Update readme

* Update change note
2026-02-04 10:11:09 +01:00
XLBilly
455f1be3fb Fix missing semicolon in Snow White (#9625)
* Fix missing comma in Snow White

* Update change note
2026-02-04 10:09:39 +01:00
Mohammad Rahmani
bffa0bb95a Update Documentation for list-tagged-draggable and list-links-draggable. (#9553)
* Update documents for list-links-draggable Macro.tid

add : `<<.from-version 5.4.0>> `

* Update documentation for list-tagged-draggable Macro.tid

Added `<<.from-version 5.4.0>> `

* Update list-links-draggable Macro.tid

Correct extra space and remove colon

* Remove duplicate title view field in list.tid

Removed redundant view field for title in list.tid.
This PR should fix issue reported here: https://github.com/TiddlyWiki/TiddlyWiki5/issues/9555
2026-02-04 10:09:02 +01:00
Jeremy Ruston
a1ef2ef6d4 Merge branch 'tiddlywiki-com' 2026-01-29 14:27:59 +00:00
Saq Imtiaz
75edd9b488 Reverts change to getLocationHash utils method (#9622)
* fix: reverted change to getLocationHash utils method

* docs: update changenote
2026-01-26 16:03:50 +01:00
Mario Pietsch
cde9c931c8 Select widget handle default parameter refresh (#9617)
* select widget handle default parameter refresh

* Add change note
2026-01-25 19:58:52 +01:00
Saq Imtiaz
d07fe25cdb feat: extend fakedom implementation (#9616)
* feat: extend fakedom implementation

* docs: updated changenote
2026-01-25 19:05:46 +01:00
KiXaM_刻む
a40ce29451 Add an option to enable CORS (#9277)
* Add an option to disable CORS

* change 'disable' with 'enable' CORS, because that is what this option actually does

* add a change note

* typo
2026-01-25 17:04:16 +01:00
buggyj
75647eb623 Fixes #8092 SelectWidget does not work with multiple options organise… (#8093)
* Fixes #8092 SelectWidget does not work with multiple options organised into group

* Consolidate variables

* Apply suggestion from @saqimtiaz

* Update core/modules/widgets/select.js

Co-authored-by: Mario Pietsch <pmariojo@gmail.com>

* added release note

* chore: lint fixes

---------

Co-authored-by: Saq Imtiaz <saq.imtiaz@gmail.com>
Co-authored-by: Mario Pietsch <pmariojo@gmail.com>
2026-01-25 17:02:18 +01:00
Mario Pietsch
70b4557738 [DOCS] Add link to "TiddlyWiki Archive" tiddler to the TiddlyWiki Releases info (#9613) 2026-01-25 16:59:54 +01:00
Mario Pietsch
efe58e41bc [DOCS] Fix some typos in "days Operator (Examples)" (#9479)
* [DOCS] Fix some typos in "days Operator (Examples)"

* Remove created and modified fields from days.tid

Remove created and modified fields from days.tid
2026-01-21 09:09:14 +01:00
Saq Imtiaz
eb3a80968e docs: changenotes for previously merged PRs (#9599)
* docs: changenotes for previously merged PRs

* fix: added text field for changenotes
2026-01-21 09:08:50 +01:00
Mario Pietsch
62ae4b24bc allow space after const {}. Set keyword spacing to warning (#9589) 2026-01-20 22:03:43 +01:00
yaisog
ded76aa84f Fixes Ctrl-Enter not working in EditTemplate tag name input (#9600)
* Assign save-tiddler-actions to inputAcceptVariantActions

* Add changenote
2026-01-20 20:22:42 +01:00
Mario Pietsch
79e3d14698 [DOCS] Make TaskManagementExamples more "hackable" (#9482)
* [DOCS] Make TaskManagementExamples more "hackable"

* Update modified date in TaskManagementExample.tid

* Fix modified date in TaskManagementExampleDraggable
2026-01-20 13:23:17 +01:00
superuser-does
763d717a13 Improvements to DateFormat tiddler (#9583) 2026-01-20 13:18:24 +01:00
XLBilly
e42ed6808e Split escapecss into two platforms (#9475)
* Split escapecss into to platforms

This will reduce core size slightly

* Update change note
2026-01-20 12:13:48 +01:00
yaisog
844564180f Fix LetWidget to always set all staged variables on first render (#9494)
* Always set all staged variables on first render

* Add changenote
2026-01-20 10:24:56 +00:00
Saq Imtiaz
a670de0e95 Fixes regressions in list-tagged-draggable (#9596)
* Fix regressions in list-tagged-draggable

* Remove trailing newline from list.tid
2026-01-20 10:01:02 +01:00
Bram Chen
faee49ee01 Update chinese language files (#9576)
* Update chinese language files
* add chinese translations for alert aria message

* Update chinese language files
* update related change note
2026-01-20 07:33:05 +01:00
yaisog
dd20be49f0 Make impact note for #9337 less verbose / repetitive (#9481)
* Make impact note less verbose / repetitive for #9337

* Correct some fields
2026-01-20 07:16:21 +01:00
Simon Huber
a27f74bbdc Fixes bug in sidebar tab Open to allow disabling drag and drop (#9504)
the variable is called `tv-enable-drag-and-drop` - not `tv-allow-drag-and-drop`
2026-01-20 07:06:29 +01:00
Jeremy Ruston
ae4e99951a Revert #9554 Refactor stylesheets in single <style> tags
These changes break the palette switcher
2026-01-18 11:40:10 +00:00
Mario Pietsch
be84dee26b Allow unused variables in function headers and caught exceptions (#9588) 2026-01-17 17:51:51 +00:00
XLBilly
00e17874f0 Add stylesheet wiki information (#9565)
* Add stylesheet wiki information

* Use 2 spaces

* Update change note

* Use ∈ symbol instead
I think this one is less confusing than the previous one
2026-01-17 15:00:32 +00:00
XLBilly
9041f099a3 Refactor stylesheets in single <style> tags (#9554)
* Create RootStylesheet.tid

* put stylesheets into single <style> tags

* viewHandler should not be a widget

* format RootStylesheet

* add ROOT_STYLESHEET_TITLE constant

* use let widget in RootStylesheet

* use view widget from #8135 for testing

* reformat RootStylesheet

* update view widget

* update view widget

* update view widget

* update view widget

* update view widget

* update view widget

* trying to fix the date parsing

* refactor view widget with more extensible architecture

* remove performance instrumentation

* hardcode reset and base stylesheets

* adopt ES2017 syntax for view widget

* don't hardcode vanilla/base

* remove unused constructors

* remove unused variable

* make refresh method static

* trying to fix missingThis

* add changenote

* revert change in vanilla/base

* Revert changes to the view widget

* Refactor RootStylesheet.tid
* Use transclude widget instead of view widget
* Remove hardcoded noramlize.css

* Add comment for debugging

* Migrate some templates to use RootStylesheet

* Remove PAGE_STYLESHEET_TITLE
Since it is no longer used in render.js

* Update change note

---------

Co-authored-by: Simon Huber <huber.simon@protonmail.com>
2026-01-17 14:59:10 +00:00
yaisog
3ba31be2a8 Add the words and lines modes to $diff-text (#9551)
* Initial commit

* Add line ending configuration for consistent tests

* Initial commit

* Correctly consider editcost parameter

* Move diffPartsToChars() to $tw.utils

* Remove superfluous file

* Correct "efficiency" parameter naming in the documentation

The parameter was incorrectly referred to as "efficent" in several places.

* Update diffPartsToChars to ES2017 style

* Consolidate let/const declarations
2026-01-17 14:57:52 +00:00
XLBilly
99d8afd515 Bump markdown-it to latest version (#9513)
* Bump markdown-it to newest version

* Update change note
2026-01-17 14:56:16 +00:00
Jeremy Ruston
2ab5f26644 Merge branch 'tiddlywiki-com' 2026-01-16 17:36:54 +00:00
Mario Pietsch
419fe68ee2 [Docs] Improve tag-pill documentation and examples (#9580)
* [Docs] Improve tag-pill documentation and examples

* Apply suggestion from @saqimtiaz

---------

Co-authored-by: Saq Imtiaz <saq.imtiaz@gmail.com>
2026-01-14 14:04:34 +01:00
XLBilly
0e765bdbdb Make alert aria message translatable (#9575)
* Make alerts aria message translatable

* Update change notes

* Update change note
2026-01-12 10:21:35 +01:00
Jeremy Ruston
855d8a9638 Fix images loaded from _canonical_uri tiddlers do not have loading and error classes assigned (#9570)
* Fix images loaded from _canonical_uri tiddlers do not have loading and error classes assigned

* Create changenote

* Joyously fix eslint error
2026-01-10 14:50:31 +00:00
Jeremy Ruston
afcf108d29 Add changenote 2026-01-10 14:42:58 +00:00
Jeremy Ruston
8f9acc0ca2 Fix missing file extension 2026-01-10 14:35:26 +00:00
Jeremy Ruston
5e4b8fbb3c Additional fix for #9177 2026-01-08 18:20:57 +00:00
lin onetwo
8e301178a4 Feat/view button condition (#9466)
* feat: support condition field on $:/tags/ViewToolbar button

* Delete convert-markdown.tid

* Create #9466.tid

* Update title.tid
2026-01-08 13:34:58 +01:00
Cameron Fischer
a72d3a09bf Quick fix to some deprecated class methods (#9561) 2026-01-08 10:13:16 +01:00
Jeremy Ruston
56634ffe29 Merge branch 'tiddlywiki-com' 2026-01-05 16:36:49 +00:00
Jeremy Ruston
24c317e1ab Revert "Add macro operator (#9520)"
This reverts commit 3c8ee86e23.
2026-01-05 16:18:01 +00:00
Jeremy Ruston
07329c6849 Revert "Root stylesheet refresh - Stylesheets in single <style> tags (#8130)"
This reverts commit da41a55f29.
2026-01-05 16:05:15 +00:00
yaisog
47ab3476f6 Improve LogWidget and ActionLogWidget documentation (#9550) 2026-01-05 14:31:11 +01:00
Mario Pietsch
f0e64660f2 [DOCS] Add multi-columns class to Widgets in Wikitext (#9516) 2026-01-04 21:45:19 +00:00
Mohammad Rahmani
9663e65f4b list-tagged-draggable to use title field by default (#9177)
* Revert the list-tagged-draggable to use title field by default

* Update list.tid

It seems `<$transclude field=<<__field__>> />` when field default value is empty does not work as expected.
This commit uses `field:"title"` instead of `field:""` in the list-tagged-draggable header.

* Update list.tid

The redundant `field` removed. The new `displayField` attribute is used to let user choose the filed they like to display when the list items are rendered as simple links.

* Update list.tid

The proposed field attribute in list-tagged-draggable updated to use the same `displayField` aslist-links-draggable.

* Create #9177

change note for #9177 was created

* Update list.tid

The `list-links-draggable` now is fully backward compatible. It uses caption as default field as before and is compatible with `list-links`.

The `list-tagged-draggable` is fully backward compatible while got a new displayField parameter.

* Update list-tagged-draggable Macro.tid

Update docs to reflect new displayField parameter

* Update list-links-draggable Macro.tid

Update documentation to reflect the new displayField parameter.

* Update list-tagged-draggable Macro.tid

Update docs. Remove formatting error in doc.
2026-01-04 21:41:38 +00:00
Mario Pietsch
7cb422242a DOCS - Fix typo in Date Fields (#9518) 2026-01-04 21:36:57 +00:00
Jeremy Ruston
f075f24e6b Merge branch 'tiddlywiki-com' 2026-01-04 20:48:58 +00:00
superuser-does
5fa1098c03 tw5.com: remove duplicate text from Forums tiddler (#9523) 2026-01-04 18:15:37 +00:00
superuser-does
92dc927c7b docs: savetiddlers extension is now Firefox-only (#9524)
* tw5.com: removed Chrome browser from savetiddlers

Was deprecated in early 2025, and is now Firefox-only

Additional changes:
* Lowercased buggyj in line with how the name is used elsewhere on tw5.com and the rest of the internet
* Pulled url from the url field (following the example of Timimi resource tiddler)
* Changed formatting of title to match other community resources

* tw5.com: update French & Japanese savetiddlers plugin docs to note it is now Firefox-only

Please note this update was validated using machine translation
2026-01-04 18:12:56 +00:00
XLBilly
98a61f01bb Add locale support for sort operator (#9400)
* Locale support for sort operator

* Add checkLanguageCode util function

* Update docs & add language code validation

* Replace multiple isDescending with reverse

* Revert "Replace multiple isDescending with reverse"

This reverts commit 793177b8bc.

* Simplify sortTiddler with Intl.Collator

* Add change notes

* Remove comment

* Update makeCompareFunction to support locale

* Update checkLanguageCode

* Add locale support for sortsub

* Add locale support for sort filter run prefix

* Revert "Add locale support for sort filter run prefix"

This reverts commit 9479a156d7.

* Remove checkLanguageCode
Since filters are able to catch errors now

* Update locale example

* Revert " Add locale support for sortsub"

This reverts commit 4a617188fc.

* Revert "Update makeCompareFunction to support locale"

This reverts commit 0ebca08036.

* Update docs

* Update change note
2026-01-04 18:03:54 +00:00
superuser-does
f3fa69e229 Docs: rename 'definition lists' to 'description lists' (#9535)
* docs: Definition Lists to definition lists

* tw5.com: rename Definition Lists to Description Lists throught tiddler

* apply recommendations by @pmario on #9535
2026-01-04 17:37:54 +00:00
Mario Pietsch
e2fb22ade0 Bug report template: Rename description to about (#9546) 2026-01-04 16:50:01 +00:00
peteratkins
7fb8560908 Signing CLA (#9534)
Co-authored-by: Jeremy Ruston <jeremy@jermolene.com>
2026-01-04 13:30:54 +00:00
Jeremy Ruston
ff7814360e Cleanup whitespace in CLA 2026-01-04 13:19:24 +00:00
hsteve11
2d9303c6ff Signing CLA (#9539) 2026-01-04 13:18:46 +00:00
Mario Pietsch
6aee5eb0c7 Add Filter Syntax History link to Filters tiddler (#9541) 2026-01-04 13:16:54 +00:00
Mario Pietsch
6eb881bffe New issue and bug report templates (#9512)
* New issue and bug report templates

* Change bug_report to .md file

* update bug report text

* Move To Reproduce up next to Problem Description

* Fix typo
2026-01-04 13:08:40 +00:00
IchijikuIchigo
2a5ce95d99 Update Japanese translation (#9542)
* Update Japanese translation

* Update Japanese translation

* Update Japanese translation

* Update Japanese translation
2026-01-04 12:14:41 +00:00
XLBilly
bd4fdd8f2e Improve tabs macro accessibility (#9348)
* Improve tabs macro accessibility

* Fix wrong aria-selected attribute

* Patch button widget to allow changing the default aria-checked attribute

* Patch button widget to have aria-checked attribute set to false

* Update tests

* Further fix tests

* Update docs

* Update change notes
2026-01-04 12:13:10 +00:00
XLBilly
09379abd5d Bidirectional improvements for core classes (#9148)
* Bidirectional improvements for core classes

* Fix Control Panel table text direction

* Switch to logical properties

* Add -webkit-margin-* properties

* Improve backward compatibility

* Use supports CSS at-rule for fallback

* Tiddler controls, alert, TOC update.

* tc-tree & testcase update

* .tc-sidebar-scrollable use new syntax

* Snow white use standard value

* Update divider

* Avoid negative logic

* Remove :dir rules at the moment

* Use property procedures

* Add change note

* Update blockquote

* Update unfold banner

* Update tiddlerinfo close button

* Group supports rule

* Update tiddler title icon

* Fix wrong float and margin
2026-01-04 12:02:28 +00:00
XLBilly
c6906120d8 Migrate diff-match-patch to a modern fork (#9511)
* Migrate to diff-match-patch-es & update api

* Update acknowledgements

* Update change notes

* Fix editcost attribute not working

* Make library compatible with ES2017
2026-01-04 11:56:25 +00:00
Jeremy Ruston
c4c60933f4 Merge branch 'tiddlywiki-com' 2026-01-04 11:40:01 +00:00
XLBilly
a3979cda9c Refactor base64 utility functions (#9488)
* Split base64 utility functions to two platforms

* Simplify Nodejs atob

* Update change note

* Update docs

* Move base64Decode & base64Encode back to utils.js

* Add missing use strict
2026-01-04 11:35:02 +00:00
XLBilly
3c8ee86e23 Add macro operator (#9520)
* Add macro operator

* Replace unnecessary usage of wikify widget

* Simplify multiple let widget

* fixup! Replace unnecessary usage of wikify widget

* Update tests

* Update change note

* fixup! Replace unnecessary usage of wikify widget

* Update docs

* fixup! Update tests
2026-01-04 11:31:30 +00:00
XLBilly
921c0174fb Purge IE related docs (#9134) 2026-01-04 09:42:01 +01:00
XLBilly
4196d96adc [DOCS] Update docs about saving via WebDAV (#9543) 2026-01-02 09:42:58 +01:00
Jeremy Ruston
743e99d12d Further fix to #9538 2025-12-29 21:44:57 +00:00
Jeremy Ruston
6beeb23d10 Fix browser storage plugin triggers save (#9538)
* Initial Commit

* Add changenote
2025-12-29 21:09:43 +00:00
wiki-tutor
838fad916d Signing CLA (#9527) 2025-12-28 18:30:51 +00:00
Jeremy Ruston
935e89bd93 Tweak HelloThere thumbnail ordering 2025-12-20 09:25:25 +00:00
726 changed files with 7559 additions and 8436 deletions

62
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,62 @@
---
name: Bug report
about: Create a report to help us improve TiddlyWiki 5
title: "[Report] "
type: report
---
<!-- Remove elements, that you do not need -->
<!-- Add screenshots where needed -->
**Problem Description**
<!-- Describe your problem: A clear and concise description of what your problem is -->
**To Reproduce**
Steps to reproduce the behavior:
1. At https://tiddlywiki.com
2. Click on ...
3. Scroll down to ...
4. See ...
**Expected behavior**
As a user,
<!-- As a developer, -->
I would expect ...
**TiddlyWiki Configuration**
<!-- Please complete the following information -->
- Report created with: [Wiki Information](https://tiddlywiki.com/#%24%3A%2Fcore%2Fui%2FControlPanel%2FWikiInformation)
<!-- Your report comes here -->
<!-- or -->
<!-- Add it manually -->
- Version: <!-- e.g. v5.3.8 -->
- Saving mechanism: <!-- e.g. Node.js, TiddlyDesktop, TiddlyHost etc -->
- Plugins installed: <!-- e.g. Freelinks, TiddlyMap ... other 3rd party plugins -->
**Desktop**
<!-- Please complete the following information -->
- OS: <!-- e.g. iOS -->
- Browser: <!-- e.g. chrome, safari, FireFox -- Version: -->
**Smartphone**
<!-- Please complete the following information -->
- Device: <!-- e.g. iPhone6 -->
- OS: <!-- e.g. iOS8.1 -->
- Browser: <!-- e.g. stock browser, safari, FireFox -- Version: -->
**Additional context**
<!-- Add any other context about the problem here. -->

View File

@@ -1,68 +0,0 @@
name: Bug report
description: Create a report to help us improve TiddlyWiki 5
title: "[BUG] "
type: bug
body:
- type: textarea
id: Describe
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: Expected
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
validations:
required: false
- type: textarea
id: Reproduce
attributes:
label: To Reproduce
description: "Steps to reproduce the behavior:"
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: false
- type: textarea
id: Screenshots
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem.
placeholder: Drag image here to upload screenshot!
validations:
required: false
- type: textarea
id: Configuration
attributes:
label: TiddlyWiki Configuration
description: please complete the following information
placeholder: |
- Version [e.g. v5.1.24]
- Saving mechanism [e.g. Node.js, TiddlyDesktop, TiddlyHost etc]
- Plugins installed [e.g. Freelinks, TiddlyMap]
### Desktop (please complete the following information):
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
### Smartphone (please complete the following information):
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
validations:
required: true
- type: textarea
id: Context
attributes:
label: Additional context
description: Add any other context about the problem here.

View File

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

View File

@@ -120,7 +120,6 @@ node $TW5_BUILD_TIDDLYWIKI \
|| exit 1 || exit 1
# /empty.html Empty # /empty.html Empty
# /empty.hta For Internet Explorer
# /empty-external-core.html External core empty # /empty-external-core.html External core empty
# /tiddlywikicore-<version>.js Core plugin javascript # /tiddlywikicore-<version>.js Core plugin javascript
node $TW5_BUILD_TIDDLYWIKI \ node $TW5_BUILD_TIDDLYWIKI \

View File

@@ -316,8 +316,25 @@ $tw.utils.htmlDecode = function(s) {
return s.toString().replace(/&lt;/mg,"<").replace(/&nbsp;/mg,"\xA0").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/mg,"&"); return s.toString().replace(/&lt;/mg,"<").replace(/&nbsp;/mg,"\xA0").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/mg,"&");
}; };
/** @deprecated Use window.location.hash instead. */ /*
$tw.utils.getLocationHash = () => window.location.hash; Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
*/
$tw.utils.getLocationHash = function() {
const href = window.location.href,
idx = href.indexOf("#");
if(idx === -1) {
return "#";
}
const afterHash = href.substring(idx + 1);
if(afterHash.startsWith("#") || afterHash.startsWith("%23")) {
// Special case: ignore location hash if it itself starts with a #
return "#";
}
return href.substring(idx);
};
/** @deprecated Pad a string to a given length with "0"s. Length defaults to 2 */ /** @deprecated Pad a string to a given length with "0"s. Length defaults to 2 */
$tw.utils.pad = function(value,length = 2) { $tw.utils.pad = function(value,length = 2) {
@@ -596,7 +613,7 @@ $tw.utils.evalGlobal = function(code,context,filename,sandbox,allowGlobals) {
// Compile the code into a function // Compile the code into a function
var fn; var fn;
if($tw.browser) { if($tw.browser) {
fn = window["eval"](code + "\n\n//# sourceURL=" + filename); // eslint-disable-line no-eval -- See https://github.com/TiddlyWiki/TiddlyWiki5/issues/6839 fn = Function("return " + code + "\n\n//# sourceURL=" + filename)(); // See https://github.com/TiddlyWiki/TiddlyWiki5/issues/6839
} else { } else {
if(sandbox){ if(sandbox){
fn = vm.runInContext(code,sandbox,filename) fn = vm.runInContext(code,sandbox,filename)

View File

@@ -33,8 +33,8 @@ exports.handler = function(request,response,state) {
} }
var text = state.wiki.renderTiddler(renderType,renderTemplate,{parseAsInline: true, variables: {currentTiddler: title}}); var text = state.wiki.renderTiddler(renderType,renderTemplate,{parseAsInline: true, variables: {currentTiddler: title}});
// Naughty not to set a content-type, but it's the easiest way to ensure the browser will see HTML pages as HTML, and accept plain text tiddlers as CSS or JS var headers = {"Content-Type": renderType};
state.sendResponse(200,{},text,"utf8"); state.sendResponse(200,headers,text,"utf8");
} else { } else {
response.writeHead(404); response.writeHead(404);
response.end(); response.end();

View File

@@ -42,6 +42,8 @@ function Server(options) {
} }
// Setup the default required plugins // Setup the default required plugins
this.requiredPlugins = this.get("required-plugins").split(','); this.requiredPlugins = this.get("required-plugins").split(',');
// Initialise CORS
this.corsEnable = this.get("cors-enable") === "yes";
// Initialise CSRF // Initialise CSRF
this.csrfDisable = this.get("csrf-disable") === "yes"; this.csrfDisable = this.get("csrf-disable") === "yes";
// Initialize Gzip compression // Initialize Gzip compression
@@ -261,6 +263,13 @@ Server.prototype.requestHandler = function(request,response,options) {
state.urlInfo = url.parse(request.url); state.urlInfo = url.parse(request.url);
state.queryParameters = querystring.parse(state.urlInfo.query); state.queryParameters = querystring.parse(state.urlInfo.query);
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || ""; state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
// Enable CORS
if(this.corsEnable) {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Expose-Headers", "*");
}
state.sendResponse = sendResponse.bind(self,request,response); state.sendResponse = sendResponse.bind(self,request,response);
// Get the principals authorized to access this resource // Get the principals authorized to access this resource
state.authorizationType = options.authorizationType || this.methodMappings[request.method] || "readers"; state.authorizationType = options.authorizationType || this.methodMappings[request.method] || "readers";
@@ -285,6 +294,12 @@ Server.prototype.requestHandler = function(request,response,options) {
response.end(); response.end();
return; return;
} }
// Reply to OPTIONS
if(this.corsEnable && request.method === "OPTIONS") {
response.writeHead(204);
response.end();
return;
}
// Find the route that matches this path // Find the route that matches this path
var route = self.findMatchingRoute(request,state); var route = self.findMatchingRoute(request,state);
// Optionally output debug info // Optionally output debug info

View File

@@ -0,0 +1,30 @@
/*\
title: $:/core-modules/modules/utils/base64.js
type: application/javascript
module-type: utils-node
Base64 UTF-8 utlity functions.
\*/
"use strict";
const{ TextEncoder, TextDecoder } = require("node:util");
exports.btoa = binstr => Buffer.from(binstr, "binary").toString("base64");
exports.atob = b64 => Buffer.from(b64, "base64").toString("binary");
function base64ToBytes(base64) {
const binString = exports.atob(base64);
return Uint8Array.from(binString, m => m.codePointAt(0));
};
function bytesToBase64(bytes) {
const binString = Array.from(bytes, byte => String.fromCodePoint(byte)).join("");
return exports.btoa(binString);
};
exports.base64EncodeUtf8 = str => bytesToBase64(new TextEncoder().encode(str));
exports.base64DecodeUtf8 = str => new TextDecoder().decode(base64ToBytes(str));

View File

@@ -0,0 +1,95 @@
/*\
title: $:/core-server/modules/utils/escapecss.js
type: application/javascript
module-type: utils-node
Provides CSS.escape() functionality.
\*/
"use strict";
exports.escapeCSS = (function() {
// see also https://drafts.csswg.org/cssom/#serialize-an-identifier
/* eslint-disable */
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
return function(value) {
if (arguments.length == 0) {
throw new TypeError('`CSS.escape` requires an argument.');
}
var string = String(value);
var length = string.length;
var index = -1;
var codeUnit;
var result = '';
var firstCodeUnit = string.charCodeAt(0);
while (++index < length) {
codeUnit = string.charCodeAt(index);
// Note: theres no need to special-case astral symbols, surrogate
// pairs, or lone surrogates.
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
// (U+FFFD).
if (codeUnit == 0x0000) {
result += '\uFFFD';
continue;
}
if (
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
// U+007F, […]
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
// If the character is the first character and is in the range [0-9]
// (U+0030 to U+0039), […]
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
// If the character is the second character and is in the range [0-9]
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
(
index == 1 &&
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
firstCodeUnit == 0x002D
)
) {
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
result += '\\' + codeUnit.toString(16) + ' ';
continue;
}
if (
// If the character is the first character and is a `-` (U+002D), and
// there is no second character, […]
index == 0 &&
length == 1 &&
codeUnit == 0x002D
) {
result += '\\' + string.charAt(index);
continue;
}
// If the character is not handled by one of the above rules and is
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
// U+005A), or [a-z] (U+0061 to U+007A), […]
if (
codeUnit >= 0x0080 ||
codeUnit == 0x002D ||
codeUnit == 0x005F ||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
codeUnit >= 0x0061 && codeUnit <= 0x007A
) {
// the character itself
result += string.charAt(index);
continue;
}
// Otherwise, the escaped character.
// https://drafts.csswg.org/cssom/#escape-a-character
result += '\\' + string.charAt(index);
}
return result;
};
/* eslint-enable */
})();

View File

@@ -5,3 +5,4 @@ TiddlyWiki incorporates code from these fine OpenSource projects:
* [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]] * [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]]
* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]] * [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]]
* [[modern-normalize by Sindre Sorhus|https://github.com/sindresorhus/modern-normalize]] * [[modern-normalize by Sindre Sorhus|https://github.com/sindresorhus/modern-normalize]]
* [[diff-match-patch-es by antfu|https://github.com/antfu/diff-match-patch-es]]

View File

@@ -6,6 +6,7 @@ Appearance/Caption: Appearance
Appearance/Hint: Ways to customise the appearance of your TiddlyWiki. Appearance/Hint: Ways to customise the appearance of your TiddlyWiki.
Basics/AnimDuration/Prompt: Animation duration Basics/AnimDuration/Prompt: Animation duration
Basics/AutoFocus/Prompt: Default focus field for new tiddlers Basics/AutoFocus/Prompt: Default focus field for new tiddlers
Basics/AutoFocusEdit/Prompt: Default focus field for existing tiddlers
Basics/Caption: Basics Basics/Caption: Basics
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/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/Prompt: Default tiddlers

View File

@@ -0,0 +1,4 @@
title: $:/language/Draft/
Attribution: Draft of '<<draft-title>>' by {{$:/status/UserName}}
Title: Draft of '<<draft-title>>'

View File

@@ -1,5 +1,6 @@
title: $:/language/ title: $:/language/
Alerts: Alerts
AboveStory/ClassicPlugin/Warning: It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|https://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected: AboveStory/ClassicPlugin/Warning: It looks like you are trying to load a plugin designed for ~TiddlyWiki Classic. Please note that [[these plugins do not work with TiddlyWiki version 5.x.x|https://tiddlywiki.com/#TiddlyWikiClassic]]. ~TiddlyWiki Classic plugins detected:
BinaryWarning/Prompt: This tiddler contains binary data BinaryWarning/Prompt: This tiddler contains binary data
ClassicWarning/Hint: This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See https://tiddlywiki.com/static/Upgrading.html for more details. ClassicWarning/Hint: This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See https://tiddlywiki.com/static/Upgrading.html for more details.

View File

@@ -9,6 +9,11 @@ Advanced/ShadowInfo/NotShadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text
Advanced/ShadowInfo/Shadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is a shadow tiddler Advanced/ShadowInfo/Shadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text text=<<infoTiddler>>/></$link> is a shadow tiddler
Advanced/ShadowInfo/Shadow/Source: It is defined in the plugin <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link> Advanced/ShadowInfo/Shadow/Source: It is defined in the plugin <$link to=<<pluginTiddler>>><$text text=<<pluginTiddler>>/></$link>
Advanced/ShadowInfo/OverriddenShadow/Hint: It is overridden by an ordinary tiddler Advanced/ShadowInfo/OverriddenShadow/Hint: It is overridden by an ordinary tiddler
Advanced/CascadeInfo/Heading: Cascade Details
Advanced/CascadeInfo/Hint: These are the view template segments (tagged <<tag "$:/tags/ViewTemplate">>) using a cascade filter and their resulting template for the current tiddler.
Advanced/CascadeInfo/Detail/View: View
Advanced/CascadeInfo/Detail/ActiveCascadeFilter: Active cascade filter
Advanced/CascadeInfo/Detail/Template: Template
Fields/Caption: Fields Fields/Caption: Fields
List/Caption: List List/Caption: List
List/Empty: This tiddler does not have a list List/Empty: This tiddler does not have a list

View File

@@ -0,0 +1,106 @@
/*\
title: $:/core/modules/background-actions.js
type: application/javascript
module-type: global
\*/
"use strict";
class BackgroundActionDispatcher {
constructor(filterTracker, wiki) {
this.filterTracker = filterTracker;
this.wiki = wiki;
this.nextTrackedFilterId = 1;
this.trackedFilters = new Map(); // Use Map for better key management
this.filterTracker.track({
filterString: "[all[tiddlers+shadows]tag[$:/tags/BackgroundAction]!is[draft]]",
fnEnter: title => this.trackFilter(title),
fnLeave: (title, enterValue) => this.untrackFilter(enterValue),
fnChange: (title, enterValue) => {
this.untrackFilter(enterValue);
return this.trackFilter(title);
},
fnProcess: changes => this.process(changes)
});
}
trackFilter(title) {
const tiddler = this.wiki.getTiddler(title);
const id = this.nextTrackedFilterId++;
const tracker = new BackgroundActionTracker({
wiki: this.wiki,
title,
trackFilter: tiddler.fields["track-filter"],
actions: tiddler.fields.text
});
this.trackedFilters.set(id, tracker);
return id;
}
untrackFilter(enterValue) {
const tracker = this.trackedFilters.get(enterValue);
if(tracker) {
tracker.destroy();
}
this.trackedFilters.delete(enterValue);
}
process(changes) {
for(const tracker of this.trackedFilters.values()) {
tracker.process(changes);
}
}
}
class BackgroundActionTracker {
constructor({wiki, title, trackFilter, actions}) {
this.wiki = wiki;
this.title = title;
this.trackFilter = trackFilter;
this.actions = actions;
this.filterTracker = new $tw.FilterTracker(this.wiki);
this.hasChanged = false;
this.trackerID = this.filterTracker.track({
filterString: this.trackFilter,
fnEnter: () => { this.hasChanged = true; },
fnLeave: () => { this.hasChanged = true; },
fnProcess: changes => {
if(this.hasChanged) {
this.hasChanged = false;
console.log("Processing background action", this.title);
const tiddler = this.wiki.getTiddler(this.title);
let doActions = true;
if(tiddler && tiddler.fields.platforms) {
doActions = false;
const platforms = $tw.utils.parseStringArray(tiddler.fields.platforms);
if(($tw.browser && platforms.includes("browser")) || ($tw.node && platforms.includes("node"))) {
doActions = true;
}
}
if(doActions) {
this.wiki.invokeActionString(
this.actions,
null,
{
currentTiddler: this.title
},{
parentWidget: $tw.rootWidget
}
);
}
}
}
});
}
process(changes) {
this.filterTracker.handleChangeEvent(changes);
}
destroy() {
this.filterTracker.untrack(this.trackerID);
}
}
exports.BackgroundActionDispatcher = BackgroundActionDispatcher;

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/config.js title: $:/core/modules/config.js
type: application/javascript type: application/javascript
module-type: config module-type: config
Core configuration constants
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/deserializers.js title: $:/core/modules/deserializers.js
type: application/javascript type: application/javascript
module-type: tiddlerdeserializer module-type: tiddlerdeserializer
Functions to deserialise tiddlers from a block of text
\*/ \*/
"use strict"; "use strict";
@@ -37,12 +34,6 @@ exports["application/json"] = function(text,fields) {
return results; return results;
}; };
/*
Parse an HTML file into tiddlers. There are three possibilities:
# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers
# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers
# An ordinary HTML file
*/
exports["text/html"] = function(text,fields) { exports["text/html"] = function(text,fields) {
var results = []; var results = [];
// Check if we've got an old-style store area // Check if we've got an old-style store area
@@ -60,11 +51,11 @@ exports["text/html"] = function(text,fields) {
results.push.apply(results,deserializeNewStoreArea(text,newStoreAreaMarkerRegExp.lastIndex,newStoreAreaMatch[1],fields)); results.push.apply(results,deserializeNewStoreArea(text,newStoreAreaMarkerRegExp.lastIndex,newStoreAreaMatch[1],fields));
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text); newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text);
} }
// Return if we had either an old-style or a new-style store area
if(storeAreaMatch || haveHadNewStoreArea) { if(storeAreaMatch || haveHadNewStoreArea) {
return results; return results;
} }
// Otherwise, check whether we've got an encrypted file
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text); var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedStoreArea) { if(encryptedStoreArea) {
// If so, attempt to decrypt it using the current password // If so, attempt to decrypt it using the current password
@@ -124,30 +115,18 @@ function deserializeStoreArea(text,storeAreaEnd,isTiddlyWiki5,fields) {
return results; return results;
} }
/* var deserializeTiddlerDiv = function(text) {
Utility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:
<div title="Title" creator="JoeBloggs" modifier="JoeBloggs" created="201102111106" modified="201102111310" tags="myTag [[my long tag]]">
<pre>The text of the tiddler (without the expected HTML encoding).
</pre>
</div>
Note that the field attributes are HTML encoded, but that the body of the <PRE> tag is not encoded.
When these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.
*/
var deserializeTiddlerDiv = function(text /* [,fields] */) {
// Slot together the default results // Slot together the default results
var result = {}; var result = {};
if(arguments.length > 1) { if(arguments.length > 1) {
for(var f=1; f<arguments.length; f++) { for(var f=1; f<arguments.length; f++) {
var fields = arguments[f]; var fields = arguments[f];
for(var t in fields) { for(var t in fields) {
result[t] = fields[t]; result[t] = fields[t];
} }
} }
} }
// Parse the DIV body
var startRegExp = /^\s*<div\s+([^>]*)>(\s*<pre>)?/gi, var startRegExp = /^\s*<div\s+([^>]*)>(\s*<pre>)?/gi,
endRegExp, endRegExp,
match = startRegExp.exec(text); match = startRegExp.exec(text);

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/engines/framed.js title: $:/core/modules/editor/engines/framed.js
type: application/javascript type: application/javascript
module-type: library module-type: library
Text editor engine based on a simple input or textarea within an iframe. This is done so that the selection is preserved even when clicking away from the textarea
\*/ \*/
"use strict"; "use strict";
@@ -56,7 +53,7 @@ function FramedEngine(options) {
} else { } else {
this.domNode.value = this.value; this.domNode.value = this.value;
} }
// Set the attributes
if(this.widget.editType && this.widget.editTag !== "textarea") { if(this.widget.editType && this.widget.editTag !== "textarea") {
this.domNode.setAttribute("type",this.widget.editType); this.domNode.setAttribute("type",this.widget.editType);
} }
@@ -78,7 +75,7 @@ function FramedEngine(options) {
if(this.widget.isDisabled === "yes") { if(this.widget.isDisabled === "yes") {
this.domNode.setAttribute("disabled",true); this.domNode.setAttribute("disabled",true);
} }
// Copy the styles from the dummy textarea
this.copyStyles(); this.copyStyles();
// Add event listeners // Add event listeners
$tw.utils.addEventListeners(this.domNode,[ $tw.utils.addEventListeners(this.domNode,[
@@ -99,13 +96,10 @@ function FramedEngine(options) {
{name: "click",handlerObject: this.widget,handlerMethod: "handleClickEvent"} {name: "click",handlerObject: this.widget,handlerMethod: "handleClickEvent"}
]); ]);
} }
// Insert the element into the DOM
this.iframeDoc.body.appendChild(this.domNode); this.iframeDoc.body.appendChild(this.domNode);
} }
/*
Copy styles from the dummy text area to the textarea in the iframe
*/
FramedEngine.prototype.copyStyles = function() { FramedEngine.prototype.copyStyles = function() {
// Copy all styles // Copy all styles
$tw.utils.copyStyles(this.dummyTextArea,this.domNode); $tw.utils.copyStyles(this.dummyTextArea,this.domNode);
@@ -127,14 +121,11 @@ FramedEngine.prototype.setText = function(text,type) {
if(this.domNode.ownerDocument.activeElement !== this.domNode) { if(this.domNode.ownerDocument.activeElement !== this.domNode) {
this.updateDomNodeText(text); this.updateDomNodeText(text);
} }
// Fix the height if needed
this.fixHeight(); this.fixHeight();
} }
}; };
/*
Update the DomNode with the new text
*/
FramedEngine.prototype.updateDomNodeText = function(text) { FramedEngine.prototype.updateDomNodeText = function(text) {
try { try {
this.domNode.value = text; this.domNode.value = text;
@@ -143,16 +134,10 @@ FramedEngine.prototype.updateDomNodeText = function(text) {
} }
}; };
/*
Get the text of the engine
*/
FramedEngine.prototype.getText = function() { FramedEngine.prototype.getText = function() {
return this.domNode.value; return this.domNode.value;
}; };
/*
Fix the height of textarea to fit content
*/
FramedEngine.prototype.fixHeight = function() { FramedEngine.prototype.fixHeight = function() {
// Make sure styles are updated // Make sure styles are updated
this.copyStyles(); this.copyStyles();
@@ -172,9 +157,6 @@ FramedEngine.prototype.fixHeight = function() {
} }
}; };
/*
Focus the engine node
*/
FramedEngine.prototype.focus = function() { FramedEngine.prototype.focus = function() {
if(this.domNode.focus) { if(this.domNode.focus) {
this.domNode.focus(); this.domNode.focus();
@@ -184,18 +166,12 @@ FramedEngine.prototype.focus = function() {
} }
}; };
/*
Handle a focus event
*/
FramedEngine.prototype.handleFocusEvent = function(event) { FramedEngine.prototype.handleFocusEvent = function(event) {
if(this.widget.editCancelPopups) { if(this.widget.editCancelPopups) {
$tw.popup.cancel(0); $tw.popup.cancel(0);
} }
}; };
/*
Handle a keydown event
*/
FramedEngine.prototype.handleKeydownEvent = function(event) { FramedEngine.prototype.handleKeydownEvent = function(event) {
if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) { if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) {
return true; return true;
@@ -204,17 +180,11 @@ FramedEngine.prototype.handleKeydownEvent = function(event) {
return this.widget.handleKeydownEvent(event); return this.widget.handleKeydownEvent(event);
}; };
/*
Handle a click
*/
FramedEngine.prototype.handleClickEvent = function(event) { FramedEngine.prototype.handleClickEvent = function(event) {
this.fixHeight(); this.fixHeight();
return true; return true;
}; };
/*
Handle a dom "input" event which occurs when the text has changed
*/
FramedEngine.prototype.handleInputEvent = function(event) { FramedEngine.prototype.handleInputEvent = function(event) {
this.widget.saveChanges(this.getText()); this.widget.saveChanges(this.getText());
this.fixHeight(); this.fixHeight();
@@ -224,9 +194,6 @@ FramedEngine.prototype.handleInputEvent = function(event) {
return true; return true;
}; };
/*
Create a blank structure representing a text operation
*/
FramedEngine.prototype.createTextOperation = function() { FramedEngine.prototype.createTextOperation = function() {
var operation = { var operation = {
text: this.domNode.value, text: this.domNode.value,
@@ -242,9 +209,6 @@ FramedEngine.prototype.createTextOperation = function() {
return operation; return operation;
}; };
/*
Execute a text operation
*/
FramedEngine.prototype.executeTextOperation = function(operation) { FramedEngine.prototype.executeTextOperation = function(operation) {
// Perform the required changes to the text area and the underlying tiddler // Perform the required changes to the text area and the underlying tiddler
var newText = operation.text; var newText = operation.text;

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/engines/simple.js title: $:/core/modules/editor/engines/simple.js
type: application/javascript type: application/javascript
module-type: library module-type: library
Text editor engine based on a simple input or textarea tag
\*/ \*/
"use strict"; "use strict";
@@ -30,7 +27,7 @@ function SimpleEngine(options) {
} else { } else {
this.domNode.value = this.value; this.domNode.value = this.value;
} }
// Set the attributes
if(this.widget.editType && this.widget.editTag !== "textarea") { if(this.widget.editType && this.widget.editTag !== "textarea") {
this.domNode.setAttribute("type",this.widget.editType); this.domNode.setAttribute("type",this.widget.editType);
} }
@@ -55,7 +52,7 @@ function SimpleEngine(options) {
if(this.widget.isDisabled === "yes") { if(this.widget.isDisabled === "yes") {
this.domNode.setAttribute("disabled",true); this.domNode.setAttribute("disabled",true);
} }
// Add an input event handler
$tw.utils.addEventListeners(this.domNode,[ $tw.utils.addEventListeners(this.domNode,[
{name: "focus", handlerObject: this, handlerMethod: "handleFocusEvent"}, {name: "focus", handlerObject: this, handlerMethod: "handleFocusEvent"},
{name: "input", handlerObject: this, handlerMethod: "handleInputEvent"} {name: "input", handlerObject: this, handlerMethod: "handleInputEvent"}
@@ -65,22 +62,16 @@ function SimpleEngine(options) {
this.widget.domNodes.push(this.domNode); this.widget.domNodes.push(this.domNode);
} }
/*
Set the text of the engine if it doesn't currently have focus
*/
SimpleEngine.prototype.setText = function(text,type) { SimpleEngine.prototype.setText = function(text,type) {
if(!this.domNode.isTiddlyWikiFakeDom) { if(!this.domNode.isTiddlyWikiFakeDom) {
if(this.domNode.ownerDocument.activeElement !== this.domNode || text === "") { if(this.domNode.ownerDocument.activeElement !== this.domNode || text === "") {
this.updateDomNodeText(text); this.updateDomNodeText(text);
} }
// Fix the height if needed
this.fixHeight(); this.fixHeight();
} }
}; };
/*
Update the DomNode with the new text
*/
SimpleEngine.prototype.updateDomNodeText = function(text) { SimpleEngine.prototype.updateDomNodeText = function(text) {
try { try {
this.domNode.value = text; this.domNode.value = text;
@@ -89,16 +80,10 @@ SimpleEngine.prototype.updateDomNodeText = function(text) {
} }
}; };
/*
Get the text of the engine
*/
SimpleEngine.prototype.getText = function() { SimpleEngine.prototype.getText = function() {
return this.domNode.value; return this.domNode.value;
}; };
/*
Fix the height of textarea to fit content
*/
SimpleEngine.prototype.fixHeight = function() { SimpleEngine.prototype.fixHeight = function() {
// If .editRows is initialised, it takes precedence // If .editRows is initialised, it takes precedence
if((this.widget.editTag === "textarea") && !this.widget.editRows) { if((this.widget.editTag === "textarea") && !this.widget.editRows) {
@@ -114,9 +99,6 @@ SimpleEngine.prototype.fixHeight = function() {
} }
}; };
/*
Focus the engine node
*/
SimpleEngine.prototype.focus = function() { SimpleEngine.prototype.focus = function() {
if(this.domNode.focus) { if(this.domNode.focus) {
this.domNode.focus(); this.domNode.focus();
@@ -126,9 +108,6 @@ SimpleEngine.prototype.focus = function() {
} }
}; };
/*
Handle a dom "input" event which occurs when the text has changed
*/
SimpleEngine.prototype.handleInputEvent = function(event) { SimpleEngine.prototype.handleInputEvent = function(event) {
this.widget.saveChanges(this.getText()); this.widget.saveChanges(this.getText());
this.fixHeight(); this.fixHeight();
@@ -138,9 +117,6 @@ SimpleEngine.prototype.handleInputEvent = function(event) {
return true; return true;
}; };
/*
Handle a dom "focus" event
*/
SimpleEngine.prototype.handleFocusEvent = function(event) { SimpleEngine.prototype.handleFocusEvent = function(event) {
if(this.widget.editCancelPopups) { if(this.widget.editCancelPopups) {
$tw.popup.cancel(0); $tw.popup.cancel(0);
@@ -156,16 +132,10 @@ SimpleEngine.prototype.handleFocusEvent = function(event) {
return true; return true;
}; };
/*
Create a blank structure representing a text operation
*/
SimpleEngine.prototype.createTextOperation = function() { SimpleEngine.prototype.createTextOperation = function() {
return null; return null;
}; };
/*
Execute a text operation
*/
SimpleEngine.prototype.executeTextOperation = function(operation) { SimpleEngine.prototype.executeTextOperation = function(operation) {
}; };

View File

@@ -2,16 +2,12 @@
title: $:/core/modules/editor/factory.js title: $:/core/modules/editor/factory.js
type: application/javascript type: application/javascript
module-type: library module-type: library
Factory for constructing text editor widgets with specified engines for the toolbar and non-toolbar cases
\*/ \*/
"use strict"; "use strict";
var DEFAULT_MIN_TEXT_AREA_HEIGHT = "100px"; // Minimum height of textareas in pixels var DEFAULT_MIN_TEXT_AREA_HEIGHT = "100px"; // Minimum height of textareas in pixels
// Configuration tiddlers
var HEIGHT_MODE_TITLE = "$:/config/TextEditor/EditorHeight/Mode"; var HEIGHT_MODE_TITLE = "$:/config/TextEditor/EditorHeight/Mode";
var ENABLE_TOOLBAR_TITLE = "$:/config/TextEditor/EnableToolbar"; var ENABLE_TOOLBAR_TITLE = "$:/config/TextEditor/EnableToolbar";
@@ -48,8 +44,8 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.toolbarNode = this.document.createElement("div"); this.toolbarNode = this.document.createElement("div");
this.toolbarNode.className = "tc-editor-toolbar"; this.toolbarNode.className = "tc-editor-toolbar";
parent.insertBefore(this.toolbarNode,nextSibling); parent.insertBefore(this.toolbarNode,nextSibling);
this.renderChildren(this.toolbarNode,null);
this.domNodes.push(this.toolbarNode); this.domNodes.push(this.toolbarNode);
this.renderChildren(this.toolbarNode,null);
} }
// Create our element // Create our element
var editInfo = this.getEditInfo(), var editInfo = this.getEditInfo(),
@@ -141,9 +137,6 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
return {value: value || "", type: type, update: update}; return {value: value || "", type: type, update: update};
}; };
/*
Handle an edit text operation message from the toolbar
*/
EditTextWidget.prototype.handleEditTextOperationMessage = function(event) { EditTextWidget.prototype.handleEditTextOperationMessage = function(event) {
// Prepare information about the operation // Prepare information about the operation
var operation = this.engine.createTextOperation(); var operation = this.engine.createTextOperation();
@@ -152,16 +145,13 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
if(handler) { if(handler) {
handler.call(this,event,operation); handler.call(this,event,operation);
} }
// Execute the operation via the engine
var newText = this.engine.executeTextOperation(operation); var newText = this.engine.executeTextOperation(operation);
// Fix the tiddler height and save changes // Fix the tiddler height and save changes
this.engine.fixHeight(); this.engine.fixHeight();
this.saveChanges(newText); this.saveChanges(newText);
}; };
/*
Compute the internal state of the widget
*/
EditTextWidget.prototype.execute = function() { EditTextWidget.prototype.execute = function() {
// Get our parameters // Get our parameters
this.editTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler")); this.editTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
@@ -201,7 +191,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
} }
type = type || "text"; type = type || "text";
} }
// Get the rest of our parameters
this.editTag = this.getAttribute("tag",tag) || "input"; this.editTag = this.getAttribute("tag",tag) || "input";
this.editType = this.getAttribute("type",type); this.editType = this.getAttribute("type",type);
// Make the child widgets // Make the child widgets
@@ -211,9 +201,6 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.editShowToolbar = (this.editShowToolbar === "yes") && !!(this.children && this.children.length > 0) && (!this.document.isTiddlyWikiFakeDom); this.editShowToolbar = (this.editShowToolbar === "yes") && !!(this.children && this.children.length > 0) && (!this.document.isTiddlyWikiFakeDom);
}; };
/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
EditTextWidget.prototype.refresh = function(changedTiddlers) { EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes(); var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed // Completely rerender if any of our attributes have changed
@@ -234,24 +221,14 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
} }
}; };
/*
Update the editor with new text. This method is separate from updateEditorDomNode()
so that subclasses can override updateEditor() and still use updateEditorDomNode()
*/
EditTextWidget.prototype.updateEditor = function(text,type) { EditTextWidget.prototype.updateEditor = function(text,type) {
this.updateEditorDomNode(text,type); this.updateEditorDomNode(text,type);
}; };
/*
Update the editor dom node with new text
*/
EditTextWidget.prototype.updateEditorDomNode = function(text,type) { EditTextWidget.prototype.updateEditorDomNode = function(text,type) {
this.engine.setText(text,type); this.engine.setText(text,type);
}; };
/*
Save changes back to the tiddler store
*/
EditTextWidget.prototype.saveChanges = function(text) { EditTextWidget.prototype.saveChanges = function(text) {
var editInfo = this.getEditInfo(); var editInfo = this.getEditInfo();
if(text !== editInfo.value) { if(text !== editInfo.value) {
@@ -259,9 +236,6 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
} }
}; };
/*
Handle a dom "keydown" event, which we'll bubble up to our container for the keyboard widgets benefit
*/
EditTextWidget.prototype.handleKeydownEvent = function(event) { EditTextWidget.prototype.handleKeydownEvent = function(event) {
// Check for a keyboard shortcut // Check for a keyboard shortcut
if(this.toolbarNode) { if(this.toolbarNode) {
@@ -282,20 +256,17 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
} }
} }
} }
// Propogate the event to the container
if(this.propogateKeydownEvent(event)) { if(this.propogateKeydownEvent(event)) {
// Ignore the keydown if it was already handled // Ignore the keydown if it was already handled
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
return true; return true;
} }
// Otherwise, process the keydown normally
return false; return false;
}; };
/*
Propogate keydown events to our container for the keyboard widgets benefit
*/
EditTextWidget.prototype.propogateKeydownEvent = function(event) { EditTextWidget.prototype.propogateKeydownEvent = function(event) {
var newEvent = this.cloneEvent(event,["keyCode","code","which","key","metaKey","ctrlKey","altKey","shiftKey"]); var newEvent = this.cloneEvent(event,["keyCode","code","which","key","metaKey","ctrlKey","altKey","shiftKey"]);
return !this.parentDomNode.dispatchEvent(newEvent); return !this.parentDomNode.dispatchEvent(newEvent);
@@ -318,16 +289,12 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
return dispatchNode.dispatchEvent(newEvent); return dispatchNode.dispatchEvent(newEvent);
}; };
/*
Propogate drag and drop events with File data to our container for the dropzone widgets benefit.
If there are no Files, let the browser handle it.
*/
EditTextWidget.prototype.handleDropEvent = function(event) { EditTextWidget.prototype.handleDropEvent = function(event) {
if($tw.utils.dragEventContainsFiles(event)) { if($tw.utils.dragEventContainsFiles(event)) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"])); this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
} }
}; };
EditTextWidget.prototype.handlePasteEvent = function(event) { EditTextWidget.prototype.handlePasteEvent = function(event) {

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/bitmap/clear.js title: $:/core/modules/editor/operations/bitmap/clear.js
type: application/javascript type: application/javascript
module-type: bitmapeditoroperation module-type: bitmapeditoroperation
Bitmap editor operation to clear the image
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/bitmap/resize.js title: $:/core/modules/editor/operations/bitmap/resize.js
type: application/javascript type: application/javascript
module-type: bitmapeditoroperation module-type: bitmapeditoroperation
Bitmap editor operation to resize the image
\*/ \*/
"use strict"; "use strict";
@@ -17,7 +14,7 @@ exports["resize"] = function(event) {
if(newWidth > 0 && newHeight > 0 && !(newWidth === this.currCanvas.width && newHeight === this.currCanvas.height)) { if(newWidth > 0 && newHeight > 0 && !(newWidth === this.currCanvas.width && newHeight === this.currCanvas.height)) {
this.changeCanvasSize(newWidth,newHeight); this.changeCanvasSize(newWidth,newHeight);
} }
// Update the input controls
this.refreshToolbar(); this.refreshToolbar();
// Save the image into the tiddler // Save the image into the tiddler
this.saveChanges(); this.saveChanges();

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/bitmap/rotate-left.js title: $:/core/modules/editor/operations/bitmap/rotate-left.js
type: application/javascript type: application/javascript
module-type: bitmapeditoroperation module-type: bitmapeditoroperation
Bitmap editor operation to rotate the image left by 90 degrees
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/excise.js title: $:/core/modules/editor/operations/text/excise.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation to excise the selection to a new tiddler
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/insert-text.js title: $:/core/modules/editor/operations/text/insert-text.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation insert text at the caret position. If there is a selection it is replaced.
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/make-link.js title: $:/core/modules/editor/operations/text/make-link.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation to make a link
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/prefix-lines.js title: $:/core/modules/editor/operations/text/prefix-lines.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation to add a prefix to the selected lines
\*/ \*/
"use strict"; "use strict";
@@ -26,16 +23,16 @@ exports["prefix-lines"] = function(event,operation) {
line = line.substring(event.paramObject.character.length); line = line.substring(event.paramObject.character.length);
count++; count++;
} }
// Remove any whitespace
while(line.charAt(0) === " ") { while(line.charAt(0) === " ") {
line = line.substring(1); line = line.substring(1);
} }
// We're done if we removed the exact required prefix, otherwise add it
if(count !== targetCount) { if(count !== targetCount) {
// Apply the prefix // Apply the prefix
line = prefix + " " + line; line = prefix + " " + line;
} }
// Save the modified line
lines[index] = line; lines[index] = line;
}); });
// Stitch the replacement text together and set the selection // Stitch the replacement text together and set the selection

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/replace-all.js title: $:/core/modules/editor/operations/text/replace-all.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation to replace the entire text
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/replace-selection.js title: $:/core/modules/editor/operations/text/replace-selection.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation to replace the selection
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/save-selection.js title: $:/core/modules/editor/operations/text/save-selection.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation to save the current selection in a specified tiddler
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/wrap-lines.js title: $:/core/modules/editor/operations/text/wrap-lines.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation to wrap the selected lines with a prefix and suffix
\*/ \*/
"use strict"; "use strict";
@@ -15,14 +12,14 @@ exports["wrap-lines"] = function(event,operation) {
if($tw.utils.endsWith(operation.text.substring(0,operation.selStart), prefix + "\n") && if($tw.utils.endsWith(operation.text.substring(0,operation.selStart), prefix + "\n") &&
$tw.utils.startsWith(operation.text.substring(operation.selEnd), "\n" + suffix)) { $tw.utils.startsWith(operation.text.substring(operation.selEnd), "\n" + suffix)) {
// Selected text is already surrounded by prefix and suffix: Remove them // Selected text is already surrounded by prefix and suffix: Remove them
// Cut selected text plus prefix and suffix
operation.cutStart = operation.selStart - (prefix.length + 1); operation.cutStart = operation.selStart - (prefix.length + 1);
operation.cutEnd = operation.selEnd + suffix.length + 1; operation.cutEnd = operation.selEnd + suffix.length + 1;
// Also cut the following newline (if there is any) // Also cut the following newline (if there is any)
if (operation.text[operation.cutEnd] === "\n") { if (operation.text[operation.cutEnd] === "\n") {
operation.cutEnd++; operation.cutEnd++;
} }
// Replace with selection
operation.replacement = operation.text.substring(operation.selStart,operation.selEnd); operation.replacement = operation.text.substring(operation.selStart,operation.selEnd);
// Select text that was in between prefix and suffix // Select text that was in between prefix and suffix
operation.newSelStart = operation.cutStart; operation.newSelStart = operation.cutStart;

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/editor/operations/text/wrap-selection.js title: $:/core/modules/editor/operations/text/wrap-selection.js
type: application/javascript type: application/javascript
module-type: texteditoroperation module-type: texteditoroperation
Text editor operation to wrap the selection with the specified prefix and suffix
\*/ \*/
"use strict"; "use strict";
@@ -17,11 +14,11 @@ exports["wrap-selection"] = function(event,operation) {
selLength = o.selEnd - o.selStart; selLength = o.selEnd - o.selStart;
// This function detects, if trailing spaces are part of the selection __and__ if the user wants to handle them // This function detects, if trailing spaces are part of the selection __and__ if the user wants to handle them
// Returns "yes", "start", "end", "no" (default)
// yes .. there are trailing spaces at both ends // yes .. there are trailing spaces at both ends
// start .. there are trailing spaces at the start
// end .. there are trailing spaces at the end // end .. there are trailing spaces at the end
// no .. no trailing spaces are taken into account
var trailingSpaceAt = function(sel) { var trailingSpaceAt = function(sel) {
var _start, var _start,
_end, _end,
@@ -64,7 +61,6 @@ exports["wrap-selection"] = function(event,operation) {
} }
} }
// options: lenPrefix, lenSuffix
function removePrefixSuffix(options) { function removePrefixSuffix(options) {
options = options || {}; options = options || {};
var _lenPrefix = options.lenPrefix || 0; var _lenPrefix = options.lenPrefix || 0;

View File

@@ -0,0 +1,95 @@
/*\
title: $:/core/modules/filter-tracker.js
type: application/javascript
module-type: global
\*/
"use strict";
class FilterTracker {
constructor(wiki) {
this.wiki = wiki;
this.trackers = new Map();
this.nextTrackerId = 1;
}
handleChangeEvent(changes) {
this.processTrackers();
this.processChanges(changes);
}
track(options = {}) {
const {
filterString,
fnEnter,
fnLeave,
fnChange,
fnProcess
} = options;
const id = this.nextTrackerId++;
const tracker = {
id,
filterString,
fnEnter,
fnLeave,
fnChange,
fnProcess,
previousResults: [],
resultValues: {}
};
this.trackers.set(id, tracker);
// Process the tracker
this.processTracker(id);
return id;
}
untrack(id) {
this.trackers.delete(id);
}
processTrackers() {
for(const id of this.trackers.keys()) {
this.processTracker(id);
}
}
processTracker(id) {
const tracker = this.trackers.get(id);
if(!tracker) return;
const results = [];
// Evaluate the filter and remove duplicate results
$tw.utils.each(this.wiki.filterTiddlers(tracker.filterString), title => {
$tw.utils.pushTop(results, title);
});
// Process the newly entered results
results.forEach(title => {
if(!tracker.previousResults.includes(title) && !tracker.resultValues[title] && tracker.fnEnter) {
tracker.resultValues[title] = tracker.fnEnter(title) || true;
}
});
// Process the results that have just left
tracker.previousResults.forEach(title => {
if(!results.includes(title) && tracker.resultValues[title] && tracker.fnLeave) {
tracker.fnLeave(title, tracker.resultValues[title]);
delete tracker.resultValues[title];
}
});
// Update the previous results
tracker.previousResults = results;
}
processChanges(changes) {
for(const tracker of this.trackers.values()) {
Object.keys(changes).forEach(title => {
if(title && tracker.previousResults.includes(title) && tracker.fnChange) {
tracker.resultValues[title] = tracker.fnChange(title, tracker.resultValues[title]) || tracker.resultValues[title];
}
});
if(tracker.fnProcess) {
tracker.fnProcess(changes);
}
}
}
}
exports.FilterTracker = FilterTracker;

View File

@@ -2,17 +2,10 @@
title: $:/core/modules/filterrunprefixes/all.js title: $:/core/modules/filterrunprefixes/all.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
Union of sets without de-duplication.
Equivalent to = filter run prefix.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.all = function(operationSubFunction) { exports.all = function(operationSubFunction) {
return function(results,source,widget) { return function(results,source,widget) {
results.push.apply(results, operationSubFunction(source,widget)); results.push.apply(results, operationSubFunction(source,widget));

View File

@@ -2,17 +2,10 @@
title: $:/core/modules/filterrunprefixes/and.js title: $:/core/modules/filterrunprefixes/and.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
Intersection of sets.
Equivalent to + filter run prefix.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.and = function(operationSubFunction,options) { exports.and = function(operationSubFunction,options) {
return function(results,source,widget) { return function(results,source,widget) {
// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved // This replaces all the elements of the array, but keeps the actual array so that references to it are preserved

View File

@@ -6,9 +6,6 @@ module-type: filterrunprefix
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.cascade = function(operationSubFunction,options) { exports.cascade = function(operationSubFunction,options) {
return function(results,source,widget) { return function(results,source,widget) {
if(results.length !== 0) { if(results.length !== 0) {
@@ -24,7 +21,7 @@ exports.cascade = function(operationSubFunction,options) {
} }
var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title, "currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler","") "..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""})
})); }));
if(output.length !== 0) { if(output.length !== 0) {
result = output[0]; result = output[0];

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filterrunprefixes/else.js title: $:/core/modules/filterrunprefixes/else.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
Equivalent to ~ filter run prefix.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.else = function(operationSubFunction) { exports.else = function(operationSubFunction) {
return function(results,source,widget) { return function(results,source,widget) {
if(results.length === 0) { if(results.length === 0) {

View File

@@ -2,17 +2,10 @@
title: $:/core/modules/filterrunprefixes/except.js title: $:/core/modules/filterrunprefixes/except.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
Difference of sets.
Equivalent to - filter run prefix.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.except = function(operationSubFunction) { exports.except = function(operationSubFunction) {
return function(results,source,widget) { return function(results,source,widget) {
results.remove(operationSubFunction(source,widget)); results.remove(operationSubFunction(source,widget));

View File

@@ -2,14 +2,10 @@
title: $:/core/modules/filterrunprefixes/filter.js title: $:/core/modules/filterrunprefixes/filter.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.filter = function(operationSubFunction,options) { exports.filter = function(operationSubFunction,options) {
return function(results,source,widget) { return function(results,source,widget) {
if(results.length > 0) { if(results.length > 0) {
@@ -18,7 +14,7 @@ exports.filter = function(operationSubFunction,options) {
results.each(function(title) { results.each(function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title, "currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler",""), "..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""}),
"index": "" + index, "index": "" + index,
"revIndex": "" + (results.length - 1 - index), "revIndex": "" + (results.length - 1 - index),
"length": "" + results.length "length": "" + results.length

View File

@@ -2,14 +2,10 @@
title: $:/core/modules/filterrunprefixes/intersection.js title: $:/core/modules/filterrunprefixes/intersection.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
\*/ \*/
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.intersection = function(operationSubFunction) { exports.intersection = function(operationSubFunction) {
return function(results,source,widget) { return function(results,source,widget) {
if(results.length !== 0) { if(results.length !== 0) {

View File

@@ -2,18 +2,10 @@
title: $:/core/modules/filterrunprefixes/let.js title: $:/core/modules/filterrunprefixes/let.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
Assign a value to a variable
\*/ \*/
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.let = function(operationSubFunction,options) { exports.let = function(operationSubFunction,options) {
// Return the filter run prefix function // Return the filter run prefix function
return function(results,source,widget) { return function(results,source,widget) {
@@ -30,7 +22,7 @@ exports.let = function(operationSubFunction,options) {
if(typeof name !== "string" || name.length === 0) { if(typeof name !== "string" || name.length === 0) {
return; return;
} }
// Assign the result of the subfunction to the variable
var variables = {}; var variables = {};
variables[name] = resultList; variables[name] = resultList;
// Return the variables // Return the variables

View File

@@ -6,9 +6,6 @@ module-type: filterrunprefix
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.map = function(operationSubFunction,options) { exports.map = function(operationSubFunction,options) {
return function(results,source,widget) { return function(results,source,widget) {
if(results.length > 0) { if(results.length > 0) {
@@ -20,7 +17,7 @@ exports.map = function(operationSubFunction,options) {
$tw.utils.each(inputTitles,function(title) { $tw.utils.each(inputTitles,function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title, "currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler",""), "..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""}),
"index": "" + index, "index": "" + index,
"revIndex": "" + (inputTitles.length - 1 - index), "revIndex": "" + (inputTitles.length - 1 - index),
"length": "" + inputTitles.length "length": "" + inputTitles.length

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filterrunprefixes/or.js title: $:/core/modules/filterrunprefixes/or.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
Equivalent to a filter run with no prefix.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.or = function(operationSubFunction) { exports.or = function(operationSubFunction) {
return function(results,source,widget) { return function(results,source,widget) {
results.pushTop(operationSubFunction(source,widget)); results.pushTop(operationSubFunction(source,widget));

View File

@@ -6,9 +6,6 @@ module-type: filterrunprefix
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.reduce = function(operationSubFunction,options) { exports.reduce = function(operationSubFunction,options) {
return function(results,source,widget) { return function(results,source,widget) {
if(results.length > 0) { if(results.length > 0) {
@@ -17,7 +14,7 @@ exports.reduce = function(operationSubFunction,options) {
results.each(function(title) { results.each(function(title) {
var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title, "currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler"), "..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""}),
"index": "" + index, "index": "" + index,
"revIndex": "" + (results.length - 1 - index), "revIndex": "" + (results.length - 1 - index),
"length": "" + results.length, "length": "" + results.length,

View File

@@ -2,14 +2,10 @@
title: $:/core/modules/filterrunprefixes/sort.js title: $:/core/modules/filterrunprefixes/sort.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
\*/ \*/
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.sort = function(operationSubFunction,options) { exports.sort = function(operationSubFunction,options) {
return function(results,source,widget) { return function(results,source,widget) {
if(results.length > 0) { if(results.length > 0) {
@@ -24,7 +20,7 @@ exports.sort = function(operationSubFunction,options) {
results.each(function(title) { results.each(function(title) {
var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title, "currentTiddler": "" + title,
"..currentTiddler": widget.getVariable("currentTiddler") "..currentTiddler": widget.getVariable("currentTiddler",{defaultValue:""})
})); }));
sortKeys.push(key[0] || ""); sortKeys.push(key[0] || "");
}); });
@@ -33,7 +29,7 @@ exports.sort = function(operationSubFunction,options) {
for(var t=0; t<inputTitles.length; t++) { for(var t=0; t<inputTitles.length; t++) {
indexes[t] = t; indexes[t] = t;
} }
// Sort the indexes
compareFn = $tw.utils.makeCompareFunction(sortType,{defaultType: "string", invert:invert, isCaseSensitive:isCaseSensitive}); compareFn = $tw.utils.makeCompareFunction(sortType,{defaultType: "string", invert:invert, isCaseSensitive:isCaseSensitive});
indexes = indexes.sort(function(a,b) { indexes = indexes.sort(function(a,b) {
return compareFn(sortKeys[a],sortKeys[b]); return compareFn(sortKeys[a],sortKeys[b]);

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filterrunprefixes/then.js title: $:/core/modules/filterrunprefixes/then.js
type: application/javascript type: application/javascript
module-type: filterrunprefix module-type: filterrunprefix
Replace results of previous runs unless empty
\*/ \*/
"use strict"; "use strict";
/*
Export our filter prefix function
*/
exports.then = function(operationSubFunction) { exports.then = function(operationSubFunction) {
return function(results,source,widget) { return function(results,source,widget) {
if(results.length !== 0) { if(results.length !== 0) {

View File

@@ -2,39 +2,28 @@
title: $:/core/modules/filters.js title: $:/core/modules/filters.js
type: application/javascript type: application/javascript
module-type: wikimethod module-type: wikimethod
Adds tiddler filtering methods to the $tw.Wiki object.
\*/ \*/
"use strict"; "use strict";
var widgetClass = require("$:/core/modules/widgets/widget.js").widget; var widgetClass = require("$:/core/modules/widgets/widget.js").widget;
/* Maximum permitted filter recursion depth */
var MAX_FILTER_DEPTH = 300; 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
filterString: filter string
p: start position within the string
Returns the new start position, after the parsed operation
*/
function parseFilterOperation(operators,filterString,p) { function parseFilterOperation(operators,filterString,p) {
var nextBracketPos, operator; var nextBracketPos, operator;
// Skip the starting square bracket // Skip the starting square bracket
if(filterString.charAt(p++) !== "[") { if(filterString.charAt(p++) !== "[") {
throw "Missing [ in filter expression"; throw "Missing [ in filter expression";
} }
// Process each operator in turn
do { do {
operator = {}; operator = {};
// Check for an operator prefix // Check for an operator prefix
if(filterString.charAt(p) === "!") { if(filterString.charAt(p) === "!") {
operator.prefix = filterString.charAt(p++); operator.prefix = filterString.charAt(p++);
} }
// Get the operator name
nextBracketPos = filterString.substring(p).search(/[\[\{<\/\(]/); nextBracketPos = filterString.substring(p).search(/[\[\{<\/\(]/);
if(nextBracketPos === -1) { if(nextBracketPos === -1) {
throw "Missing [ in filter expression"; throw "Missing [ in filter expression";
@@ -55,12 +44,12 @@ function parseFilterOperation(operators,filterString,p) {
$tw.utils.each(subsuffix.split(","),function(entry) { $tw.utils.each(subsuffix.split(","),function(entry) {
entry = $tw.utils.trim(entry); entry = $tw.utils.trim(entry);
if(entry) { if(entry) {
operator.suffixes[operator.suffixes.length - 1].push(entry); operator.suffixes[operator.suffixes.length - 1].push(entry);
} }
}); });
}); });
} }
// Empty operator means: title
else if(operator.operator === "") { else if(operator.operator === "") {
operator.operator = "title"; operator.operator = "title";
} }
@@ -88,8 +77,8 @@ function parseFilterOperation(operators,filterString,p) {
rexMatch = rex.exec(filterString.substring(p)); rexMatch = rex.exec(filterString.substring(p));
if(rexMatch) { if(rexMatch) {
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]); operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
// DEPRECATION WARNING // DEPRECATION WARNING
console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp); console.log("WARNING: Filter",operator.operator,"has a deprecated regexp operand",operator.regexp);
nextBracketPos = p + rex.lastIndex - 1; nextBracketPos = p + rex.lastIndex - 1;
} }
else { else {
@@ -125,20 +114,16 @@ function parseFilterOperation(operators,filterString,p) {
} }
} }
// Push this operator
operators.push(operator); operators.push(operator);
} while(filterString.charAt(p) !== "]"); } while(filterString.charAt(p) !== "]");
// Skip the ending square bracket // Skip the ending square bracket
if(filterString.charAt(p++) !== "]") { if(filterString.charAt(p++) !== "]") {
throw "Missing ] in filter expression"; throw "Missing ] in filter expression";
} }
// Return the parsing position
return p; return p;
} }
/*
Parse a filter string
*/
exports.parseFilter = function(filterString) { exports.parseFilter = function(filterString) {
filterString = filterString || ""; filterString = filterString || "";
var results = [], // Array of arrays of operator nodes {operator:,operand:} var results = [], // Array of arrays of operator nodes {operator:,operand:}
@@ -147,11 +132,11 @@ exports.parseFilter = function(filterString) {
var whitespaceRegExp = /(\s+)/mg, var whitespaceRegExp = /(\s+)/mg,
// Groups: // Groups:
// 1 - entire filter run prefix // 1 - entire filter run prefix
// 2 - filter run prefix itself
// 3 - filter run prefix suffixes // 3 - filter run prefix suffixes
// 4 - opening square bracket following filter run prefix
// 5 - double quoted string following filter run prefix // 5 - double quoted string following filter run prefix
// 6 - single quoted string following filter run prefix
// 7 - anything except for whitespace and square brackets // 7 - anything except for whitespace and square brackets
operandRegExp = /((?:\+|\-|~|(?:=>?)|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg; operandRegExp = /((?:\+|\-|~|(?:=>?)|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
while(p < filterString.length) { while(p < filterString.length) {
@@ -161,7 +146,7 @@ exports.parseFilter = function(filterString) {
if(match && match.index === p) { if(match && match.index === p) {
p = p + match[0].length; p = p + match[0].length;
} }
// Match the start of the operation
if(p < filterString.length) { if(p < filterString.length) {
operandRegExp.lastIndex = p; operandRegExp.lastIndex = p;
var operation = { var operation = {
@@ -178,7 +163,7 @@ exports.parseFilter = function(filterString) {
if(match[2]) { if(match[2]) {
operation.namedPrefix = match[2]; operation.namedPrefix = match[2];
} }
// Suffixes for filter run prefix
if(match[3]) { if(match[3]) {
operation.suffixes = []; operation.suffixes = [];
$tw.utils.each(match[3].split(":"),function(subsuffix) { $tw.utils.each(match[3].split(":"),function(subsuffix) {
@@ -192,7 +177,7 @@ exports.parseFilter = function(filterString) {
}); });
} }
} }
// Opening square bracket
if(match[4]) { if(match[4]) {
p = parseFilterOperation(operation.operators,filterString,p); p = parseFilterOperation(operation.operators,filterString,p);
} else { } else {
@@ -202,7 +187,7 @@ exports.parseFilter = function(filterString) {
// No filter run prefix // No filter run prefix
p = parseFilterOperation(operation.operators,filterString,p); p = parseFilterOperation(operation.operators,filterString,p);
} }
// Quoted strings and unquoted title
if(match[5] || match[6] || match[7]) { // Double quoted string, single quoted string or unquoted title if(match[5] || match[6] || match[7]) { // Double quoted string, single quoted string or unquoted title
operation.operators.push( operation.operators.push(
{operator: "title", operands: [{text: match[5] || match[6] || match[7]}]} {operator: "title", operands: [{text: match[5] || match[6] || match[7]}]}
@@ -232,19 +217,9 @@ exports.getFilterRunPrefixes = function() {
exports.filterTiddlers = function(filterString,widget,source) { exports.filterTiddlers = function(filterString,widget,source) {
var fn = this.compileFilter(filterString); var fn = this.compileFilter(filterString);
try { return fn.call(this,source,widget);
const fnResult = fn.call(this,source,widget);
return fnResult;
} catch(e) {
return [`${$tw.language.getString("Error/Filter")}: ${e}`];
}
}; };
/*
Compile a filter into a function with the signature fn(source,widget) where:
source: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)
widget: an optional widget node for retrieving the current tiddler etc.
*/
exports.compileFilter = function(filterString) { exports.compileFilter = function(filterString) {
if(!this.filterCache) { if(!this.filterCache) {
this.filterCache = Object.create(null); this.filterCache = Object.create(null);
@@ -262,7 +237,7 @@ exports.compileFilter = function(filterString) {
return [$tw.language.getString("Error/Filter") + ": " + e]; return [$tw.language.getString("Error/Filter") + ": " + e];
}; };
} }
// Get the hashmap of filter operator functions
var filterOperators = this.getFilterOperators(); var filterOperators = this.getFilterOperators();
// Assemble array of functions, one for each operation // Assemble array of functions, one for each operation
var operationFunctions = []; var operationFunctions = [];
@@ -307,7 +282,7 @@ exports.compileFilter = function(filterString) {
operand.value = ""; operand.value = "";
operand.multiValue = []; operand.multiValue = [];
} }
operand.isMultiValueOperand = true; operand.isMultiValueOperand = true;
} else { } else {
operand.value = operand.text; operand.value = operand.text;
operand.multiValue = [operand.value]; operand.multiValue = [operand.value];
@@ -319,19 +294,19 @@ exports.compileFilter = function(filterString) {
// Invoke the appropriate filteroperator module // Invoke the appropriate filteroperator module
results = operatorFunction(accumulator,{ results = operatorFunction(accumulator,{
operator: operator.operator, operator: operator.operator,
operand: operands.length > 0 ? operands[0] : undefined, operand: operands.length > 0 ? operands[0] : undefined,
operands: operands, operands: operands,
multiValueOperands: multiValueOperands, multiValueOperands: multiValueOperands,
isMultiValueOperand: isMultiValueOperand, isMultiValueOperand: isMultiValueOperand,
prefix: operator.prefix, prefix: operator.prefix,
suffix: operator.suffix, suffix: operator.suffix,
suffixes: operator.suffixes, suffixes: operator.suffixes,
regexp: operator.regexp regexp: operator.regexp
},{ },{
wiki: self, wiki: self,
widget: widget widget: widget
}); });
if($tw.utils.isArray(results)) { if($tw.utils.isArray(results)) {
accumulator = self.makeTiddlerIterator(results); accumulator = self.makeTiddlerIterator(results);
} else { } else {
@@ -365,7 +340,7 @@ exports.compileFilter = function(filterString) {
return filterRunPrefixes["else"](operationSubFunction, options); return filterRunPrefixes["else"](operationSubFunction, options);
case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable
return filterRunPrefixes["let"](operationSubFunction, options); return filterRunPrefixes["let"](operationSubFunction, options);
default: default:
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) { if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options); return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
} else { } else {
@@ -407,7 +382,7 @@ exports.compileFilter = function(filterString) {
}); });
if(this.filterCacheCount >= 2000) { if(this.filterCacheCount >= 2000) {
// To prevent memory leak, we maintain an upper limit for cache size. // To prevent memory leak, we maintain an upper limit for cache size.
// Reset if exceeded. This should give us 95% of the benefit
// that no cache limit would give us. // that no cache limit would give us.
this.filterCache = Object.create(null); this.filterCache = Object.create(null);
this.filterCacheCount = 0; this.filterCacheCount = 0;

View File

@@ -2,18 +2,10 @@
title: $:/core/modules/filters/addprefix.js title: $:/core/modules/filters/addprefix.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for adding a prefix to each title in the list. This is
especially useful in contexts where only a filter expression is allowed
and macro substitution isn't available.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.addprefix = function(source,operator,options) { exports.addprefix = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,18 +2,10 @@
title: $:/core/modules/filters/addsuffix.js title: $:/core/modules/filters/addsuffix.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for adding a suffix to each title in the list. This is
especially useful in contexts where only a filter expression is allowed
and macro substitution isn't available.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.addsuffix = function(source,operator,options) { exports.addsuffix = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/after.js title: $:/core/modules/filters/after.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator returning the tiddler from the current list that is after the tiddler named in the operand.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.after = function(source,operator,options) { exports.after = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,11 +2,6 @@
title: $:/core/modules/filters/all.js title: $:/core/modules/filters/all.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for selecting tiddlers
[all[shadows+tiddlers]]
\*/ \*/
"use strict"; "use strict";
@@ -21,9 +16,6 @@ function getAllFilterOperators() {
return allFilterOperators; return allFilterOperators;
} }
/*
Export our filter function
*/
exports.all = function(source,operator,options) { exports.all = function(source,operator,options) {
// Check for common optimisations // Check for common optimisations
var subops = operator.operand.split("+"); var subops = operator.operand.split("+");
@@ -38,7 +30,7 @@ exports.all = function(source,operator,options) {
} else if(subops.length === 2 && subops[0] === "shadows" && subops[1] === "tiddlers") { } else if(subops.length === 2 && subops[0] === "shadows" && subops[1] === "tiddlers") {
return options.wiki.eachShadowPlusTiddlers; return options.wiki.eachShadowPlusTiddlers;
} }
// Do it the hard way
// Get our suboperators // Get our suboperators
var allFilterOperators = getAllFilterOperators(); var allFilterOperators = getAllFilterOperators();
// Cycle through the suboperators accumulating their results // Cycle through the suboperators accumulating their results

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/all/current.js title: $:/core/modules/filters/all/current.js
type: application/javascript type: application/javascript
module-type: allfilteroperator module-type: allfilteroperator
Filter function for [all[current]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.current = function(source,prefix,options) { exports.current = function(source,prefix,options) {
var currTiddlerTitle = options.widget && options.widget.getVariable("currentTiddler"); var currTiddlerTitle = options.widget && options.widget.getVariable("currentTiddler");
if(currTiddlerTitle) { if(currTiddlerTitle) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/all/missing.js title: $:/core/modules/filters/all/missing.js
type: application/javascript type: application/javascript
module-type: allfilteroperator module-type: allfilteroperator
Filter function for [all[missing]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.missing = function(source,prefix,options) { exports.missing = function(source,prefix,options) {
return options.wiki.getMissingTitles(); return options.wiki.getMissingTitles();
}; };

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/all/orphans.js title: $:/core/modules/filters/all/orphans.js
type: application/javascript type: application/javascript
module-type: allfilteroperator module-type: allfilteroperator
Filter function for [all[orphans]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.orphans = function(source,prefix,options) { exports.orphans = function(source,prefix,options) {
return options.wiki.getOrphanTitles(); return options.wiki.getOrphanTitles();
}; };

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/all/shadows.js title: $:/core/modules/filters/all/shadows.js
type: application/javascript type: application/javascript
module-type: allfilteroperator module-type: allfilteroperator
Filter function for [all[shadows]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.shadows = function(source,prefix,options) { exports.shadows = function(source,prefix,options) {
return options.wiki.allShadowTitles(); return options.wiki.allShadowTitles();
}; };

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/all/tags.js title: $:/core/modules/filters/all/tags.js
type: application/javascript type: application/javascript
module-type: allfilteroperator module-type: allfilteroperator
Filter function for [all[tags]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.tags = function(source,prefix,options) { exports.tags = function(source,prefix,options) {
return Object.keys(options.wiki.getTagMap()); return Object.keys(options.wiki.getTagMap());
}; };

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/all/tiddlers.js title: $:/core/modules/filters/all/tiddlers.js
type: application/javascript type: application/javascript
module-type: allfilteroperator module-type: allfilteroperator
Filter function for [all[tiddlers]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.tiddlers = function(source,prefix,options) { exports.tiddlers = function(source,prefix,options) {
return options.wiki.allTitles(); return options.wiki.allTitles();
}; };

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/backlinks.js title: $:/core/modules/filters/backlinks.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for returning all the backlinks from a tiddler
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.backlinks = function(source,operator,options) { exports.backlinks = function(source,operator,options) {
var results = new $tw.utils.LinkedList(); var results = new $tw.utils.LinkedList();
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,15 +2,9 @@
title: $:/core/modules/filters/backtranscludes.js title: $:/core/modules/filters/backtranscludes.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for returning all the backtranscludes from a tiddler
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.backtranscludes = function(source,operator,options) { exports.backtranscludes = function(source,operator,options) {
var results = new $tw.utils.LinkedList(); var results = new $tw.utils.LinkedList();
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/before.js title: $:/core/modules/filters/before.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator returning the tiddler from the current list that is before the tiddler named in the operand.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.before = function(source,operator,options) { exports.before = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/commands.js title: $:/core/modules/filters/commands.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for returning the names of the commands available in this wiki
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.commands = function(source,operator,options) { exports.commands = function(source,operator,options) {
var results = []; var results = [];
$tw.utils.each($tw.commands,function(commandInfo,name) { $tw.utils.each($tw.commands,function(commandInfo,name) {

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/filters/compare.js title: $:/core/modules/filters/compare.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
General purpose comparison operator
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/contains.js title: $:/core/modules/filters/contains.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for finding values in array fields
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.contains = function(source,operator,options) { exports.contains = function(source,operator,options) {
var results = [], var results = [],
fieldname = operator.suffix || "list"; fieldname = operator.suffix || "list";

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/count.js title: $:/core/modules/filters/count.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator returning the number of entries in the current list.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.count = function(source,operator,options) { exports.count = function(source,operator,options) {
var count = 0; var count = 0;
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/filters/crypto.js title: $:/core/modules/filters/crypto.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operators for cryptography, using the Stanford JavaScript library
\*/ \*/
"use strict"; "use strict";

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/days.js title: $:/core/modules/filters/days.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator that selects tiddlers with a specified date field within a specified date interval.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.days = function(source,operator,options) { exports.days = function(source,operator,options) {
var results = [], var results = [],
fieldName = operator.suffix || "modified", fieldName = operator.suffix || "modified",

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/deserializers.js title: $:/core/modules/filters/deserializers.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for returning the names of the deserializers in this wiki
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.deserializers = function(source,operator,options) { exports.deserializers = function(source,operator,options) {
var results = []; var results = [];
$tw.utils.each($tw.Wiki.tiddlerDeserializerModules,function(deserializer,type) { $tw.utils.each($tw.Wiki.tiddlerDeserializerModules,function(deserializer,type) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/duplicateslugs.js title: $:/core/modules/filters/duplicateslugs.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter function for [duplicateslugs[]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.duplicateslugs = function(source,operator,options) { exports.duplicateslugs = function(source,operator,options) {
var slugs = Object.create(null), // Hashmap by slug of title, replaced with "true" if the duplicate title has already been output var slugs = Object.create(null), // Hashmap by slug of title, replaced with "true" if the duplicate title has already been output
results = []; results = [];

View File

@@ -2,17 +2,10 @@
title: $:/core/modules/filters/each.js title: $:/core/modules/filters/each.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator that selects one tiddler for each unique value of the specified field.
With suffix "list", selects all tiddlers that are values in a specified list field.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.each = function(source,operator,options) { exports.each = function(source,operator,options) {
var results =[] , var results =[] ,
value,values = {}, value,values = {},

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/eachday.js title: $:/core/modules/filters/eachday.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator that selects one tiddler for each unique day covered by the specified date field
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.eachday = function(source,operator,options) { exports.eachday = function(source,operator,options) {
var results = [], var results = [],
values = [], values = [],

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/editiondescription.js title: $:/core/modules/filters/editiondescription.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for returning the descriptions of the specified edition names
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.editiondescription = function(source,operator,options) { exports.editiondescription = function(source,operator,options) {
var results = []; var results = [];
if($tw.node) { if($tw.node) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/editions.js title: $:/core/modules/filters/editions.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for returning the names of the available editions in this wiki
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.editions = function(source,operator,options) { exports.editions = function(source,operator,options) {
var results = []; var results = [];
if($tw.node) { if($tw.node) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/else.js title: $:/core/modules/filters/else.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for replacing an empty input list with a constant, passing a non-empty input list straight through
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.else = function(source,operator,options) { exports.else = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,17 +2,10 @@
title: $:/core/modules/filters/decodeuricomponent.js title: $:/core/modules/filters/decodeuricomponent.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for applying decodeURIComponent() to each item.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter functions
*/
exports.decodebase64 = function(source,operator,options) { exports.decodebase64 = function(source,operator,options) {
var results = []; var results = [];
var binary = operator.suffixes && operator.suffixes[0].indexOf("binary") !== -1; var binary = operator.suffixes && operator.suffixes[0].indexOf("binary") !== -1;

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/enlist.js title: $:/core/modules/filters/enlist.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator returning its operand parsed as a list
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.enlist = function(source,operator,options) { exports.enlist = function(source,operator,options) {
var allowDuplicates = false; var allowDuplicates = false;
switch(operator.suffix) { switch(operator.suffix) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/field.js title: $:/core/modules/filters/field.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for comparing fields for equality
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.field = function(source,operator,options) { exports.field = function(source,operator,options) {
var results = [],indexedResults, var results = [],indexedResults,
fieldname = operator.suffix || operator.operator || "title"; fieldname = operator.suffix || operator.operator || "title";

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/fields.js title: $:/core/modules/filters/fields.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for returning the names of the fields on the selected tiddlers
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.fields = function(source,operator,options) { exports.fields = function(source,operator,options) {
var results = [], var results = [],
fieldName, fieldName,
@@ -28,13 +22,13 @@ exports.fields = function(source,operator,options) {
for(fieldName in tiddler.fields) { for(fieldName in tiddler.fields) {
(operand.indexOf(fieldName) !== -1) ? "" : $tw.utils.pushTop(results,fieldName); (operand.indexOf(fieldName) !== -1) ? "" : $tw.utils.pushTop(results,fieldName);
} }
} // else if }
else { else {
for(fieldName in tiddler.fields) { for(fieldName in tiddler.fields) {
$tw.utils.pushTop(results,fieldName); $tw.utils.pushTop(results,fieldName);
} }
} // else }
} // if (tiddler) }
}); });
return results; return results;
}; };

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/filter.js title: $:/core/modules/filters/filter.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator returning those input titles that pass a subfilter
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.filter = function(source,operator,options) { exports.filter = function(source,operator,options) {
var filterFn = options.wiki.compileFilter(operator.operand), var filterFn = options.wiki.compileFilter(operator.operand),
results = [], results = [],
@@ -19,7 +13,7 @@ exports.filter = function(source,operator,options) {
source(function(tiddler,title) { source(function(tiddler,title) {
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),options.widget.makeFakeWidgetWithVariables({ var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),options.widget.makeFakeWidgetWithVariables({
"currentTiddler": "" + title, "currentTiddler": "" + title,
"..currentTiddler": options.widget.getVariable("currentTiddler","") "..currentTiddler": options.widget.getVariable("currentTiddler",{defaultValue:""})
})); }));
if((list.length > 0) === target) { if((list.length > 0) === target) {
results.push(title); results.push(title);

View File

@@ -17,9 +17,6 @@ function getFormatFilterOperators() {
return formatFilterOperators; return formatFilterOperators;
} }
/*
Export our filter function
*/
exports.format = function(source,operator,options) { exports.format = function(source,operator,options) {
// Dispatch to the correct formatfilteroperator // Dispatch to the correct formatfilteroperator
var formatFilterOperators = getFormatFilterOperators(); var formatFilterOperators = getFormatFilterOperators();

View File

@@ -6,9 +6,6 @@ module-type: formatfilteroperator
"use strict"; "use strict";
/*
Export our filter function
*/
exports.date = function(source,operand,options) { exports.date = function(source,operand,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -6,9 +6,6 @@ module-type: formatfilteroperator
"use strict"; "use strict";
/*
Export our filter function
*/
exports.json = function(source,operand,options) { exports.json = function(source,operand,options) {
var results = [], var results = [],
spaces = null; spaces = null;

View File

@@ -6,9 +6,6 @@ module-type: formatfilteroperator
"use strict"; "use strict";
/*
Export our filter function
*/
exports.relativedate = function(source,operand,options) { exports.relativedate = function(source,operand,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -6,9 +6,6 @@ module-type: formatfilteroperator
"use strict"; "use strict";
/*
Export our filter function
*/
exports.timestamp = function(source,operand,options) { exports.timestamp = function(source,operand,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -6,9 +6,6 @@ module-type: formatfilteroperator
"use strict"; "use strict";
/*
Export our filter function
*/
exports.titlelist = function(source,operand,options) { exports.titlelist = function(source,operand,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/function.js title: $:/core/modules/filters/function.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator returning those input titles that are returned from a function
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.function = function(source,operator,options) { exports.function = function(source,operator,options) {
var functionName = operator.operands[0], var functionName = operator.operands[0],
params = [], params = [],
@@ -24,13 +18,13 @@ exports.function = function(source,operator,options) {
if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) { if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) {
results = variableInfo.resultList ? variableInfo.resultList : [variableInfo.text]; results = variableInfo.resultList ? variableInfo.resultList : [variableInfo.text];
} }
// Return the input list if the function wasn't found
if(!results) { if(!results) {
results = []; results = [];
source(function(tiddler,title) { source(function(tiddler,title) {
results.push(title); results.push(title);
}); });
} }
// console.log(`function ${functionName} with params ${JSON.stringify(params)} results: ${JSON.stringify(results)}`);
return results; return results;
}; };

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/get.js title: $:/core/modules/filters/get.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for replacing tiddler titles by the value of the field specified in the operand.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.get = function(source,operator,options) { exports.get = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/getindex.js title: $:/core/modules/filters/getindex.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
returns the value at a given index of datatiddlers
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.getindex = function(source,operator,options) { exports.getindex = function(source,operator,options) {
var data,title,results = []; var data,title,results = [];
if(operator.operand){ if(operator.operand){

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/getvariable.js title: $:/core/modules/filters/getvariable.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for replacing input values by the value of the variable with the same name, or blank if the variable is missing
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.getvariable = function(source,operator,options) { exports.getvariable = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/has.js title: $:/core/modules/filters/has.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for checking if a tiddler has the specified field or index
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.has = function(source,operator,options) { exports.has = function(source,operator,options) {
var results = [], var results = [],
invert = operator.prefix === "!"; invert = operator.prefix === "!";

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/haschanged.js title: $:/core/modules/filters/haschanged.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator returns tiddlers from the list that have a non-zero changecount.
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.haschanged = function(source,operator,options) { exports.haschanged = function(source,operator,options) {
var results = []; var results = [];
if(operator.prefix === "!") { if(operator.prefix === "!") {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/indexes.js title: $:/core/modules/filters/indexes.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for returning the indexes of a data tiddler
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.indexes = function(source,operator,options) { exports.indexes = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/insertafter.js title: $:/core/modules/filters/insertafter.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Insert an item after another item in a list
\*/ \*/
"use strict"; "use strict";
/*
Order a list
*/
exports.insertafter = function(source,operator,options) { exports.insertafter = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {
@@ -24,7 +18,7 @@ exports.insertafter = function(source,operator,options) {
if(pos !== -1) { if(pos !== -1) {
results.splice(pos,1); results.splice(pos,1);
} }
// Insert the entry after the target marker
pos = results.indexOf(target); pos = results.indexOf(target);
if(pos !== -1) { if(pos !== -1) {
results.splice(pos+1,0,operator.operand); results.splice(pos+1,0,operator.operand);

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/insertbefore.js title: $:/core/modules/filters/insertbefore.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Insert an item before another item in a list
\*/ \*/
"use strict"; "use strict";
/*
Order a list
*/
exports.insertbefore = function(source,operator,options) { exports.insertbefore = function(source,operator,options) {
var results = []; var results = [];
source(function(tiddler,title) { source(function(tiddler,title) {
@@ -24,7 +18,7 @@ exports.insertbefore = function(source,operator,options) {
if(pos !== -1) { if(pos !== -1) {
results.splice(pos,1); results.splice(pos,1);
} }
// Insert the entry before the target marker
pos = results.indexOf(target); pos = results.indexOf(target);
if(pos !== -1) { if(pos !== -1) {
results.splice(pos,0,operator.operand); results.splice(pos,0,operator.operand);

View File

@@ -2,9 +2,6 @@
title: $:/core/modules/filters/is.js title: $:/core/modules/filters/is.js
type: application/javascript type: application/javascript
module-type: filteroperator module-type: filteroperator
Filter operator for checking tiddler properties
\*/ \*/
"use strict"; "use strict";
@@ -19,9 +16,6 @@ function getIsFilterOperators() {
return isFilterOperators; return isFilterOperators;
} }
/*
Export our filter function
*/
exports.is = function(source,operator,options) { exports.is = function(source,operator,options) {
// Dispatch to the correct isfilteroperator // Dispatch to the correct isfilteroperator
var isFilterOperators = getIsFilterOperators(); var isFilterOperators = getIsFilterOperators();

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/is/binary.js title: $:/core/modules/filters/is/binary.js
type: application/javascript type: application/javascript
module-type: isfilteroperator module-type: isfilteroperator
Filter function for [is[binary]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.binary = function(source,prefix,options) { exports.binary = function(source,prefix,options) {
var results = []; var results = [];
if(prefix === "!") { if(prefix === "!") {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/is/blank.js title: $:/core/modules/filters/is/blank.js
type: application/javascript type: application/javascript
module-type: isfilteroperator module-type: isfilteroperator
Filter function for [is[blank]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.blank = function(source,prefix,options) { exports.blank = function(source,prefix,options) {
var results = []; var results = [];
if(prefix === "!") { if(prefix === "!") {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/is/current.js title: $:/core/modules/filters/is/current.js
type: application/javascript type: application/javascript
module-type: isfilteroperator module-type: isfilteroperator
Filter function for [is[current]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.current = function(source,prefix,options) { exports.current = function(source,prefix,options) {
var results = [], var results = [],
currTiddlerTitle = options.widget && options.widget.getVariable("currentTiddler"); currTiddlerTitle = options.widget && options.widget.getVariable("currentTiddler");

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/is/draft.js title: $:/core/modules/filters/is/draft.js
type: application/javascript type: application/javascript
module-type: isfilteroperator module-type: isfilteroperator
Filter function for [is[draft]] analagous to [has[draft.of]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.draft = function(source,prefix,options) { exports.draft = function(source,prefix,options) {
var results = []; var results = [];
if(prefix === "!") { if(prefix === "!") {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/is/image.js title: $:/core/modules/filters/is/image.js
type: application/javascript type: application/javascript
module-type: isfilteroperator module-type: isfilteroperator
Filter function for [is[image]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.image = function(source,prefix,options) { exports.image = function(source,prefix,options) {
var results = []; var results = [];
if(prefix === "!") { if(prefix === "!") {

View File

@@ -2,16 +2,10 @@
title: $:/core/modules/filters/is/missing.js title: $:/core/modules/filters/is/missing.js
type: application/javascript type: application/javascript
module-type: isfilteroperator module-type: isfilteroperator
Filter function for [is[missing]]
\*/ \*/
"use strict"; "use strict";
/*
Export our filter function
*/
exports.missing = function(source,prefix,options) { exports.missing = function(source,prefix,options) {
var results = []; var results = [];
if(prefix === "!") { if(prefix === "!") {

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