mirror of
https://github.com/rabirabirara/obsidian-jelly-snippets.git
synced 2026-07-22 07:30:22 +00:00
Compare commits
34 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18204f227c | ||
|
|
8a88ae3a68 | ||
|
|
e05c88e941 | ||
|
|
7313ef9d44 | ||
|
|
2e1764a3bf | ||
|
|
4a50f993b7 | ||
|
|
5737b07d36 | ||
|
|
bbc462f18c | ||
|
|
56935ca760 | ||
|
|
eba93321df | ||
|
|
32fc03607c | ||
|
|
6e15adc2d4 | ||
|
|
257616bf9f | ||
|
|
8cfee7d4dd | ||
|
|
27e04f24ee | ||
|
|
7e1c6f7954 | ||
|
|
6b6787a552 | ||
|
|
66ba56328c | ||
|
|
998489b576 | ||
|
|
b10ec1ade3 | ||
|
|
8cf68cfc87 | ||
|
|
b769bf70be | ||
|
|
641fef15df | ||
|
|
7c75776464 | ||
|
|
65572b4632 | ||
|
|
ebea47cde8 | ||
|
|
18e4c2e28f | ||
|
|
86ba8bfade | ||
|
|
a17c4d0dd4 | ||
|
|
2236c94372 | ||
|
|
56dd23b30d | ||
|
|
a4c6600aaf | ||
|
|
b8984d2e69 | ||
|
|
b43bd93d0f |
5 changed files with 236 additions and 110 deletions
55
README.md
55
README.md
|
|
@ -1,6 +1,9 @@
|
|||
# jelly-snippets
|
||||
A simple text snippets plugin for Obsidian.md.
|
||||
|
||||
## BEFORE UPDATING,READ:
|
||||
|
||||
If you have used an older version of this plugin (1.5) or below, updating to version 1.6 will erase your snippets. Backup your snippets before updating; I will update the plugin with a backup functionality later too in case I mess up again. Deepest apologies.
|
||||
|
||||
## What does it do?
|
||||
|
||||
|
|
@ -26,7 +29,9 @@ Pretty simple. You probably have run into snippets before.
|
|||
|
||||
Snippets are defined in a text area (like a file) in settings. Each snippet has two parts: lhs and rhs.
|
||||
|
||||
The lhs (left hand side) determines what text gets replaced; the rhs (right hand side) determines what replaces the text.
|
||||
##### The lhs (left hand side) determines what text gets replaced; the rhs (right hand side) determines what replaces the text.
|
||||
|
||||
##### The lhs is *exactly* the text that will be replaced, while the rhs can have certain symbols to represent things like whitespace.
|
||||
|
||||
Naturally, there is a symbol to divide these two halves of a snippet, called a snippet part divider:
|
||||
|
||||
|
|
@ -40,6 +45,8 @@ And, there is a symbol to divide each separate snippet in the list of snippets,
|
|||
|
||||
`-==-`, for example.
|
||||
|
||||
You must keep the snippet divider on their own line - that is, the plugin expects a newline after the snippet divider. (Implicitly, no two snippets can be on the same line.)
|
||||
|
||||
So if you had the following snippets file:
|
||||
|
||||
```
|
||||
|
|
@ -61,7 +68,34 @@ Then typing `lhs` and triggering the snippet command would replace `lhs` with:
|
|||
rhs
|
||||
superb |+| superbowls
|
||||
```
|
||||
|
||||
|
||||
## Using Symbols (simple)
|
||||
|
||||
Say you want to expand `hw` into a full hello-world function. Say we're using Rust. You define the snippet:
|
||||
|
||||
```
|
||||
hw |+| fn hello() {
|
||||
%\t%\e
|
||||
}
|
||||
```
|
||||
|
||||
When you trigger the snippet, you'll end up with this:
|
||||
|
||||
```
|
||||
fn hello() {
|
||||
|
|
||||
}
|
||||
```
|
||||
|
||||
... where `|` represents your cursor. Of course, Obsidian is a markdown editor, so expect the little indent guide.
|
||||
|
||||
#### List of supported symbols
|
||||
|
||||
- Newline: `%\n`
|
||||
- Tab: `%\t`
|
||||
- Space: `%\s`
|
||||
- Cursor Ending position (after snippet replacement): `%\e`
|
||||
|
||||
## Why?
|
||||
|
||||
I wanted to make a generic snippets plugin that operated on text and worked as I needed. There is an existing snippets plugin already, [Text Snippets](https://github.com/ArianaKhit/text-snippets-obsidian) by ArianaKhit, but not only is the plugin code somewhat outdated and a little complex, it seems to use an older API. (It is a very good plugin by the way.)
|
||||
|
|
@ -76,13 +110,16 @@ It's since been incorporated back into [julia.vim](https://github.com/JuliaEdito
|
|||
|
||||
## Future Improvements/TODO
|
||||
|
||||
- [ ] Control characters in snippets (e.g. whitespace, particularly newlines? currently snippets are trimmed on both ends; should probably not trim spaces)
|
||||
- [ ] Semantic symbols in snippets (e.g. where does cursor go afterwards? a snippet with braces might benefit from placing the cursor inside...)
|
||||
- [ ] Regex capabilities
|
||||
- [ ] Bugfixes and auditing?
|
||||
- [x] Add newline option for snippet definition to make simple snippets easy rather than cumbersome
|
||||
- [x] Control characters in snippets (whitespace only)
|
||||
- [x] Semantic symbols in snippets (e.g. where does cursor go afterwards? a snippet with braces might benefit from placing the cursor inside...)
|
||||
- [ ] Regex capabilities - at least on selection.
|
||||
- [ ] A backup for snippets - or a way of specifying snippets in a file, to modularize snippets. May be useful if regex snippets need to be defined separately from text snippets.
|
||||
- [ ] Bugfixes and auditing.
|
||||
- [ ] AUTOMATED TESTING. Use Jest.
|
||||
- [ ] Do the things liamcain suggested in my plugin PR to the Obsidian plugin repo. (one half done)
|
||||
|
||||
- [ ] Working with Obsidians template stuff.
|
||||
- [ ] REWRITE: CodeMirror editor extension. [See here on state fields.](https://docs.obsidian.md/Plugins/Editor/State+fields) This should also make things such as tabstops and working in live preview possible, but I don't know for sure. This would mark a version upgrade.
|
||||
|
||||
### Other caveats
|
||||
|
||||
- The lhs of a snippet (currently) cannot have newlines in it. Snippets of that sort will simply fail to work; they'll register but never trigger. The reason why is because I only search from cursor to start of line for snippet text; this is efficient and simple. To fix, we'd have to look backwards from the cursor position and match with the lhs of the snippet. Probably not a hard update, but given that this use case is somewhat rare (imo), I have neglected it. Do submit an issue. EDIT: the issue was submitted. Time to get to work.
|
||||
- None right now, except that the maintainer of this plugin (me) is inexperienced and may break something. Keep your snippets safe if you write a lot of them.
|
||||
|
|
|
|||
186
main.ts
186
main.ts
|
|
@ -8,19 +8,17 @@ import {
|
|||
Setting,
|
||||
} from "obsidian";
|
||||
|
||||
import { EditorView } from "@codemirror/view";
|
||||
|
||||
import { Symbol } from "src/symbol";
|
||||
import { LHS, RHS, Snippet, SnippetType } from "src/snippet";
|
||||
|
||||
enum AutoTriggerOptions {
|
||||
Disabled = "disabled",
|
||||
EnabledNoWS = "n-ws",
|
||||
EnabledYesWS = "y-ws",
|
||||
}
|
||||
|
||||
enum SnippetType {
|
||||
SLSR = 0,
|
||||
SLMR = 1,
|
||||
MLSR = 2,
|
||||
MLMR = 3,
|
||||
}
|
||||
|
||||
interface JellySnippetsSettings {
|
||||
snippetsFile: string;
|
||||
triggerOnSpace: AutoTriggerOptions;
|
||||
|
|
@ -28,10 +26,7 @@ interface JellySnippetsSettings {
|
|||
triggerOnTab: AutoTriggerOptions;
|
||||
snippetPartDivider: string;
|
||||
snippetDivider: string;
|
||||
// postSnippetCursorSymbol: string; // TODO
|
||||
}
|
||||
// TODO: implement cursor move after snippet replace.
|
||||
// ? TODO: Can we implement growable lists in settings?
|
||||
|
||||
const DEFAULT_SETTINGS: JellySnippetsSettings = {
|
||||
snippetsFile: String.raw`Snip me! |+| Snippet successfully replaced.
|
||||
|
|
@ -46,26 +41,14 @@ const DEFAULT_SETTINGS: JellySnippetsSettings = {
|
|||
triggerOnTab: AutoTriggerOptions.Disabled,
|
||||
snippetPartDivider: " |+| ",
|
||||
snippetDivider: "-==-",
|
||||
// postSnippetCursorSymbol: "%move%", // TODO: Actually implement this symbol.
|
||||
};
|
||||
|
||||
// TODO: Add semantic symbols to represent certain special characters.
|
||||
// TODO: Also implement those semantic symbols for control characters.
|
||||
// Specifically, allow me to add a "whitespace" symbol so that I can put newlines in snippets if I need.
|
||||
// TODO: I should use regexable snippets. Or at least implement it somehow somewhere.
|
||||
// regex: ^.*(all the whitespace, word delimiters)<snippet regex>
|
||||
/*
|
||||
The thing about regex snippets is that the more power we want to add, the harder it is to implement.
|
||||
! Also, need to test safety of regex... use safe-regex (npm)
|
||||
*/
|
||||
|
||||
export default class JellySnippets extends Plugin {
|
||||
settings: JellySnippetsSettings;
|
||||
private multilineSnippets: { [key: string]: string } = {};
|
||||
private multilineSnippets: { [key: LHS]: RHS } = {};
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
console.log("load");
|
||||
|
||||
// Check settings and load snippets in.
|
||||
this.reloadSnippets();
|
||||
|
|
@ -97,7 +80,6 @@ export default class JellySnippets extends Plugin {
|
|||
})
|
||||
);
|
||||
}
|
||||
console.log("load 2");
|
||||
|
||||
this.addCommand({
|
||||
id: "trigger-snippet",
|
||||
|
|
@ -133,44 +115,47 @@ export default class JellySnippets extends Plugin {
|
|||
}
|
||||
|
||||
reloadSnippets(): void {
|
||||
console.log("reloading");
|
||||
console.log("Jelly Snippets: Reloading snippets.");
|
||||
this.multilineSnippets = {};
|
||||
this.parseSnippets();
|
||||
}
|
||||
|
||||
parseSnippets(): void {
|
||||
// If they specified newline control character, split snippets by newline.
|
||||
// ! If so, there can be no multiline snippets!
|
||||
// TODO: Can we make it so that leaving the setting blank is newline separation?
|
||||
let snippetDivider =
|
||||
this.settings.snippetDivider == "\\n"
|
||||
? "\n"
|
||||
: this.settings.snippetDivider;
|
||||
: this.settings.snippetDivider + "\n";
|
||||
|
||||
// go through the snippets file, split by the snippet divider, split by the part divider, put in map
|
||||
let snippetLines = this.settings.snippetsFile.split(snippetDivider);
|
||||
for (let snippet of snippetLines) {
|
||||
// trim() is used so that each snippet line does not retain newlines.
|
||||
// TODO: Again, control characters or semantic symbols in lhs.
|
||||
|
||||
// Trim newlines. Instead, use symbols to let people insert whitespace.
|
||||
// This split means only the first division of the part divider is the LHS.
|
||||
let snippetParts = snippet
|
||||
.trim()
|
||||
.trimEnd()
|
||||
.split(this.settings.snippetPartDivider);
|
||||
if (snippetParts.length !== 2) {
|
||||
// probably an incomplete snippet
|
||||
continue;
|
||||
}
|
||||
// Produce lhs. Continue if undefined.
|
||||
let lhs = snippetParts.shift();
|
||||
console.log(lhs);
|
||||
let rhs = snippetParts.join(this.settings.snippetPartDivider);
|
||||
if (lhs === undefined) {
|
||||
console.log("Failed to register snippet: ", snippet);
|
||||
} else {
|
||||
this.multilineSnippets[lhs] = rhs;
|
||||
continue;
|
||||
}
|
||||
// Produce rhs (raw data).
|
||||
// * This is a join in case they used their snippetPartDivider too many times.
|
||||
let rhsData = snippetParts.join(this.settings.snippetPartDivider);
|
||||
// Scan rhs for symbols and perform the replacements; acquire RHS.
|
||||
let rhs = Symbol.replaceSymbolsOnParse(rhsData);
|
||||
this.multilineSnippets[lhs] = rhs;
|
||||
}
|
||||
console.log(this.multilineSnippets);
|
||||
}
|
||||
|
||||
triggerSnippet(
|
||||
editor: Editor,
|
||||
pos?: EditorPosition
|
||||
): [string, string] | undefined {
|
||||
triggerSnippet(editor: Editor, pos?: EditorPosition): Snippet | undefined {
|
||||
let curpos = pos ? pos : editor.getCursor();
|
||||
return this.triggerMultilineSnippet(editor, curpos);
|
||||
}
|
||||
|
|
@ -183,7 +168,6 @@ export default class JellySnippets extends Plugin {
|
|||
this.settings.triggerOnSpace !== AutoTriggerOptions.Disabled
|
||||
) {
|
||||
if (this.triggerSnippet(editor)) {
|
||||
// TODO: actually provide autotriggeroptions for Space.
|
||||
// Currently impossible to undo the space because the entire snippet
|
||||
// and all this code triggers before the space actually happens.
|
||||
return true;
|
||||
|
|
@ -224,7 +208,7 @@ export default class JellySnippets extends Plugin {
|
|||
) {
|
||||
return false;
|
||||
}
|
||||
// Since the newline comes out first, we need to track where our old position was before newline.
|
||||
// Since the newline comes out first, we need to find our old position before newline (peekPos).
|
||||
let curpos = editor.getCursor();
|
||||
let aboveline = curpos.line - 1;
|
||||
let abovelineEnd = editor.getLine(aboveline).length;
|
||||
|
|
@ -232,45 +216,43 @@ export default class JellySnippets extends Plugin {
|
|||
line: aboveline,
|
||||
ch: abovelineEnd,
|
||||
};
|
||||
// Try to trigger the snippet at the old position.
|
||||
let maybeSnippet = this.triggerSnippet(editor, peekPos);
|
||||
|
||||
// If the snippet triggered, clean up the newline.
|
||||
if (maybeSnippet) {
|
||||
let snippetType = this.getSnippetType(maybeSnippet);
|
||||
// delete newline at the end of snippet
|
||||
let curpos = editor.getCursor();
|
||||
let curoffset = editor.posToOffset(curpos);
|
||||
// get end of replacement part
|
||||
let rhsEndOffset =
|
||||
curoffset + maybeSnippet.rhs.info.cursorEnd;
|
||||
let rhsEndPos = editor.offsetToPos(rhsEndOffset);
|
||||
// the line after that (works at document end)
|
||||
let afterSnippetLinePos = {
|
||||
line: rhsEndPos.line + 1,
|
||||
ch: 0,
|
||||
};
|
||||
editor.replaceRange("", rhsEndPos, afterSnippetLinePos);
|
||||
|
||||
// If they want the newline added where the cursor is at (works weird for cursorEnd snippets but eh)
|
||||
// TODO: maybe make another setting where add newline on enter is disabled if snippet has a cursorEnd?
|
||||
if (
|
||||
this.settings.triggerOnEnter ===
|
||||
AutoTriggerOptions.EnabledNoWS
|
||||
AutoTriggerOptions.EnabledYesWS
|
||||
) {
|
||||
// NoWS
|
||||
if (snippetType === SnippetType.MLSR) {
|
||||
// RCNN - do nothing
|
||||
} else {
|
||||
// RCNDMU - delete from curpos to start of next line
|
||||
let curpos = editor.getCursor();
|
||||
let nextLine = curpos.line + 1;
|
||||
let nextLineStartPos: EditorPosition = {
|
||||
line: nextLine,
|
||||
// Insert newline where we are at.
|
||||
editor.exec("newlineAndIndent");
|
||||
curpos = editor.getCursor();
|
||||
// To "de-indent", delete until start of line.
|
||||
editor.replaceRange(
|
||||
"",
|
||||
{
|
||||
line: curpos.line,
|
||||
ch: 0,
|
||||
};
|
||||
editor.replaceRange("", curpos, nextLineStartPos);
|
||||
}
|
||||
} else {
|
||||
// YesWS
|
||||
let curpos = editor.getCursor();
|
||||
if (snippetType === SnippetType.MLSR) {
|
||||
// RCNN - insert newline ("repeat enter") / replace curpos with newline
|
||||
editor.exec("newlineAndIndent");
|
||||
editor.exec("indentLess");
|
||||
} else {
|
||||
// RCNDMU - move to start of next line / to the right
|
||||
editor.exec("goRight");
|
||||
|
||||
// * To calculate it:
|
||||
// let nextLine = curpos.line + 1;
|
||||
// let nextLineStartPos: EditorPosition = {
|
||||
// line: nextLine,
|
||||
// ch: 0,
|
||||
// };
|
||||
// editor.setCursor(nextLineStartPos);
|
||||
}
|
||||
},
|
||||
curpos
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -290,35 +272,41 @@ export default class JellySnippets extends Plugin {
|
|||
triggerMultilineSnippet(
|
||||
editor: Editor,
|
||||
pos?: EditorPosition
|
||||
): [string, string] | undefined {
|
||||
): Snippet | undefined {
|
||||
const curpos = pos ? pos : editor.getCursor();
|
||||
const curoffset = editor.posToOffset(curpos);
|
||||
|
||||
// @ts-expect-error
|
||||
const view = editor.cm as EditorView;
|
||||
|
||||
for (let [lhs, rhs] of Object.entries(this.multilineSnippets)) {
|
||||
if (!this.selectBackN(editor, lhs.length, curpos)) {
|
||||
// console.log(
|
||||
// "Error: failed to select back N at: " +
|
||||
// pos +
|
||||
// " with lhs: " +
|
||||
// lhs
|
||||
// );
|
||||
continue;
|
||||
}
|
||||
const from = curoffset - lhs.length;
|
||||
const to = curoffset;
|
||||
|
||||
// Get the text just before the cursor
|
||||
let selected = view.state.sliceDoc(from, to);
|
||||
|
||||
// If the selected string is the LHS, replace it!
|
||||
let selected = editor.getSelection();
|
||||
if (lhs === selected) {
|
||||
editor.replaceSelection(rhs);
|
||||
// Dispatch the replacement and move the cursor to where it should be.
|
||||
view.dispatch({
|
||||
changes: [
|
||||
{
|
||||
from,
|
||||
to,
|
||||
insert: rhs.data,
|
||||
},
|
||||
],
|
||||
selection: {
|
||||
anchor: from + rhs.data.length - rhs.info.cursorEnd,
|
||||
},
|
||||
});
|
||||
|
||||
// Reset selection to where the cursor is *after* replacement.
|
||||
// Allows "enabled-with-whitespace" auto replacements to work.
|
||||
this.unselect(editor);
|
||||
return [lhs, rhs];
|
||||
// Return what you replaced.
|
||||
return { lhs, rhs };
|
||||
}
|
||||
|
||||
// Reset selection to where the cursor is.
|
||||
this.unselect(editor, curpos);
|
||||
}
|
||||
|
||||
// No replace - return undefined
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -326,12 +314,12 @@ export default class JellySnippets extends Plugin {
|
|||
// Single snippets (no newlines) and multi snippets (newlines)
|
||||
// have different, weird interaction with Obsidian. Sometimes the whitespace goes through, sometimes not.
|
||||
// There needs to be a way of determining what type (mlhs->srhs? mlhs->mrhs? slhs? srhs? etc.) a snippet is.
|
||||
getSnippetType(snippet: [string, string]): SnippetType {
|
||||
let [lhs, rhs] = snippet;
|
||||
getSnippetType(snippet: Snippet): SnippetType {
|
||||
let { lhs, rhs } = snippet;
|
||||
let type = SnippetType.SLSR;
|
||||
// Compiler doesn't complain if we convert boolean to number with unary '+'.
|
||||
type |= +lhs.contains("\n") && SnippetType.MLSR;
|
||||
type |= +rhs.contains("\n") && SnippetType.SLMR;
|
||||
type |= +lhs.includes("\n") ? SnippetType.MLSR : 0;
|
||||
type |= +rhs.info.hasNewline ? SnippetType.SLMR : 0;
|
||||
return type;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"id": "jelly-snippets",
|
||||
"name": "Jelly Snippets",
|
||||
"version": "0.1.6",
|
||||
"version": "0.2.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "A simple plugin for text snippets, with auto replacement",
|
||||
"author": "Spencer Gouw",
|
||||
"authorUrl": "github.com/rabirabirara",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
}
|
||||
20
src/snippet.ts
Normal file
20
src/snippet.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
export type LHS = string;
|
||||
export interface RHS {
|
||||
data: string;
|
||||
info: {
|
||||
hasNewline: boolean;
|
||||
cursorEnd: number;
|
||||
};
|
||||
}
|
||||
|
||||
export type Snippet = {
|
||||
lhs: LHS;
|
||||
rhs: RHS;
|
||||
};
|
||||
|
||||
export enum SnippetType {
|
||||
SLSR = 0,
|
||||
SLMR = 1,
|
||||
MLSR = 2,
|
||||
MLMR = 3,
|
||||
}
|
||||
81
src/symbol.ts
Normal file
81
src/symbol.ts
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import { RHS } from "src/snippet";
|
||||
|
||||
export enum Symbol {
|
||||
// on parse
|
||||
Newline = "%\\n",
|
||||
Tab = "%\\t",
|
||||
Space = "%\\s",
|
||||
// on replace
|
||||
CursorEnd = "%\\e",
|
||||
}
|
||||
|
||||
export namespace Symbol {
|
||||
const REPLACEABLE: Record<string, string> = {
|
||||
[Symbol.Newline]: "\n",
|
||||
[Symbol.Tab]: "\t",
|
||||
[Symbol.Space]: " ",
|
||||
};
|
||||
// const ON_REPLACE: Record<string, string> = {
|
||||
// [Symbol.CursorEnd]: "",
|
||||
// };
|
||||
export function replaceSymbolsOnParse(inputStr: string): RHS {
|
||||
const result: string[] = [];
|
||||
const len = inputStr.length;
|
||||
let i = 0;
|
||||
let cursor = 0;
|
||||
let endFoundIdx = -1;
|
||||
let hasNewline = false;
|
||||
let found;
|
||||
while (i < inputStr.length) {
|
||||
found = false;
|
||||
for (const symbol in REPLACEABLE) {
|
||||
if (inputStr.startsWith(symbol, i)) {
|
||||
result.push(REPLACEABLE[symbol]);
|
||||
cursor += REPLACEABLE[symbol].length;
|
||||
i += symbol.length;
|
||||
found = true;
|
||||
if (symbol == Symbol.Newline) {
|
||||
hasNewline = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Check for cursorEnd symbol.
|
||||
if (inputStr.startsWith(Symbol.CursorEnd, i)) {
|
||||
i += Symbol.CursorEnd.length;
|
||||
// cursor marks the index in final string, we derive the "how far to move left" from it
|
||||
endFoundIdx = cursor;
|
||||
found = true;
|
||||
}
|
||||
if (!found) {
|
||||
result.push(inputStr[i]);
|
||||
cursor++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
let data = result.join("");
|
||||
let info = {
|
||||
hasNewline,
|
||||
cursorEnd: endFoundIdx < 0 ? 0 : data.length - endFoundIdx,
|
||||
};
|
||||
|
||||
return { data, info };
|
||||
}
|
||||
}
|
||||
|
||||
// Some tests!
|
||||
// let rhs1 = Symbol.replaceSymbolsOnParse("123%\\e45678");
|
||||
// console.log(rhs1);
|
||||
// let rhs2 = Symbol.replaceSymbolsOnParse("12345678%\\e");
|
||||
// console.log(rhs2);
|
||||
// let rhs3 = Symbol.replaceSymbolsOnParse("%\\e12345678");
|
||||
// console.log(rhs3);
|
||||
// let rhs4 = Symbol.replaceSymbolsOnParse("12%\\e3");
|
||||
// console.log(rhs4);
|
||||
// let rhs5 = Symbol.replaceSymbolsOnParse("1%\\e23");
|
||||
// console.log(rhs5);
|
||||
// let rhs6 = Symbol.replaceSymbolsOnParse("%\\e123");
|
||||
// console.log(rhs6);
|
||||
// let rhs7 = Symbol.replaceSymbolsOnParse("123%\\n4%\\e56");
|
||||
// console.log(rhs7);
|
||||
// console.log(rhs7.data);
|
||||
Loading…
Reference in a new issue