* 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.
* 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
* [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
* [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
* 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
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.