mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 14:32:22 -04:00
Use Unicode delimiter character
This commit is contained in:
parent
6ccf75a077
commit
3de1d6e604
3 changed files with 48 additions and 38 deletions
|
@ -16,18 +16,28 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
import ButtonToolbar from "components/ButtonToolbar.svelte";
|
||||||
import { controlPressed } from "lib/keys";
|
import { controlPressed } from "lib/keys";
|
||||||
import type { Tag as TagType } from "./tags";
|
import type { Tag as TagType } from "./tags";
|
||||||
import { attachId, getName } from "./tags";
|
import {
|
||||||
|
attachId,
|
||||||
|
getName,
|
||||||
|
delimChar,
|
||||||
|
replaceWithDelimChar,
|
||||||
|
replaceWithColon,
|
||||||
|
} from "./tags";
|
||||||
|
|
||||||
export let size = isApplePlatform() ? 1.6 : 2.0;
|
export let size = isApplePlatform() ? 1.6 : 2.0;
|
||||||
|
|
||||||
export let tags: TagType[] = [];
|
export let tags: TagType[] = [];
|
||||||
|
|
||||||
export function resetTags(names: string[]): void {
|
export function resetTags(names: string[]): void {
|
||||||
tags = names.map(attachId);
|
tags = names.map(replaceWithDelimChar).map(attachId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveTags(): void {
|
function saveTags(): void {
|
||||||
bridgeCommand(`saveTags:${JSON.stringify(tags.map((tag) => tag.name))}`);
|
bridgeCommand(
|
||||||
|
`saveTags:${JSON.stringify(
|
||||||
|
tags.map((tag) => tag.name).map(replaceWithColon)
|
||||||
|
)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let active: number | null = null;
|
let active: number | null = null;
|
||||||
|
@ -43,7 +53,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
"en::vocabulary",
|
"en::vocabulary",
|
||||||
"en::idioms",
|
"en::idioms",
|
||||||
Math.random().toString(36).substring(2),
|
Math.random().toString(36).substring(2),
|
||||||
]);
|
]).then((names: string[]): string[] => names.map(replaceWithDelimChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAutocomplete(selected: string): void {
|
function onAutocomplete(selected: string): void {
|
||||||
|
@ -369,17 +379,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
$: shortenTags = shortenTags || assumedRows > 2;
|
$: shortenTags = shortenTags || assumedRows > 2;
|
||||||
|
|
||||||
function processTagName(name: string): string {
|
function processTagName(name: string): string {
|
||||||
const parts = name.split("::");
|
const parts = name.split(delimChar);
|
||||||
|
|
||||||
if (parts.length === 1) {
|
if (parts.length === 1) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "…::" + parts[parts.length - 1];
|
return `…${delimChar}` + parts[parts.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasMultipleParts(name: string): boolean {
|
function hasMultipleParts(name: string): boolean {
|
||||||
return name.split("::").length > 1;
|
return name.split(delimChar).length > 1;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
-->
|
-->
|
||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import { onMount, createEventDispatcher, tick } from "svelte";
|
import { onMount, createEventDispatcher, tick } from "svelte";
|
||||||
import { normalizeTagname } from "./tags";
|
import { normalizeTagname, delimChar } from "./tags";
|
||||||
|
|
||||||
export let id: string | undefined = undefined;
|
export let id: string | undefined = undefined;
|
||||||
let className: string = "";
|
let className: string = "";
|
||||||
|
@ -55,11 +55,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
const nameUptoCaret = name.slice(0, position);
|
const nameUptoCaret = name.slice(0, position);
|
||||||
|
|
||||||
if (nameUptoCaret.endsWith("::")) {
|
if (nameUptoCaret.endsWith(delimChar)) {
|
||||||
name = name.slice(0, position - 2) + name.slice(position, name.length);
|
name = name.slice(0, position - 1) + name.slice(position, name.length);
|
||||||
await tick();
|
await tick();
|
||||||
|
|
||||||
setPosition(position - 2);
|
setPosition(position - 1);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,36 +106,30 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onDelimiter(event: Event, single: boolean = false): Promise<void> {
|
async function onDelimiter(event: Event, single: boolean = false): Promise<void> {
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
const positionStart = input.selectionStart!;
|
const positionStart = input.selectionStart!;
|
||||||
const positionEnd = input.selectionEnd!;
|
const positionEnd = input.selectionEnd!;
|
||||||
|
|
||||||
const before = name.slice(0, positionStart);
|
const before = name.slice(0, positionStart);
|
||||||
if (before.endsWith("::")) {
|
|
||||||
|
if (before.endsWith(delimChar)) {
|
||||||
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return;
|
return;
|
||||||
|
} else if (before.endsWith(":")) {
|
||||||
|
event.preventDefault();
|
||||||
|
name = `${before.slice(0, -1)}${delimChar}${name.slice(
|
||||||
|
positionEnd,
|
||||||
|
name.length
|
||||||
|
)}`;
|
||||||
|
} else if (single) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
event.preventDefault();
|
||||||
|
name = `${before}${delimChar}${name.slice(positionEnd, name.length)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = `${before}${single ? ":" : "::"}${name.slice(positionEnd, name.length)}`;
|
|
||||||
|
|
||||||
await tick();
|
await tick();
|
||||||
setPosition(positionStart + (single ? 1 : 2));
|
setPosition(positionStart + 1);
|
||||||
}
|
|
||||||
|
|
||||||
function maybeMovePastDelimiter(event: Event, forwards: boolean): void {
|
|
||||||
const position = input.selectionStart!;
|
|
||||||
|
|
||||||
const before = name.slice(0, position);
|
|
||||||
const after = name.slice(position, name.length);
|
|
||||||
|
|
||||||
if (!forwards && before.endsWith("::")) {
|
|
||||||
setPosition(position - 2);
|
|
||||||
event.preventDefault();
|
|
||||||
} else if (forwards && after.startsWith("::")) {
|
|
||||||
setPosition(position + 2);
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKeydown(event: KeyboardEvent): void {
|
function onKeydown(event: KeyboardEvent): void {
|
||||||
|
@ -166,8 +160,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
} else if (caretAtStart()) {
|
} else if (caretAtStart()) {
|
||||||
dispatch("tagmoveprevious");
|
dispatch("tagmoveprevious");
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
} else if (isCollapsed()) {
|
|
||||||
maybeMovePastDelimiter(event, false);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -177,8 +169,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
} else if (caretAtEnd()) {
|
} else if (caretAtEnd()) {
|
||||||
dispatch("tagmovenext");
|
dispatch("tagmovenext");
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
} else if (isCollapsed()) {
|
|
||||||
maybeMovePastDelimiter(event, true);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
export const delimChar = "\u2237";
|
||||||
|
|
||||||
|
export function replaceWithDelimChar(name: string): string {
|
||||||
|
return name.replace(/::/g, delimChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function replaceWithColon(name: string): string {
|
||||||
|
return name.replace(/\u2237/gu, "::");
|
||||||
|
}
|
||||||
|
|
||||||
export function normalizeTagname(tagname: string): string {
|
export function normalizeTagname(tagname: string): string {
|
||||||
let trimmed = tagname.trim();
|
let trimmed = tagname.trim();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (trimmed.startsWith(":")) {
|
if (trimmed.startsWith(":") || trimmed.startsWith(delimChar)) {
|
||||||
trimmed = trimmed.slice(1).trimStart();
|
trimmed = trimmed.slice(1).trimStart();
|
||||||
} else if (trimmed.endsWith(":")) {
|
} else if (trimmed.endsWith(":") || trimmed.endsWith(delimChar)) {
|
||||||
trimmed = trimmed.slice(0, -1).trimEnd();
|
trimmed = trimmed.slice(0, -1).trimEnd();
|
||||||
} else {
|
} else {
|
||||||
return trimmed;
|
return trimmed;
|
||||||
|
|
Loading…
Reference in a new issue