lexxy 0.9.20 → 0.9.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e6fda495d92cad60dac933e1fbe6466f0813def098debbe4bea232130db0721
4
- data.tar.gz: 0e579b377be3610f91228422dcd3480bae586942aee4294c5d3bd580f60f0de4
3
+ metadata.gz: 3dd84ec12b2544306275e4c55775e2ef95770e6e9de65adb028663f51bd099e6
4
+ data.tar.gz: c3bc7b9f5834a80f1e40de9e2c82fec32ce590aba1cb2022eb13c320303dd92d
5
5
  SHA512:
6
- metadata.gz: 4527448422497989de11f0173dbaab24f357c477e8661f7511f8b1d3f9794b60e0073496266205ae641975a08439cabbbe084a435f6b9499e3d9675a394959bf
7
- data.tar.gz: f43f34d4a40a05f0fdd13d29afa67c68abb9e55b13f0d3703e36181af4f7e1d12fcb4ddf29d706bdf301d877cd95147cb734310f9b5110fd449556984b35293f
6
+ metadata.gz: 3a29b71559385f62b6b084731cc77baea92c67ebe10b0f588610de8d5d9cecba54403f7201c8bbc1143a0122402195b356d7c0b45bac6d176136dbefcb016b02
7
+ data.tar.gz: 05cac4466fc4374f1cfbe3e547a462e2cdceed094b2eb043e6a713ff165ff852ec39f08d8f15aed0ae4e24634376243cced2ca36e37e5657bb87faaac4991f8b
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A modern rich text editor for Rails.
4
4
 
5
- **[Try it out!](https://basecamp.github.io/lexxy/try-it)**
5
+ [Documentation](https://basecamp.github.io/lexxy/docs/) | <mark>[Try it out!](https://basecamp.github.io/lexxy/sandbox/)</mark>
6
6
 
7
7
  ## Features
8
8
 
@@ -15,24 +15,7 @@ A modern rich text editor for Rails.
15
15
  - Preview attachments like PDFs and Videos in the editor.
16
16
  - Works seamlessly with Action Text, generating the same canonical HTML format it expects for attachments.
17
17
 
18
- ![Lexxy editor screenshot](docs/images/home.screenshot.png)
19
-
20
- ## Documentation
21
-
22
- Visit the **[documentation site](https://basecamp.github.io/lexxy)**.
23
-
24
- ## Roadmap
25
-
26
- This is a beta. Here's what's coming next:
27
-
28
- - [x] Configurable editors in Action Text: Choose your editor like you choose your database.
29
- - [x] More editing features:
30
- - [x] Tables
31
- - [x] Text highlighting
32
- - [x] Configuration hooks.
33
- - [x] Standalone JS package: to use in non-Rails environments.
34
- - [x] Image galleries: The only remaining feature for full Action Text compatibility
35
- - [ ] Install task that generates the necessary JS and adds stylesheets.
18
+ ![Lexxy editor screenshot](home/docs/images/home.screenshot.png)
36
19
 
37
20
  ## Contributing
38
21
 
@@ -12884,7 +12884,7 @@ class Clipboard {
12884
12884
  }
12885
12885
 
12886
12886
  if (this.#isPlainTextOrURLPasted(clipboardData)) {
12887
- this.#pastePlainText(clipboardData);
12887
+ this.#pastePlainTextOrURL(clipboardData);
12888
12888
  event.preventDefault();
12889
12889
  return true
12890
12890
  }
@@ -12922,14 +12922,34 @@ class Clipboard {
12922
12922
  return types.length === 1 && types[0] === "text/plain"
12923
12923
  }
12924
12924
 
12925
+ // Browsers expose a copied URL in several shapes:
12926
+ // Safari [ text/plain, text/uri-list ]
12927
+ // App ShareSheet [ text/uri-list ]
12928
+ // Chromium macOS [ text/plain, text/html, (?:text/link-preview) ]
12925
12929
  #isOnlyURLPasted(clipboardData) {
12926
- // Safari URLs are copied as a text/plain + text/uri-list object
12927
- // App ShareSheet URLs are copied as solo text/uri-list object
12930
+ if (this.#isLexicalClipboardData(clipboardData)) return false
12931
+
12928
12932
  const types = Array.from(clipboardData.types);
12929
- return types.length
12930
- && types.length <= 2
12931
- && types.includes("text/uri-list")
12932
- && (types.length < 2 || types.includes("text/plain"))
12933
+ if (types.includes("text/uri-list")) {
12934
+ return types.every(type => type === "text/plain" || type === "text/uri-list")
12935
+ }
12936
+
12937
+ if (clipboardData.files.length) return false
12938
+
12939
+ const text = clipboardData.getData("text/plain").trim();
12940
+ if (!isAutolinkableURL(text)) return false
12941
+
12942
+ const html = clipboardData.getData("text/html");
12943
+ return !html || this.#htmlIsBareLinkToURL(html, text)
12944
+ }
12945
+
12946
+ #htmlIsBareLinkToURL(html, url) {
12947
+ const doc = parseHtml(html);
12948
+ if (doc.body.textContent.trim() !== url) return false
12949
+
12950
+ const links = doc.body.querySelectorAll("a");
12951
+ if (links.length === 0) return true
12952
+ return links.length === 1 && links[0].getAttribute("href") === url
12933
12953
  }
12934
12954
 
12935
12955
  #isPastingIntoCodeBlock() {
@@ -12963,14 +12983,12 @@ class Clipboard {
12963
12983
  }, { tag: jn });
12964
12984
  }
12965
12985
 
12966
- #pastePlainText(clipboardData) {
12967
- const item = clipboardData.items[0];
12986
+ #pastePlainTextOrURL(clipboardData) {
12987
+ const item = this.#plainTextOrURLItem(clipboardData);
12968
12988
  item.getAsString((text) => {
12969
- if (isAutolinkableURL(text) && this.contents.hasSelectedText()) {
12970
- this.contents.createLinkWithSelectedText(text);
12971
- } else if (isAutolinkableURL(text)) {
12972
- const nodeKey = this.contents.createLink(text);
12973
- this.#dispatchLinkInsertEvent(nodeKey, { url: text });
12989
+ const url = text.trim();
12990
+ if (isAutolinkableURL(url)) {
12991
+ this.#pasteURL(url);
12974
12992
  } else if (this.editorElement.supportsMarkdown) {
12975
12993
  this.#pasteMarkdown(text);
12976
12994
  } else {
@@ -12979,6 +12997,20 @@ class Clipboard {
12979
12997
  });
12980
12998
  }
12981
12999
 
13000
+ #plainTextOrURLItem(clipboardData) {
13001
+ const items = Array.from(clipboardData.items);
13002
+ return items.find((item) => item.type === "text/plain") || items.find((item) => item.type === "text/uri-list")
13003
+ }
13004
+
13005
+ #pasteURL(url) {
13006
+ if (this.contents.hasSelectedText()) {
13007
+ this.contents.createLinkWithSelectedText(url);
13008
+ } else {
13009
+ const nodeKey = this.contents.createLink(url);
13010
+ this.#dispatchLinkInsertEvent(nodeKey, { url });
13011
+ }
13012
+ }
13013
+
12982
13014
  #insertSingleLinkAt(selection, url) {
12983
13015
  if (!Fr(selection)) return
12984
13016
 
@@ -13437,6 +13469,26 @@ function $getAllProvisionalParagraphs(rootNode = Zo()) {
13437
13469
  return Ht$3(rootNode.getChildren(), $isProvisionalParagraphNode)
13438
13470
  }
13439
13471
 
13472
+ // Registers code highlighting through the extension system so its node
13473
+ // transforms exist before the initial editor state is applied. Registering
13474
+ // after editor creation misses code blocks loaded from the initial value:
13475
+ // their transform pass has already run, and Lexical's catch-up dirtying
13476
+ // only sees the committed (still empty) state.
13477
+ class CodeHighlightingExtension extends LexxyExtension {
13478
+ get enabled() {
13479
+ return this.editorElement.supportsRichText
13480
+ }
13481
+
13482
+ get lexicalExtension() {
13483
+ return dc({
13484
+ name: "lexxy/code-highlighting",
13485
+ register(editor) {
13486
+ return L$1(editor)
13487
+ }
13488
+ })
13489
+ }
13490
+ }
13491
+
13440
13492
  const TRIX_LANGUAGE_ATTR = "language";
13441
13493
 
13442
13494
  class TrixContentExtension extends LexxyExtension {
@@ -14957,6 +15009,7 @@ class LexicalEditorElement extends HTMLElement {
14957
15009
  get baseExtensions() {
14958
15010
  return [
14959
15011
  ProvisionalParagraphExtension,
15012
+ CodeHighlightingExtension,
14960
15013
  HighlightExtension,
14961
15014
  TrixContentExtension,
14962
15015
  TablesExtension,
@@ -15364,7 +15417,7 @@ class LexicalEditorElement extends HTMLElement {
15364
15417
  Ie$2(this.editor)
15365
15418
  );
15366
15419
  this.#registerTableComponents();
15367
- this.#registerCodeHiglightingComponents();
15420
+ this.#registerCodeLanguagePicker();
15368
15421
  if (this.supportsMarkdown) {
15369
15422
  const transformers = [ ...te, HORIZONTAL_DIVIDER ];
15370
15423
  registered.push(
@@ -15386,8 +15439,7 @@ class LexicalEditorElement extends HTMLElement {
15386
15439
  this.#disposables.push(tableTools);
15387
15440
  }
15388
15441
 
15389
- #registerCodeHiglightingComponents() {
15390
- L$1(this.editor);
15442
+ #registerCodeLanguagePicker() {
15391
15443
  let codeLanguagePicker = this.querySelector("lexxy-code-language-picker");
15392
15444
  codeLanguagePicker ??= createElement("lexxy-code-language-picker");
15393
15445
  this.append(codeLanguagePicker);
Binary file
Binary file