From 9b2378c3d28ba57f2a71f7336b4cf943dbc011d7 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Wed, 4 Aug 2021 00:32:30 +0200 Subject: [PATCH] Introduce editable module --- qt/aqt/data/web/css/BUILD.bazel | 10 +- ts/editable/BUILD.bazel | 102 ++++++++++++++++++ .../editable-base.scss} | 0 ts/{editor => editable}/editable-container.ts | 2 + ts/{editor => editable}/editable.ts | 25 +++-- ts/editable/index.ts | 5 + ts/editor/BUILD.bazel | 14 +-- ts/editor/FormatBlockButtons.svelte | 7 +- ts/editor/WithImageConstrained.svelte | 4 +- ts/editor/codable.ts | 2 + ts/editor/editing-area.ts | 6 +- ts/editor/editor-field.ts | 2 + ts/editor/helpers.ts | 91 ---------------- ts/editor/index.ts | 24 ++--- ts/editor/input-handlers.ts | 2 +- ts/editor/label-container.ts | 2 + ts/lib/dom.ts | 89 +++++++++++++++ ts/tsconfig.json | 1 + 18 files changed, 255 insertions(+), 133 deletions(-) create mode 100644 ts/editable/BUILD.bazel rename ts/{editor/editable.scss => editable/editable-base.scss} (100%) rename ts/{editor => editable}/editable-container.ts (95%) rename ts/{editor => editable}/editable.ts (70%) create mode 100644 ts/editable/index.ts create mode 100644 ts/lib/dom.ts diff --git a/qt/aqt/data/web/css/BUILD.bazel b/qt/aqt/data/web/css/BUILD.bazel index 6ac2deb4c..30f5a4788 100644 --- a/qt/aqt/data/web/css/BUILD.bazel +++ b/qt/aqt/data/web/css/BUILD.bazel @@ -21,11 +21,19 @@ copy_files_into_group( name = "editor", srcs = [ "editor.css", - "editable.css", ], package = "//ts/editor", ) + +copy_files_into_group( + name = "editable", + srcs = [ + "editable-build.css", + ], + package = "//ts/editable", +) + copy_files_into_group( name = "reviewer", srcs = [ diff --git a/ts/editable/BUILD.bazel b/ts/editable/BUILD.bazel new file mode 100644 index 000000000..fa22483a0 --- /dev/null +++ b/ts/editable/BUILD.bazel @@ -0,0 +1,102 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") +load("//ts/svelte:svelte.bzl", "compile_svelte", "svelte_check") +load("//ts:prettier.bzl", "prettier_test") +load("//ts:eslint.bzl", "eslint_test") +load("//ts:esbuild.bzl", "esbuild") +load("//ts:vendor.bzl", "copy_bootstrap_icons", "copy_mdi_icons") +load("//ts:compile_sass.bzl", "compile_sass") + +svelte_files = glob(["*.svelte"]) + +svelte_names = [f.replace(".svelte", "") for f in svelte_files] + +filegroup( + name = "svelte_components", + srcs = svelte_names, + visibility = ["//visibility:public"], +) + +compile_svelte( + name = "svelte", + srcs = svelte_files, + visibility = ["//visibility:public"], + deps = [ + "//ts/components", + ], +) + +compile_sass( + srcs = [ + "editable-base.scss", + ], + group = "editable_scss", + visibility = ["//visibility:public"], + deps = [ + "//ts/sass:scrollbar_lib", + "//ts/sass/codemirror", + ], +) + +ts_library( + name = "editable", + srcs = glob(["*.ts"]), + module_name = "editable", + tsconfig = "//ts:tsconfig.json", + visibility = ["//visibility:public"], + deps = [ + "//ts/lib", + "//ts/sveltelib", + "//ts/components", + "//ts:image_module_support", + "@npm//svelte", + ] + svelte_names, +) + +esbuild( + name = "editable-build", + args = [ + "--loader:.svg=text", + "--resolve-extensions=.mjs,.js", + "--log-level=warning", + ], + entry_point = "index.ts", + output_css = "editable-build.css", + visibility = ["//visibility:public"], + deps = [ + "editable_ts", + "svelte_components", + "//ts/components", + "//ts/components:svelte_components", + "@npm//protobufjs", + ], +) + +# Tests +################ + +prettier_test( + name = "format_check", + srcs = glob([ + "*.ts", + "*.svelte", + ]), +) + +eslint_test( + name = "eslint", + srcs = glob( + [ + "*.ts", + ], + ), +) + +svelte_check( + name = "svelte_check", + srcs = glob([ + "*.ts", + "*.svelte", + ]) + [ + "//ts/components", + ], +) diff --git a/ts/editor/editable.scss b/ts/editable/editable-base.scss similarity index 100% rename from ts/editor/editable.scss rename to ts/editable/editable-base.scss diff --git a/ts/editor/editable-container.ts b/ts/editable/editable-container.ts similarity index 95% rename from ts/editor/editable-container.ts rename to ts/editable/editable-container.ts index 3448e662e..ed9d2c7e4 100644 --- a/ts/editor/editable-container.ts +++ b/ts/editable/editable-container.ts @@ -57,3 +57,5 @@ export class EditableContainer extends HTMLDivElement { return this.baseRule!.style.direction === "rtl"; } } + +customElements.define("anki-editable-container", EditableContainer, { extends: "div" }); diff --git a/ts/editor/editable.ts b/ts/editable/editable.ts similarity index 70% rename from ts/editor/editable.ts rename to ts/editable/editable.ts index 38ee75646..57ce5c7ce 100644 --- a/ts/editor/editable.ts +++ b/ts/editable/editable.ts @@ -1,10 +1,19 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -import { bridgeCommand } from "./lib"; -import { elementIsBlock, caretToEnd, getBlockElement } from "./helpers"; -import { inCodable } from "./toolbar"; -import { wrap } from "./wrap"; +import { bridgeCommand } from "lib/bridgecommand"; +import { elementIsBlock, getBlockElement } from "lib/dom"; +// import { inCodable } from "./toolbar"; +// import { wrap } from "./wrap"; + +export function caretToEnd(node: Node): void { + const range = document.createRange(); + range.selectNodeContents(node); + range.collapse(false); + const selection = (node.getRootNode() as Document | ShadowRoot).getSelection()!; + selection.removeAllRanges(); + selection.addRange(range); +} function containsInlineContent(element: Element): boolean { for (const child of element.children) { @@ -37,7 +46,8 @@ export class Editable extends HTMLElement { focus(): void { super.focus(); - inCodable.set(false); + // TODO + // inCodable.set(false); } caretToEnd(): void { @@ -45,7 +55,8 @@ export class Editable extends HTMLElement { } surroundSelection(before: string, after: string): void { - wrap(before, after); + // TODO + // wrap(before, after); } onEnter(event: KeyboardEvent): void { @@ -63,3 +74,5 @@ export class Editable extends HTMLElement { event.preventDefault(); } } + +customElements.define("anki-editable", Editable); diff --git a/ts/editable/index.ts b/ts/editable/index.ts new file mode 100644 index 000000000..9dd688339 --- /dev/null +++ b/ts/editable/index.ts @@ -0,0 +1,5 @@ +// Copyright: Ankitects Pty Ltd and contributors +// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +import "./editable-container"; +import "./editable"; diff --git a/ts/editor/BUILD.bazel b/ts/editor/BUILD.bazel index 2d25e998c..e2ff25dae 100644 --- a/ts/editor/BUILD.bazel +++ b/ts/editor/BUILD.bazel @@ -25,18 +25,6 @@ compile_svelte( ], ) -compile_sass( - srcs = [ - "editable.scss", - ], - group = "editable_scss", - visibility = ["//visibility:public"], - deps = [ - "//ts/sass:scrollbar_lib", - "//ts/sass/codemirror", - ], -) - compile_sass( srcs = [ "fields.scss", @@ -71,6 +59,7 @@ ts_library( "//ts/lib", "//ts/sveltelib", "//ts/components", + "//ts/editable", "//ts/html-filter", "//ts:image_module_support", "@npm//svelte", @@ -156,6 +145,7 @@ esbuild( "bootstrap-icons", "mdi-icons", "svelte_components", + "//ts/editable", "//ts/components", "//ts/components:svelte_components", "@npm//protobufjs", diff --git a/ts/editor/FormatBlockButtons.svelte b/ts/editor/FormatBlockButtons.svelte index d2fc2a140..b7cf587c8 100644 --- a/ts/editor/FormatBlockButtons.svelte +++ b/ts/editor/FormatBlockButtons.svelte @@ -14,7 +14,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import OnlyEditable from "./OnlyEditable.svelte"; import CommandIconButton from "./CommandIconButton.svelte"; - import { getCurrentField, getListItem } from "./helpers"; + import { getListItem } from "lib/dom"; + import { getCurrentField } from "./helpers"; import { ulIcon, olIcon, @@ -31,7 +32,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html function outdentListItem() { const currentField = getCurrentField(); - if (getListItem(currentField.editableContainer.shadowRoot!)) { + if (getListItem(currentField!.editableContainer.shadowRoot!)) { document.execCommand("outdent"); } else { alert("Indent/unindent currently only works with lists."); @@ -40,7 +41,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html function indentListItem() { const currentField = getCurrentField(); - if (getListItem(currentField.editableContainer.shadowRoot!)) { + if (getListItem(currentField!.editableContainer.shadowRoot!)) { document.execCommand("indent"); } else { alert("Indent/unindent currently only works with lists."); diff --git a/ts/editor/WithImageConstrained.svelte b/ts/editor/WithImageConstrained.svelte index a9e303b2d..ab48e6fe5 100644 --- a/ts/editor/WithImageConstrained.svelte +++ b/ts/editor/WithImageConstrained.svelte @@ -4,12 +4,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -->