From 2340d48844f00f39bc6697b86d2e10dc6825efcf Mon Sep 17 00:00:00 2001 From: yaisog Date: Sat, 6 May 2023 12:30:21 +0200 Subject: [PATCH] Add additional searchModes to Dynannotate (#7260) * Add searchModes: literal, some and words * Add additional search modes Description of selection tracker config tiddlers was also changed. * Update simple.tid * Improve View Template examples Transcludes a sample tiddler for demonstration instead of the dynannotate view template code. Adds an example for usage with $genesis to add state tiddler controlled per-tiddler highlights. * Make search highlights not case sensitive * Remove created and modified fields * Add another example text (Searching in Tiddlywiki) * Add dynannotate for vercel deployment This should probably not be merged... * Create LegacySelectionTracker.tid * Create SelectionTracker.tid * Revert putting the SelectionTracker config titles in code blocks * Replace inline styles with CSS class * Add class for view template examples Class name is tc-dynannotate-example-frame. * Remove some
line breaks. * Remove first example transclusion and fix some tab spacing * Add class to override control panel table layout * Add class to settings table * More tab shenanigans Great Scott! * Add explanatory comment to example macro * Change defaults to match widget behavior * Make previous macro comment more concise * Change example to transclude CP tiddler $:/core/ui/ControlPanel/TiddlerFields * Delete unnecessary example tiddler --- editions/tw5.com/tiddlywiki.info | 3 +- .../config/LegacySelectionTracker.tid | 3 + .../dynannotate/config/SelectionTracker.tid | 3 + .../tiddlywiki/dynannotate/docs/readme.tid | 9 +- .../dynannotate/examples/simple.tid | 88 +++++++++---------- .../examples/viewtemplate-text.tid | 1 + .../dynannotate/examples/viewtemplate.tid | 59 +++++++++++-- .../tiddlywiki/dynannotate/modules/textmap.js | 13 ++- plugins/tiddlywiki/dynannotate/styles.tid | 10 +++ 9 files changed, 125 insertions(+), 64 deletions(-) create mode 100644 plugins/tiddlywiki/dynannotate/config/LegacySelectionTracker.tid create mode 100644 plugins/tiddlywiki/dynannotate/config/SelectionTracker.tid diff --git a/editions/tw5.com/tiddlywiki.info b/editions/tw5.com/tiddlywiki.info index 7379908ee..b71c9ad1f 100644 --- a/editions/tw5.com/tiddlywiki.info +++ b/editions/tw5.com/tiddlywiki.info @@ -6,7 +6,8 @@ "tiddlywiki/railroad", "tiddlywiki/evernote", "tiddlywiki/internals", - "tiddlywiki/menubar" + "tiddlywiki/menubar", + "tiddlywiki/dynannotate" ], "themes": [ "tiddlywiki/vanilla", diff --git a/plugins/tiddlywiki/dynannotate/config/LegacySelectionTracker.tid b/plugins/tiddlywiki/dynannotate/config/LegacySelectionTracker.tid new file mode 100644 index 000000000..83a547633 --- /dev/null +++ b/plugins/tiddlywiki/dynannotate/config/LegacySelectionTracker.tid @@ -0,0 +1,3 @@ +title: $:/config/Dynannotate/LegacySelectionTracker/Enable + +no diff --git a/plugins/tiddlywiki/dynannotate/config/SelectionTracker.tid b/plugins/tiddlywiki/dynannotate/config/SelectionTracker.tid new file mode 100644 index 000000000..6162c992c --- /dev/null +++ b/plugins/tiddlywiki/dynannotate/config/SelectionTracker.tid @@ -0,0 +1,3 @@ +title: $:/config/Dynannotate/SelectionTracker/Enable + +no diff --git a/plugins/tiddlywiki/dynannotate/docs/readme.tid b/plugins/tiddlywiki/dynannotate/docs/readme.tid index 487c25561..ff0483a79 100644 --- a/plugins/tiddlywiki/dynannotate/docs/readme.tid +++ b/plugins/tiddlywiki/dynannotate/docs/readme.tid @@ -25,7 +25,7 @@ The `<$dynannotate>` widget uses the selection tracker to support a popup that d |popup |Popup state tiddler to be used to trigger a popup when an annotation is clicked | |search |Search text to be highlighted within the widget | |searchDisplay |"overlay" or "snippet" (see below) | -|searchMode |"normal" (default), "regexp" or "whitespace" (see below) | +|searchMode |"literal" (default), "regexp", "whitespace", "words" or "some" (see below) | |searchMinLength |Optional minimum length of search string | |searchCaseSensitive |"yes" (the default) for a case sensitive search, or "no" for a case insensitive search| |searchClass |Optional CSS class to be added to search overlays | @@ -46,9 +46,10 @@ The values supported by the `searchDisplay` attribute are: The search modes supported by the `searchMode` attribute are: -* `normal` - a literal string of plain text to match +* `literal` or `normal` - a literal string of plain text to match (default). * `regexp` - a JavaScript-style regular expression (without the quoting backslashes and flags) -* `whitespace` - a literal string to match while normalising runs of whitespace. This allows `a. b` to match `a. b` +* `whitespace` - a literal string to match while normalising runs of whitespace. Thus `A B` matches `A B`. +* `words` or `some` - treats the search string as a list of tokens separated by whitespace, and matches all tokens (regardless of ordering and whether there is other text in between) When the selection popup is triggered, the currently selected text can be found in the tiddler named in the `selection` attribute, with the disambiguating prefix and suffix in the tiddlers named in the `selectionPrefix` and `selectionPopup` tiddlers. Note that the selection text will be an empty string if the selection popup was triggered in response to a click (ie zero width selection). @@ -95,7 +96,7 @@ Note that using the `annotate-tiddler` field to associate an annotation with the !! Selection Trackers -The following configuration tiddlers can be used to control whether the selection trackers are enabled when the following configuration tiddlers are set to ''yes'' (the default). +The selection trackers are enabled when the following configuration tiddlers are set to ''yes''. * $:/config/Dynannotate/SelectionTracker/Enable for the main selection tracker * $:/config/Dynannotate/LegacySelectionTracker/Enable for the legacy selection tracker diff --git a/plugins/tiddlywiki/dynannotate/examples/simple.tid b/plugins/tiddlywiki/dynannotate/examples/simple.tid index aa1837b78..59a8d7e1d 100644 --- a/plugins/tiddlywiki/dynannotate/examples/simple.tid +++ b/plugins/tiddlywiki/dynannotate/examples/simple.tid @@ -10,16 +10,33 @@ caption: Simple $example$ \end +\define search-example-code() + +\rules only filteredtranscludeinline +<$dynannotate + search="{{{ [{$:/temp/dynannotate-example/search}!is[blank]else[The human mind]] }}}"{{{ [{$:/temp/dynannotate-example/searchMode}!search::some[literal normal]addprefix[ + searchMode="]addsuffix["]] }}} + searchCaseSensitive="{{{ [{$:/temp/dynannotate-example/searchCaseSensitive}!is[blank]else[yes]] }}}"{{{ [{$:/temp/dynannotate-example/searchClass}!is[blank]addprefix[ + searchClass="]addsuffix["]] }}} +> +<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> +<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-2" mode="block"/> + +\end +
-!! Simple annotation +!! Annotations with `target` -We use the `target*` attributes to specify a target string for the annotation and optionally a prefix and suffix for disambiguating multiple occurances. +We use the `target*` attributes to specify a target string for the annotation and optionally a prefix and suffix for disambiguating multiple occurences.
-< -!! Plain text searching +!! Highlights with `search` -We use the `search` attribute to specify a search string for highlighting: +We use the `search` attribute to specify a search string for highlighting. + +The search type can be set with the `searchMode` and `searchCaseSensitive` attributes. + +We can style the highlights with the `searchClass` attribute, which has some predefined values. -<| +|search mode |<$select tiddler="$:/temp/dynannotate-example/searchMode" field="text" default="literal"> | +|case sensitive |<$checkbox tiddler="$:/temp/dynannotate-example/searchCaseSensitive" field="text" checked="yes" unchecked="no" default="yes"> <$text text={{{ [{$:/temp/dynannotate-example/searchCaseSensitive}!is[blank]else[yes]] }}} /> | +|search class |<$select tiddler="$:/temp/dynannotate-example/searchClass" field="text" default=""> | + <$dynannotate - search="the" + search={{{ [{$:/temp/dynannotate-example/search}!is[blank]else[The human mind]] }}} + searchMode={{{ [{$:/temp/dynannotate-example/searchMode}] }}} + searchCaseSensitive={{{ [{$:/temp/dynannotate-example/searchCaseSensitive}!is[blank]else[yes]] }}} + searchClass={{{ [{$:/temp/dynannotate-example/searchClass}] }}} > <$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> +<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-2" mode="block"/> -""">> -
- -!! Regular expression searching - -We use the `mode` attribute set to `regexp` to highlight matches of a regular expression: - -
- -< -<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> - -""">> - -
- -!! Normalised whitespace searching - -We use the `mode` attribute set to `whitespace` to search for a string with whitespace normalised (ie runs of whitespace are collapsed to a single space for matching purposes): - -
- -< -<$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> - -""">> +<$wikify name="wikifiedCode" text=<> mode="block" output="text"> +<$codeblock code=<>/> +
@@ -90,8 +87,7 @@ Annotation tiddlers can be used to describe annotations. This example references <> -< <$transclude tiddler="$:/plugins/tiddlywiki/dynannotate/example-text-1" mode="block"/> diff --git a/plugins/tiddlywiki/dynannotate/examples/viewtemplate-text.tid b/plugins/tiddlywiki/dynannotate/examples/viewtemplate-text.tid index 15588c420..81c3c2b25 100644 --- a/plugins/tiddlywiki/dynannotate/examples/viewtemplate-text.tid +++ b/plugins/tiddlywiki/dynannotate/examples/viewtemplate-text.tid @@ -34,6 +34,7 @@ title: $:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text selectionPopup={{{ [addprefix[$:/state/dynannotate/popup-selection/]] }}} search={{$:/temp/search}} searchClass="tc-dynannotation-search-overlay-blurred" + searchCaseSensitive="no" searchMinLength={{$:/config/Search/MinLength}} > <$transclude mode="block"> diff --git a/plugins/tiddlywiki/dynannotate/examples/viewtemplate.tid b/plugins/tiddlywiki/dynannotate/examples/viewtemplate.tid index a0b99eb79..150a6f88f 100644 --- a/plugins/tiddlywiki/dynannotate/examples/viewtemplate.tid +++ b/plugins/tiddlywiki/dynannotate/examples/viewtemplate.tid @@ -1,28 +1,69 @@ -title: $:/plugins/tiddlywiki/dynannotate/examples/viewtemplate -tags: $:/tags/dynannotateExamples caption: View Template +tags: $:/tags/dynannotateExamples +title: $:/plugins/tiddlywiki/dynannotate/examples/viewtemplate + +\define show-example(example) +<$codeblock code=<<__example__>>/> + +//''Displays as:''// + +$example$ +\end
!! Using Dynannotate in the view template -This example shows how to override the core view template with a custom template that includes dynannotate. It is disabled by default but can be enabled by clicking the button below. (Clicking the button below copies the custom view template from $:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text to $:/core/ui/ViewTemplate/body). +This example shows how to override the core view template with a custom template that includes dynannotate. It is disabled by default but can be enabled by clicking the corresponding button below. The example transcludes the [[Searching in TiddlyWiki|$:/plugins/tiddlywiki/dynannotate/searching-in-tiddlywiki]] tiddler for illustration purposes, but the chosen view template is applied to all open tiddlers. -Once enabled, this example demonstrates several features: +Once enabled, this example demonstrates several features of Dynannotate: -* Highlighting of search results within tiddler bodies -* Creating annotations on any tiddler by selecting text and then clicking a colour in the resulting dropdown +* Highlight text within tiddler bodies -- any text entered in the sidebar search input will be highlighted (in all tiddlers) +* Create annotations (on any tiddler) by selecting text and then clicking //Create annotation// in the resulting dropdown + +(Clicking the buttons below either puts the custom body view template [[$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text]] in front of the default in the [[View Template Body Cascade|https://tiddlywiki.com/#View%20Template%20Body%20Cascade]] or removes it from the cascade).
<$button> -<$action-setfield $tiddler="$:/config/ViewTemplateTitleFilters/dynannotate" tags="$:/tags/ViewTemplateTitleFilter" text="[[$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text]]" list-before="$:/config/ViewTemplateBodyFilters/default"/> +<$action-setfield $tiddler="$:/config/ViewTemplateBodyFilters/dynannotate" tags="$:/tags/ViewTemplateBodyFilter" text="[[$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text]]" list-before="$:/config/ViewTemplateBodyFilters/default"/> Click here to use the custom view template <$button> -<$action-deletetiddler $tiddler="$:/config/ViewTemplateTitleFilters/dynannotate"/> +<$action-deletetiddler $tiddler="$:/config/ViewTemplateBodyFilters/dynannotate"/> Click here to revert to the core view template -<$codeblock code={{$:/plugins/tiddlywiki/dynannotate/examples/viewtemplate/text}}/> \ No newline at end of file +

+ +

+ +!! Using Dynannotate to highlight text on a per-tiddler basis + +Using state tiddlers containing the text which is to be highlighted, Dynannotate highlights can be applied on a per-tiddler basis when used in the body view template. This can also be combined with the [[GenesisWidget]] to insert the Dynannotate widget into the DOM only when such a highlight is configured. + +This example uses a transcluded tiddler, but Dynannotate could be added to the view template (to show highlights in all parts of a tiddler) or to the body view template (to show highlights only in the tiddler body) in the same way. Note how in this example, Dynannotate only affects the transcluded content. + +
+ +<Highlight "tiddler" +<$button set="$:/state/dynannotate/examples/viewtemplate" setTo="created">Highlight "created" +<$button set="$:/state/dynannotate/examples/viewtemplate" setTo="">Clear highlights +

+<$let dynannotateText={{$:/state/dynannotate/examples/viewtemplate}}> + <$genesis $type={{{ [!is[blank]then[$dynannotate]] }}} + search=<> + searchDisplay="overlay" + searchClass="tc-dynannotation-search-overlay-animated" + searchCaseSensitive="no"> +

+ + !! `$:/core/ui/ControlPanel/TiddlerFields`: + <$transclude tiddler="$:/core/ui/ControlPanel/TiddlerFields" mode="block" /> +
+ + +""">> + +When used in the view template, the state tiddler title could be derived from the current tiddler, e.g. `<$let dynannotateText={{{ [addprefix[$:/state/dynannotate/]get[text]] }}}>`, to configure highlights for each tiddler separately. diff --git a/plugins/tiddlywiki/dynannotate/modules/textmap.js b/plugins/tiddlywiki/dynannotate/modules/textmap.js index 9f9dbbbe3..934ceb0ff 100644 --- a/plugins/tiddlywiki/dynannotate/modules/textmap.js +++ b/plugins/tiddlywiki/dynannotate/modules/textmap.js @@ -15,7 +15,7 @@ Structure for modelling mapping between a string and its representation in the D var PREFIX_SUFFIX_LENGTH = 50; /* -Build a map of the text content of a dom node and its descendents: +Build a map of the text content of a DOM node and its descendants: string: concatenation of the text content of child nodes metadata: array of {start,end,domNode} where start and end identify position in the string @@ -60,7 +60,7 @@ exports.TextMap.prototype.locateMetadata = function(position) { }; /* -Search for the first occurance of a target string within the textmap of a dom node +Search for the first occurrence of a target string within the textmap of a DOM node Returns an object with the following properties: startNode: node containing the start of the text @@ -92,10 +92,10 @@ exports.TextMap.prototype.findText = function(targetString,targetPrefix,targetSu }; /* -Search for all occurances of a string within the textmap of a dom node +Search for all occurrences of a string within the textmap of a DOM node Options include: - mode: "normal", "regexp" or "whitespace" + mode: "normal", "literal", "regexp", "whitespace", "some" or "words" caseSensitive: true if the search should be case sensitive Returns an array of objects with the following properties: @@ -121,6 +121,11 @@ exports.TextMap.prototype.search = function(searchString,options) { regExpString = "(" + searchString.split(/\s+/g).filter(function(word) { return !!word }).map($tw.utils.escapeRegExp).join("\\s+") + ")"; + } else if(options.mode === "words" || options.mode === "some") { + // Match any word separated by whitespace + regExpString = "(" + searchString.split(/\s+/g).filter(function(word) { + return !!word + }).map($tw.utils.escapeRegExp).join("|") + ")"; } else { // Normal search regExpString = "(" + $tw.utils.escapeRegExp(searchString) + ")"; diff --git a/plugins/tiddlywiki/dynannotate/styles.tid b/plugins/tiddlywiki/dynannotate/styles.tid index cd635eed5..8b13eba58 100644 --- a/plugins/tiddlywiki/dynannotate/styles.tid +++ b/plugins/tiddlywiki/dynannotate/styles.tid @@ -34,6 +34,16 @@ tags: [[$:/tags/Stylesheet]] animation: ta-dynannotation-search-overlay-animated 12s linear infinite; } +.tc-dynannotate-example-frame { + border: 1px solid black; + border-radius: 20px; + padding: 1em; +} + +.tc-control-panel table.tc-dynannotate-search-parameters, .tc-control-panel table.tc-dynannotate-search-parameters input { + width: initial; +} + .tc-dynannotate-snippet-highlight { background: #efef53; }