Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trimSelection parameter to text editor #7944

Merged
merged 13 commits into from
Sep 10, 2024
136 changes: 112 additions & 24 deletions core/modules/editor/operations/text/wrap-selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,125 @@ Text editor operation to wrap the selection with the specified prefix and suffix
"use strict";

exports["wrap-selection"] = function(event,operation) {
if(operation.selStart === operation.selEnd) {
// No selection; check if we're within the prefix/suffix
if(operation.text.substring(operation.selStart - event.paramObject.prefix.length,operation.selStart + event.paramObject.suffix.length) === event.paramObject.prefix + event.paramObject.suffix) {
var o = operation,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a huge fan of this abbreviation pattern. I understand that it saves a bit of space, but it is hard to apply consistently. For example, here one might wonder why "operation" is abbreviated but "prefix" is not.

On balance, I would prefer to find ways to refactor the code to avoid the repetition, rather than use this pattern.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefix is an abbreviation. It is the shorthand for event.paramObject.prefix

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "o" abbreviation is used 99 times and was introduced to make the code readable and understandable. If I add it back again, it will make the code completely unreadable. Reducing the file size by 800bytes is a side effect.

IMO there is no redundant, repettitive code on the right side of any =. Every line, that defines o.cutStart, o.cutEnd, ... and so on, has a different pattern on the right side. -- So I do not really see a possility to optimize that any further.

prefix = event.paramObject.prefix,
suffix = event.paramObject.suffix,
trimSelection = event.paramObject.trimSelection || "no",
selLength = o.selEnd - o.selStart;

// This function detects, if trailing spaces are part of the selection __and__ if the user wants to handle them
// Returns "yes", "start", "end", "no" (default)
// yes .. there are trailing spaces at both ends
// start .. there are trailing spaces at the start
// end .. there are trailing spaces at the end
// no .. no trailing spaces are taken into account
var trailingSpaceAt = function(sel) {
var _start,
_end,
result;
// trimSelection is a user parameter, which this evaluations takes into account
switch(trimSelection) {
case "end":
result = (sel.trimEnd().length !== selLength) ? "end" : "no";
break;
case "yes":
_start = sel.trimStart().length !== selLength;
_end = sel.trimEnd().length !== selLength;
result = (_start && _end) ? "yes" : (_start) ? "start" : (_end) ? "end" : "no";
break;
case "start":
result = (sel.trimStart().length !== selLength) ? "start" : "no";
break;
default:
result = "no";
break;
}
return result;
}

function togglePrefixSuffix() {
if(o.text.substring(o.selStart - prefix.length, o.selStart + suffix.length) === prefix + suffix) {
// Remove the prefix and suffix
operation.cutStart = operation.selStart - event.paramObject.prefix.length;
operation.cutEnd = operation.selEnd + event.paramObject.suffix.length;
operation.replacement = "";
operation.newSelStart = operation.cutStart;
operation.newSelEnd = operation.newSelStart;
o.cutStart = o.selStart - prefix.length;
o.cutEnd = o.selEnd + suffix.length;
o.replacement = "";
o.newSelStart = o.cutStart;
o.newSelEnd = o.newSelStart;
} else {
// Wrap the cursor instead
operation.cutStart = operation.selStart;
operation.cutEnd = operation.selEnd;
operation.replacement = event.paramObject.prefix + event.paramObject.suffix;
operation.newSelStart = operation.selStart + event.paramObject.prefix.length;
operation.newSelEnd = operation.newSelStart;
o.cutStart = o.selStart;
o.cutEnd = o.selEnd;
o.replacement = prefix + suffix;
o.newSelStart = o.selStart + prefix.length;
o.newSelEnd = o.newSelStart;
}
}

// options: lenPrefix, lenSuffix
function removePrefixSuffix(options) {
options = options || {};
var _lenPrefix = options.lenPrefix || 0;
var _lenSuffix = options.lenSuffix || 0;

o.cutStart = o.selStart - _lenPrefix;
o.cutEnd = o.selEnd + _lenSuffix;
o.replacement = (_lenPrefix || _lenSuffix) ? o.selection : o.selection.substring(prefix.length, o.selection.length - suffix.length);
o.newSelStart = o.cutStart;
o.newSelEnd = o.cutStart + o.replacement.length;
}

function addPrefixSuffix() {
// remove trailing space if requested
switch(trailingSpaceAt(o.selection)) {
case "no":
// has no trailing spaces
o.cutStart = o.selStart;
o.cutEnd = o.selEnd;
o.replacement = prefix + o.selection + suffix;
o.newSelStart = o.selStart;
o.newSelEnd = o.selStart + o.replacement.length;
break;
case "yes":
// handle both ends
o.cutStart = o.selEnd - (o.selection.trimStart().length);
o.cutEnd = o.selection.trimEnd().length + o.selStart;
o.replacement = prefix + o.selection.trim() + suffix;
o.newSelStart = o.cutStart;
o.newSelEnd = o.cutStart + o.replacement.length;
break;
case "start":
// handle leading
o.cutStart = o.selEnd - (o.selection.trimStart().length);
o.cutEnd = o.selEnd;
o.replacement = prefix + o.selection.trimStart() + suffix;
o.newSelStart = o.cutStart;
o.newSelEnd = o.cutStart + o.replacement.length;
break;
case "end":
// handle trailing
o.cutStart = o.selStart;
o.cutEnd = o.selection.trimEnd().length + o.selStart;
o.replacement = prefix + o.selection.trimEnd() + suffix;
o.newSelStart = o.selStart;
o.newSelEnd = o.selStart + o.replacement.length;
break;
}
} else if(operation.text.substring(operation.selStart,operation.selStart + event.paramObject.prefix.length) === event.paramObject.prefix && operation.text.substring(operation.selEnd - event.paramObject.suffix.length,operation.selEnd) === event.paramObject.suffix) {
}

if(o.selStart === o.selEnd) {
// No selection; Create prefix and suffix. Set cursor in between them: ""|""
togglePrefixSuffix();
} else if(o.text.substring(o.selStart, o.selStart + prefix.length) === prefix &&
o.text.substring(o.selEnd - suffix.length,o.selEnd) === suffix) {
// Prefix and suffix are already present, so remove them
operation.cutStart = operation.selStart;
operation.cutEnd = operation.selEnd;
operation.replacement = operation.selection.substring(event.paramObject.prefix.length,operation.selection.length - event.paramObject.suffix.length);
operation.newSelStart = operation.selStart;
operation.newSelEnd = operation.selStart + operation.replacement.length;
removePrefixSuffix();
} else if(o.text.substring(o.selStart - prefix.length, o.selStart) === prefix &&
o.text.substring(o.selEnd, o.selEnd + suffix.length) === suffix) {
// Prefix and suffix are present BUT not selected -> remove them
removePrefixSuffix({"lenPrefix": prefix.length, "lenSuffix": suffix.length});
} else {
// Add the prefix and suffix
operation.cutStart = operation.selStart;
operation.cutEnd = operation.selEnd;
operation.replacement = event.paramObject.prefix + operation.selection + event.paramObject.suffix;
operation.newSelStart = operation.selStart;
operation.newSelEnd = operation.selStart + operation.replacement.length;
addPrefixSuffix();
}
};

Expand Down
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/bold.tid
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ shortcuts: ((bold))
$param="wrap-selection"
prefix="''"
suffix="''"
trimSelection="yes"
/>
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/italic.tid
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ shortcuts: ((italic))
$param="wrap-selection"
prefix="//"
suffix="//"
trimSelection="yes"
/>
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/linkify.tid
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ tags: $:/tags/EditorToolbar
$param="wrap-selection"
prefix="[["
suffix="]]"
trimSelection="yes"
/>
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/mono-line.tid
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ shortcuts: ((mono-line))
$param="wrap-selection"
prefix="`"
suffix="`"
trimSelection="yes"
/>
2 changes: 1 addition & 1 deletion core/ui/EditorToolbar/stamp-dropdown-item-template.tid
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ title: $:/core/ui/EditorToolbar/StampDropdown/ItemTemplate
$message="tm-edit-text-operation"
$param="wrap-selection"
prefix={{{ [<currentTiddler>addsuffix[/prefix]get[text]] }}}
suffix={{{ [<currentTiddler>addsuffix[/suffix]get[text]] }}}
suffix={{{ [<currentTiddler>addsuffix[/suffix]get[text]] }}}
/>

</$list>
Expand Down
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/strikethrough.tid
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ shortcuts: ((strikethrough))
$param="wrap-selection"
prefix="~~"
suffix="~~"
trimSelection="yes"
/>
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/subscript.tid
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ shortcuts: ((subscript))
$param="wrap-selection"
prefix=",,"
suffix=",,"
trimSelection="yes"
/>
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/superscript.tid
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ shortcuts: ((superscript))
$param="wrap-selection"
prefix="^^"
suffix="^^"
trimSelection="yes"
/>
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/transcludify.tid
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ tags: $:/tags/EditorToolbar
$param="wrap-selection"
prefix="{{"
suffix="}}"
trimSelection="yes"
/>
1 change: 1 addition & 0 deletions core/ui/EditorToolbar/underline.tid
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ shortcuts: ((underline))
$param="wrap-selection"
prefix="__"
suffix="__"
trimSelection="yes"
/>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
caption: tm-edit-text-operation
created: 20160424211339792
modified: 20230803045746596
modified: 20240909083525060
tags: Messages
title: WidgetMessage: tm-edit-text-operation
type: text/vnd.tiddlywiki
Expand All @@ -11,9 +11,9 @@ type: text/vnd.tiddlywiki
Excises the currently selected text into a new tiddler and replaces it with a link, a macro or a transclude of the new tiddler. Parameters include:

|!Name |!Description |
|title |Title of the new tiddler the selected content is excised to|
|type |Type of the replacement to be inserted: Can be one of <<.value "transclude">>, <<.value "link">> or <<.value "macro">>|
|macro |In case //type=<<.value "macro">>//, specifies the name of the macro to be inserted. The title of the new tiddler is provided as the first parameter to the macro. Defaults to the [[translink macro|translink Macro]]|
|title |Title of the new tiddler the selected content is excised to |
|type |Type of the replacement to be inserted: Can be one of <<.value "transclude">>, <<.value "link">> or <<.value "macro">> |
|macro |In case //type=<<.value "macro">>//, specifies the name of the macro to be inserted. The title of the new tiddler is provided as the first parameter to the macro. Defaults to the [[translink macro|translink Macro]] |
|tagnew |If '<<.value "yes">>', will tag the new tiddler with the title of the tiddler currently being edited |

</div>
Expand All @@ -25,7 +25,7 @@ Excises the currently selected text into a new tiddler and replaces it with a li
Replaces ''all'' contents of the editor with the provided text.

|!Name |!Description |
|text |Text to be inserted|
|text |Text to be inserted |

</div>
\end
Expand All @@ -36,7 +36,7 @@ Replaces ''all'' contents of the editor with the provided text.
Replaces the current selection with the provided text.

|!Name |!Description |
|text |Text to be inserted|
|text |Text to be inserted |

</div>
\end
Expand All @@ -47,8 +47,8 @@ Replaces the current selection with the provided text.
Prefixes the currently selected line//(s)// with the provided character. If a line is already prefixed by the provided prefix, the prefix is removed instead.

|!Name |!Description |
|character |Prefix character|
|count |Number of characters that make up the prefix|
|character |Prefix character |
|count |Number of characters that make up the prefix |

''Example'' Setting //character="<<.value "!">>"// and //count="<<.value "3">>"// would insert the prefix "<<.value "!!!" >>", which will resolve to a subheading when parsed as WikiText.

Expand All @@ -61,8 +61,8 @@ Prefixes the currently selected line//(s)// with the provided character. If a li
Surrounds the selected //lines// with the provided <<.param "prefix">> and <<.param "suffix">>.

|!Name |!Description |
|prefix |String to be prefixed to the selected lines|
|suffix |Suffix to be inserted after the selected lines|
|prefix |String to be prefixed to the selected lines |
|suffix |Suffix to be inserted after the selected lines |


</div>
Expand All @@ -75,8 +75,9 @@ Surrounds the selected //lines// with the provided <<.param "prefix">> and <<.pa
Surrounds the current //selection// with the provided <<.param "prefix">> and <<.param "suffix">>.

|!Name |!Description |
|prefix |String to be prefixed to the selection|
|suffix |Suffix to be inserted after the selection|
|prefix |String to be prefixed to the selection |
|suffix |Suffix to be inserted after the selection |
|trimSelection |<<.from-version 5.3.6>> Trim leading and trailing white-space from the selection and move it to the surrounding text. Possible values are: `yes`, `no` (default), `start` and `end` |

</div>
\end
Expand Down Expand Up @@ -138,11 +139,11 @@ At this point the following text operations have been implemented:
|<<.def "wrap-selection">>|<<wrapSelectionDescription>> |
|<<.def "save-selection">>|<<saveSelectionDescription>> |
|<<.def "make-link">>|<<makeLinkDescription>> |
|<<.def "insert-text">>|<<insertTextDescription>>|
|<<.def "insert-text">>|<<insertTextDescription>> |
|<<.def "focus-editor">>|<<.from-version 5.2.0>> <<focusEditorDescription>> |


!Example
! Example

An example can be seen in [[$:/core/ui/EditorToolbar/bold]]:

Expand All @@ -152,6 +153,7 @@ An example can be seen in [[$:/core/ui/EditorToolbar/bold]]:
$param="wrap-selection"
prefix="''"
suffix="''"
trimSelection="yes"
/>
```

Expand Down
Loading