1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-07-14 15:52:46 +00:00

Compare commits

...

360 Commits

Author SHA1 Message Date
Jeremy Ruston 65605d7b72 Typo 2026-07-13 15:56:51 +01:00
Jeremy Ruston b3f9690941 Linting 2026-07-13 15:42:50 +01:00
Jeremy Ruston 038d9e474e Merge branch 'master' into colour-improvements 2026-07-13 14:47:21 +01:00
Mario Pietsch f5317dc225 Fix Node.js deprecated warning (#9742)
* Fix Node.js deprecated warning

* Add ChangeNote

* Change deprecation to bugfix for DEP0169 warning

Updated change type from 'deprecation' to 'bugfix' for the Node.js server's handling of the DEP0169 warning.
2026-07-13 13:43:07 +02:00
lin onetwo c952450c2e fix(filter): optimize tag[] and !tag[] with Set for O(1) lookup (#9715)
* fix(filter): optimize tag[] and !tag[] with Set for O(1) lookup, resolves performance gap vs search:tags[]

* useless test

* note

* note
2026-07-13 13:37:05 +02:00
Rob Hoelz 1eb7ec4402 Convert deeply nested if/else to do/while(false) with breaks for parseAttribute (#9770)
01d3cde96 refactored parseMacroParameterAsAttribute to use a
do/while(false) construct with break statements - this updates
parseAttribute with an analogous refactoring for consistency
2026-07-13 08:15:26 +02:00
dependabot[bot] 869557f7d1 Bump js-yaml from 4.1.1 to 4.3.0 (#9903)
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.1 to 4.3.0.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.1...4.3.0)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-12 09:22:08 +02:00
saqimtiaz c9f1154643 chore: preparing for v5.5.0 2026-07-10 12:41:53 +02:00
Jeremy Ruston 748f04c9e3 Update TiddlyWiki release checklist 2026-07-10 11:01:22 +01:00
saqimtiaz d391595836 Version number update for 5.4.1 2026-07-10 11:39:38 +02:00
saqimtiaz 967140a148 Merge branch 'master' of github.com:TiddlyWiki/TiddlyWiki5 2026-07-10 11:37:07 +02:00
saqimtiaz 95e68b0437 chore: added missing changenotes 2026-07-10 11:36:59 +02:00
Jeremy Ruston 8ddede1611 Missing v5.4.1 release notes 2026-07-10 10:36:20 +01:00
saqimtiaz ceb200b08c chore: update license and readme 2026-07-10 11:17:53 +02:00
saqimtiaz 00e5f48a59 chore: preparing for v5.4.1 release 2026-07-10 11:12:01 +02:00
saqimtiaz ea0e9105bc Merge branch 'tiddlywiki-com' 2026-07-10 11:00:56 +02:00
Jeremy Ruston 51459815ba Fix CI errors 2026-07-09 16:16:36 +01:00
Jeremy Ruston 8c62935a01 Fix incorrect reference to BurningTreeC's website 2026-07-09 14:14:47 +01:00
Jeremy Ruston 839fa2417d Fix CI issues
1. Remove references to obsolete plugins
2. Fix duplicate language string entry
2026-07-09 14:12:10 +01:00
Saq Imtiaz 1b8610e4d8 Fixes issue with copying cross window event properties (#9905)
* fix: issue with copying cross window event properties

* docs: added changenote
2026-07-09 12:50:12 +01:00
Mario Pietsch ca063cbe90 Add quick test runner (#9743) 2026-07-08 13:56:16 +01:00
Jeremy Ruston 7d4328b2fb Merge branch 'master' of https://github.com/TiddlyWiki/TiddlyWiki5 2026-07-08 12:02:55 +01:00
Jeremy Ruston 1ae224ab74 Merge branch 'tiddlywiki-com' 2026-07-08 12:02:50 +01:00
Mario Pietsch c308fc44c4 Fix invalid source positions in parse tree nodes (#9882)
* Fix invalid source positions in parse tree nodes

Several wikitext rules recorded start and end offsets that did not match
the source they represent. The offsets are only used for source position
mapping, not rendering or serialization, so output is unchanged and
source.slice(start, end) now equals the node text.

* import: the filter attribute start was set to the whole source string
  instead of the numeric offset. It used this.parser.source where it
  meant this.parser.pos, so every \import node carried a copy of the
  entire source as its start.

* codeinline: the text node end pointed past the closing backtick, so the
  span included the closing delimiter and could read one or two characters
  too far. It now ends where the content ends.

* wikilinkprefix and extlink: a suppressed link such as ~SomeLink or
  ~http://example.com produced a text node whose span included the
  leading ~ while its text did not. The span now starts after the ~.

* Add 5.4.1 change note for #9882

Document the parse tree source position fixes: inline code, suppressed
external links, suppressed wikilinks, and the import filter rule.

* Add tests for parse tree source positions

Cover the four wikitext parser rules whose `start` and `end` offsets are
corrected in this PR: codeinline, extlink, wikilinkprefix, and import.
2026-07-08 10:03:11 +01:00
Jeremy Ruston aa3fb85919 BurningTreeC is leader of the TiddlyDesktop team
@BurningTreeC please check the details of your card,
2026-07-08 09:58:40 +01:00
Jeremy Ruston bd052a33f8 Correct v5.4.1 banner 2026-07-08 09:45:29 +01:00
superuser-does bb766c36c3 [DOCS] Fix survey image link (#9897) 2026-07-01 15:55:49 +02:00
dependabot[bot] 566a341328 Bump js-yaml from 4.1.0 to 4.1.1 (#9777)
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.1.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 08:11:15 +01:00
dependabot[bot] 9316234001 Bump picomatch from 4.0.3 to 4.0.4 (#9776)
Bumps [picomatch](https://github.com/micromatch/picomatch) from 4.0.3 to 4.0.4.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 08:11:02 +01:00
dependabot[bot] c1cb93c9df Bump minimatch from 3.1.2 to 3.1.5 (#9775)
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.1.2 to 3.1.5.
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 08:10:52 +01:00
dependabot[bot] e46361fbc0 Bump flatted from 3.3.3 to 3.4.2 (#9774)
Bumps [flatted](https://github.com/WebReflection/flatted) from 3.3.3 to 3.4.2.
- [Commits](https://github.com/WebReflection/flatted/compare/v3.3.3...v3.4.2)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 08:10:40 +01:00
s793016 e730836d6f Freelinks Plugin: Add configurable MaxLinks cap and remove search truncation (#9836)
* Update aho-corasick.js

Optimized Aho-Corasick string matching algorithm implementation with enhanced
performance and error handling for TiddlyWiki freelinking functionality.
 
- Uses WeakMap for failure links. WeakMap keys are compared by object identity
  (reference equality), which is required here because trie nodes are plain
  objects — a regular {} map would not work because JavaScript only supports
  string and Symbol keys, forcing object keys to be coerced to strings.
- Outputs are merged at build time (classic AC optimization), eliminating the
  need to walk the failure chain during search.
- search() converts case per character to avoid Unicode index desync (e.g.
  Turkish İ expands under toLowerCase(), shifting subsequent indices).
- No match count cap in search(); truncation is handled at the render stage
  by processTextWithMatches() to avoid silently dropping matches mid-text.
- Optional word boundary filtering: CJK always allowed; Latin requires
  non-word characters on both sides.

* Update text.js

- Render output capped by $:/config/Freelinks/MaxLinks (default 500).
  The cap applies to the final set of non-overlapping rendered links, not to
  the raw search results: search always runs to completion so that the
  longest-match selection has full information. Text beyond the cap remains
  as plain text rather than being silently omitted.

* Create config-Freelinks-MAX_LINKS_TIDDLER.tid

setting for MAX_LINKS_TIDDLER

* Update and rename config-Freelinks-MAX_LINKS_TIDDLER.tid to config-Freelinks-MaxLinks.tid

fix typo

* Update settings.tid

add MaxLinks setting

* Update readme.tid

add MaxLinks setting text

* Create #9836.tid

release note

* Update tiddlywiki.info

add freelinks for test build

* Update macros-view.tid

fix structure problem

* Update text.js

add IGNORE_CASE_TIDDLER  to whitelist

* Rename #9836.tid to #9836.tid

move to 5.4.1

* Update text.js

I deleted the wrong line last time, so I'm putting it back.

* Update text.js

eslint fix

* Update text.js

refactor: inline plain-text via dynamic core reference

* Delete plugins/tiddlywiki/freelinks/plain-text.js

remove plain-text.js: now inlined via dynamic core reference

* Update text.js

restore plain-text.js, remove new Function extraction

* Add files via upload

restore plain-text.js, remove new Function extraction

* Update #9836.tid

update new bug

* Update #9836.tid

tw version fix

* Update tiddlywiki.info

reverse to original
2026-06-20 19:25:19 +01:00
XLBilly d050dd30cc Fix KaTeX missing font (#9873) 2026-06-09 16:36:22 +01:00
IchijikuIchigo 635f6b5e76 [ja_JP] Update of Japanese translations (#9870)
* [ja_JP] Japanese translation update from commit: 3ed481b

* [ja_JP] Japanese translation update from commit: ad3587b

* [ja_JP] Japanese translation update from commit: 6bc77cf

* [ja_JP] Japanese translation update from commit: 5d1c1ea, c4991a5

* [ja_JP] Japanese translation update from commit: 37a4613

* [ja_JP] Japanese translation update from commit: 748ef8a

* [ja_JP] Japanese translation update from commit: 92caa73

* [ja_JP] Japanese translation update from commit: 87ba87b

* [ja_JP] Japanese translation update from commit: 15ba415

* [ja_JP] Japanese translation update from commit: 64ee20e

* [ja_JP] Japanese translation update from commit: 5d1c1ea,add3d42

* [ja_JP] Japanese translation update from commit: 64ee20e

* [ja_JP] Japanese translation update from commit: b001333

* [ja_JP] Japanese translation update from commit: b434b9d

* [ja_JP] Japanese translation update from commit: 3983086
2026-06-05 16:23:47 +01:00
Saq Imtiaz 40d0d542f7 playwright: revert timeout to 60s 2026-06-04 09:46:36 +02:00
Saq Imtiaz a66d9a596c playwright: change timeout to 45s 2026-06-04 09:37:21 +02:00
Saq Imtiaz 23063ea9c8 playwright: increase timeout to 60s 2026-06-04 09:32:23 +02:00
Jeremy Ruston 9c1f69e9c1 Revert "[ja_JP] Update of Japanese translations (#9853)"
Reverting as was inadvertently merged to tiddlywiki-com

This reverts commit 14b11575d0.
2026-06-04 08:28:09 +01:00
Saq Imtiaz 6abfcb631d Update playwright.config.js to address build failures 2026-06-04 09:26:56 +02:00
IchijikuIchigo 14b11575d0 [ja_JP] Update of Japanese translations (#9853)
* [ja_JP] Japanese translation update from commit: 3ed481b

* [ja_JP] Japanese translation update from commit: ad3587b

* [ja_JP] Japanese translation update from commit: 6bc77cf

* [ja_JP] Japanese translation update from commit: 5d1c1ea, c4991a5

* [ja_JP] Japanese translation update from commit: 37a4613

* [ja_JP] Japanese translation update from commit: 748ef8a

* [ja_JP] Japanese translation update from commit: 92caa73

* [ja_JP] Japanese translation update from commit: 87ba87b

* [ja_JP] Japanese translation update from commit: 15ba415

* [ja_JP] Japanese translation update from commit: 64ee20e

* [ja_JP] Japanese translation update from commit: 5d1c1ea,add3d42

* [ja_JP] Japanese translation update from commit: 64ee20e

* [ja_JP] Japanese translation update from commit: b001333

* [ja_JP] Japanese translation update from commit: b434b9d

* [ja_JP] Japanese translation update from commit: 3983086
2026-06-04 08:25:12 +01:00
Maurycy Zarzycki c9b1fbbb76 Add/update translations to Polish language: (#9829)
- 0e765bd
- 9c09841
- 33b2f51
- cd8b1fa
- 0177f09
- b673651
- 9afe522
2026-06-04 08:24:43 +01:00
Jeremy Ruston 27c568e53e Try increasing Firefox timeout because of build errors 2026-06-04 08:21:35 +01:00
Jeremy Ruston 0023d3f6fa Update license date 2026-06-04 08:03:01 +01:00
Jeremy Ruston 76ebe9d8e9 Merge branch 'tiddlywiki-com' 2026-05-17 16:09:36 +01:00
Sean Clayton 40444eade5 Signing CLA (#9856) 2026-05-17 15:15:54 +01:00
Jeremy Ruston fe8723be49 Prepare for v5.4.1, not v5.5.0
See discussion at #9832
2026-05-08 18:13:41 +01:00
Mario Pietsch 56ea0789e1 Update deprecated.js issues (#9833)
* Fix RSOD when $tw.utils.addClass receives a class string with whitespace

PR #9251 replaced the manual setAttribute("class", ...) implementation of
$tw.utils.addClass/removeClass/toggleClass with direct Element.classList
calls. Unlike setAttribute, classList.add/remove/toggle throws
InvalidCharacterError on any token containing whitespace, so callers that
pass a whole class string (e.g. modal.js passing tiddler.fields.class)
now crash.

Manual repro on tw5-com: open SampleWizard, set the `class` field to
"aaa bbb", Done, open popup -> OK -> open nested popup -> RSOD.

Fix: split the className argument on whitespace in deprecated.js and feed
individual tokens to classList. A small splitClasses() helper keeps the
three functions symmetrical.

Adds adversarial regression tests in test-utils.js covering:
- ASCII whitespace variants (space, tab, CR, LF, mixed runs, padding)
- Unicode whitespace (U+00A0 non-breaking space)
- de-duplication across single and multiple calls
- remove/toggle no-op on missing tokens
- toggle with status undefined / true / false
- silent no-op for whitespace-only / empty / non-string / null input
- silent no-op when the element has no classList

* Move new tests to their own file

* Add backwards-compat regression tests for deprecated.js

Locks in pre-5.4.0 tolerant behaviour of $:/core/modules/utils/
deprecated.js helpers that regressed in PR #9251. Each spec targets an
edge-case input the current one-line modern equivalents reject:

- repeat: negative count / null / undefined str
- startsWith / endsWith: RegExp search arg
- stringifyNumber: null / undefined
- domContains: boolean return, self-check
- hasClass: null element, classless element
- getLocationPath: query preservation, hash stripping
  (browser-only; pends in Node because the TW5 sandbox has no `window`)

Also picks up the addClass/removeClass/toggleClass whitespace specs
moved out of test-utils.js by the previous commit, so all deprecated.js
coverage lives together.

Fails 8 specs on current HEAD; the follow-up deprecated.js restoration
commit turns them green.

* Restore pre-5.4.0 behaviour of deprecated.js utilities

PR #9251 replaced several helpers in $:/core/modules/utils/deprecated.js
with one-line ES2017 equivalents that diverge from the originals on
edge-case inputs. Follow-up PRs fixed the most visible cases
(getLocationHash #9622, isDate #9771, addClass empty-string #9561 and
whitespace 005e17537); this commit closes the rest:

- repeat: manual loop tolerates negative count / null / undefined str
- startsWith / endsWith: substring compare tolerates RegExp search arg
- stringifyNumber: `num + ""` coercion tolerates null / undefined
- domContains: `a !== b && a.contains(b)` returns boolean, handles self
- hasClass: null-element guard, strict-false return
- getLocationPath: `toString().split("#")[0]` preserves the query
  string in permalinks (startup/story.js:214, 217) -- the most visible
  user-facing regression, causing ?lang=de etc. to silently drop.

IE-only fallbacks in Math.sign, strEndsWith, domContains, and
domMatchesSelector are removed; TW5 no longer supports IE.

Covered by the regression specs added in the previous commit.

* make comments more refined
2026-05-05 15:27:40 +01:00
Jeremy Ruston fff648b959 Exclude Claude from npm (#9847) 2026-05-05 10:28:28 +01:00
Mario Pietsch e1cff6068c Fix SelectWidget multi-select highlight regression for options containing HTML (#9839) (#9841)
PR #8093 used `child.children.length === 0` to distinguish a plain <option> from an <optgroup>. This test misfires when an <option> contains inline HTML.

E.g. tc-tiddlylink anchors auto-generated for "$:/..." titles.
So on refresh the option's `selected` state was never restored.

- This change switches to a tagName check.
- Adds a regression test plus a guard for the original PR #8092 optgroup
behaviour.
2026-05-05 10:23:36 +01:00
Mario Pietsch 6721164f15 Add a new test that fails, because a missing typeof test in fakedom.js (#9840)
* Add a new test that fails, because a missing typeof test in fakedom.js

* Add typeof strint fix to fakedom to avoid throw
2026-05-05 11:20:49 +02:00
buggyj 3c37aa267d Fix for #9834 Widgets are compiled before modules are loaded (#9835) 2026-05-05 10:16:21 +01:00
Jeremy Ruston a603146b3c Update version number to v5.4.1 2026-05-05 10:13:05 +01:00
Mario Pietsch f992f4ffab Fix 9826 min height issue (#9828)
* Add new tests

* fix 9826 minHeight handling + docs
2026-05-05 10:11:01 +01:00
Mario Pietsch dfedd8594f save impact note 9609 as .tid instead of .json (#9844) 2026-04-29 16:01:35 +02:00
Jeremy Ruston ea84baa5a3 Merge branch 'tiddlywiki-com' 2026-04-21 20:24:23 +01:00
Mario Pietsch a4e4d36bf6 Fix Typo in Link in Multi-Valued Variables (#9824) 2026-04-20 21:31:52 +01:00
Mario Pietsch 3ed481b2e2 Update the Archive and Release Notes Description (#9823) 2026-04-20 21:31:09 +01:00
Jeremy Ruston 27c60ff58d Prepare for v5.5.0 2026-04-20 20:03:12 +01:00
Jeremy Ruston 748ef8aa8d New release should be first thumbnail 2026-04-20 19:56:08 +01:00
Jeremy Ruston 9cfa5a29fb Version number update for 5.4.0 2026-04-20 19:36:07 +01:00
Jeremy Ruston 5ea43ce212 Revert package.json 2026-04-20 19:35:55 +01:00
Jeremy Ruston df6bbbdedf More v5.4.0 preparations 2026-04-20 19:33:07 +01:00
Jeremy Ruston 37a461323e Preparing for release of v5.4.0 2026-04-20 19:31:36 +01:00
Cameron Fischer b29da7baac I didn't capitalize one of the instances of my name (#9822) 2026-04-19 16:42:52 +01:00
Mario Pietsch 75b54457ed German translations update (#9821)
* German translations update

* fix typo
2026-04-18 15:16:32 +01:00
superuser-does 51f322c3c6 [5.4.0] Add release note for Greek translation update (#9818)
* [5.4.0] Add release note for Greek translation update

Add release note for #9782

* Remove trailing newline
2026-04-18 14:03:27 +01:00
lin onetwo 853af2d848 Fix: limit macro call parser to need >> to work, prevent > in regex (#9813)
* fix: limit macro call parser to need >> to work, prevent > in regex

* test: add malformed macro parameter regression coverage

The parser fix on this branch only changes parseMacroParameterAsAttribute() when an unquoted value starts with <<, so the previous broader parser tests did not prove the regression. Add a focused structural test that fails without the guard and passes with it.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* Revert "fix: limit macro call parser to need >> to work, prevent > in regex"

This reverts commit f96b062902.

* lint: test

* Reapply "fix: limit macro call parser to need >> to work, prevent > in regex"

This reverts commit 075f7cc282.

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-18 09:59:22 +01:00
Jeremy Ruston 2c1cb33081 Restore v5.3.8 handling of malformed attribute syntax (#9812)
Also add a bunch of tests

Fixes #9808
2026-04-18 09:56:22 +01:00
Keiran Harcombe 2f63abc12a Merge pull request #9809 from kjharcombe/master
Remove CNAME
2026-04-15 10:34:50 +01:00
Keiran Harcombe 5f80256576 Remove CNAME
I've removed the CNAME file which is blocking access to Yunohost
2026-04-14 12:44:30 +01:00
Jeremy Ruston aa837300d0 Update Chinese translation change note 2026-04-13 17:10:03 +01:00
Bram Chen 7f2baa17a9 Update chinese translations (#9804)
* Update chinese translations

* Update languages/zh-Hans/ControlPanel.multids (commit 33b2f51)
* Update languages/zh-Hant/ControlPanel.multids (commit 33b2f51)
* Update languages/zh-Hans/Import.multids (commit b673651)
* Update languages/zh-Hant/Import.multids (commit b673651)
* Update languages/zh-Hans/TiddlerInfo.multids (commit 0177f09, cd8b1fa )
* Update languages/zh-Hant/TiddlerInfo.multids (commit 0177f09, cd8b1fa )
* Add languages/zh-Hant/Draft.multids (commit 9c09841)

* Update chinese translations

* Clarify wording of tiddler info cascade view
2026-04-13 17:08:23 +01:00
Jeremy Ruston 39c6d8fb53 Missing change notes
Fixes #9773
2026-04-12 14:50:40 +01:00
Jeremy Ruston 9afe5226f1 Clarify wording of tiddler info cascade view 2026-04-12 14:33:52 +01:00
Jeremy Ruston 94aa37fe7e Merge branch 'tiddlywiki-com' 2026-04-11 08:38:49 +01:00
superuser-does 1e9c1ef82a [DOCS] Fix MWS Banner image display (#9801) 2026-04-11 08:45:27 +02:00
Saq Imtiaz 6cde5e94ff Update pr-validation.yml to use Cerebrus v8.1 2026-04-11 08:45:01 +02:00
Saq Imtiaz fd0d3ccc27 Revert "Replace fill rules in tw5.com edition (#9624)" (#9800)
This reverts commit dc764b3a4a.
2026-04-10 12:23:37 +02:00
Saq Imtiaz 1ad2e66cbc Revert "Use currentColor to style svg (#9316)" (#9799)
This reverts commit dc7f2a57bb.
2026-04-10 12:23:07 +02:00
Saq Imtiaz 4699db9f89 Revert "Fix side effects of PR 9316 (#9568)" (#9798)
This reverts commit bf7c0b575c.
2026-04-10 12:22:41 +02:00
lin onetwo d977b0ac5c Fix #9788: only allow colon-separator named params with strict identifiers (#9791)
The reAttributeName regexp in parseMacroParameterAsAttribute was too
permissive, allowing single-character names like dollar sign followed by
colon. This caused values such as dollar-colon-slash-plugins-foo to be
mis-parsed as a named parameter dollar with value slash-plugins-foo.

Fix: when the separator is colon (legacy syntax), require the parameter
name to match [A-Za-z0-9-_]+ (same as the historic parseMacroParameter).
When the separator is equals (new-style dynamic parameters from #9055),
the wide character set is preserved so that names like double-dollar-one
continue to work.

Adds regression test Transclude/Procedures/Dollar/Param.
2026-04-10 11:06:07 +02:00
Saq Imtiaz 7298684951 Update package.json to resolve CI issues 2026-04-10 08:35:32 +02:00
Mario Pietsch f78d8252af Fix issue #9795 tree view regression (#9796) 2026-04-10 08:29:54 +02:00
Saq Imtiaz 54260b5be8 Updates Cerebrus action to v8.1 (#9793)
* Update pr-check-build-size.yml

* Update pr-comment-build-size.yml

* Update pr-validation.yml
2026-04-09 09:13:45 +02:00
IchijikuIchigo 95f12eb857 [ja_JP] Update of Japanese translations (#9792)
* [ja_JP] Japanese translation update from commit: a71ac56

* [ja_JP] Japanese translation update from commit: 32a3a3e

* [ja_JP] Japanese translation update from commit: 65fcded

* [ja_JP] Japanese translation update from commit: a3acbaa

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\functions\Functions.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\functions\Functions.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\definitions\Base64.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\definitions\Definitions.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\definitions\Cascading Style Sheets.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\definitions\Tiddlyhost.tid'
2026-04-07 14:56:55 +02:00
IchijikuIchigo 207a68cc59 [ja_JP] Japanese translation update - 'Reference' section of tiddlywiki.com (#9790)
* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\reference\Reference.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\concepts\WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Horizontal Rules in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\_tw_shared\doc-utilities\wikitext-macros.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Block Quotes in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Code Blocks in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Conditional Shortcut Syntax.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Block Quotes in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Block Quotes in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Dashes in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Description Lists in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Filtered Attribute Values.tid'

* [ja-JP] A little correction to the Japanese translation

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Formatting in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Headings in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Paragraphs in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Hard Linebreaks in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\howtos\Hard_Linebreaks_with_CSS.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\howtos\Hard_Linebreaks_with_CSS_-_Example.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\HTML Entities.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Literal Attribute Values.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Lists in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Tables in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Table Classes Captions Headers and Footers.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Transcluded Attribute Values.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Utility Classes.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Widgets in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\parser\WikiText Parser Modes.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\HTML in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\HTML_Links_in_WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Typed Blocks in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Anchor Links using HTML.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Linking in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Macro Calls.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Macro Definitions.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Macro Parameter Handling.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Substituted Attribute Values.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Substituted Attribute Values.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\Concatenating variables to create a URL.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\Concatenating a text reference to create a URL.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\procedures\Procedure Calls.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\procedures\Procedure Definitions.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\procedures\Procedure Parameter Handling.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Transclusion and Substitution.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Transclusion in WikiText.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Transclusion Basic Usage.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Transclusion Basic Usage.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Transclusion with Templates.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Variable Attribute Values.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\variables\Behaviour of variables invoked via widget attributes.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Tables in WikiText CSS Utility Classes.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\Widget Attributes.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\concepts\TemplateTiddlers.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\concepts\Transclusion.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\parser\table-example.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\wikitext\parser\WikiText parser mode_ transclusion examples.tid'

* [ja-JP] Japanese translation of 'editions\tw5.com\tiddlers\concepts\TextReference.tid'
2026-04-06 11:34:48 +02:00
superuser-does b434b9d7ea [DOCS] Include description lists in lists tiddler (#9786) 2026-04-05 10:55:36 +01:00
superuser-does b0013333de [DOCS] Expand description list documentation (#9784)
* [DOCS] Expand description list documentation

* remove stray word
2026-04-05 10:15:15 +01:00
superuser-does bcc30e305a Update Greek translation for 5.4.0 (#9782)
* Update Greek translation for 5.4.0

* Add Greek translation for Draft

* Correction to 'Saving'
2026-04-04 14:08:54 +01:00
Jeremy Ruston 34f4dfb903 Merge branch 'tiddlywiki-com' 2026-04-04 09:23:58 +01:00
superuser-does 32a3a3e478 [DOCS] Clean up Forums tiddler (#9780) 2026-04-04 08:49:55 +01:00
Bram Chen c6520c4429 Update chinese translations (#9781)
* Update languages/zh-Hans/ControlPanel.multids (commit 33b2f51)
* Update languages/zh-Hant/ControlPanel.multids (commit 33b2f51)
* Update languages/zh-Hans/Import.multids (commit b673651)
* Update languages/zh-Hant/Import.multids (commit b673651)
* Update languages/zh-Hans/TiddlerInfo.multids (commit 0177f09, cd8b1fa )
* Update languages/zh-Hant/TiddlerInfo.multids (commit 0177f09, cd8b1fa )
* Add languages/zh-Hant/Draft.multids (commit 9c09841)
2026-04-04 08:48:34 +01:00
Jeremy Ruston 83d242fb2c Merge branch 'tiddlywiki-com' 2026-04-03 11:10:58 +01:00
Jeremy Ruston ecafb7a4c0 A very minor tweak to the donation graphic
Spot the difference; the wonky text was offending me
2026-04-03 11:10:45 +01:00
Jeremy Ruston 0640e0abe2 Merge branch 'tiddlywiki-com' 2026-04-03 11:00:11 +01:00
Jeremy Ruston a71ac56cc9 More prominent donations link 2026-04-03 10:49:26 +01:00
Jeremy Ruston f518bdf27c Hire Jeremy banner now defaults to just being in the sidebar 2026-04-03 10:49:14 +01:00
Jeremy Ruston 0387b1100b Update CI dependencies 2026-04-01 17:13:32 +01:00
Jeremy Ruston c3a73fccd1 Fixed typo in v5.3.8 change note 2026-04-01 17:00:29 +01:00
Jeremy Ruston c25659d87c Restore compact call syntax (#9778)
* Initial commit

* Oops broken test
2026-04-01 15:22:42 +02:00
Saq Imtiaz 0c26a75472 Updates cerebrus action to v8 (#9779)
* Update pr-validation.yml

* Update pr-comment-build-size.yml

* Update pr-check-build-size.yml
2026-04-01 15:21:16 +02:00
Saq Imtiaz a24dc0e9e8 Update package.json to allow all current LTS versions of nodejs 2026-04-01 15:13:27 +02:00
Jeremy Ruston a499ed0906 Fix CI
Broken by 3cfb6b1202
2026-04-01 13:22:42 +01:00
Jeremy Ruston 3cfb6b1202 Update minimum Node version for as discussed for v5.4.0 2026-04-01 11:51:43 +01:00
Jeremy Ruston ac769e5dcd Commit package-lock.json
Benefit is that it pins dependencies and sub-dependencies, helping mitigate supply chain attacks
2026-04-01 11:42:17 +01:00
Jeremy Ruston ed01af8e47 Update release note with new release banner 2026-03-31 18:43:00 +01:00
Jeremy Ruston 92caa7312e Update new release banner
See https://talk.tiddlywiki.org/t/discussion-ai-and-vote-for-the-banner-for-5-4-0/15108/10
2026-03-31 18:25:20 +01:00
Mario Pietsch 478dce7009 fix problem with idDate() duplication in boot.js (#9771) 2026-03-31 18:50:31 +02:00
IchijikuIchigo f3c9cb2310 [ja_JP] Update Japanese translation (#9768)
* [ja_JP] Japanese translation update from commit: 5d0d2b1, e8fe6b9, 33b2f51

* [ja_JP] Japanese translation update from commit: 3543fe5

* [ja_JP] Japanese translation update from commit: 9c09841

* [ja_JP] Japanese translation update from commit: 390b755, 3e966d4, d17525e

* [ja_JP] Japanese translation update from commit: 4007610, 65afdac

* [ja_JP] Japanese translation update from commit: 5e8420a, 2adf091

* [ja_JP] Japanese translation update from commit: b673651

* [ja_JP] Japanese translation update from commit: a494361, 3af2a0a, 0e765bd

* [ja_JP] Japanese translation update from commit: daa24a5

* [ja_JP] Japanese translation update from commit: daa24a5, 881aed8

* [ja_JP] Japanese translation update from commit: 98e7255

* [ja_JP] Japanese translation update from commit: 4d9e683, cd8b1fa, 0177f09

* [ja_JP] Japanese translation update from commit: a494361

* [ja_JP] Japanese translation update from commit: eee3a0c, 169a381, f4fd5e7, 6332089, 1ce9973, c05c0d3, 9268a8c, e16635a

* [ja_JP] Delete duplicate Japanese translation files

* [ja_JP] Japanese translation update from commit: c02c3a0

* [ja_JP] Japanese translation update from commit: 147d758

* [ja_JP] Japanese translation update from commit: c6e4b7a, c4e2793, 12630d4

* [ja_JP] Japanese translation update from commit: 11b09be

* [ja_JP] Japanese translation update from commit: f7e50e0, e9557b5, 4ccdaf3, 6f93ce6

* [ja_JP] Japanese translation update from commit: f7e50e0, e9557b5, e87dadd, 814353d, 35a7a66, 5d91c27

* [ja_JP] Japanese translation update from commit: f7e50e0, e9557b5, 35a7a66

* [ja_JP] Japanese translation update from commit: d880cb1, 5176f00, 814353d, 35a7a66

* [ja_JP] Japanese translation update from commit: 5e8420a, 2adf091
2026-03-30 07:52:57 +02:00
Cameron Fischer 85fb634cae Moved bulkops relink behavior into dedicated module (#9703)
* Moved bulkops relink behavior into dedicated module

* Release notes

* Fixes for lint
2026-03-28 12:06:27 +00:00
Saq Imtiaz 280701fbde Fixes MVV's so that getVariableInfo returns undefined (#9765)
* wip: non-existent variables as attributes should be undefined

* wip: non-existent variables as attributes should be undefined

* tests: added missing test

* fix: restore mistakenly commited files

* fix: whitespace
2026-03-28 12:04:29 +00:00
Saq Imtiaz 01d3cde964 Fixes an issue where blockquotes trigger parsing as macros (#9695)
* fix: blockquotes trigger parsing as macros

* fix: blockquotes trigger parsing as macros

* fix: remove backwards incompatible change

* fix: whitespace

* fix: whitespace

* merge improvents from @hoelzro
2026-03-25 12:24:32 +01:00
Jeremy Ruston 2ea3663ea7 Merge branch 'tiddlywiki-com' 2026-03-24 17:14:24 +00:00
Jeremy Ruston 78b6f6f442 Docs: clarify parameters within calls in filters 2026-03-24 12:23:58 +00:00
Jeremy Ruston 3a4a8a206f Hotfix for broken test for dates
Fixes #9726
2026-03-24 11:19:17 +00:00
Mario Pietsch aff5be7195 fix flaky test runner (#9718) 2026-03-24 09:48:32 +01:00
Mario Pietsch c4991a54a0 Some minor changes to the filter docs (#9709)
* Some minor changes to the filter docs

* Fix wording in Intersection Filter Run Prefix documentation
2026-03-24 09:46:03 +01:00
Mario Pietsch 1d915389d9 Gitignore for automated tests (#9761)
* Add elements to gitignore, that are used for automated future test

* Add playwright configuration for Edge users that have no Chrome installed

* update tw-mcp setting
2026-03-22 08:42:13 +00:00
Mario Pietsch f5b4b1781e Fix edit toolbar button spaceing (#9763) 2026-03-22 08:31:38 +00:00
Mario Pietsch 65fcded29f Fix name clashes - definition tiddlers with images (#9759) 2026-03-20 07:54:03 +00:00
Urban Alič 962692c90c FIX: restore mhchem require for \ce and \pu macro support (#9756) 2026-03-19 22:34:56 +00:00
Mario Pietsch 533414b1df Change codewrapping option to pre-wrap
Fixes: #9757

Changed at: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9107/changes#diff-9c7b0f26dc347b90265ea42dd89565ecf1d7b85ac8b5ff3f7dc49eeec42003b5

Talk:  https://talk.tiddlywiki.org/t/5-4-0-prerelease-code-lines-pre-wrap-setting-as-default/15066
2026-03-19 19:47:26 +01:00
Himmel ec27a4bf20 Add new contributor Himmel to CLA (#9755) 2026-03-19 07:12:33 +00:00
Jeremy Ruston e1cf523e2c Merge branch 'tiddlywiki-com' 2026-03-17 13:20:55 +00:00
Keiran Harcombe 1ece822d7a Update kjharcombe.tid (#9750)
I've created my community card for tiddlywiki.com
2026-03-16 23:27:50 +00:00
Keiran Harcombe b7a3418823 Signing CLA (#9749) 2026-03-16 21:58:42 +00:00
Xavier Cazin bb6d88f144 fr-FR translation catchup before 5.4.0 (#9748)
* fr-FR translation for the Alerts aria string

* fr-FR translation for WikiInformation-related strings

* fr-FR updates for TiddlySpot/TiddlyHost-related strings

* fr-FR translation for Stability- and InfoTab-related strings
2026-03-16 17:08:06 +00:00
Jeremy Ruston 57c72756ef Fix releasenote avatars
Fixes #9746

Thanks @pmario
2026-03-16 16:57:55 +00:00
Jeremy Ruston dda4c7fb10 Update to latest version of dom-to-image-more library
Include it in tw5.com for testing
2026-03-15 16:53:51 +00:00
Jeremy Ruston fd3b96e2dd Merge branch 'tiddlywiki-com' 2026-03-15 10:46:16 +00:00
Jeremy Ruston c07396c453 Community: Add @kjharcombe as infrastructure team lead
Please add your community card when you can, many thanks.
2026-03-15 10:46:02 +00:00
Jeremy Ruston 7fc255f90c Merge branch 'tiddlywiki-com' 2026-03-14 18:18:09 +00:00
Jeremy Ruston 4cd84a6ba1 Geospatial plugin: remove residue of dom-to-image plugin
Fixes #9683
2026-03-11 17:30:23 +00:00
Jeremy Ruston fdfcd66c9b dom-to-image fix indentation 2026-03-11 17:14:47 +00:00
Andrew Gregory 3983086b96 Document alternating table row styling (#9713)
* Document alternating table row styling

Resolves issue #8738 (and explains why my old wiki row styles were swapped).

* Make note more prominent

Use note macro for note

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

---------

Co-authored-by: Mario Pietsch <pmariojo@gmail.com>
2026-03-11 14:22:49 +00:00
Jeremy Ruston a61331e6ed Fix readme for tw5.com-docs plugin
Fixes #9721
2026-03-11 13:50:37 +00:00
Jeremy Ruston 8773a0433c Dynaview: Fix RSOE with Update address bar while scrolling
See https://talk.tiddlywiki.org/t/your-help-is-needed-to-test-v5-4-0/14945/52
2026-03-11 12:22:14 +00:00
Mario Pietsch 846deb3039 Git Ignore Claude AI local settings (#9719) 2026-03-09 17:09:07 +00:00
Saq Imtiaz 111a168b0c feat: added community card for saqimtiaz (#9701) 2026-03-06 22:47:35 +00:00
Cameron Fischer 02b4c04a56 Release notes for PRs I've made, as requested (#9707)
* Release notes for PRs I've made, as requested

* Update #9297.tid

blog -> blob
2026-03-03 09:23:27 +01:00
Saq Imtiaz 9d5b5111d0 Revert "Add locale support for sort operator (#9400)" (#9702)
This reverts commit 98a61f01bb.
2026-03-01 08:02:18 +01:00
btheado 48cff401b2 Add tests/examples for transclusion shortcut syntax (#9705) 2026-03-01 07:58:59 +01:00
Jeremy Ruston a3acbaa2f1 Update road map 2026-02-20 09:30:25 +00:00
Jeremy Ruston 2dd9a2006d Impact note about wikified palettes 2026-01-30 20:57:13 +00:00
Jeremy Ruston ebff5aa3db Make Palette be the default Appearance tab in control panel 2026-01-30 20:56:59 +00:00
Jeremy Ruston 3bc2c5fabc Remove appply filter run prefix 2026-01-30 20:56:38 +00:00
Jeremy Ruston d423aa926e Tweak lingo 2026-01-30 20:56:14 +00:00
Jeremy Ruston fe708eefc6 Merge branch 'master' into colour-improvements 2026-01-23 09:03:47 +00:00
Jeremy Ruston a7525037fd Improve English 2026-01-22 12:11:45 +00:00
Jeremy Ruston 15736bceb9 Add test for invalid pragma 2026-01-21 21:49:16 +00:00
Jeremy Ruston 35b0108da6 Fix parsing bug 2026-01-21 21:45:45 +00:00
Jeremy Ruston 59d23da97c Merge branch 'default-prefix-for-subfilter' into colour-improvements 2026-01-20 16:22:01 +00:00
Jeremy Ruston 3f654bccaa Revert previous merge from #9595
This reverts commit eb8f69dd03.
2026-01-20 16:04:28 +00:00
Jeremy Ruston a45a8723c0 Add a view template body for palettes 2026-01-19 21:20:08 +00:00
Jeremy Ruston ae7d6da35b Add a P3 palette for testing 2026-01-19 12:54:27 +00:00
Jeremy Ruston a8e056c88c Merge branch 'default-prefix-for-subfilter' into colour-improvements 2026-01-19 12:54:01 +00:00
Jeremy Ruston 5b0af905a2 Use the subfilter suffix to suppress deduping palette entries 2026-01-19 12:53:45 +00:00
Jeremy Ruston eb8f69dd03 Merge subfilter fix from #9595 2026-01-19 12:52:58 +00:00
Jeremy Ruston ef49828989 temp 2026-01-19 12:49:08 +00:00
Jeremy Ruston 9b56734451 Extend subfilter operator with suffix for specifying the default filter run prefix 2026-01-19 11:31:09 +00:00
Jeremy Ruston 2f8d53d3f7 Allow default filter run prefix to be specified for filter evaluation 2026-01-19 11:30:50 +00:00
Jeremy Ruston 5b96929f4e Fix tests 2026-01-18 12:03:59 +00:00
Jeremy Ruston 829bb61378 Merge branch 'master' into colour-improvements 2026-01-18 11:48:42 +00:00
Jeremy Ruston 421ecff30f Merge branch 'master' into colour-improvements 2026-01-17 17:52:34 +00:00
Jeremy Ruston c7511fc99f Tweak credits for 2026 palettes 2026-01-17 17:50:27 +00:00
Jeremy Ruston 87f797b1ae Fix use of creaky old technique for setting alpha/opacity from a different base colour 2026-01-17 17:46:25 +00:00
Jeremy Ruston 8cc94d8ea7 Fix year category for new palettes 2026-01-17 17:45:12 +00:00
Jeremy Ruston dcaff6a243 Revert linter fixes for unused function parameters 2026-01-17 17:29:28 +00:00
Jeremy Ruston e98aed6f6e Fix remaining references to palettes-2025 plugin 2026-01-17 17:23:16 +00:00
Jeremy Ruston d35e34b55e Remove debugging code
It was breaking colour assignment as a property, rather than in a stylesheet
2026-01-17 17:22:57 +00:00
Jeremy Ruston bb4d57e170 More linting dancing 2026-01-17 17:00:24 +00:00
Jeremy Ruston fd709afc37 More linting errors 2026-01-17 16:53:52 +00:00
Jeremy Ruston 93388bc3cc Fix lint errors 2026-01-17 16:05:32 +00:00
Jeremy Ruston a8c4437587 Properly credit the new palettes 2026-01-17 15:48:16 +00:00
Jeremy Ruston 6dc83386bd Update new palettes to 2026 category 2026-01-17 15:44:42 +00:00
Jeremy Ruston 9641e6a2d0 Remove docs for apply filter run prefix 2026-01-17 15:43:45 +00:00
Jeremy Ruston 3254544eb2 Update the 2025 palette plugin to 2026 2026-01-17 15:42:09 +00:00
Jeremy Ruston c707b9a432 Enable change note 2026-01-17 15:39:37 +00:00
Jeremy Ruston 3cab1571be Don't lint color.js 2026-01-17 15:39:19 +00:00
Jeremy Ruston 502598bd25 Switch from apply filter run to let filter run 2026-01-17 15:35:27 +00:00
Jeremy Ruston 8a18f92710 Typo 2026-01-17 13:02:54 +00:00
Jeremy Ruston 3353d0e005 Upgrade color.js 2026-01-17 12:53:41 +00:00
Jeremy Ruston fd85842036 Merge branch 'master' into colour-improvements 2026-01-16 22:40:35 +00:00
Jeremy Ruston b0dc46c9e9 Avoid using camel case for new docs tiddlers 2026-01-16 22:40:27 +00:00
Jeremy Ruston 5b0c923a82 Merge branch 'master' into colour-improvements 2026-01-08 11:23:43 +00:00
Jeremy Ruston ae33a4521d Merge branch 'master' into colour-improvements 2025-09-14 17:22:59 +01:00
Jeremy Ruston 4b83e89d40 Move palettes into plugins 2025-08-06 15:13:10 +01:00
Jeremy Ruston da41483172 Prepare to split palettes out into plugins 2025-08-06 15:07:15 +01:00
Jeremy Ruston 39488f118b Use TwentyTwenties palette by default 2025-08-06 14:39:48 +01:00
Jeremy Ruston f9721b029e Merge branch 'master' into colour-improvements 2025-08-06 10:30:30 +01:00
Jeremy Ruston 974904588c Switch to minified version of color.js
See this discussion https://github.com/TiddlyWiki/TiddlyWiki5/pull/8702#issuecomment-3158465038
2025-08-06 10:29:04 +01:00
Jeremy Ruston 38457a4667 Add category field to palettes 2025-06-21 15:14:25 +01:00
Jeremy Ruston 96ef5c8314 Move palettes into category folders 2025-06-21 14:53:49 +01:00
Jeremy Ruston 96d24756ea Add new palettes from https://yatagarasu.tiddlyhost.com 2025-06-21 14:41:49 +01:00
Jeremy Ruston 77c99b418f Change default colour space for interpolation 2025-06-21 11:36:34 +01:00
Jeremy Ruston 7f2a47f303 Adopt more ES2017 features 2025-06-20 17:54:28 +01:00
Jeremy Ruston dcf0f449c4 Adopt class syntax 2025-06-20 17:46:31 +01:00
Jeremy Ruston a4c84d727c Remove function wrappers 2025-06-20 17:33:28 +01:00
Jeremy Ruston 5335ebf044 Merge branch 'master' into colour-improvements 2025-06-20 17:23:43 +01:00
Jeremy Ruston e9d87fb551 Merge branch 'master' into colour-improvements 2025-06-19 17:13:53 +01:00
Jeremy Ruston 54382d6666 Merge branch 'master' into colour-improvements 2025-04-16 14:31:47 +01:00
Jeremy Ruston e86eb28890 Merge branch 'master' into colour-improvements 2025-03-21 17:24:19 +00:00
Jeremy Ruston 5897b82c51 Fix tests 2025-03-07 16:34:09 +00:00
Jeremy Ruston 5e27462acf TwentyTwenties improvements 2025-03-07 16:23:29 +00:00
Jeremy Ruston 4c95ae546f Fix colour-interpolate with missing colours 2025-03-07 16:23:16 +00:00
Jeremy Ruston d42e3d36bc Add colour-set-alpha operator 2025-03-07 16:23:00 +00:00
Jeremy Ruston ee977def52 Include palette entry name in palette entries
Makes debugging easier, and works in CSS and as a style.prop assignment
2025-03-07 16:21:51 +00:00
Jeremy Ruston 30016967b1 Preview: Fix sidebar link colour 2025-03-07 16:21:07 +00:00
Jeremy Ruston 250ee90b07 TwentyTwenties: copy over missing palette entries
These are mostly RGB entries that were previously missing, filled in with values from Vanilla.

The goal is still not to have any direct RGB colours in the palette, just computed colours derived from the base colours
2025-03-06 21:53:45 +00:00
Jeremy Ruston 624cf95197 Fix from mismerging from master 2025-03-06 21:44:16 +00:00
Jeremy Ruston 8467fa333d Merge branch 'master' into colour-improvements 2025-03-06 21:38:49 +00:00
Jeremy Ruston 75ba08556f Merge branch 'master' into colour-improvements 2025-02-18 21:15:13 +00:00
Jeremy Ruston 93f954411b Merge branch 'master' into colour-improvements 2025-02-18 16:54:54 +00:00
Jeremy Ruston 059e439702 Merge branch 'master' into colour-improvements 2025-02-14 16:46:02 +00:00
Jeremy Ruston 2028420e3b Fixes suggested by @pmario 2025-02-14 14:11:08 +00:00
Jeremy Ruston 8b05b725aa Merge branch 'master' into colour-improvements 2025-02-14 12:01:14 +00:00
Jeremy Ruston d7df7eddb1 Introduce tf.colour function to make palette entries more concise 2025-02-13 16:26:22 +00:00
Jeremy Ruston 0037813b39 Background action demos should require explicit enabling 2025-02-13 09:10:30 +00:00
Jeremy Ruston 377856c6a1 Add temporary guide tiddler at the top 2025-02-12 18:43:19 +00:00
Jeremy Ruston 49969a2f1e Docs for apply filter run prefix 2025-02-12 16:41:37 +00:00
Jeremy Ruston 09f8ab9962 Move from v5.3.7 -> v5.4.0 2025-02-12 12:48:35 +00:00
Jeremy Ruston 422b092eb2 Don't need consent banner anymore
Was just for testing
2025-02-12 12:48:02 +00:00
Jeremy Ruston 067a1a22c6 Move sample background item out of the core
It shouldn't be enabled by default, either, but we'll come back to that
2025-02-12 12:47:41 +00:00
Jeremy Ruston 83c6223617 Refactor the interpolate operator so it can be used with the range operator 2025-02-12 10:05:16 +00:00
Jeremy Ruston 611adadaed Add apply filter run prefix
The map filter run prefix is often used as a way to move a computed value in the input list into a variable so that it can be used as a parameter of a filter operator. The apply filter run prefix extends this idea to make the input list available as variables $1, $2 etc. Unlike the map prefix, the apply filter run is only evaluated once.
2025-02-12 10:04:46 +00:00
Jeremy Ruston 28935a5856 Add hue adjuster to colour-interpolate operator 2025-02-11 20:46:11 +00:00
Jeremy Ruston 71a144f6f9 Typo 2025-02-10 17:01:45 +00:00
Jeremy Ruston 92b7819259 Fix Codemirror colour palette fallbacks 2025-02-10 17:01:37 +00:00
Jeremy Ruston d2204ae72e Fill in some missing palette entries 2025-02-10 13:48:02 +00:00
Jeremy Ruston 7da70ecf6a Add tabs and recent list to the sidebar 2025-02-10 13:47:41 +00:00
Jeremy Ruston d8dfc10ea8 Typo 2025-02-09 21:54:31 +00:00
Jeremy Ruston 7df987803d Move generic tests into a background palette
These are the generic tests that should be applied to every palette
2025-02-09 21:40:15 +00:00
Jeremy Ruston 4665bab700 AutoToggle should default to light mode so that static exports are light mode 2025-02-09 14:29:12 +00:00
Jeremy Ruston e87aaff06b Add tabs to the preview 2025-02-06 22:19:10 +00:00
Jeremy Ruston 7c4938293e Refactor the palette preview macros into a generic widget
Takes the opportunity to simplify things now that we don't have to worry about wikified palettes
2025-02-06 21:27:06 +00:00
Jeremy Ruston eba73eebcb Missed off 961b26a984 2025-02-06 17:28:28 +00:00
Jeremy Ruston 1f4f164d5e Take advantage of compiled palettes
More robust because previously we couldn't cope with indirect palette entries in these situations
2025-02-06 12:55:45 +00:00
Jeremy Ruston bfea62b43b The tags macros do not actually need access to the palette 2025-02-06 12:53:40 +00:00
Jeremy Ruston 4c216646a4 Introduce background palettes for plugins 2025-02-06 11:53:07 +00:00
Jeremy Ruston 4fe90a6c73 Add VanillaCherry palette 2025-02-06 11:28:24 +00:00
Jeremy Ruston 961b26a984 Get rid of palette-types...
Instead, we'll special case transforming `<<colour X>>` into `[function[colour],[x]]`

Makes everything much easier and avoids all the kerfuffle of not being able to mix palettes
2025-02-06 11:27:04 +00:00
Jeremy Ruston 0d9ab2e2f6 Remove unneeded scheme processing
Now that we're dealing with the schemes during the import process it is no longer necessary for the compilation process to worry about it.
2025-02-05 18:05:57 +00:00
Jeremy Ruston 796c33bc46 Refactor some variable names 2025-02-05 17:11:51 +00:00
Jeremy Ruston 4d06ecd535 Only allow palettes to import palettes of the same type 2025-02-04 21:18:54 +00:00
Jeremy Ruston f9e4dd8fd3 Rename custom palette editor to custom palette settings
To avoid confusion with existing usage of "palette editor"
2025-02-04 21:08:02 +00:00
Jeremy Ruston 6e4d7aa7f1 Give the AutoToggle palette a custom editor 2025-02-04 21:03:13 +00:00
Jeremy Ruston 998d5c8d8f The lingo macro shouldn't mess with currentTiddler 2025-02-04 21:02:47 +00:00
Jeremy Ruston 38865a40ad Palette should autocompile when the palette tiddler itself changes 2025-02-04 20:00:17 +00:00
Jeremy Ruston a5c4d90154 Refactor palette switcher a little 2025-02-04 19:59:39 +00:00
Jeremy Ruston 2e5a988bb3 Clarify comment 2025-02-04 16:44:07 +00:00
Jeremy Ruston 0ee2f286aa Set colour scheme property of root element 2025-02-04 16:40:48 +00:00
Jeremy Ruston 30a7d61e56 Easier for development if the prerelease uses the tw5.com palette 2025-02-04 16:26:46 +00:00
Jeremy Ruston c7f9dbfc29 Compile colour scheme handling 2025-02-04 16:26:15 +00:00
Jeremy Ruston c6bb2b51e6 Rethink palette manager
The current content of $:/PaletteManager is moved into $:/PaletteEditor, and $:/PaletteManager repurposed as the control panel palette switcher
2025-02-04 16:11:51 +00:00
Jeremy Ruston a053f03818 Remove logging 2025-02-04 16:10:38 +00:00
Jeremy Ruston 6970ac24bf Typo 2025-02-03 18:44:58 +00:00
Jeremy Ruston 431149d20c Introduce dynamic colour scheme mechanism
Also introduces palette inheritance

This finally allows us to have a palette that automatically switches between dark and light variants. The mechanism is more flexible that that, and allows for multiple colour schemes (night, morning, day, evening, for example) with automatic switching between them.
2025-02-03 13:26:25 +00:00
Jeremy Ruston a366d62358 Include tiddler borders in preview
Several of the core palettes have distinctive borders
2025-01-31 17:06:55 +00:00
Jeremy Ruston a6a91d49b7 Restore accidentally deleted field 2025-01-30 18:35:58 +00:00
Jeremy Ruston 22cf3b25bd Remove infinite loop that was added for testing 2025-01-28 21:40:34 +00:00
Jeremy Ruston 139b61fff1 Proper recursion detection for palettes 2025-01-28 19:18:58 +00:00
Jeremy Ruston c1fd82f50f Minor cleanups 2025-01-28 15:44:42 +00:00
Jeremy Ruston effeed7ade Remove extraneous logging 2025-01-27 21:47:03 +00:00
Jeremy Ruston 546e438943 Allow background actions to be scoped by platform 2025-01-27 21:45:17 +00:00
Jeremy Ruston efcd23993e Merge branch 'master' into colour-improvements 2025-01-27 16:55:03 +00:00
Jeremy Ruston 0c8aad49f9 Replace accumulate-palette-entries with new changecount filter
Much more direct and efficient
2025-01-27 11:09:18 +00:00
Jeremy Ruston 317e1245c8 Introduce an improved but temporary cache invalidation method for palettes 2025-01-26 17:54:47 +00:00
Jeremy Ruston d2bbc56c78 Move modern palettes to correct directory 2025-01-25 17:28:06 +00:00
Jeremy Ruston 8957424e55 Start adding tests for palette operations 2025-01-25 17:28:00 +00:00
Jeremy Ruston 0fd5b04b9a Merge branch 'master' into colour-improvements 2025-01-25 11:05:21 +00:00
Jeremy Ruston 3ea7cd3bf7 Palette editors no longer need to manually recompile the palette 2025-01-25 11:05:13 +00:00
Jeremy Ruston 7513e4426c Allow text editor type=color for colours not in hex RGB format
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/color#value
2025-01-25 11:03:53 +00:00
Jeremy Ruston 0dfde0660a Detect darkmode at startup 2025-01-24 18:34:55 +00:00
Jeremy Ruston 8c619fd86e Compile palette at startup 2025-01-24 18:32:00 +00:00
Jeremy Ruston 407e58f837 Add a basic dark palette
Obviously some things are hardcoded at the moment
2025-01-24 11:17:55 +00:00
Jeremy Ruston 9588b7f1a3 Autocompile palettes when they change 2025-01-24 11:16:31 +00:00
Jeremy Ruston 28c1e77b60 Make sure rootwidget is available before background actions start 2025-01-24 11:15:27 +00:00
Jeremy Ruston 0baf395030 Merge background actions and media tracker from #8555
The changes in #8555 are needed in order to be able to offer the desired user experience for dark mode changes.
2025-01-23 18:16:10 +00:00
Jeremy Ruston 9681b0deda Merge branch 'master' into colour-improvements 2025-01-23 18:15:44 +00:00
Jeremy Ruston 62fb916a68 Merge branch 'master' into colour-improvements 2025-01-23 14:37:23 +00:00
Jeremy Ruston 3614236cfc Paldette and style tweaks 2025-01-21 16:36:00 +00:00
Jeremy Ruston c75f50e99a Fix palette switcher used in the sidebar
by adding a new "thumbnails" parameter to the template
2025-01-09 14:51:48 +00:00
Jeremy Ruston 55d9e92032 Edit text widget shouldn't fully refresh when default attribute changes 2025-01-09 10:51:02 +00:00
Jeremy Ruston 2edcf0f46b Refactor TwentyTwenties editor 2025-01-09 10:50:37 +00:00
Jeremy Ruston 69363bf7ef Palette manager should recompile palette on edits 2025-01-08 21:38:08 +00:00
Jeremy Ruston 2b0c634fb8 Refactor actions for recompiling current palette 2025-01-08 21:37:44 +00:00
Jeremy Ruston 28167adc22 Add a palette that automatically switches between dark and light
Will requires #7999 to work fully; for the moment when you switch between dark and light you will see the preview change, and then next time you select the palette it will be in the correct mode
2025-01-08 16:02:05 +00:00
Jeremy Ruston bd4b3e4107 Fix some old-style palette references 2025-01-08 16:00:29 +00:00
Jeremy Ruston 2cbd1080fa Fix more TwentyTwenties entries 2025-01-08 15:57:39 +00:00
Jeremy Ruston a4293068bf Clarify method name 2025-01-08 14:49:19 +00:00
Jeremy Ruston d1ce54806f Download button should use palette colours 2025-01-08 10:06:56 +00:00
Jeremy Ruston 6b39d6aa43 Fix editing colours that are not in 6 digit hex format
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/color#value
2025-01-08 09:59:04 +00:00
Jeremy Ruston 5d1cf251b9 Add best contrast operator 2025-01-07 17:40:23 +00:00
Jeremy Ruston c02c82557b Add a primitive custom palette editor 2025-01-02 17:10:51 +00:00
Jeremy Ruston b90b449ceb Use interpolation to derive colours 2025-01-02 17:10:29 +00:00
Jeremy Ruston 6a06df79c4 Fix palette switcher 2024-12-27 12:00:50 +00:00
Jeremy Ruston 2558dc0b10 TwentyTwenties palette: use interpolation 2024-12-22 19:20:05 +00:00
Jeremy Ruston 2eee3bfcd6 Merge branch 'master' into colour-improvements 2024-12-21 09:48:10 +00:00
Jeremy Ruston 2685fa7c4e Improvements to TwentyTwenties palettes
Still a work in progress, but getting more coherent
2024-12-15 18:55:17 +00:00
Jeremy Ruston 3c44532551 Barebones docs for colour spaces 2024-12-15 18:49:04 +00:00
Jeremy Ruston 2640406f5b Include contrast value in contrast errors 2024-12-15 18:48:48 +00:00
Jeremy Ruston c1e36a1e5f Add colour-interpolate operator 2024-12-15 18:48:28 +00:00
Jeremy Ruston ae1d9f5b86 Add colour-get-oklch operator 2024-12-15 13:04:33 +00:00
Jeremy Ruston 1df0ac486b Refactor colour-oklch operator to colour-set-oklch 2024-12-15 11:56:49 +00:00
Jeremy Ruston b1fcb18d9e Refactor for clearer variable names 2024-12-15 11:49:23 +00:00
Jeremy Ruston 5a6eea7fa2 Make the alert and notification previews be optional
Via some future UI
2024-12-14 17:33:02 +00:00
Jeremy Ruston 6fe16bc71a Fix colour for site title 2024-12-14 17:32:43 +00:00
Jeremy Ruston 6a66c49261 Merge branch 'master' into colour-improvements 2024-12-14 17:12:51 +00:00
Jeremy Ruston fc695e7a50 Merge branch 'master' into colour-improvements 2024-12-05 17:38:50 +00:00
Jeremy Ruston 9efcad9360 Display test results at the bottom of the palette switcher 2024-11-19 09:09:11 +00:00
Jeremy Ruston cd5bbcda8d Add contrast checks to TwentyTwenties palette
I think I might be building a programming language for writing palettes...
2024-11-18 18:15:53 +00:00
Jeremy Ruston aa69c3ae91 Add colour-contrast operator 2024-11-18 18:15:20 +00:00
Jeremy Ruston 76f2decf8b Start fixing the TwentyTwenties palettes 2024-11-18 16:40:49 +00:00
Jeremy Ruston 84bef54802 Docs for colour-oklch operator 2024-11-18 16:38:54 +00:00
Jeremy Ruston 3507b0f952 Fix filtered palette previews 2024-11-17 16:11:10 +00:00
Jeremy Ruston b0828cc099 Add notification preview 2024-11-17 16:10:57 +00:00
Jeremy Ruston 32ac67166a Add alert preview 2024-11-17 14:45:52 +00:00
Jeremy Ruston b2d0c22d75 Componentise more preview components 2024-11-17 14:45:41 +00:00
Jeremy Ruston cfabc92945 Update contrastcolour macro to use color.js 2024-11-16 14:37:14 +00:00
Jeremy Ruston 809465b6e2 Merge branch 'master' into colour-improvements 2024-11-16 14:22:19 +00:00
Jeremy Ruston 8b59b6166e Palette tweaks
These filtered palettes are still just experiments with the techniques, and not yet a serious palette
2024-11-14 17:45:10 +00:00
Jeremy Ruston 3faf9bae5c Fix previews of filtered palettes 2024-11-14 17:40:58 +00:00
Jeremy Ruston c2ee0727a5 Merge branch 'master' into colour-improvements 2024-11-12 20:57:46 +00:00
Jeremy Ruston 7de5f40884 Merge branch 'master' into colour-improvements 2024-11-12 20:37:01 +00:00
Jeremy Ruston 21cd3b86ad Merge branch 'master' into colour-improvements 2024-11-12 19:51:52 +00:00
Jeremy Ruston ad1b0fdddd Palette tweaks 2024-11-12 19:26:20 +00:00
Jeremy Ruston 1db8cf7fe5 Merge branch 'master' into colour-improvements 2024-11-12 19:18:54 +00:00
Jeremy Ruston 46da1619af Add aria labels to palette switcher
Co-authored-by: Mario Pietsch <pmariojo@gmail.com>
2024-11-11 15:52:55 +00:00
Jeremy Ruston bad9517153 Another fix for filtered palette previews 2024-11-10 16:52:49 +00:00
Jeremy Ruston 38d5daaf12 Improve chooser chosen item highlight 2024-11-10 16:52:23 +00:00
Jeremy Ruston 297ae7eccb Fix preview of filtered palettes 2024-11-10 09:52:43 +00:00
Jeremy Ruston b54d56ec47 Support for imported palettes
Also consolidate the palette entries into a temporary palette before compiling them

Note that imported palettes is not currently recursive
2024-11-09 19:03:54 +00:00
Jeremy Ruston 4e2f2bebd0 Avoid redefining the colour function by adding a configuration variable 2024-11-09 17:02:00 +00:00
Jeremy Ruston f88915728f Introduce new static palette architecture 2024-11-09 16:15:33 +00:00
Jeremy Ruston 1be89a28bf Make preview templates tag driven and extensible 2024-11-08 09:12:48 +00:00
Jeremy Ruston 250e57cd79 Remove wikify operator and refactor palette preview
The implementation of the palette preview is much less elegant like this, but it does work
2024-11-07 18:30:39 +00:00
Jeremy Ruston a4d930322e Testing CI 2024-11-06 08:32:42 +00:00
Jeremy Ruston c3ce9cafb7 Testing Netlify CI 2024-11-06 08:22:42 +00:00
Jeremy Ruston 348f7177a7 Remove logging 2024-11-05 22:42:46 +00:00
Jeremy Ruston c6074402bb Restore default styling for chosen chooser item
See https://github.com/TiddlyWiki/TiddlyWiki5/pull/8702#discussion_r1816584692
2024-11-05 10:24:01 +00:00
Jeremy Ruston 23eccd1df6 Merge branch 'master' into colour-improvements 2024-11-04 19:26:16 +00:00
Jeremy Ruston ff5c846130 Indentation for palette switcher 2024-11-04 18:12:00 +00:00
Jeremy Ruston 81b7bb4124 Merge branch 'master' into colour-improvements 2024-11-04 10:39:28 +00:00
Jeremy Ruston a8fb07137d Add expertimental colour-oklch operator 2024-11-03 16:13:09 +00:00
Jeremy Ruston 85fa913b1c Merge branch 'master' into colour-improvements 2024-11-03 16:10:47 +00:00
Jeremy Ruston bc0fde6853 Fix palette chooser when displayed in "Tools" dropdown 2024-10-31 18:03:50 +00:00
Jeremy Ruston 4f2754d16c Merge branch 'master' into colour-improvements 2024-10-31 17:46:30 +00:00
Jeremy Ruston 4445111a08 Merge branch 'master' into colour-improvements 2024-10-30 20:38:58 +00:00
Jeremy Ruston 151f61adc0 Palette chooser styling tweaks 2024-10-25 11:03:21 +01:00
Jeremy Ruston fc369415e4 Improve colour palette switcher with previews 2024-10-25 09:28:33 +01:00
Jeremy Ruston b5a22e3e9e Remove obsolete comment 2024-10-25 09:28:17 +01:00
Jeremy Ruston d372729ed0 Add colour-lighten and colour-darken operators 2024-10-24 12:01:50 +01:00
Jeremy Ruston 96b85edfa2 Fix up the tests 2024-10-24 10:46:48 +01:00
Jeremy Ruston 4af573aaf9 Fix nested colour definitions 2024-10-23 09:39:18 +01:00
Jeremy Ruston 1e5c69eb99 Fix typo 2024-10-23 08:25:24 +01:00
Jeremy Ruston e1e73d2aa0 Merge branch 'master' into colour-improvements 2024-10-23 08:22:01 +01:00
Jeremy Ruston a23ee165d8 Rewrite colour macro as a function
Using the new wikify operator.

Currently has a bug whereby redirected colours (like "tiddler-background") do not work. Direct colours like "background" do work.

Note the hacks needed to makeFakeWidgetWithVariables work
2024-10-22 17:26:04 +01:00
Jeremy Ruston 467a1a47cc Introduce wikify operator
Really just syntactic sugar for the wikify widget
2024-10-22 17:24:51 +01:00
Jeremy Ruston 93d1c05ca7 Include colour.js license and mark version number 2024-10-21 17:25:56 +01:00
Jeremy Ruston fb9c0d6a5a Replace 12 year old CSS colour parsing library
The replacement library from https://colorjs.io/ is much, much larger but I think we can develop a custom build that uses treeshaking to whittle the code down to the bits that we need. @linonetwo does that sound feasible?

I intend the explore further improvements but I wanted to start by establishing a library that can do modern P3 and OKLCH colour calculations.
2024-10-21 09:03:39 +01:00
515 changed files with 13144 additions and 1524 deletions
+8 -8
View File
@@ -5,17 +5,17 @@ on:
- master
- tiddlywiki-com
env:
NODE_VERSION: "22"
NODE_VERSION: "22.22"
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/ci-test.sh"
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
if: always()
with:
name: playwright-report
@@ -30,8 +30,8 @@ jobs:
TW5_BUILD_MAIN_EDITION: "./editions/prerelease"
TW5_BUILD_OUTPUT: "./output/prerelease"
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/ci-pre-build.sh"
@@ -62,8 +62,8 @@ jobs:
TW5_BUILD_OUTPUT: "./output"
TW5_BUILD_ARCHIVE: "./output"
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: "${{ env.NODE_VERSION }}"
- run: "./bin/ci-pre-build.sh"
+2 -2
View File
@@ -20,7 +20,7 @@ jobs:
steps:
- name: build-size-check
id: get_sizes
uses: TiddlyWiki/cerebrus@v7
uses: TiddlyWiki/cerebrus@v8.1
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
@@ -52,4 +52,4 @@ jobs:
pr_size: '${{ needs.calculate-build-size.outputs.pr_size }}',
base_size: '${{ needs.calculate-build-size.outputs.base_size }}'
}
});
});
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
steps:
- name: Build and check size
uses: TiddlyWiki/cerebrus@v7
uses: TiddlyWiki/cerebrus@v8.1
with:
pr_number: ${{ inputs.pr_number }}
repo: ${{ github.repository }}
+2 -2
View File
@@ -15,7 +15,7 @@ jobs:
steps:
# Step 1: Validate PR paths
- name: Validate PR Paths
uses: TiddlyWiki/cerebrus@v6
uses: TiddlyWiki/cerebrus@v8.1
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
@@ -26,7 +26,7 @@ jobs:
# Step 2: Validate change notes
- name: Validate Change Notes
uses: TiddlyWiki/cerebrus@v7
uses: TiddlyWiki/cerebrus@v8.1
with:
pr_number: ${{ github.event.pull_request.number }}
repo: ${{ github.repository }}
+11 -1
View File
@@ -2,10 +2,20 @@
.c9/
.vs/
.vscode/
.claude/
# TiddlyWiki
tmp/
output/
node_modules/
$__StoryList.tid
# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
$__StoryList.tid
/playwright/.auth/
test-screenshots/
test-output.txt
.playwright-mcp
# TiddlyWiki MPC
.tw-mcp
+1
View File
@@ -3,3 +3,4 @@
tmp/
output/
node_modules/
.claude/
+1 -1
View File
@@ -5,7 +5,7 @@
# Default to the current version number for building the plugin library
if [ -z "$TW5_BUILD_VERSION" ]; then
TW5_BUILD_VERSION=v5.4.0
TW5_BUILD_VERSION=v5.5.0.
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
+1 -1
View File
@@ -45,7 +45,7 @@ git clone --depth=1 --branch=main "https://github.com/TiddlyWiki/tiddlywiki.org-
# Make the CNAME file that GitHub Pages requires
echo "tiddlywiki.org" > $TWORG_BUILD_OUTPUT/CNAME
# echo "tiddlywiki.org" > $TWORG_BUILD_OUTPUT/CNAME
# Delete any existing static content
+7 -3
View File
@@ -47,6 +47,13 @@ $tw.utils.hop = function(object,property) {
/** @deprecated Use Array.isArray instead */
$tw.utils.isArray = (value) => Array.isArray(value);
/*
Determine if a value is a date, even across VM boundaries
*/
$tw.utils.isDate = function(value) {
return Object.prototype.toString.call(value) === "[object Date]";
};
/*
Check if an array is equal by value and by reference.
*/
@@ -124,9 +131,6 @@ $tw.utils.pushTop = function(array,value) {
return array;
};
/** @deprecated Use instanceof Date instead */
$tw.utils.isDate = (value) => value instanceof Date;
/** @deprecated Use array iterative methods instead */
$tw.utils.each = function(object,callback) {
if(object) {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
created: 20250909171928024
modified: 20251110133437795
tags: Community/Team
leader: @kjharcombe
team: @MotovunJack
title: Infrastructure Team
@@ -12,4 +13,4 @@ The infrastructure includes:
* github.com/TiddlyWiki
* tiddlywiki.com DNS
* Netlify account for PR previews
* edit.tiddlywiki.com
* edit.tiddlywiki.com
@@ -0,0 +1,8 @@
title: TiddlyWiki Team
tags: Community/Team
modified: 20260708095630754
created: 20260708095630754
leader: @BurningTreeC
team:
The TiddlyDesktop development repository is at https://github.com/TiddlyWiki/TiddlyDesktop
+1 -1
View File
File diff suppressed because one or more lines are too long
+4 -5
View File
@@ -9,15 +9,14 @@ Serve tiddlers over http
"use strict";
let fs, url, path, querystring, crypto, zlib;
let fs, path, crypto, zlib, URL;
if($tw.node) {
fs = require("fs"),
url = require("url"),
path = require("path"),
querystring = require("querystring"),
crypto = require("crypto"),
zlib = require("zlib");
URL = require("url").URL;
}
/*
@@ -260,8 +259,8 @@ Server.prototype.requestHandler = function(request,response,options) {
state.wiki = options.wiki || self.wiki;
state.boot = options.boot || self.boot;
state.server = self;
state.urlInfo = url.parse(request.url);
state.queryParameters = querystring.parse(state.urlInfo.query);
state.urlInfo = new URL(request.url, "http://localhost");
state.queryParameters = Object.fromEntries(state.urlInfo.searchParams);
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
// Enable CORS
if(this.corsEnable) {
+2 -1
View File
@@ -58,10 +58,11 @@ LayoutSwitcher/Caption: Layout
LoadedModules/Caption: Loaded Modules
LoadedModules/Hint: These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process.
Palette/Caption: Palette
Palette/CustomSettings/Prompt: Custom settings for current palette: <<palette-link>>
Palette/Editor/Clone/Caption: clone
Palette/Editor/Clone/Prompt: It is recommended that you clone this shadow palette before editing it
Palette/Editor/Delete/Hint: delete this entry from the current palette
Palette/Editor/Names/External/Show: Show color names that are not part of the current palette
Palette/Editor/Names/External/Show: Show inherited palette entries
Palette/Editor/Prompt/Modified: This shadow palette has been modified
Palette/Editor/Prompt: Editing
Palette/Editor/Reset/Caption: reset
+1
View File
@@ -30,6 +30,7 @@ Error/DeserializeOperator/MissingOperand: Filter Error: Missing operand for 'des
Error/DeserializeOperator/UnknownDeserializer: Filter Error: Unknown deserializer provided as operand for the 'deserialize' operator
Error/Filter: Filter error
Error/FilterSyntax: Syntax error in filter expression
Error/FilterPragma: Filter Error: Unknown filter pragma
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run
Error/IsFilterOperator: Filter Error: Unknown parameter for the 'is' filter operator
Error/FormatFilterOperator: Filter Error: Unknown suffix for the 'format' filter operator
+1 -1
View File
@@ -10,7 +10,7 @@ Advanced/ShadowInfo/Shadow/Hint: The tiddler <$link to=<<infoTiddler>>><$text te
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/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/Hint: These are the view template segments that are resolved for each of the system view template cascades
Advanced/CascadeInfo/Detail/View: View
Advanced/CascadeInfo/Detail/ActiveCascadeFilter: Active cascade filter
Advanced/CascadeInfo/Detail/Template: Template
+3 -4
View File
@@ -31,7 +31,7 @@ function FramedEngine(options) {
this.parentNode.insertBefore(this.iframeNode,this.nextSibling);
this.iframeDoc = this.iframeNode.contentWindow.document;
// (Firefox requires us to put some empty content in the iframe)
var paletteTitle = this.widget.wiki.getTiddlerText("$:/palette");
var paletteTitle = this.widget.wiki.getTiddlerText("$:/palette/palette-colours");
var colorScheme = (this.widget.wiki.getTiddler(paletteTitle) || {fields: {}}).fields["color-scheme"] || "light";
this.iframeDoc.open();
this.iframeDoc.write("<!DOCTYPE html><html><head><meta name='color-scheme' content='" + colorScheme + "'></head><body></body></html>");
@@ -156,14 +156,13 @@ Fix the height of textarea to fit content
FramedEngine.prototype.fixHeight = function() {
// Make sure styles are updated
this.copyStyles();
// If .editRows is initialised, it takes precedence
if(this.widget.editTag === "textarea" && !this.widget.editRows) {
if(this.widget.editTag === "textarea") {
if(this.widget.editAutoHeight) {
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
this.iframeNode.style.height = newHeight + "px";
}
} else {
} else if(!this.widget.editRows) {
var fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,"400px"),10);
fixedHeight = Math.max(fixedHeight,20);
this.domNode.style.height = fixedHeight + "px";
+11 -4
View File
@@ -28,7 +28,12 @@ function SimpleEngine(options) {
if(this.widget.editTag === "textarea") {
this.domNode.appendChild(this.widget.document.createTextNode(this.value));
} else {
this.domNode.value = this.value;
if(this.widget.editType === "color") {
// The <input type="color"> element requires a six digit hex value
this.domNode.value = $tw.utils.convertCSSColorToRGBString(this.value);
} else {
this.domNode.value = this.value;
}
}
// Set the attributes
if(this.widget.editType && this.widget.editTag !== "textarea") {
@@ -83,6 +88,9 @@ Update the DomNode with the new text
*/
SimpleEngine.prototype.updateDomNodeText = function(text) {
try {
if(this.widget.editType === "color") {
text = $tw.utils.convertCSSColorToRGBString(text);
}
this.domNode.value = text;
} catch(e) {
// Ignore
@@ -100,13 +108,12 @@ SimpleEngine.prototype.getText = function() {
Fix the height of textarea to fit content
*/
SimpleEngine.prototype.fixHeight = function() {
// If .editRows is initialised, it takes precedence
if((this.widget.editTag === "textarea") && !this.widget.editRows) {
if(this.widget.editTag === "textarea") {
if(this.widget.editAutoHeight) {
if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) {
$tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight);
}
} else {
} else if(!this.widget.editRows) {
var fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,"400px"),10);
fixedHeight = Math.max(fixedHeight,20);
this.domNode.style.height = fixedHeight + "px";
+2 -2
View File
@@ -217,10 +217,10 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
this.refreshSelf();
return true;
} else if(changedTiddlers[this.editRefreshTitle]) {
} else if(changedAttributes["default"] || changedTiddlers[this.editRefreshTitle]) {
this.engine.updateDomNodeText(this.getEditInfo().value);
} else if(changedTiddlers[this.editTitle]) {
var editInfo = this.getEditInfo();
+71 -45
View File
@@ -146,14 +146,16 @@ exports.parseFilter = function(filterString) {
match;
var whitespaceRegExp = /(\s+)/mg,
// Groups:
// 1 - entire filter run prefix
// 2 - filter run prefix itself
// 3 - filter run prefix suffixes
// 4 - opening square bracket following filter run prefix
// 5 - double quoted string following filter run prefix
// 6 - single quoted string following filter run prefix
// 7 - anything except for whitespace and square brackets
operandRegExp = /((?:\+|\-|~|(?:=>?)|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
// 1 - pragma
// 2 - pragma suffix
// 3 - entire filter run prefix
// 4 - filter run prefix name
// 5 - filter run prefix suffixes
// 6 - opening square bracket following filter run prefix
// 7 - double quoted string following filter run prefix
// 8 - single quoted string following filter run prefix
// 9 - anything except for whitespace and square brackets
operandRegExp = /(?:::(\w+)(?:\:(\w+))?(?=\s|$)|((?:\+|\-|~|(?:=>?)|:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+)))/mg;
while(p < filterString.length) {
// Skip any whitespace
whitespaceRegExp.lastIndex = p;
@@ -170,18 +172,23 @@ exports.parseFilter = function(filterString) {
};
match = operandRegExp.exec(filterString);
if(match && match.index === p) {
// If there is a filter run prefix
if(match[1]) {
operation.prefix = match[1];
// If there is a filter pragma
operation.pragma = match[1];
operation.suffix = match[2];
p = match.index + match[0].length;
} else if(match[3]) {
// If there is a filter run prefix
operation.prefix = match[3];
p = p + operation.prefix.length;
// Name for named prefixes
if(match[2]) {
operation.namedPrefix = match[2];
if(match[4]) {
operation.namedPrefix = match[4];
}
// Suffixes for filter run prefix
if(match[3]) {
if(match[5]) {
operation.suffixes = [];
$tw.utils.each(match[3].split(":"),function(subsuffix) {
$tw.utils.each(match[5].split(":"),function(subsuffix) {
operation.suffixes.push([]);
$tw.utils.each(subsuffix.split(","),function(entry) {
entry = $tw.utils.trim(entry);
@@ -193,7 +200,7 @@ exports.parseFilter = function(filterString) {
}
}
// Opening square bracket
if(match[4]) {
if(match[6]) {
p = parseFilterOperation(operation.operators,filterString,p);
} else {
p = match.index + match[0].length;
@@ -203,9 +210,9 @@ exports.parseFilter = function(filterString) {
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[7] || match[8] || match[9]) { // Double quoted string, single quoted string or unquoted title
operation.operators.push(
{operator: "title", operands: [{text: match[5] || match[6] || match[7]}]}
{operator: "title", operands: [{text: match[7] || match[8] || match[9]}]}
);
}
results.push(operation);
@@ -230,23 +237,25 @@ exports.getFilterRunPrefixes = function() {
return this.filterRunPrefixes;
};
exports.filterTiddlers = function(filterString,widget,source) {
var fn = this.compileFilter(filterString);
exports.filterTiddlers = function(filterString,widget,source,options) {
var fn = this.compileFilter(filterString,options);
return fn.call(this,source,widget);
};
/*
Compile a filter into a function with the signature fn(source,widget) where:
Compile a filter into a function with the signature fn(source,widget,options) 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,options) {
var defaultFilterRunPrefix = (options || {}).defaultFilterRunPrefix || "or";
var cacheKey = filterString + "|" + defaultFilterRunPrefix;
if(!this.filterCache) {
this.filterCache = Object.create(null);
this.filterCacheCount = 0;
}
if(this.filterCache[filterString] !== undefined) {
return this.filterCache[filterString];
if(this.filterCache[cacheKey] !== undefined) {
return this.filterCache[cacheKey];
}
var filterParseTree;
try {
@@ -325,7 +334,8 @@ exports.compileFilter = function(filterString) {
regexp: operator.regexp
},{
wiki: self,
widget: widget
widget: widget,
defaultFilterRunPrefix: defaultFilterRunPrefix
});
if($tw.utils.isArray(results)) {
accumulator = self.makeTiddlerIterator(results);
@@ -346,29 +356,45 @@ exports.compileFilter = function(filterString) {
var filterRunPrefixes = self.getFilterRunPrefixes();
// Wrap the operator functions in a wrapper function that depends on the prefix
operationFunctions.push((function() {
var options = {wiki: self, suffixes: operation.suffixes || []};
switch(operation.prefix || "") {
case "": // No prefix means that the operation is unioned into the result
return filterRunPrefixes["or"](operationSubFunction, options);
case "=": // The results of the operation are pushed into the result without deduplication
return filterRunPrefixes["all"](operationSubFunction, options);
case "-": // The results of this operation are removed from the main result
return filterRunPrefixes["except"](operationSubFunction, options);
case "+": // This operation is applied to the main results so far
return filterRunPrefixes["and"](operationSubFunction, options);
case "~": // This operation is unioned into the result only if the main result so far is empty
return filterRunPrefixes["else"](operationSubFunction, options);
case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable
return filterRunPrefixes["let"](operationSubFunction, options);
default:
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
} else {
if(operation.pragma) {
switch(operation.pragma) {
case "defaultprefix":
defaultFilterRunPrefix = operation.suffix || "or";
break;
default:
return function(results,source,widget) {
results.clear();
results.push($tw.language.getString("Error/FilterRunPrefix"));
results.push($tw.language.getString("Error/FilterPragma"));
};
}
}
return function(results,source,widget) {
// Dummy response
};
} else {
var options = {wiki: self, suffixes: operation.suffixes || []};
switch(operation.prefix || "") {
case "": // Use the default filter run prefix if none is specified
return filterRunPrefixes[defaultFilterRunPrefix](operationSubFunction, options);
case "=": // The results of the operation are pushed into the result without deduplication
return filterRunPrefixes["all"](operationSubFunction, options);
case "-": // The results of this operation are removed from the main result
return filterRunPrefixes["except"](operationSubFunction, options);
case "+": // This operation is applied to the main results so far
return filterRunPrefixes["and"](operationSubFunction, options);
case "~": // This operation is unioned into the result only if the main result so far is empty
return filterRunPrefixes["else"](operationSubFunction, options);
case "=>": // This operation is applied to the main results so far, and the results are assigned to a variable
return filterRunPrefixes["let"](operationSubFunction, options);
default:
if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) {
return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options);
} else {
return function(results,source,widget) {
results.clear();
results.push($tw.language.getString("Error/FilterRunPrefix"));
};
}
}
}
})());
});
@@ -407,7 +433,7 @@ exports.compileFilter = function(filterString) {
this.filterCache = Object.create(null);
this.filterCacheCount = 0;
}
this.filterCache[filterString] = fnMeasured;
this.filterCache[cacheKey] = fnMeasured;
this.filterCacheCount++;
return fnMeasured;
};
+21
View File
@@ -0,0 +1,21 @@
/*\
title: $:/core/modules/filters/changecount.js
type: application/javascript
module-type: filteroperator
Filter operator for retrieving the changecount for each title in the list.
\*/
"use strict";
/*
Export our filter function
*/
exports.changecount = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(options.wiki.getChangeCount(title) + "");
});
return results;
};
+140
View File
@@ -0,0 +1,140 @@
/*\
title: $:/core/modules/filters/colour-ops.js
type: application/javascript
module-type: filteroperator
Filter operators for colour operations
\*/
"use strict";
var Color = require("$:/core/modules/utils/dom/color.js").Color,
colourSpacesList = Object.keys(Color.spaces),
hueAdjustersList = ["raw","increasing","decreasing","longer","shorter"];
exports["colour-lighten"] = makeSerialColourOperator(function (colour, operator, options) {
return colour.lighten($tw.utils.parseNumber(operator.operand)).display().toString();
});
exports["colour-darken"] = makeSerialColourOperator(function (colour, operator, options) {
return colour.darken($tw.utils.parseNumber(operator.operand)).display().toString();
});
exports["colour-get-oklch"] = makeSerialColourOperator(function (colour, operator, options) {
var prop = ((operator.suffixes || [])[0] || ["l"])[0];
if(["l","c","h"].indexOf(prop) !== -1) {
colour = colour.oklch[prop];
}
return colour.toString();
});
exports["colour-set-oklch"] = makeSerialColourOperator(function (colour, operator, options) {
var prop = ((operator.suffixes || [])[0] || ["l"])[0];
if(["l","c","h"].indexOf(prop) !== -1) {
colour.oklch[prop] = $tw.utils.parseNumber(operator.operand);
}
return colour.display().toString();
});
exports["colour-set-alpha"] = makeSerialColourOperator(function (colour, operator, options) {
colour.alpha = $tw.utils.parseNumber(operator.operand);
return colour.display().toString();
});
exports["colour-contrast"] = makeParallelColourOperator(function (colours, operator, options) {
var colourContrasts = [];
$tw.utils.each(colours,function(colour,index) {
if(!colour) {
colour = $tw.utils.parseCSSColorObject("white");
colours[index] = colour;
}
if(index > 0) {
colourContrasts.push(colour.contrast(colours[index - 1],"DeltaPhi").toString());
}
});
return colourContrasts;
});
exports["colour-best-contrast"] = makeParallelColourOperator(function (colours, operator, options, originalColours) {
var bestContrast = 0,
bestColour = null;
if(colours.length < 2) {
return [];
}
var targetColour = colours[colours.length - 1];
for(var t=0; t<colours.length; t++) {
var colour = colours[t];
if(colour) {
var contrast = colour.contrast(targetColour,"DeltaPhi");
if(contrast > bestContrast) {
bestContrast = contrast;
bestColour = originalColours[t];
}
}
}
if(bestColour) {
return [bestColour];
} else {
return [];
}
});
exports["colour-interpolate"] = function(source,operator,options) {
// Get the colour space suffix
var space = ((((operator.suffixes || [])[0] || ["srgb"])[0]) || "").toLowerCase();
if(colourSpacesList.indexOf(space) === -1) {
space = "lch";
}
// Get the hue adjuster suffix
var hueAdjuster = ((((operator.suffixes || [])[1] || ["shorter"])[0]) || "").toLowerCase();
if(hueAdjustersList.indexOf(hueAdjuster) === -1) {
hueAdjuster = "shorter";
}
// Get the colours
if(operator.operands.length < 2) {
return [];
}
var colourA = $tw.utils.parseCSSColorObject(operator.operands[0]),
colourB = $tw.utils.parseCSSColorObject(operator.operands[1]);
if(!colourA || !colourB) {
return [];
}
var rangefn = colourA.range(colourB,{space: space, hue: hueAdjuster});
// Cycle through the weights
var results = [];
source(function(tiddler,title) {
var index = $tw.utils.parseNumber(title);
var colour = rangefn(index);
results.push(colour.display().toString());
});
return results;
};
function makeSerialColourOperator(fn) {
return function (source, operator, options) {
var results = [];
source(function (tiddler, title) {
var c = $tw.utils.parseCSSColorObject(title);
if(c) {
c = fn(c, operator, options);
results.push(c);
} else {
results.push("");
}
});
return results;
};
}
function makeParallelColourOperator(fn) {
return function (source, operator, options) {
var originalColours = [],
colours = [];
source(function (tiddler, title) {
originalColours.push(title);
colours.push($tw.utils.parseCSSColorObject(title));
});
return fn(colours, operator, options, originalColours);
};
}
+3 -1
View File
@@ -13,7 +13,9 @@ Filter operator returning those input titles that pass a subfilter
Export our filter function
*/
exports.filter = function(source,operator,options) {
var filterFn = options.wiki.compileFilter(operator.operand),
var suffixes = operator.suffixes || [],
defaultFilterRunPrefix = (suffixes[0] || [options.defaultFilterRunPrefix] || [])[0] || "or",
filterFn = options.wiki.compileFilter(operator.operand,{defaultFilterRunPrefix}),
results = [],
target = operator.prefix !== "!";
source(function(tiddler,title) {
+5 -5
View File
@@ -14,31 +14,31 @@ Export our filter function
*/
exports.sort = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,false,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,false);
return results;
};
exports.nsort = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",false,true,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",false,true);
return results;
};
exports.sortan = function(source, operator, options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results, operator.operands[0] || "title", operator.prefix === "!",false,false,true,operator.operands[1]);
options.wiki.sortTiddlers(results, operator.operand || "title", operator.prefix === "!",false,false,true);
return results;
};
exports.sortcs = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,false,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,false);
return results;
};
exports.nsortcs = function(source,operator,options) {
var results = prepare_results(source);
options.wiki.sortTiddlers(results,operator.operands[0] || "title",operator.prefix === "!",true,true,undefined,operator.operands[1]);
options.wiki.sortTiddlers(results,operator.operand || "title",operator.prefix === "!",true,true);
return results;
};
+3 -1
View File
@@ -13,7 +13,9 @@ Filter operator returning its operand evaluated as a filter
Export our filter function
*/
exports.subfilter = function(source,operator,options) {
var list = options.wiki.filterTiddlers(operator.operand,options.widget,source);
var suffixes = operator.suffixes || [],
defaultFilterRunPrefix = (suffixes[0] || [options.defaultFilterRunPrefix] || [])[0] || "or";
var list = options.wiki.filterTiddlers(operator.operand,options.widget,source,{defaultFilterRunPrefix});
if(operator.prefix === "!") {
var results = [];
source(function(tiddler,title) {
+4 -5
View File
@@ -22,12 +22,11 @@ exports.tag = function(source,operator,options) {
});
} else {
// Old semantics:
var tiddlers;
if(operator.prefix === "!") {
// Returns a copy of the input if operator.operand is missing
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
const excludeTagSet = new Set(options.wiki.getTiddlersWithTag(operator.operand));
source(function(tiddler,title) {
if(tiddlers.indexOf(title) === -1) {
if(!excludeTagSet.has(title)) {
results.push(title);
}
});
@@ -39,9 +38,9 @@ exports.tag = function(source,operator,options) {
return indexedResults;
}
} else {
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
const includeTagSet = new Set(options.wiki.getTiddlersWithTag(operator.operand));
source(function(tiddler,title) {
if(tiddlers.indexOf(title) !== -1) {
if(includeTagSet.has(title)) {
results.push(title);
}
});
+12 -11
View File
@@ -26,25 +26,26 @@ exports.params = [
Run the macro
*/
exports.run = function(target,fallbackTarget,colourA,colourB) {
var rgbTarget = $tw.utils.parseCSSColor(target) || $tw.utils.parseCSSColor(fallbackTarget);
var rgbTarget = $tw.utils.parseCSSColorObject(target) || $tw.utils.parseCSSColorObject(fallbackTarget);
if(!rgbTarget) {
return colourA;
}
var rgbColourA = $tw.utils.parseCSSColor(colourA),
rgbColourB = $tw.utils.parseCSSColor(colourB);
var rgbColourA = $tw.utils.parseCSSColorObject(colourA),
rgbColourB = $tw.utils.parseCSSColorObject(colourB);
if(rgbColourA && !rgbColourB) {
return rgbColourA;
return colourA;
}
if(rgbColourB && !rgbColourA) {
return rgbColourB;
return colourB;
}
if(!rgbColourA && !rgbColourB) {
// If neither colour is readable, return a crude inverse of the target
return [255 - rgbTarget[0],255 - rgbTarget[1],255 - rgbTarget[2],rgbTarget[3]];
rgbTarget.srgb.r = 1 - rgbTarget.srgb.r;
rgbTarget.srgb.g = 1 - rgbTarget.srgb.g;
rgbTarget.srgb.b = 1 - rgbTarget.srgb.b;
return rgbTarget.display();
}
// Colour brightness formula derived from http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
var brightnessTarget = rgbTarget[0] * 0.299 + rgbTarget[1] * 0.587 + rgbTarget[2] * 0.114,
brightnessA = rgbColourA[0] * 0.299 + rgbColourA[1] * 0.587 + rgbColourA[2] * 0.114,
brightnessB = rgbColourB[0] * 0.299 + rgbColourB[1] * 0.587 + rgbColourB[2] * 0.114;
return Math.abs(brightnessTarget - brightnessA) > Math.abs(brightnessTarget - brightnessB) ? colourA : colourB;
var aContrast = rgbColourA.contrast(rgbTarget,"DeltaPhi"),
bContrast = rgbColourB.contrast(rgbTarget,"DeltaPhi");
return aContrast > bContrast ? colourA : colourB;
};
+151 -114
View File
@@ -107,7 +107,7 @@ exports.parseStringLiteral = function(source,pos) {
type: "string",
start: pos
};
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')|\[\[((?:[^\]]|\](?!\]))*)\]\]/g;
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')|\[\[((?:[^\]]|\](?!\]))*)\]\]/y;
reString.lastIndex = pos;
var match = reString.exec(source);
if(match && match.index === pos) {
@@ -221,7 +221,7 @@ exports.parseMacroInvocationAsTransclusion = function(source,pos) {
orderedAttributes: []
};
// Define our regexps
var reVarName = /([^\s>"'=:]+)/g;
var reVarName = /([^\s>"'=:]+)/y;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double opening angle bracket
@@ -237,9 +237,11 @@ exports.parseMacroInvocationAsTransclusion = function(source,pos) {
}
$tw.utils.addAttributeToParseTreeNode(node,"$variable",token.match[1]);
pos = token.end;
// Check that the tag is terminated by a space or >>
if(!$tw.utils.parseWhiteSpace(source,pos) && !(source.charAt(pos) === ">" && source.charAt(pos + 1) === ">") ) {
return null;
// Check that the tag is terminated by a space or >>, and that there is a closing >> somewhere ahead
if(!(source.charAt(pos) === ">" && source.charAt(pos + 1) === ">") ) {
if(source.indexOf(">>",pos) === -1) {
return null;
}
}
// Process attributes
pos = $tw.utils.parseMacroParametersAsAttributes(node,source,pos);
@@ -267,7 +269,7 @@ exports.parseMVVReferenceAsTransclusion = function(source,pos) {
orderedAttributes: []
};
// Define our regexps
var reVarName = /([^\s>"'=:)]+)/g;
var reVarName = /([^\s>"'=:)]+)/y;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double opening parenthesis
@@ -323,18 +325,24 @@ exports.parseMacroParameterAsAttribute = function(source,pos) {
start: pos
};
// Define our regexps
var reAttributeName = /([^\/\s>"'`=:]+)/g,
reUnquotedAttribute = /((?:(?:>(?!>))|[^\s>"'])+)/g,
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g,
reIndirectValue = /\{\{([^\}]+)\}\}/g,
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/g;
var reAttributeName = /([^\/\s>"'`=:]+)/y,
reStrictIdentifier = /^[A-Za-z0-9\-_]+$/,
reUnquotedAttribute = /(?!<<)((?:(?:>(?!>))|[^\s>"'])+)/y,
reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/y,
reIndirectValue = /\{\{([^\}]+)\}\}/y,
reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/y;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Get the attribute name and the separator token
var nameToken = $tw.utils.parseTokenRegExp(source,pos,reAttributeName),
namePos = nameToken && $tw.utils.skipWhiteSpace(source,nameToken.end),
separatorToken = nameToken && $tw.utils.parseTokenRegExp(source,namePos,/=|:/g),
separatorToken = nameToken && $tw.utils.parseTokenRegExp(source,namePos,/=|:/y),
isNewStyleSeparator = false; // If there is no separator then we don't allow new style values
// Colon separator requires a strict identifier name to avoid mis-parsing values like $:/foo
if(nameToken && separatorToken && separatorToken.match[0] === ":" && !reStrictIdentifier.test(nameToken.match[1])) {
nameToken = null;
separatorToken = null;
}
// If we have a name and a separator then we have a named attribute
if(nameToken && separatorToken) {
node.name = nameToken.match[1];
@@ -345,64 +353,78 @@ exports.parseMacroParameterAsAttribute = function(source,pos) {
}
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
// Mark the value as having been quoted in the source
node.quoted = true;
} else {
// Look for a filtered value
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
if(filteredValue && isNewStyleSeparator) {
pos = filteredValue.end;
node.type = "filtered";
node.filter = filteredValue.match[1];
} else {
do {
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
// Mark the value as having been quoted in the source
node.quoted = true;
break;
}
if(isNewStyleSeparator) {
// Look for a filtered value
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
if(filteredValue) {
pos = filteredValue.end;
node.type = "filtered";
node.filter = filteredValue.match[1];
break;
}
// Look for an indirect value
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue && isNewStyleSeparator) {
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
if(macroInvocation && isNewStyleSeparator) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
// Look for an MVV reference value
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
if(mvvReference && isNewStyleSeparator) {
pos = mvvReference.end;
node.type = "macro";
node.value = mvvReference;
node.isMVV = true;
} else {
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
if(substitutedValue && isNewStyleSeparator) {
pos = substitutedValue.end;
node.type = "substituted";
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
} else {
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else {
}
}
}
}
break;
}
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
break;
}
// Look for an MVV reference value
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
if(mvvReference) {
pos = mvvReference.end;
node.type = "macro";
node.value = mvvReference;
node.isMVV = true;
break;
}
// Look for a substituted value
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
if(substitutedValue) {
pos = substitutedValue.end;
node.type = "substituted";
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
break;
}
}
}
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
break; // redundant, but leaving for consistency
}
} while(false);
// Bail if we don't have a value
if(!node.type) {
return null;
@@ -506,64 +528,79 @@ exports.parseAttribute = function(source,pos) {
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
} else {
do {
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
break;
}
// Look for a filtered value
var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue);
if(filteredValue) {
pos = filteredValue.end;
node.type = "filtered";
node.filter = filteredValue.match[1];
} else {
// Look for an indirect value
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
// Look for an MVV reference value
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
if(mvvReference) {
pos = mvvReference.end;
node.type = "macro";
node.value = mvvReference;
node.isMVV = true;
} else {
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
if(substitutedValue) {
pos = substitutedValue.end;
node.type = "substituted";
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
} else {
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else {
node.type = "string";
node.value = "true";
}
}
}
}
}
break;
}
}
// Look for an indirect value
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
break;
}
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocationAsTransclusion(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
break;
}
// Look for an MVV reference value
var mvvReference = $tw.utils.parseMVVReferenceAsTransclusion(source,pos);
if(mvvReference) {
pos = mvvReference.end;
node.type = "macro";
node.value = mvvReference;
node.isMVV = true;
break;
}
// Look for a substituted value
var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue);
if(substitutedValue) {
pos = substitutedValue.end;
node.type = "substituted";
node.rawValue = substitutedValue.match[1] || substitutedValue.match[2];
break;
}
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
break;
}
if(source.charAt(pos) === "<" && source.charAt(pos + 1) === "<" && source.indexOf(">>",pos) !== -1) {
// Value looks like a macro invocation (starts with << with a closing >> ahead) but does not parse as one. Return null so the enclosing tag fails to parse rather than silently binding the attribute to "true" and treating the remainder as further attributes (restores v5.3.8 behaviour)
return null;
}
node.type = "string";
node.value = "true";
} while(false);
} else {
// If there is no equals sign or colon, then this is an attribute with no value, defaulting to "true"
node.type = "string";
@@ -31,13 +31,16 @@ exports.parse = function() {
reEnd.lastIndex = this.parser.pos;
var match = reEnd.exec(this.parser.source),
text,
start = this.parser.pos;
start = this.parser.pos,
textEnd;
// Process the text
if(match) {
text = this.parser.source.substring(this.parser.pos,match.index);
textEnd = match.index;
this.parser.pos = match.index + match[0].length;
} else {
text = this.parser.source.substr(this.parser.pos);
textEnd = this.parser.sourceLength;
this.parser.pos = this.parser.sourceLength;
}
return [{
@@ -47,7 +50,7 @@ exports.parse = function() {
type: "text",
text: text,
start: start,
end: this.parser.pos
end: textEnd
}]
}];
};
@@ -32,7 +32,8 @@ exports.parse = function() {
this.parser.pos = this.matchRegExp.lastIndex;
// Create the link unless it is suppressed
if(this.match[0].substr(0,1) === "~") {
return [{type: "text", text: this.match[0].substr(1), start: start, end: this.parser.pos}];
// Start after the suppressing "~" so the span matches the plain text
return [{type: "text", text: this.match[0].substr(1), start: start + 1, end: this.parser.pos}];
} else {
return [{
type: "element",
@@ -34,7 +34,7 @@ exports.parse = function() {
// Parse the filter terminated by a line break
var reMatch = /(.*)(?:$|\r?\n)/mg;
reMatch.lastIndex = this.parser.pos;
var filterStart = this.parser.source;
var filterStart = this.parser.pos;
var match = reMatch.exec(this.parser.source);
this.parser.pos = reMatch.lastIndex;
// Parse tree nodes to return
@@ -27,9 +27,11 @@ Parse the most recent match
*/
exports.parse = function() {
// Get the details of the match
var linkText = this.match[0];
var linkText = this.match[0],
// Start after the suppressing "~" so the span matches the plain text
start = this.parser.pos + 1;
// Move past the wikilink
this.parser.pos = this.matchRegExp.lastIndex;
// Return the link without unwikilink character as plain text
return [{type: "text", text: linkText.substr(1)}];
return [{type: "text", text: linkText.substr(1), start: start, end: this.parser.pos}];
};
+54
View File
@@ -0,0 +1,54 @@
/*\
title: $:/core/modules/relinkers/tiddlers.js
type: application/javascript
module-type: relinker
Relinks the tags and list fields of tiddlers.
Calls a tw-relinking-tiddler hook for every altered tiddler.
\*/
exports.name = "tiddlers";
exports.relink = function(wiki,fromTitle,toTitle,options) {
wiki.each(function(tiddler,title) {
var type = tiddler.fields.type || "";
// Don't touch plugins or JavaScript modules
if(!tiddler.fields["plugin-type"] && type !== "application/javascript") {
var tags = tiddler.fields.tags ? tiddler.fields.tags.slice(0) : undefined,
list = tiddler.fields.list ? tiddler.fields.list.slice(0) : undefined,
isModified = false,
processList = function(listField) {
if(listField && listField.indexOf(fromTitle) !== -1) {
// Remove any existing instances of the toTitle
var p = listField.indexOf(toTitle);
while(p !== -1) {
listField.splice(p,1);
p = listField.indexOf(toTitle);
}
// Replace the fromTitle with toTitle
$tw.utils.each(listField,function (title,index) {
if(title === fromTitle) {
listField[index] = toTitle;
isModified = true;
}
});
}
};
if(!options.dontRenameInTags) {
// Rename tags
processList(tags);
}
if(!options.dontRenameInLists) {
// Rename lists
processList(list);
}
if(isModified) {
var newTiddler = new $tw.Tiddler(tiddler,{tags: tags, list: list},wiki.getModificationFields());
newTiddler = $tw.hooks.invokeHook("th-relinking-tiddler",newTiddler,tiddler);
wiki.addTiddler(newTiddler);
}
}
});
};
+2
View File
@@ -40,6 +40,8 @@ exports.startup = function() {
// The rest of the startup process here is not strictly to do with loading modules, but are needed before other startup
// modules are executed. It is easier to put them here than to introduce a new startup module
// --------------------------
// Set up the performance framework
$tw.perf = new $tw.Performance($tw.wiki.getTiddlerText(PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE,"no") === "yes");
// Create a root widget for attaching event handlers. By using it as the parentWidget for another widget tree, one can reuse the event handlers
$tw.rootWidget = new widget.widget({
type: "widget",
+60 -11
View File
@@ -3,18 +3,43 @@ title: $:/core/modules/utils/deprecated.js
type: application/javascript
module-type: utils
Deprecated util functions
Deprecated util functions. These preserve the pre-5.4.0 signatures and
behaviour for backwards compatibility with plugins and external scripts.
Prefer modern alternatives in new code (Array.prototype methods, classList,
Math.sign, String.prototype.repeat, etc.).
\*/
exports.logTable = (data) => console.table(data);
exports.repeat = (str,count) => str.repeat(count);
/*
Repeats a string
*/
exports.repeat = function(str,count) {
var result = "";
for(var t=0;t<count;t++) {
result += str;
}
return result;
};
exports.startsWith = (str,search) => str.startsWith(search);
/*
Check if a string starts with another string
*/
exports.startsWith = function(str,search) {
return str.substring(0, search.length) === search;
};
exports.endsWith = (str,search) => str.endsWith(search);
/*
Check if a string ends with another string
*/
exports.endsWith = function(str,search) {
return str.substring(str.length - search.length) === search;
};
/*
Trim whitespace from the start and end of a string
*/
exports.trim = function(str) {
if(typeof str === "string") {
return str.trim();
@@ -29,30 +54,54 @@ exports.sign = Math.sign;
exports.strEndsWith = (str,ending,position) => str.endsWith(ending,position);
exports.stringifyNumber = (num) => num.toString();
exports.stringifyNumber = function(num) {
return num + "";
};
// Returns the fully escaped CSS selector for a tag, e.g.
// "$:/tags/Stylesheet" -> "tc-tagged-\%24\%3A\%2Ftags\%2FStylesheet"
exports.tagToCssSelector = function(tagName) {
return "tc-tagged-" + encodeURIComponent(tagName).replace(/[!"#$%&'()*+,\-./:;<=>?@[\\\]^`{\|}~,]/mg,function(c) {
return "\\" + c;
});
};
exports.domContains = (a,b) => a.compareDocumentPosition(b) & 16;
/*
Determines whether element 'a' contains element 'b'.
Returns false when a === b (matches the original John Resig semantics).
*/
exports.domContains = function(a,b) {
return a !== b && a.contains(b);
};
exports.domMatchesSelector = (node,selector) => node.matches(selector);
exports.hasClass = (el,className) => el.classList && el.classList.contains(className);
exports.hasClass = function(el,className) {
return !!(el && el.classList && el.classList.contains(className));
};
// addClass/removeClass/toggleClass split on whitespace to preserve the
// original setAttribute("class", ...) acceptance of "foo bar" as two
// classes. Regressed in #9251.
function splitClasses(className) {
return (typeof className === "string" && className.match(/\S+/g)) || [];
}
exports.addClass = function(el,className) {
el.classList && className && el.classList.add(className);
if(!el.classList) return;
splitClasses(className).forEach(function(c) { el.classList.add(c); });
};
exports.removeClass = function(el,className) {
el.classList && className && el.classList.remove(className);
if(!el.classList) return;
splitClasses(className).forEach(function(c) { el.classList.remove(c); });
};
exports.toggleClass = function(el,className,status) {
el.classList && className && el.classList.toggle(className, status);
if(!el.classList) return;
splitClasses(className).forEach(function(c) { el.classList.toggle(c,status); });
};
exports.getLocationPath = () => window.location.origin + window.location.pathname;
exports.getLocationPath = function() {
return window.location.toString().split("#")[0];
};
+55
View File
@@ -0,0 +1,55 @@
/*\
title: $:/core/modules/utils/color-utils.js
type: application/javascript
module-type: utils
Color.js related utilities
\*/
"use strict";
var Color = require("$:/core/modules/utils/dom/color.js").Color;
/*
For backwards compatibility
*/
exports.parseCSSColor = function(colourString) {
var c = exports.parseCSSColorObject(colourString);
if(c) {
var rgb = c.srgb;
return [rgb[0],rgb[1],rgb[2],c.alpha];
} else {
return null;
}
};
/*
Preferred way to parse a Color.js colour
*/
exports.parseCSSColorObject = function(colourString) {
var c = null;
try {
c = new Color(colourString);
} catch(e) {
// Return null if there is an error
}
return c;
};
/*
Convert a CSS colour to an RGB string suitable for use with the <input type="color"> element
*/
exports.convertCSSColorToRGBString = function(colourString) {
var c = exports.parseCSSColorObject(colourString);
if(c) {
var hex = c.toString({format: "hex"});
if(hex.length === 4) {
hex = "#" + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
}
return hex;
} else {
return null;
}
};
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Lea Verou, Chris Lilley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,21 @@
{
"tiddlers": [
{
"file": "color.global.min.v0.6.1.js",
"fields": {
"type": "application/javascript",
"title": "$:/core/modules/utils/dom/color.js",
"module-type": "library"
},
"prefix": "",
"suffix": ";\nexports.Color = Color;"
},
{
"file": "LICENSE",
"fields": {
"type": "text/plain",
"title": "$:/core/modules/utils/dom/color.js/license"
}
}
]
}
-200
View File
@@ -1,200 +0,0 @@
// (c) Dean McNamee <dean@gmail.com>, 2012.
//
// https://github.com/deanm/css-color-parser-js
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// http://www.w3.org/TR/css3-color/
var kCSSColorTable = {
"transparent": [0,0,0,0], "aliceblue": [240,248,255,1],
"antiquewhite": [250,235,215,1], "aqua": [0,255,255,1],
"aquamarine": [127,255,212,1], "azure": [240,255,255,1],
"beige": [245,245,220,1], "bisque": [255,228,196,1],
"black": [0,0,0,1], "blanchedalmond": [255,235,205,1],
"blue": [0,0,255,1], "blueviolet": [138,43,226,1],
"brown": [165,42,42,1], "burlywood": [222,184,135,1],
"cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1],
"chocolate": [210,105,30,1], "coral": [255,127,80,1],
"cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1],
"crimson": [220,20,60,1], "cyan": [0,255,255,1],
"darkblue": [0,0,139,1], "darkcyan": [0,139,139,1],
"darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1],
"darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1],
"darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1],
"darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1],
"darkorchid": [153,50,204,1], "darkred": [139,0,0,1],
"darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1],
"darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1],
"darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1],
"darkviolet": [148,0,211,1], "deeppink": [255,20,147,1],
"deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1],
"dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1],
"firebrick": [178,34,34,1], "floralwhite": [255,250,240,1],
"forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1],
"gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1],
"gold": [255,215,0,1], "goldenrod": [218,165,32,1],
"gray": [128,128,128,1], "green": [0,128,0,1],
"greenyellow": [173,255,47,1], "grey": [128,128,128,1],
"honeydew": [240,255,240,1], "hotpink": [255,105,180,1],
"indianred": [205,92,92,1], "indigo": [75,0,130,1],
"ivory": [255,255,240,1], "khaki": [240,230,140,1],
"lavender": [230,230,250,1], "lavenderblush": [255,240,245,1],
"lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1],
"lightblue": [173,216,230,1], "lightcoral": [240,128,128,1],
"lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1],
"lightgray": [211,211,211,1], "lightgreen": [144,238,144,1],
"lightgrey": [211,211,211,1], "lightpink": [255,182,193,1],
"lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1],
"lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1],
"lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1],
"lightyellow": [255,255,224,1], "lime": [0,255,0,1],
"limegreen": [50,205,50,1], "linen": [250,240,230,1],
"magenta": [255,0,255,1], "maroon": [128,0,0,1],
"mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1],
"mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1],
"mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1],
"mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1],
"mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1],
"mintcream": [245,255,250,1], "mistyrose": [255,228,225,1],
"moccasin": [255,228,181,1], "navajowhite": [255,222,173,1],
"navy": [0,0,128,1], "oldlace": [253,245,230,1],
"olive": [128,128,0,1], "olivedrab": [107,142,35,1],
"orange": [255,165,0,1], "orangered": [255,69,0,1],
"orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1],
"palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1],
"palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1],
"peachpuff": [255,218,185,1], "peru": [205,133,63,1],
"pink": [255,192,203,1], "plum": [221,160,221,1],
"powderblue": [176,224,230,1], "purple": [128,0,128,1],
"red": [255,0,0,1], "rosybrown": [188,143,143,1],
"royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1],
"salmon": [250,128,114,1], "sandybrown": [244,164,96,1],
"seagreen": [46,139,87,1], "seashell": [255,245,238,1],
"sienna": [160,82,45,1], "silver": [192,192,192,1],
"skyblue": [135,206,235,1], "slateblue": [106,90,205,1],
"slategray": [112,128,144,1], "slategrey": [112,128,144,1],
"snow": [255,250,250,1], "springgreen": [0,255,127,1],
"steelblue": [70,130,180,1], "tan": [210,180,140,1],
"teal": [0,128,128,1], "thistle": [216,191,216,1],
"tomato": [255,99,71,1], "turquoise": [64,224,208,1],
"violet": [238,130,238,1], "wheat": [245,222,179,1],
"white": [255,255,255,1], "whitesmoke": [245,245,245,1],
"yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]}
function clamp_css_byte(i) { // Clamp to integer 0 .. 255.
i = Math.round(i); // Seems to be what Chrome does (vs truncation).
return i < 0 ? 0 : i > 255 ? 255 : i;
}
function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0.
return f < 0 ? 0 : f > 1 ? 1 : f;
}
function parse_css_int(str) { // int or percentage.
if (str[str.length - 1] === '%')
return clamp_css_byte(parseFloat(str) / 100 * 255);
return clamp_css_byte(parseInt(str));
}
function parse_css_float(str) { // float or percentage.
if (str[str.length - 1] === '%')
return clamp_css_float(parseFloat(str) / 100);
return clamp_css_float(parseFloat(str));
}
function css_hue_to_rgb(m1, m2, h) {
if (h < 0) h += 1;
else if (h > 1) h -= 1;
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
if (h * 2 < 1) return m2;
if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
return m1;
}
function parseCSSColor(css_str) {
// Remove all whitespace, not compliant, but should just be more accepting.
var str = css_str.replace(/ /g, '').toLowerCase();
// Color keywords (and transparent) lookup.
if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup.
// #abc and #abc123 syntax.
if (str[0] === '#') {
if (str.length === 4) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN.
return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
(iv & 0xf0) | ((iv & 0xf0) >> 4),
(iv & 0xf) | ((iv & 0xf) << 4),
1];
} else if (str.length === 7) {
var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN.
return [(iv & 0xff0000) >> 16,
(iv & 0xff00) >> 8,
iv & 0xff,
1];
}
return null;
}
var op = str.indexOf('('), ep = str.indexOf(')');
if (op !== -1 && ep + 1 === str.length) {
var fname = str.substr(0, op);
var params = str.substr(op+1, ep-(op+1)).split(',');
var alpha = 1; // To allow case fallthrough.
switch (fname) {
case 'rgba':
if (params.length !== 4) return null;
alpha = parse_css_float(params.pop());
// Fall through.
case 'rgb':
if (params.length !== 3) return null;
return [parse_css_int(params[0]),
parse_css_int(params[1]),
parse_css_int(params[2]),
alpha];
case 'hsla':
if (params.length !== 4) return null;
alpha = parse_css_float(params.pop());
// Fall through.
case 'hsl':
if (params.length !== 3) return null;
var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1
// NOTE(deanm): According to the CSS spec s/l should only be
// percentages, but we don't bother and let float or percentage.
var s = parse_css_float(params[1]);
var l = parse_css_float(params[2]);
var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
var m1 = l * 2 - m2;
return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255),
clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255),
alpha];
default:
return null;
}
}
return null;
}
try { exports.parseCSSColor = parseCSSColor } catch(e) { }
@@ -1,3 +0,0 @@
title: $:/core/modules/utils/dom/csscolorparser.js
type: application/javascript
module-type: utils
+13
View File
@@ -77,10 +77,23 @@ exports.resizeTextAreaToFit = function(domNode,minHeight) {
// Measure the specified minimum height
domNode.style.height = minHeight;
var measuredHeight = domNode.offsetHeight || parseInt(minHeight,10);
// Temporarily force rows=1 during auto-measurement so the intrinsic floor
// is one row rather than the HTML default of two; restore afterwards
var hadRowsAttr = domNode.hasAttribute("rows"),
savedRows = hadRowsAttr ? domNode.getAttribute("rows") : null;
if(!hadRowsAttr) {
domNode.setAttribute("rows","1");
}
// Set its height to auto so that it snaps to the correct height
domNode.style.height = "auto";
// Calculate the revised height
var newHeight = Math.max(domNode.scrollHeight + domNode.offsetHeight - domNode.clientHeight,measuredHeight);
// Restore the original rows attribute state
if(!hadRowsAttr) {
domNode.removeAttribute("rows");
} else {
domNode.setAttribute("rows",savedRows);
}
// Only try to change the height if it has changed
if(newHeight !== domNode.offsetHeight) {
domNode.style.height = newHeight + "px";
+9
View File
@@ -82,6 +82,11 @@ var TW_Style = function(el) {
// Return a Proxy to handle direct access to individual style properties
return new Proxy(styleObject, {
get: function(target, property) {
// Real CSSStyleDeclaration returns undefined for non-string keys.
// Guards against crashes when consumers probe Symbol.toPrimitive etc.
if(typeof property !== "string") {
return undefined;
}
// If the property exists on styleObject, return it (get, set, setProperty methods)
if(property in target) {
return target[property];
@@ -90,6 +95,10 @@ var TW_Style = function(el) {
return el._style[$tw.utils.convertStyleNameToPropertyName(property)] || "";
},
set: function(target, property, value) {
// Mirror the get trap: ignore non-string keys instead of crashing.
if(typeof property !== "string") {
return true;
}
// Set the property in _style
el._style[$tw.utils.convertStyleNameToPropertyName(property)] = value;
return true;
+27 -7
View File
@@ -243,8 +243,28 @@ exports.slowInSlowOut = function(t) {
};
exports.copyObjectPropertiesSafe = function(object) {
const seen = new Set(),
isDOMElement = (value) => value instanceof Node || value instanceof Window;
const seen = new Set();
function isDOMElement(value) {
if(!value || typeof value !== "object") {
return false;
}
// Cross-realm DOM nodes
if(typeof value.nodeType === "number" &&
typeof value.nodeName === "string") {
return true;
}
// Cross-realm Window objects
if(value.window === value &&
value.document &&
value.location) {
return true;
}
return false;
}
function safeCopy(obj) {
// skip circular references
@@ -255,10 +275,6 @@ exports.copyObjectPropertiesSafe = function(object) {
if(typeof obj !== "object" || obj === null) {
return obj;
}
// skip DOM elements
if(isDOMElement(obj)) {
return undefined;
}
// copy arrays, preserving positions
if(Array.isArray(obj)) {
return obj.map((item) => {
@@ -266,7 +282,11 @@ exports.copyObjectPropertiesSafe = function(object) {
return value === undefined ? null : value;
});
}
// skip DOM elements
if(isDOMElement(obj)) {
return undefined;
}
seen.add(obj);
const copy = {};
let key,
+2 -2
View File
@@ -61,7 +61,7 @@ LogWidget.prototype.log = function() {
$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
if(name.substring(0,2) !== "$$") {
var resultList = self.computeAttribute(attribute,{asList: true});
if(resultList.length <= 1) {
if(resultList && resultList.length <= 1) {
data[name] = resultList[0] || "";
} else {
data[name] = resultList;
@@ -75,7 +75,7 @@ LogWidget.prototype.log = function() {
allVars[v] = variable.value;
} else {
var variableInfo = this.getVariableInfo(v);
allVars[v] = variableInfo.resultList.length > 1 ? variableInfo.resultList : variableInfo.text;
allVars[v] = variableInfo && variableInfo.resultList && variableInfo.resultList.length > 1 ? variableInfo.resultList : variableInfo.text;
}
}
if(this.filter) {
+2 -2
View File
@@ -62,8 +62,8 @@ SendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {
var paramObject = Object.create(null);
// Add names/values pairs if present
if(this.actionNames && this.actionValues) {
var names = this.wiki.filterTiddlers(this.actionNames,this),
values = this.wiki.filterTiddlers(this.actionValues,this);
var names = this.wiki.filterTiddlers(this.actionNames,this,{defaultFilterRunPrefix: "all"}),
values = this.wiki.filterTiddlers(this.actionValues,this,{defaultFilterRunPrefix: "all"});
$tw.utils.each(names,function(name,index) {
paramObject[name] = values[index] || "";
});
@@ -56,10 +56,10 @@ Invoke the action associated with this widget
*/
SetMultipleFieldsWidget.prototype.invokeAction = function(triggeringWidget,event) {
var tiddler = this.wiki.getTiddler(this.actionTiddler),
names, values = this.wiki.filterTiddlers(this.actionValues,this);
names, values = this.wiki.filterTiddlers(this.actionValues,this,{defaultFilterRunPrefix: "all"});
if(this.actionFields) {
var additions = {};
names = this.wiki.filterTiddlers(this.actionFields,this);
names = this.wiki.filterTiddlers(this.actionFields,this,{defaultFilterRunPrefix: "all"});
$tw.utils.each(names,function(fieldname,index) {
additions[fieldname] = values[index] || "";
});
@@ -68,7 +68,7 @@ SetMultipleFieldsWidget.prototype.invokeAction = function(triggeringWidget,event
this.wiki.addTiddler(new $tw.Tiddler(creationFields,tiddler,{title: this.actionTiddler},modificationFields,additions));
} else if(this.actionIndexes) {
var data = this.wiki.getTiddlerData(this.actionTiddler,Object.create(null));
names = this.wiki.filterTiddlers(this.actionIndexes,this);
names = this.wiki.filterTiddlers(this.actionIndexes,this,{defaultFilterRunPrefix: "all"});
$tw.utils.each(names,function(name,index) {
data[name] = values[index] || "";
});
+4 -4
View File
@@ -72,8 +72,8 @@ GenesisWidget.prototype.execute = function() {
this.attributeNames = [];
this.attributeValues = [];
if(this.genesisNames && this.genesisValues) {
this.attributeNames = this.wiki.filterTiddlers(self.genesisNames,this);
this.attributeValues = this.wiki.filterTiddlers(self.genesisValues,this);
this.attributeNames = this.wiki.filterTiddlers(self.genesisNames,this,{defaultFilterRunPrefix: "all"});
this.attributeValues = this.wiki.filterTiddlers(self.genesisValues,this,{defaultFilterRunPrefix: "all"});
$tw.utils.each(this.attributeNames,function(varname,index) {
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],varname,self.attributeValues[index] || "");
});
@@ -103,8 +103,8 @@ GenesisWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes(),
filterNames = this.getAttribute("$names",""),
filterValues = this.getAttribute("$values",""),
attributeNames = this.wiki.filterTiddlers(filterNames,this),
attributeValues = this.wiki.filterTiddlers(filterValues,this);
attributeNames = this.wiki.filterTiddlers(filterNames,this,{defaultFilterRunPrefix: "all"}),
attributeValues = this.wiki.filterTiddlers(filterValues,this,{defaultFilterRunPrefix: "all"});
if($tw.utils.count(changedAttributes) > 0 || !$tw.utils.isArrayEqual(this.attributeNames,attributeNames) || !$tw.utils.isArrayEqual(this.attributeValues,attributeValues)) {
this.refreshSelf();
return true;
+3 -4
View File
@@ -125,13 +125,12 @@ SelectWidget.prototype.setSelectValue = function() {
values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value);
for(var i=0; i < select.children.length; i++){
child=select.children[i];
if(child.children.length === 0){
child.selected = values.indexOf(child.value) !== -1;
} else {
// grouped options
if(child.tagName && child.tagName.toUpperCase() === "OPTGROUP"){
for(var y=0; y < child.children.length; y++){
child.children[y].selected = values.indexOf(child.children[y].value) !== -1;
}
} else {
child.selected = values.indexOf(child.value) !== -1;
}
}
} else {
+4 -4
View File
@@ -49,8 +49,8 @@ SetMultipleVariablesWidget.prototype.setVariables = function() {
this.variableNames = [];
this.variableValues = [];
if(filterNames && filterValues) {
this.variableNames = this.wiki.filterTiddlers(filterNames,this);
this.variableValues = this.wiki.filterTiddlers(filterValues,this);
this.variableNames = this.wiki.filterTiddlers(filterNames,this,{defaultFilterRunPrefix: "all"});
this.variableValues = this.wiki.filterTiddlers(filterValues,this,{defaultFilterRunPrefix: "all"});
$tw.utils.each(this.variableNames,function(varname,index) {
self.setVariable(varname,self.variableValues[index]);
});
@@ -63,8 +63,8 @@ Refresh the widget by ensuring our attributes are up to date
SetMultipleVariablesWidget.prototype.refresh = function(changedTiddlers) {
var filterNames = this.getAttribute("$names",""),
filterValues = this.getAttribute("$values",""),
variableNames = this.wiki.filterTiddlers(filterNames,this),
variableValues = this.wiki.filterTiddlers(filterValues,this);
variableNames = this.wiki.filterTiddlers(filterNames,this,{defaultFilterRunPrefix: "all"}),
variableValues = this.wiki.filterTiddlers(filterValues,this,{defaultFilterRunPrefix: "all"});
if(!$tw.utils.isArrayEqual(this.variableNames,variableNames) || !$tw.utils.isArrayEqual(this.variableValues,variableValues)) {
this.refreshSelf();
return true;
+2 -2
View File
@@ -189,7 +189,7 @@ Widget.prototype.getVariableInfo = function(name,options) {
}
return {
text: text,
resultList: [text]
resultList: text === undefined ? text : [text]
};
};
@@ -338,7 +338,7 @@ Widget.prototype.makeFakeWidgetWithVariables = function(vars = {}) {
const value = vars[name];
return Array.isArray(value)
? { text: value[0], resultList: value }
: { text: value, resultList: [value] };
: { text: value, resultList: value === undefined ? value : [value] };
}
opts = opts || {};
opts.variables = Object.assign({}, vars, opts.variables || {});
+4 -40
View File
@@ -9,6 +9,7 @@ Bulk tiddler operations such as rename.
"use strict";
var relinkers = $tw.modules.getModulesByTypeAsHashmap("relinker");
/*
Rename a tiddler, and relink any tags or lists that reference it.
*/
@@ -32,50 +33,13 @@ function renameTiddler(fromTitle,toTitle,options) {
Relink any tags or lists that reference a given tiddler
*/
function relinkTiddler(fromTitle,toTitle,options) {
var self = this;
fromTitle = (fromTitle || "").trim();
toTitle = (toTitle || "").trim();
options = options || {};
if(fromTitle && toTitle && fromTitle !== toTitle) {
this.each(function(tiddler,title) {
var type = tiddler.fields.type || "";
// Don't touch plugins or JavaScript modules
if(!tiddler.fields["plugin-type"] && type !== "application/javascript") {
var tags = tiddler.fields.tags ? tiddler.fields.tags.slice(0) : undefined,
list = tiddler.fields.list ? tiddler.fields.list.slice(0) : undefined,
isModified = false,
processList = function(listField) {
if(listField && listField.indexOf(fromTitle) !== -1) {
// Remove any existing instances of the toTitle
var p = listField.indexOf(toTitle);
while(p !== -1) {
listField.splice(p,1);
p = listField.indexOf(toTitle);
}
// Replace the fromTitle with toTitle
$tw.utils.each(listField,function (title,index) {
if(title === fromTitle) {
listField[index] = toTitle;
isModified = true;
}
});
}
};
if(!options.dontRenameInTags) {
// Rename tags
processList(tags);
}
if(!options.dontRenameInLists) {
// Rename lists
processList(list);
}
if(isModified) {
var newTiddler = new $tw.Tiddler(tiddler,{tags: tags, list: list},self.getModificationFields());
newTiddler = $tw.hooks.invokeHook("th-relinking-tiddler",newTiddler,tiddler);
self.addTiddler(newTiddler);
}
}
});
for(var name in relinkers) {
relinkers[name].relink(this,fromTitle,toTitle,options);
}
}
};
+37 -10
View File
@@ -369,16 +369,31 @@ Sort an array of tiddler titles by a specified field
isDescending: true if the sort should be descending
isCaseSensitive: true if the sort should consider upper and lower case letters to be different
*/
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric,locale) {
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) {
var self = this;
if(sortField === "title") {
if(!isNumeric && !isAlphaNumeric) {
const sorter = new Intl.Collator(locale, { sensitivity: isCaseSensitive ? "variant" : "accent" });
if(isDescending) {
titles.sort((a,b) => sorter.compare(b, a));
if(isCaseSensitive) {
if(isDescending) {
titles.sort(function(a,b) {
return b.localeCompare(a);
});
} else {
titles.sort(function(a,b) {
return a.localeCompare(b);
});
}
} else {
titles.sort((a,b) => sorter.compare(a, b));
}
if(isDescending) {
titles.sort(function(a,b) {
return b.toLowerCase().localeCompare(a.toLowerCase());
});
} else {
titles.sort(function(a,b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
}
}
} else {
titles.sort(function(a,b) {
var x,y;
@@ -399,8 +414,14 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
}
}
}
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
if(isAlphaNumeric) {
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
}
if(!isCaseSensitive) {
a = a.toLowerCase();
b = b.toLowerCase();
}
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
});
}
} else {
@@ -442,8 +463,14 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,is
}
a = String(a);
b = String(b);
const sorter = new Intl.Collator(locale, { numeric: isAlphaNumeric, sensitivity: isAlphaNumeric ? "base" : isCaseSensitive ? "variant" : "accent" });
return isDescending ? sorter.compare(b, a) : sorter.compare(a, b);
if(isAlphaNumeric) {
return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"});
}
if(!isCaseSensitive) {
a = a.toLowerCase();
b = b.toLowerCase();
}
return isDescending ? b.localeCompare(a) : a.localeCompare(b);
});
}
};
+10
View File
@@ -0,0 +1,10 @@
title: $:/palettes/AutoToggle
name: AutoToggle
description: Automatically switch between dark and light modes
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: [{$:/info/browser/darkmode}!match[yes]then[light]else[dark]]
settings: $:/palettes/AutoToggle/Settings
palette-import@light: $:/palettes/TwentyTwenties
palette-import@dark: $:/palettes/TwentyTwentiesDark
category: 2026
+19
View File
@@ -0,0 +1,19 @@
title: $:/palettes/AutoToggle/Settings
\procedure set-imported-palette(field)
<$select field=<<field>>>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Palette]sort[name]] -[<currentTiddler>]">
<option value=<<currentTiddler>>><$view field="name"><$view field="title"/></$view></option>
</$list>
</$select>
\end set-imported-palette
This palette can be used to automatically switch between two palettes based on the browser's dark mode setting.
<$tiddler tiddler={{$:/palette}}>
Light palette: <<set-imported-palette field:"palette-import@light">>
Dark palette: <<set-imported-palette field:"palette-import@dark">>
</$tiddler>
+226
View File
@@ -0,0 +1,226 @@
title: $:/palettes/TwentyTwenties
name: TwentyTwenties
description: Modern and flexible
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
settings: $:/palettes/TwentyTwenties/Settings
palette-import: $:/palettes/Vanilla
category: 2026
# Background and foreground colours, which are interpolated as required
base-paper: #FFFCF0
base-background: #edcec1
base-ink: #333344
?base-paper-ink: [tf.check-colour-contrast[base-paper],[base-ink],[45]]
?base-background-ink: [tf.check-colour-contrast[base-background],[base-ink],[45]]
# Primary colour, used for links and other accented elements
base-primary: #5778d8
?base-paper-primary: [tf.check-colour-contrast[base-paper],[base-primary],[45]]
?base-background-primary: [tf.check-colour-contrast[base-background],[base-primary],[45]]
# Secondary colour, used for alerts and other secondary elements
base-secondary: #f0e48a
?base-ink-secondary: [tf.check-colour-contrast[base-ink],[base-secondary],[45]]
# Tertiary base colour, used for monospaced text and other tertiary elements
base-tertiary: rgb(183, 95, 95)
?base-paper-tertiary: [tf.check-colour-contrast[base-paper],[base-tertiary],[45]]
# Basic spectrum colours
base-black: #100F0F
base-red: #D14D41
base-orange: #DA702C
base-yellow: #D0A215
base-green: #879A39
base-cyan: #3AA99F
base-blue: #4385BE
base-purple: #8B7EC8
base-magenta: #CE5D97
base-white: #FFFCF0
# Darker variants
# base-red: #AF3029
# base-orange: #BC5215
# base-yellow: #AD8301
# base-green: #66800B
# base-cyan: #24837B
# base-blue: #205EA6
# base-purple: #5E409D
# base-magenta: #A02F6F
# Palette definitions
alert-background: [tf.colour[base-secondary]]
alert-border: [tf.interpolate-colours[base-ink],[alert-background],[0.6]]
alert-highlight: [tf.interpolate-colours[base-ink],[base-primary],[0.3]]
alert-muted-foreground: [tf.interpolate-colours[base-ink],[alert-background],[0.4]]
background: [tf.colour[base-paper]]
blockquote-bar: [tf.colour[muted-foreground]]
button-background:
button-border:
button-foreground:
code-background: [tf.interpolate-colours[base-paper],[base-tertiary],[0.1]]
code-border: [tf.interpolate-colours[base-paper],[base-tertiary],[0.6]]
code-foreground: [tf.colour[base-tertiary]]
diff-delete-background: [tf.colour[base-red]]
diff-delete-foreground: [tf.colour[foreground]]
diff-equal-background:
diff-equal-foreground: [tf.colour[foreground]]
diff-insert-background: [tf.colour[base-green]]
diff-insert-foreground: [tf.colour[foreground]]
diff-invisible-background:
diff-invisible-foreground: [tf.colour[muted-foreground]]
dirty-indicator: [tf.colour[base-tertiary]]
download-background: [tf.interpolate-colours[base-paper],[base-green],[0.6]]
download-foreground: [tf.interpolate-colours[base-ink],[base-green],[0.1]]
dragger-background: [tf.colour[foreground]]
dragger-foreground: [tf.colour[background]]
dropdown-background: [tf.colour[background]]
dropdown-border: [tf.colour[muted-foreground]]
dropdown-tab-background-selected: [tf.colour[background]]
dropdown-tab-background: [tf.interpolate-colours[base-paper],[base-ink],[0.9]]
dropzone-background: [tf.colour[base-secondary]colour-set-alpha[0.7]]
external-link-background-hover: inherit
external-link-background-visited: inherit
external-link-background: inherit
external-link-foreground-hover: inherit
external-link-foreground-visited: [tf.colour[primary]]
external-link-foreground: [tf.colour[primary]]
footnote-target-background: [tf.interpolate-colours[base-paper],[base-ink],[0.2]]
foreground: [tf.colour[base-ink]]
highlight-background: [tf.interpolate-colours[base-paper],[base-yellow],[0.5]]
highlight-foreground: [tf.interpolate-colours[base-yellow],[base-ink],[0.8]]
menubar-background: #5778d8
menubar-foreground: #fff
message-background: [tf.interpolate-colours[base-paper],[base-blue],[0.2]]
message-border: [tf.interpolate-colours[base-blue],[base-ink],[0.5]]
message-foreground: [tf.interpolate-colours[base-blue],[base-ink],[0.8]]
modal-backdrop: [tf.colour[foreground]]
modal-background: [tf.colour[background]]
modal-border: #999999
modal-footer-background: #f5f5f5
modal-footer-border: #dddddd
modal-header-border: #eeeeee
muted-foreground: [tf.interpolate-colours[base-paper],[base-ink],[0.3]]
network-activity-foreground: #448844
notification-background: [tf.colour[base-tertiary]colour-set-oklch:l[0.9]]
notification-border: [tf.colour[base-tertiary]colour-set-oklch:l[0.2]]
page-background: [tf.colour[base-background]]
pre-background: [tf.interpolate-colours[base-paper],[base-tertiary],[0.1]]
pre-border: [tf.interpolate-colours[base-paper],[base-tertiary],[0.6]]
primary: [tf.colour[base-primary]]
select-tag-background:
select-tag-foreground:
selection-background:
selection-foreground:
sidebar-button-foreground: [tf.colour[sidebar-controls-foreground]]
sidebar-controls-foreground-hover: [tf.interpolate-colours[base-ink],[base-background],[0.2]]
sidebar-controls-foreground: [tf.interpolate-colours[base-ink],[base-background],[0.8]]
sidebar-foreground-shadow: inherit
sidebar-foreground: =[tf.colour[base-ink]] =[tf.colour[base-paper]] =[tf.colour[base-background]] +[colour-best-contrast:DeltaPhi[]]
sidebar-muted-foreground-hover: [tf.colour[sidebar-muted-foreground]colour-set-oklch:l[0.3]]
sidebar-muted-foreground: [tf.interpolate-colours[foreground],[page-background],[0.6]]
sidebar-tab-background-selected: [tf.colour[tab-background-selected]]
sidebar-tab-background: [tf.colour[tab-background]]
sidebar-tab-border-selected: [tf.colour[tab-border-selected]]
sidebar-tab-border: [tf.colour[tab-border]]
sidebar-tab-divider: [tf.colour[tab-divider]]
sidebar-tab-foreground-selected: [tf.colour[tab-foreground-selected]]
sidebar-tab-foreground: [tf.colour[tab-foreground]]
sidebar-tiddler-link-foreground-hover: [tf.colour[sidebar-tiddler-link-foreground]colour-set-oklch:l[0.5]]
sidebar-tiddler-link-foreground: =[tf.colour[base-primary]] =[tf.colour[base-secondary]] =[tf.colour[base-tertiary]] =[tf.colour[base-background]] +[colour-best-contrast:DeltaPhi[]]
site-title-foreground: [tf.colour[tiddler-title-foreground]]
stability-deprecated: #ff0000
stability-experimental: #c07c00
stability-legacy: #0000ff
stability-stable: #008000
static-alert-foreground: #aaaaaa
tab-background-selected: [tf.colour[background]]
tab-background: [tf.interpolate-colours[base-paper],[base-ink],[0.2]]
tab-border-selected: [tf.colour[muted-foreground]]
tab-border: [tf.colour[muted-foreground]]
tab-divider: [tf.colour[muted-foreground]]
tab-foreground-selected: [tf.colour[tab-foreground]]
tab-foreground: [tf.colour[foreground]]
table-border: [tf.colour[foreground]]
table-footer-background: [tf.interpolate-colours[background],[foreground],[0.2]]
table-header-background: [tf.interpolate-colours[background],[foreground],[0.1]]
tag-background: [tf.interpolate-colours[base-paper],[base-yellow],[0.9]]
tag-foreground: [tf.interpolate-colours[base-yellow],[base-ink],[0.8]]
testcase-accent-level-1: #c1eaff
testcase-accent-level-2: #E3B740
testcase-accent-level-3: #5FD564
tiddler-background: [tf.colour[background]]
tiddler-border: [tf.interpolate-colours[base-paper],[base-background],[0.5]]
tiddler-controls-foreground-hover: [tf.interpolate-colours[background],[foreground],[0.7]]
tiddler-controls-foreground-selected: [tf.interpolate-colours[background],[foreground],[0.9]]
tiddler-controls-foreground: [tf.interpolate-colours[background],[foreground],[0.5]]
tiddler-editor-background: #f8f8f8
tiddler-editor-border-image: #ffffff
tiddler-editor-border: #cccccc
tiddler-editor-fields-even: #e0e8e0
tiddler-editor-fields-odd: #f0f4f0
tiddler-info-background: #f8f8f8
tiddler-info-border: #dddddd
tiddler-info-tab-background: #f8f8f8
tiddler-link-background: [tf.colour[background]]
tiddler-link-foreground: [tf.colour[primary]]
tiddler-subtitle-foreground: [tf.interpolate-colours[background],[foreground],[0.6]]
tiddler-title-foreground: [tf.interpolate-colours[background],[foreground],[0.9]]
toolbar-cancel-button:
toolbar-close-button:
toolbar-delete-button:
toolbar-done-button:
toolbar-edit-button:
toolbar-info-button:
toolbar-new-button:
toolbar-options-button:
toolbar-save-button:
tour-chooser-button-foreground: <<colour very-muted-foreground>>
tour-chooser-button-hover-background: <<colour muted-foreground>>
tour-chooser-button-hover-foreground: : <<colour background>>
tour-chooser-button-selected-background: <<colour primary>>
tour-chooser-button-selected-foreground: <<colour background>>
tour-chooser-dropdown-foreground: <<colour very-muted-foreground>>
tour-chooser-item-background: <<colour background>>
tour-chooser-item-border: <<colour muted-foreground>>
tour-chooser-item-foreground: <<colour foreground>>
tour-chooser-item-shadow: <<colour muted-foreground>>
tour-chooser-item-start-background: <<colour download-background>>
tour-chooser-item-start-foreground: <<colour background>>
tour-chooser-item-start-hover-background: <<colour primary>>
tour-chooser-item-start-hover-foreground: <<colour background>>
tour-fullscreen-background: <<colour page-background>>
tour-fullscreen-controls-foreground: <<colour muted-foreground>>
tour-navigation-buttons-back-background: red
tour-navigation-buttons-back-foreground: white
tour-navigation-buttons-hint-background: purple
tour-navigation-buttons-hint-foreground: white
tour-navigation-buttons-hover-background: <<colour foreground>>
tour-navigation-buttons-hover-foreground: <<colour background>>
tour-navigation-buttons-next-background: purple
tour-navigation-buttons-next-foreground: white
tour-overlay-background: #cbfff8
tour-overlay-border: #228877
tour-step-heading-background: none
tour-step-task-background: <<colour download-background>>
tour-step-task-foreground: <<colour download-foreground>>
untagged-background: #999999
very-muted-foreground: #888888
wikilist-background: #e5e5e5
wikilist-button-background: #acacac
wikilist-button-foreground: #000000
wikilist-button-open-hover: green
wikilist-button-open: #4fb82b
wikilist-button-remove-hover: red
wikilist-button-remove: #d85778
wikilist-button-reveal-hover: blue
wikilist-button-reveal: #5778d8
wikilist-droplink-dragover: [tf.colour[base-secondary]colour-set-alpha[0.7]]
wikilist-info: #000000
wikilist-item: #ffffff
wikilist-title-svg: [tf.colour[wikilist-title]]
wikilist-title: #666666
wikilist-toolbar-background: #d3d3d3
wikilist-toolbar-foreground: #888888
wikilist-url: #aaaaaa
+12
View File
@@ -0,0 +1,12 @@
title: $:/palettes/TwentyTwenties/Dark
name: TwentyTwenties Dark
description: Modern and flexible, Darkish
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: dark
palette-import: $:/palettes/TwentyTwenties
category: 2026
base-paper: #111122
base-background: #f5f0f9
base-ink: #8C8F80
+12
View File
@@ -0,0 +1,12 @@
title: $:/palettes/TwentyTwenties/Green
name: TwentyTwenties (Green)
description: Modern and flexible, Greenish
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
palette-import: $:/palettes/TwentyTwenties
category: 2026
base-paper: rgb(188, 255, 161)
base-background: rgb(94, 192, 145)
base-primary: #6e803c
+13
View File
@@ -0,0 +1,13 @@
title: $:/palettes/TwentyTwenties/GreenP3
name: TwentyTwenties (Green P3)
description: Modern and flexible, Greenish and super bright
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
palette-import: $:/palettes/TwentyTwenties
category: 2026
base-paper: color(display-p3 0.281 1 0.584 / 1)
base-background: color(display-p3 1 1 0 / 1)
base-primary: color(display-p3 1 0.563 1 / 1)
+17
View File
@@ -0,0 +1,17 @@
title: $:/palettes/TwentyTwenties/Settings
\procedure entry(name,description)
<$text text=<<description>>/>: <$edit-text tiddler={{$:/palette}} index=<<name>> type="color" tag="input" default={{{ [function[colour],<name>] }}}/>
\end entry
<<entry name:"base-paper" description:"Paper">>
<<entry name:"base-background" description:"Page background">>
<<entry name:"base-ink" description:"Ink">>
<<entry name:"base-primary" description:"Primary">>
<<entry name:"base-secondary" description:"Secondary">>
<<entry name:"base-tertiary" description:"Tertiary">>
+12
View File
@@ -0,0 +1,12 @@
title: $:/palettes/VanillaCherry
name: Vanilla Cherry
category: 2026
description: Pale and unobtrusive with a cherry on top
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
color-scheme: light
palette-import: $:/palettes/Vanilla
primary:rgb(224, 32, 86);
menubar-foreground: #fff
menubar-background: <<colour primary>>
@@ -0,0 +1,7 @@
title: $:/palettes/background/contrast-tests
type: application/x-tiddler-dictionary
tags: $:/tags/BackgroundPalette
?background-foreground-contrast: [tf.check-colour-contrast[background],[foreground],[45]]
?alert-contrast: [tf.check-colour-contrast[alert-background],[foreground],[45]]
?code-contrast: [tf.check-colour-contrast[code-background],[code-foreground],[45]]
+1 -1
View File
@@ -6,5 +6,5 @@ caption: {{$:/language/ControlPanel/Appearance/Caption}}
{{$:/language/ControlPanel/Appearance/Hint}}
<div class="tc-control-panel">
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]" default="$:/core/ui/ControlPanel/Theme" explicitState="$:/state/tab--1963855381"/>
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Appearance]!has[draft.of]]" default="$:/core/ui/ControlPanel/Palette" explicitState="$:/state/tab--1963855381"/>
</div>
+1 -17
View File
@@ -2,20 +2,4 @@ title: $:/core/ui/ControlPanel/Palette
tags: $:/tags/ControlPanel/Appearance
caption: {{$:/language/ControlPanel/Palette/Caption}}
\define lingo-base() $:/language/ControlPanel/Palette/
{{$:/snippets/paletteswitcher}}
<$reveal type="nomatch" state="$:/state/ShowPaletteEditor" text="yes">
<$button set="$:/state/ShowPaletteEditor" setTo="yes"><<lingo ShowEditor/Caption>></$button>
</$reveal>
<$reveal type="match" state="$:/state/ShowPaletteEditor" text="yes">
<$button set="$:/state/ShowPaletteEditor" setTo="no"><<lingo HideEditor/Caption>></$button>
{{$:/PaletteManager}}
</$reveal>
{{$:/PaletteManager}}
@@ -1,5 +1,7 @@
title: $:/core/ui/EditTemplate/body/toolbar/button
\whitespace trim
\define toolbar-button-icon()
<$list
+4 -3
View File
@@ -17,11 +17,13 @@ tags: $:/tags/EditTemplate
<$let backgroundColor=<<colour>> >
<span class="tc-tag-label tc-tag-list-item tc-small-gap-right"
data-tag-title=<<currentTiddler>>
style=`color:$(foregroundColor)$; background-color:$(backgroundColor)$; --tp-remove-tag-button-color:$(foregroundColor)$`
style=`color:$(foregroundColor)$; fill:$(foregroundColor)$; background-color:$(backgroundColor)$;`
>
<$transclude tiddler=<<icon>>/>
<$view field="title" format="text"/>
<$button class="tc-btn-invisible tc-remove-tag-button">
<$button class="tc-btn-invisible tc-remove-tag-button"
style.fill=<<foregroundColor>>
>
<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter="-[{!!title}]"/>
{{$:/core/images/close-button}}
</$button>
@@ -46,7 +48,6 @@ tags: $:/tags/EditTemplate
<$list filter="[<currentTiddler>get<tagField>enlist-input[]sort[title]]" storyview="pop">
<$macrocall $name="tag-body"
colour={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}
palette={{$:/palette}}
icon={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}}
tagField=<<tagField>>
/>
+94
View File
@@ -0,0 +1,94 @@
title: $:/PaletteEditor
\define lingo-base() $:/language/ControlPanel/Palette/Editor/
\define describePaletteColour(colour)
<$transclude tiddler="$:/language/Docs/PaletteColours/$colour$"><$text text="$colour$"/></$transclude>
\end
\define edit-colour-placeholder()
edit $(colourName)$
\end
\define colour-tooltip(showhide) $showhide$ editor for $(newColourName)$
\define resolve-colour(macrocall)
\import $:/core/macros/utils
\whitespace trim
<$wikify name="name" text="""$macrocall$""">
<<name>>
</$wikify>
\end
\define delete-colour-index-actions() <$action-setfield $index=<<colourName>>/>
\define palette-manager-colour-row-segment()
\whitespace trim
<$edit-text index=<<colourName>> tag="input" placeholder=<<edit-colour-placeholder>> default=""/>
<br>
<$edit-text index=<<colourName>> type="color" tag="input" class="tc-palette-manager-colour-input"/>
<$list filter="[<currentTiddler>getindex<colourName>removeprefix[<<]removesuffix[>>]] [<currentTiddler>getindex<colourName>removeprefix[<$]removesuffix[/>]]" variable="ignore">
<$set name="state" value={{{ [[$:/state/palettemanager/]addsuffix<currentTiddler>addsuffix[/]addsuffix<colourName>] }}}>
<$wikify name="newColourName" text="""<$macrocall $name="resolve-colour" macrocall={{{ [<currentTiddler>getindex<colourName>] }}}/>""">
<$reveal state=<<state>> type="nomatch" text="show">
<$button tooltip=<<colour-tooltip show>> aria-label=<<colour-tooltip show>> class="tc-btn-invisible" set=<<state>> setTo="show">{{$:/core/images/down-arrow}}<$text text=<<newColourName>> class="tc-small-gap-left"/></$button><br>
</$reveal>
<$reveal state=<<state>> type="match" text="show">
<$button tooltip=<<colour-tooltip hide>> aria-label=<<colour-tooltip show>> class="tc-btn-invisible" actions="""<$action-deletetiddler $tiddler=<<state>>/>""">{{$:/core/images/up-arrow}}<$text text=<<newColourName>> class="tc-small-gap-left"/></$button><br>
</$reveal>
<$reveal state=<<state>> type="match" text="show">
<$set name="colourName" value=<<newColourName>>>
<br>
<<palette-manager-colour-row-segment>>
<br><br>
</$set>
</$reveal>
</$wikify>
</$set>
</$list>
\end
\define palette-manager-colour-row()
\whitespace trim
<tr>
<td>
<span style="float:right;">
<$button tooltip={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} aria-label={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} class="tc-btn-invisible" actions=<<delete-colour-index-actions>>>
{{$:/core/images/delete-button}}</$button>
</span>
''<$macrocall $name="describePaletteColour" colour=<<colourName>>/>''<br/>
<$macrocall $name="colourName" $output="text/plain"/>
</td>
<td>
<<palette-manager-colour-row-segment>>
</td>
</tr>
\end
\define palette-manager-table()
\whitespace trim
<table>
<tbody>
<$set name="colorList" filter="[{$:/state/palettemanager/showexternal}match[yes]]"
value="[all[shadows+tiddlers]tag[$:/tags/Palette]indexes[]]" emptyValue="[<currentTiddler>indexes[]]">
<$list filter=<<colorList>> variable="colourName"> <<palette-manager-colour-row>> </$list>
</$set>
</tbody>
</table>
\end
\whitespace trim
<$set name="currentTiddler" value={{$:/palette}}>
<<lingo Prompt>>&#32;<$link to={{$:/palette}}><$macrocall $name="currentTiddler" $output="text/plain"/></$link>
<$list filter="[all[current]is[shadow]is[tiddler]]" variable="listItem">
<<lingo Prompt/Modified>>
&#32;
<$button message="tm-delete-tiddler" param={{$:/palette}}><<lingo Reset/Caption>></$button>
</$list>
<$list filter="[all[current]is[shadow]!is[tiddler]]" variable="listItem">
<<lingo Clone/Prompt>>
</$list>
<$button message="tm-new-tiddler" param={{$:/palette}}><<lingo Clone/Caption>></$button>
<$checkbox tiddler="$:/state/palettemanager/showexternal" field="text" checked="yes" unchecked="no"><span class="tc-small-gap-left"><<lingo Names/External/Show>></span></$checkbox>
<<palette-manager-table>>
+36 -87
View File
@@ -1,94 +1,43 @@
title: $:/PaletteManager
\define lingo-base() $:/language/ControlPanel/Palette/Editor/
\define describePaletteColour(colour)
<$transclude tiddler="$:/language/Docs/PaletteColours/$colour$"><$text text="$colour$"/></$transclude>
\end
\define edit-colour-placeholder()
edit $(colourName)$
\end
\define colour-tooltip(showhide) $showhide$ editor for $(newColourName)$
\define lingo-base() $:/language/ControlPanel/Palette/
\define resolve-colour(macrocall)
\import $:/core/macros/utils
\whitespace trim
<$wikify name="name" text="""$macrocall$""">
<<name>>
</$wikify>
\end
<!-- Used by the language string CustomSettings/Prompt -->
\procedure palette-link()
<$tiddler tiddler={{$:/palette}}>
<$link to={{!!title}}>
<$view field="name" format="text">
<$view field="title" format="text"/>
</$view>
</$link>
</$tiddler>
\end palette-link
<$transclude $tiddler="$:/snippets/paletteswitcher" thumbnails="yes"/>
{{$:/snippets/palettetests}}
<$let
paletteSettings={{{ [[$:/temp/palette-consolidated]get[settings]] }}}
>
<%if [<paletteSettings>!match[]] %>
<div>
<<lingo CustomSettings/Prompt>>
<$transclude $tiddler=<<paletteSettings>> $mode="block"/>
</div>
<%endif%>
</$let>
<$reveal type="nomatch" state="$:/state/ShowPaletteEditor" text="yes">
<$button set="$:/state/ShowPaletteEditor" setTo="yes"><<lingo ShowEditor/Caption>></$button>
\define delete-colour-index-actions() <$action-setfield $index=<<colourName>>/>
\define palette-manager-colour-row-segment()
\whitespace trim
<$edit-text index=<<colourName>> tag="input" placeholder=<<edit-colour-placeholder>> default=""/>
<br>
<$edit-text index=<<colourName>> type="color" tag="input" class="tc-palette-manager-colour-input"/>
<$list filter="[<currentTiddler>getindex<colourName>removeprefix[<<]removesuffix[>>]] [<currentTiddler>getindex<colourName>removeprefix[<$]removesuffix[/>]]" variable="ignore">
<$set name="state" value={{{ [[$:/state/palettemanager/]addsuffix<currentTiddler>addsuffix[/]addsuffix<colourName>] }}}>
<$wikify name="newColourName" text="""<$macrocall $name="resolve-colour" macrocall={{{ [<currentTiddler>getindex<colourName>] }}}/>""">
<$reveal state=<<state>> type="nomatch" text="show">
<$button tooltip=<<colour-tooltip show>> aria-label=<<colour-tooltip show>> class="tc-btn-invisible" set=<<state>> setTo="show">{{$:/core/images/down-arrow}}<$text text=<<newColourName>> class="tc-small-gap-left"/></$button><br>
</$reveal>
<$reveal state=<<state>> type="match" text="show">
<$button tooltip=<<colour-tooltip hide>> aria-label=<<colour-tooltip show>> class="tc-btn-invisible" actions="""<$action-deletetiddler $tiddler=<<state>>/>""">{{$:/core/images/up-arrow}}<$text text=<<newColourName>> class="tc-small-gap-left"/></$button><br>
<$reveal type="match" state="$:/state/ShowPaletteEditor" text="yes">
<$button set="$:/state/ShowPaletteEditor" setTo="no"><<lingo HideEditor/Caption>></$button>
{{$:/PaletteEditor}}
</$reveal>
<$reveal state=<<state>> type="match" text="show">
<$set name="colourName" value=<<newColourName>>>
<br>
<<palette-manager-colour-row-segment>>
<br><br>
</$set>
</$reveal>
</$wikify>
</$set>
</$list>
\end
\define palette-manager-colour-row()
\whitespace trim
<tr>
<td>
<span style="float:right;">
<$button tooltip={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} aria-label={{$:/language/ControlPanel/Palette/Editor/Delete/Hint}} class="tc-btn-invisible" actions=<<delete-colour-index-actions>>>
{{$:/core/images/delete-button}}</$button>
</span>
''<$macrocall $name="describePaletteColour" colour=<<colourName>>/>''<br/>
<$macrocall $name="colourName" $output="text/plain"/>
</td>
<td>
<<palette-manager-colour-row-segment>>
</td>
</tr>
\end
\define palette-manager-table()
\whitespace trim
<table>
<tbody>
<$set name="colorList" filter="[{$:/state/palettemanager/showexternal}match[yes]]"
value="[all[shadows+tiddlers]tag[$:/tags/Palette]indexes[]]" emptyValue="[<currentTiddler>indexes[]]">
<$list filter=<<colorList>> variable="colourName"> <<palette-manager-colour-row>> </$list>
</$set>
</tbody>
</table>
\end
\whitespace trim
<$set name="currentTiddler" value={{$:/palette}}>
<<lingo Prompt>>&#32;<$link to={{$:/palette}}><$macrocall $name="currentTiddler" $output="text/plain"/></$link>
<$list filter="[all[current]is[shadow]is[tiddler]]" variable="listItem">
<<lingo Prompt/Modified>>
&#32;
<$button message="tm-delete-tiddler" param={{$:/palette}}><<lingo Reset/Caption>></$button>
</$list>
<$list filter="[all[current]is[shadow]!is[tiddler]]" variable="listItem">
<<lingo Clone/Prompt>>
</$list>
<$button message="tm-new-tiddler" param={{$:/palette}}><<lingo Clone/Caption>></$button>
<$checkbox tiddler="$:/state/palettemanager/showexternal" field="text" checked="yes" unchecked="no"><span class="tc-small-gap-left"><<lingo Names/External/Show>></span></$checkbox>
<<palette-manager-table>>
+19
View File
@@ -0,0 +1,19 @@
title: $:/core/ui/Palettes/Preview/Alert
tags: $:/tags/Preview/Page
\whitespace trim
<div class="tc-palette-preview-thumbnail-alert" style.background-color=<<colour alert-background>>>
<div class="tc-palette-preview-thumbnail-alert-border" style.border-color=<<colour alert-border>>>
<div style.color=<<colour foreground>>>
<div class="tc-palette-preview-thumbnail-alert-subtitle" style.color=<<colour alert-muted-foreground>>>
Lorem Ipsum
<div class="tc-palette-preview-thumbnail-alert-highlight" style.color=<<colour alert-highlight>>>
(Count: 1)
</div>
</div>
<div class="tc-palette-preview-thumbnail-alert-body">
Lorem Ipsum Dolor Sit Amet Consectetur Adipiscing Elit Sed Do Eiusmod Tempor Incididunt.
</div>
</div>
</div>
</div>
+55
View File
@@ -0,0 +1,55 @@
title: $:/core/ui/Palettes/Preview/Helpers
tags: $:/tags/Preview/Helpers
\whitespace trim
\procedure palette-preview-component-list(tag)
<$list filter="[all[shadows+tiddlers]tag<tag>!has[draft.of]]" variable="componentTitle">
<$transclude $tiddler=<<componentTitle>> title=<<title>>/>
</$list>
\end palette-preview-component-list
\procedure tab-set(tabTitles,colourPrefix:"")
<div class="tc-palette-preview-thumbnail-tab-set">
<div class="tc-palette-preview-thumbnail-tab-buttons">
<$list filter="[enlist<tabTitles>]" variable="tabTitle" counter="tabIndex">
<%if [<tabIndex>match[1]] %>
<span
class="tc-palette-preview-thumbnail-tab-button"
style.border-color={{{ [<colourPrefix>addsuffix[tab-border-selected]] :map[function[colour],<currentTiddler>] }}}
style.color={{{ [<colourPrefix>addsuffix[tab-foreground-selected]] :map[function[colour],<currentTiddler>] }}}
style.background-color={{{ [<colourPrefix>addsuffix[tab-background-selected]] :map[function[colour],<currentTiddler>] }}}
>
<$text text=<<tabTitle>>/>
</span>
<%else%>
<span
class="tc-palette-preview-thumbnail-tab-button"
style.border-color={{{ [<colourPrefix>addsuffix[tab-border]] :map[function[colour],<currentTiddler>] }}}
style.color={{{ [<colourPrefix>addsuffix[tab-foreground]] :map[function[colour],<currentTiddler>] }}}
style.background-color={{{ [<colourPrefix>addsuffix[tab-background]] :map[function[colour],<currentTiddler>] }}}
>
<$text text=<<tabTitle>>/>
</span>
<%endif%>
</$list>
</div>
<div
class="tc-palette-preview-thumbnail-tab-divider"
style.border-color={{{ [<colourPrefix>addsuffix[tab-divider]] :map[function[colour],<currentTiddler>] }}}
>
</div>
</div>
\end tab-set
\procedure link(text)
<span class="tc-palette-preview-thumbnail-tiddler-link" style.color=<<colour primary>>>
<$text text=<<text>>/>
</span>
\end link
\procedure sidebar-link(text)
<span class="tc-palette-preview-thumbnail-tiddler-link" style.color=<<colour sidebar-tiddler-link-foreground>>>
<$text text=<<text>>/>
</span>
\end sidebar-link
+11
View File
@@ -0,0 +1,11 @@
title: $:/core/ui/Palettes/Preview/Notification
tags: $:/tags/Preview/PageOptional
\whitespace trim
<div class="tc-palette-preview-thumbnail-notification" style.background-color=<<colour notification-background>>>
<div class="tc-palette-preview-thumbnail-notification-border" style.border-color=<<colour notification-border>>>
<div class="tc-palette-preview-thumbnail-notification-body" style.color=<<colour foreground>>>
Lorem Ipsum Dolor Sit Amet Consectetur
</div>
</div>
</div>
@@ -0,0 +1,8 @@
title: $:/core/ui/Palettes/Preview/Sidebar/Search
tags: $:/tags/Preview/SideBar
\whitespace trim
<div class="tc-palette-preview-thumbnail-sidebar-search" style.background-color=<<colour background>>>
<div class="tc-palette-preview-thumbnail-sidebar-search-box">
</div>
</div>
@@ -0,0 +1,7 @@
title: $:/core/ui/Palettes/Preview/Sidebar/Subtitle
tags: $:/tags/Preview/SideBar
\whitespace trim
<div class="tc-palette-preview-thumbnail-sidebar-subtitle">
a non-linear personal web notebook
</div>
+18
View File
@@ -0,0 +1,18 @@
title: $:/core/ui/Palettes/Preview/Sidebar/Tabs
tags: $:/tags/Preview/SideBar
\whitespace trim
\procedure recent-links()
HelloThere Community Portal GettingStarted Development Download Filters Palettes Plugins Macros Templates Themes Stylesheets SystemTiddlers
\end recent-links
<<tab-set "Magna Placerat Ligula Imperdiet" "sidebar-">>
<div class="tc-palette-preview-thumbnail-sidebar-list">
<$list filter="[enlist<recent-links>]">
<div>
<$transclude $variable="sidebar-link" text=<<currentTiddler>>/>
</div>
</$list>
</div>
@@ -0,0 +1,7 @@
title: $:/core/ui/Palettes/Preview/Sidebar/Title
tags: $:/tags/Preview/SideBar
\whitespace trim
<div class="tc-palette-preview-thumbnail-sidebar-title" style.color=<<colour site-title-foreground>>>
~TiddlyWiki
</div>
+7
View File
@@ -0,0 +1,7 @@
title: $:/core/ui/Palettes/Preview/SideBar
tags: $:/tags/Preview/Page
\whitespace trim
<div class="tc-palette-preview-thumbnail-sidebar" style.color=<<colour sidebar-foreground>>>
<<palette-preview-component-list "$:/tags/Preview/SideBar">>
</div>
+9
View File
@@ -0,0 +1,9 @@
title: $:/core/ui/Palettes/Preview/Story
tags: $:/tags/Preview/Page
\whitespace trim
<div class="tc-palette-preview-thumbnail-story">
<$list filter="HelloThere GettingStarted" variable="title">
<<palette-preview-component-list "$:/tags/Preview/Story">>
</$list>
</div>
+10
View File
@@ -0,0 +1,10 @@
title: $:/core/ui/Palettes/Preview/Tiddler
tags: $:/tags/Preview/Story
\parameters (title)
\whitespace trim
<div class="tc-palette-preview-thumbnail-tiddler-border" style.border-color=<<colour tiddler-border>>>
<div class="tc-palette-preview-thumbnail-tiddler" style.background-color=<<colour tiddler-background>>>
<<palette-preview-component-list "$:/tags/Preview/Tiddler">>
</div>
</div>
+15
View File
@@ -0,0 +1,15 @@
title: $:/core/ui/Palettes/Preview/Tiddler/Body
tags: $:/tags/Preview/Tiddler
\whitespace trim
<div class="tc-palette-preview-thumbnail-tiddler-body" style.color=<<colour foreground>>>
<%if [<title>match[HelloThere]] %>
Lorem ipsum dolor sit amet, <<link "consectetur adipiscing elit">>. Cras non arcu ultricies, egestas odio tempus, vestibulum ipsum. Praesent diam lorem, elementum in venenatis eget, tincidunt quis lacus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam efficitur velit tortor, sit amet tristique felis viverra sit amet. <<link "Nullam posuere facilisis purus sed">> consectetur. Integer vel elit euismod, posuere ligula et, dictum tellus. Donec in odio diam. Sed metus magna, placerat at ligula et, imperdiet sagittis ex.
<%else%>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<<tab-set "Sed Metus Magna Placerat Ligula Imperdiet">>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras non arcu ultricies, egestas odio tempus, vestibulum ipsum. Praesent diam lorem, elementum in venenatis eget, tincidunt quis lacus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
<%endif%>
</div>
@@ -0,0 +1,14 @@
title: $:/core/ui/Palettes/Preview/Tiddler/Header
tags: $:/tags/Preview/Tiddler
\whitespace trim
<div class="tc-palette-preview-thumbnail-tiddler-header">
<div class="tc-palette-preview-thumbnail-tiddler-title" style.color=<<colour tiddler-title-foreground>>>
<$text text=<<title>>/>
</div>
<div class="tc-palette-preview-thumbnail-tiddler-toolbar" style.fill=<<colour tiddler-controls-foreground>>>
{{$:/core/images/down-arrow}}
{{$:/core/images/edit-button}}
{{$:/core/images/close-button}}
</div>
</div>
@@ -0,0 +1,7 @@
title: $:/core/ui/Palettes/Preview/Tiddler/Subtitle
tags: $:/tags/Preview/Tiddler
\whitespace trim
<div class="tc-palette-preview-thumbnail-tiddler-subtitle" style.color=<<colour tiddler-subtitle-foreground>>>
Motovun Jack
</div>
@@ -0,0 +1,11 @@
title: $:/core/ui/Palettes/ViewTemplateBody
<div style.width="220px">
{{||$:/snippets/currpalettepreview}}
</div>
''<$view field="name" format="text"/>''
<br>
<$view field="description" format="text"/>
-1
View File
@@ -7,7 +7,6 @@ title: $:/core/ui/TagTemplate
tag=<<currentTiddler>>
icon={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}}
colour={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}
palette={{$:/palette}}
element-tag="$button"
element-attributes="""popup=<<qualify "$:/state/popup/tag">> dragFilter="[subfilter{$:/core/config/TagPillDragFilter}]" tag='span'"""
/>
+1 -1
View File
@@ -2,7 +2,7 @@ title: $:/core/ui/ViewTemplate/title
tags: $:/tags/ViewTemplate
\whitespace trim
\define title-styles() color:$(foregroundColor)$;
\define title-styles() fill:$(foregroundColor)$;
<div class="tc-tiddler-title tc-clearfix">
<div class="tc-titlebar">
@@ -0,0 +1,7 @@
title: $:/core/background-actions/AutoCompilePalette
tags: $:/tags/BackgroundAction $:/tags/StartupAction
platforms: browser
track-filter: [{$:/palette}get[color-scheme]] :map[subfilter<currentTiddler>] [{$:/palette}changecount[]addprefix{$:/palette}] [[$:/palette]changecount[]]
\import [subfilter{$:/core/config/GlobalImportFilter}]
<<actions-recompile-current-palette>>
+1 -1
View File
@@ -1,6 +1,6 @@
title: $:/config/OfficialPluginLibrary
tags: $:/tags/PluginLibrary
url: https://tiddlywiki.com/library/v5.4.0/index.html
url: https://tiddlywiki.com/library/v5.5.0/index.html
caption: {{$:/language/OfficialPluginLibrary}}
{{$:/language/OfficialPluginLibrary/Hint}}
@@ -10,4 +10,5 @@ code-body: [field:code-body[yes]then[$:/core/ui/ViewTemplate/body/code]]
import: [field:plugin-type[import]then[$:/core/ui/ViewTemplate/body/import]]
plugin: [has[plugin-type]then[$:/core/ui/ViewTemplate/body/plugin]]
hide-body: [field:hide-body[yes]then[$:/core/ui/ViewTemplate/body/blank]]
palette: [tag[$:/tags/Palette]then[$:/core/ui/Palettes/ViewTemplateBody]]
default: [[$:/core/ui/ViewTemplate/body/default]]
+9 -49
View File
@@ -1,52 +1,12 @@
title: $:/snippets/currpalettepreview
\define resolve-colour(macrocall)
\import $:/core/macros/utils
\whitespace trim
<$wikify name="name" text="""$macrocall$""">
<<name>>
</$wikify>
\end
\define swatchStyle()
background-color: $(swatchColour)$;
\end
\define swatch-inner()
\whitespace trim
<$set name="swatchColour" value={{##$(colourResolved)$}}>
<$list filter="[<swatchColour>!prefix[<<colour ]!suffix[>>]]" variable="ignore">
<div class="tc-swatch" style=<<swatchStyle>> title=<<swatchTitle>>/>
&#32;
</$list>
<$list filter="[<swatchColour>prefix[<<colour ]suffix[>>]]" variable="ignore">
<$wikify name="colourResolved" text="<$macrocall $name='resolve-colour' macrocall=<<swatchColour>>/>">
<<swatch-inner>>
</$wikify>
</$list>
</$set>
\end
\define swatch()
\whitespace trim
<$set name="swatchColour" value={{##$(colour)$}}>
<$set name="swatchTitle" value=<<colour>>>
<$list filter="[<swatchColour>!prefix[<<colour ]!suffix[>>]]" variable="ignore">
<div class="tc-swatch" style=<<swatchStyle>> title=<<swatchTitle>>/>
&#32;
</$list>
<$list filter="[<swatchColour>prefix[<<colour ]suffix[>>]]" variable="ignore">
<$wikify name="colourResolved" text="<$macrocall $name='resolve-colour' macrocall=<<swatchColour>>/>">
<<swatch-inner>>
</$wikify>
</$list>
</$set>
</$set>
\end
\whitespace trim
<div class="tc-swatches-horiz"><$list filter="
foreground
background
muted-foreground
primary
page-background
tab-background
tiddler-info-background
" variable="colour"><<swatch>></$list></div>
\import [all[shadows+tiddlers]tag[$:/tags/Preview/Helpers]!is[draft]sort[title]]
<!-- currentTiddler is the palette to use -->
<$palette.preview paletteTitle=<<currentTiddler>>>
<div class="tc-palette-preview-thumbnail" style.background-color=<<colour page-background>>>
<<palette-preview-component-list tag:"$:/tags/Preview/Page">>
</div>
</$palette.preview>
+150 -10
View File
@@ -1,17 +1,157 @@
title: $:/core/macros/CSS
tags: $:/tags/Macro
<!-- Needs to stay that way for backwards compatibility. See GH issue: #8326 -->
\define colour(name)
\whitespace trim
<$transclude tiddler={{$:/palette}} index="$name$">
<$transclude tiddler="$:/palettes/Vanilla" index="$name$">
<$transclude tiddler="$:/config/DefaultColourMappings/$name$"/>
</$transclude>
</$transclude>
\end
\procedure actions-compile-palette-filtered(consolidatedPalette,outputPalette)
<!-- Note the join, needed to cope with palette entries containing spaces -->
\function tf.colour(name) [<consolidatedPalette>getindex<name>] :else[[$:/config/DefaultColourMappings/]addsuffix<name>get[text]] :map[tf.colour-inner-transform-classic-palette-entry<currentTiddler>] :map[subfilter:all<currentTiddler>join[ ]]
\function colour(name) [tf.colour<name>]
\function color(name) [tf.colour<name>]
<!-- Make the colour function use the input palette -->
<$list filter="[<consolidatedPalette>indexes[]sort[]]" variable="colour-name">
<$let filter-text={{{ [<consolidatedPalette>getindex<colour-name>] :else[[$:/config/DefaultColourMappings/]addsuffix<colour-name>get[text]] :map[tf.colour-inner-transform-classic-palette-entry<currentTiddler>] }}}>
<!-- Note the join, needed to cope with palette entries containing spaces -->
<$action-setfield $tiddler=<<outputPalette>> $index=<<colour-name>> $value={{{ [subfilter:all<filter-text>join[ ]] +[join[ ]] }}}/>
</$let>
</$list>
\end actions-compile-palette-filtered
\define color(name) <<colour $name$>>
\procedure actions-compile-palette-import(inputPalette,outputPalette,exclusions:"",scheme)
<%if [enlist<exclusions>!match<inputPalette>count[]] :map[enlist<exclusions>count[]compare:number:eq<currentTiddler>] +[!match[]] %>
<$set name="exclusions" filter="[enlist<exclusions>] [<inputPalette>]">
<!-- Recursively import any imported palette -->
<$let
prefixed-palette-import={{{ [[palette-import@]addsuffix<scheme>] }}}
inputPalette={{{ [<inputPalette>get<prefixed-palette-import>has[title]] :else[<inputPalette>get[palette-import]] }}}
>
<%if [<inputPalette>has[title]] %>
<$transclude $variable="actions-compile-palette-import" inputPalette=<<inputPalette>> outputPalette=<<outputPalette>> exclusions=<<exclusions>> scheme=<<scheme>>/>
<%endif%>
</$let>
<!-- Copy the suffixed palette entries with the suffix stripped -->
<%if [<scheme>!is[blank]] %>
<$let
prefixed-scheme={{{ [<scheme>addprefix[@]] }}}
>
<$action-setmultiplefields $tiddler=<<outputPalette>> $indexes="[<inputPalette>indexes[]suffix<prefixed-scheme>removesuffix<prefixed-scheme>sort[]]" $values="[<inputPalette>indexes[]suffix<prefixed-scheme>sort[]] :map[<inputPalette>getindex<currentTiddler>]"/>
</$let>
<%endif%
<!-- Copy the unsuffixed palette entries -->
<$action-setmultiplefields $tiddler=<<outputPalette>> $indexes="[<inputPalette>indexes[]!regexp[@]sort[]]" $values="[<inputPalette>indexes[]!regexp[@]sort[]] :map[<inputPalette>getindex<currentTiddler>]"/>
<!-- Copy the fields from the palette -->
<$action-setmultiplefields $tiddler=<<outputPalette>> $fields="[<inputPalette>fields[]sort[]] -title -tags -text" $values="[<inputPalette>fields[]sort[]] -title -tags -text :map[<inputPalette>get<currentTiddler>]"/>
</$set>
<%endif%>
\end actions-compile-palette-import
\procedure actions-compile-palette(inputPalette,outputPalette)
\procedure tv-action-refresh-policy() always
<$let
consolidatedPalette="$:/temp/palette-consolidated"
>
<!-- Compute the current scheme -->
<$let
color-scheme-filter={{{ [<inputPalette>get[color-scheme]] :else[[light]] }}}
scheme={{{ [subfilter:all<color-scheme-filter>] }}}
>
<!-- Clear the consolidated palette that stores the result of flattening the chain of imported input palettes -->
<$action-deletetiddler $tiddler=<<consolidatedPalette>>/>
<$action-setfield $tiddler=<<consolidatedPalette>> type="application/x-tiddler-dictionary"/>
<!-- Clear the output palette that stores the plain CSS values of palette entries -->
<$action-deletetiddler $tiddler=<<outputPalette>>/>
<$action-setfield $tiddler=<<outputPalette>> type="application/x-tiddler-dictionary"/>
<!-- Import the background palettes -->
<$list filter="[all[shadows+tiddlers]tag[$:/tags/BackgroundPalette]sort[]]" variable="palette-name">
<$transclude $variable="actions-compile-palette-import" inputPalette=<<palette-name>> outputPalette=<<consolidatedPalette>> scheme=<<scheme>>/>
</$list>
<!-- Consolidate the chain of palettes -->
<$transclude $variable="actions-compile-palette-import" inputPalette=<<inputPalette>> outputPalette=<<consolidatedPalette>> scheme=<<scheme>>/>
<!-- Save the current scheme in the output tiddler -->
<$action-setfield $tiddler=<<outputPalette>> $field="color-scheme" $value=<<scheme>>/>
<!-- Compile the temporary palette to the output palette -->
<$transclude $variable="actions-compile-palette-filtered" consolidatedPalette=<<consolidatedPalette>> outputPalette=<<outputPalette>>/>
</$let>
</$let>
\end actions-compile-palette
\procedure actions-recompile-current-palette()
\procedure tv-action-refresh-policy() always
<$transclude $variable="actions-compile-palette" inputPalette={{$:/palette}} outputPalette="$:/temp/palette-colours"/>
\end actions-recompile-current-palette
\procedure actions-switch-colour-palette(paletteTitle)
\procedure tv-action-refresh-policy() always
<$action-deletetiddler $tiddler="$:/temp/palette-colours"/>
<<actions-recompile-current-palette>>
\end actions-switch-colour-palette
\procedure tv-palette-name() $:/temp/palette-colours
\function tf.colour(name)
[<tv-palette-name>getindex<name>] :else[[$:/config/DefaultColourMappings/]addsuffix<name>get[text]]
\end tf.colour
\function colour(name)
[tf.colour<name>]
\end colour
\function color(name)
[tf.colour<name>]
\end color
\procedure colour-function-prefix()
[tf.colour[
\end colour-function-prefix
\procedure colour-function-suffix()
]]
\end colour-function-suffix
\widget $palette.preview(paletteTitle)
\whitespace trim
\function colour-inner-get-imported-palette(name,paletteTitle)
[[palette-import@]addsuffix<scheme>] :map[<paletteTitle>get<currentTiddler>has[title]] +[!match[]] :else[<paletteTitle>get[palette-import]has[title]] :map[function[colour-inner-get-palette-entry],<name>,<currentTiddler>] +[!match[]]
\end colour-inner-get-imported-palette
\function colour-inner-get-palette-entry(name,paletteTitle)
[<name>addprefix[@]addprefix<scheme>] :map[<paletteTitle>getindex<currentTiddler>] +[!match[]] :else[<paletteTitle>getindex<name>] :map[tf.colour-inner-transform-classic-palette-entry<currentTiddler>] :else[function[colour-inner-get-imported-palette],<name>,<paletteTitle>]
\end colour-inner-get-palette-entry
<!-- Note the join, needed to cope with palette entries containing spaces -->
\function tf.colour(name)
[function[colour-inner-get-palette-entry],<name>,<paletteTitle>] :else[[$:/config/DefaultColourMappings/]addsuffix<name>get[text]] :map[subfilter:all<currentTiddler>join[ ]]
\end tf.colour
\function colour(name)
[tf.colour<name>]
\end colour
\function color(name)
[tf.colour<name>]
\end color
<$let
color-scheme-filter={{{ [<paletteTitle>get[color-scheme]] :else[[light]] }}}
scheme={{{ [subfilter:all<color-scheme-filter>] }}}
>
<$slot $name="ts-raw"/>
</$let>
\end $palette.preview
\function tf.colour-inner-transform-classic-palette-entry(colour-result)
[<colour-result>prefix[<<colour ]suffix[>>]removeprefix[<<colour ]removesuffix[>>]addprefix<colour-function-prefix>addsuffix<colour-function-suffix>] :else[<colour-result>]
\end tf.colour-inner-transform-classic-palette-entry
\function tf.check-colour-contrast-subfunction()
[function[colour],<paletteEntryA>] [function[colour],<paletteEntryB>] +[colour-contrast:DeltaPhi[]fixed[3]]
\end tf.check-colour-contrast-subfunction
\function tf.check-colour-contrast(paletteEntryA,paletteEntryB,threshold)
[function[tf.check-colour-contrast-subfunction]compare:number:gt<threshold>then[ok]] :else[function[tf.check-colour-contrast-subfunction]addsuffix[: ]addsuffix<paletteEntryA>addsuffix[/]addsuffix<paletteEntryB>addsuffix[ contrast is too low]]
\end tf.check-colour-contrast
\function tf.interpolate-colours(paletteEntryA,paletteEntryB,weight)
[function[colour],<paletteEntryA>] =>colourA [function[colour],<paletteEntryB>] =>colourB [<weight>colour-interpolate:oklch<colourA>,<colourB>]
\end tf.interpolate-colours
\procedure datauri(title)
<$macrocall $name="makedatauri" type={{{ [<title>get[type]] }}} text={{{ [<title>get[text]] }}} _canonical_uri={{{ [<title>get[_canonical_uri]] }}}/>
+1 -1
View File
@@ -6,5 +6,5 @@ $:/language/
\end
\define lingo(title)
{{$(lingo-base)$$title$}}
{{||$(lingo-base)$$title$}}
\end
+1 -1
View File
@@ -167,7 +167,7 @@ The second ESC tries to close the "draft tiddler"
<!-- keep those variables because they may "bleed" into macros using old syntax -->
<!-- "nonSystemTagsFilter", "systemTagsFilter" __need to be the same__ as fields: "first-search-filter", "second-search-filter" -->
<$let
palette={{$:/palette}}
palette="$:/temp/palette-colours"
colourA={{{ [<palette>getindex[foreground]] }}}
colourB={{{ [<palette>getindex[background]] }}}
fallbackTarget={{{ [<palette>getindex[tag-background]] }}}
+5 -4
View File
@@ -3,6 +3,7 @@ tags: $:/tags/Macro
\define tag-pill-styles()
background-color:$(backgroundColor)$;
fill:$(foregroundColor)$;
color:$(foregroundColor)$;
\end
@@ -27,15 +28,16 @@ color:$(foregroundColor)$;
</$let>
\end
<!-- Note that the 'palette' parameter is unused and is only retained for backwards compatibility -->
\define tag-pill-body(tag,icon,colour,palette,element-tag,element-attributes,actions)
\whitespace trim
<$macrocall $name="tag-pill-inner"
tag=<<__tag__>>
icon=<<__icon__>>
colour=<<__colour__>>
fallbackTarget={{$palette$##tag-background}}
colourA={{$palette$##foreground}}
colourB={{$palette$##background}}
fallbackTarget=<<colour tag-background>>
colourA=<<colour foreground>>
colourB=<<colour background>>
element-tag=<<__element-tag__>>
element-attributes=<<__element-attributes__>>
actions=<<__actions__>>
@@ -50,7 +52,6 @@ color:$(foregroundColor)$;
tag=<<__tag__>>
icon={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] }}}
colour={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}
palette={{$:/palette}}
element-tag=<<__element-tag__>>
element-attributes=<<__element-attributes__>>
actions=<<__actions__>>/>
+1 -1
View File
@@ -21,7 +21,7 @@ tags: $:/tags/Macro
style="width:$width$px;height:$height$px;background-color:$background-color$;"
></$reveal></div><div
class="tc-thumbnail-icon"
style="color:$color$;"
style="fill:$color$;color:$color$;"
>$icon$</div><div class="tc-thumbnail-caption">$caption$</div></div></$link>
\end
+1 -1
View File
@@ -1,3 +1,3 @@
title: $:/palette
$:/palettes/Vanilla
$:/palettes/AutoToggle
+25 -14
View File
@@ -1,19 +1,30 @@
title: $:/snippets/paletteswitcher
\parameters (thumbnails)
\whitespace trim
<$linkcatcher to="$:/palette">
<div class="tc-chooser">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Palette]!is[draft]sort[name]]">
<$set name="cls" filter="[all[current]prefix{$:/palette}]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item">
<div class=<<cls>>>
<$link to={{!!title}}>
''<$view field="name" format="text"/>''
&#32;-&#32;
<$view field="description" format="text"/>
{{||$:/snippets/currpalettepreview}}
</$link>
</div>
</$set>
</$list>
\procedure actions()
<$action-setfield $tiddler="$:/palette" text=<<navigateTo>>/>
\end actions
<!-- Display palette in currentTiddler with selection logic -->
\procedure palette-entry(thumbnails)
<div class={{{ [<currentTiddler>match{$:/palette}then[tc-chosen]] tc-chooser-item +[join[ ]] }}}>
<$link to={{!!title}} aria-label=`${[[$:/language/ControlPanel/Palette/Caption]get[text]]}$ - ${[all[current]get[name]]}$. ${[all[current]get[description]]}$`>
<%if [<thumbnails>match[yes]] %>
{{||$:/snippets/currpalettepreview}}
<%endif%>
''<$view field="name" format="text"/>''
<br>
<$view field="description" format="text"/>
</$link>
</div>
\end palette-entry
<$linkcatcher actions=<<actions>>>
<div class={{{ tc-chooser [<thumbnails>match[yes]then[tc-chooser-cards]] +[join[ ]] }}}>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Palette]!is[draft]sort[name]]">
<$transclude $variable="palette-entry" thumbnails=<<thumbnails>>/>
</$list>
</div>
</$linkcatcher>
+19
View File
@@ -0,0 +1,19 @@
title: $:/snippets/palettetests
<$let failureCount={{{ [[$:/temp/palette-colours]indexes[]prefix[?]] :filter[[$:/temp/palette-colours]getindex<currentTiddler>!match[ok]] +[count[]] }}}>
<%if [<failureCount>compare:number:gt[0]] %>
Palette test failures: <$text text=<<failureCount>>/>
<$list filter="[[$:/temp/palette-colours]indexes[]prefix[?]sort[]]" variable="name">
<%if [[$:/temp/palette-colours]getindex<name>!match[ok]] %>
<div>
''<$text text={{{ [<name>removeprefix[?]] }}}/>'': <$text text={{{ [[$:/temp/palette-colours]getindex<name>] }}}/>
</div>
<%endif%>
</$list>
<%endif%>
</$let>
@@ -0,0 +1,2 @@
title: $:/tags/ControlPanel/Appearance
text: $:/core/ui/ControlPanel/Palette $:/core/ui/ControlPanel/StoryView $:/core/ui/ControlPanel/Theme $:/core/ui/ControlPanel/Toolbars

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