diff --git a/Gemfile b/Gemfile index da66e1473..597899b7d 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ gem "geared_pagination", "~> 1.2" gem "rqrcode" gem "rouge" gem "jbuilder" -gem "lexxy", bc: "lexxy" +gem "lexxy", "0.8.5.beta" gem "image_processing", "~> 1.14" gem "platform_agent" gem "aws-sdk-s3", require: false diff --git a/Gemfile.lock b/Gemfile.lock index 8db6817dc..ae84f65f6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,3 @@ -GIT - remote: https://github.com/basecamp/lexxy - revision: b7f0f1429df5fa425eac043191ae2b65edee7488 - specs: - lexxy (0.7.6.beta) - rails (>= 8.0.2) - GIT remote: https://github.com/basecamp/useragent revision: 433ca320a42db1266c4b89df74d0abdb9a880c5e @@ -261,6 +254,8 @@ GEM logger (~> 1.6) letter_opener (1.10.0) launchy (>= 2.2, < 4) + lexxy (0.8.5.beta) + rails (>= 8.0.2) lint_roller (1.1.0) logger (1.7.0) loofah (2.25.0) @@ -523,7 +518,7 @@ DEPENDENCIES jbuilder kamal letter_opener - lexxy! + lexxy (= 0.8.5.beta) mission_control-jobs mittens mocha diff --git a/Gemfile.saas.lock b/Gemfile.saas.lock index 6f9b0d088..176a5218c 100644 --- a/Gemfile.saas.lock +++ b/Gemfile.saas.lock @@ -21,13 +21,6 @@ GIT rails (>= 7.0) rainbow -GIT - remote: https://github.com/basecamp/lexxy - revision: b7f0f1429df5fa425eac043191ae2b65edee7488 - specs: - lexxy (0.7.6.beta) - rails (>= 8.0.2) - GIT remote: https://github.com/basecamp/queenbee-plugin revision: 14312a940471e20617b38cdec7c092a01567d18b @@ -374,6 +367,8 @@ GEM logger (~> 1.6) letter_opener (1.10.0) launchy (>= 2.2, < 4) + lexxy (0.8.5.beta) + rails (>= 8.0.2) lint_roller (1.1.0) logger (1.7.0) loofah (2.25.0) @@ -729,7 +724,7 @@ DEPENDENCIES jbuilder kamal letter_opener - lexxy! + lexxy (= 0.8.5.beta) mission_control-jobs mittens mocha diff --git a/app/assets/stylesheets/attachments.css b/app/assets/stylesheets/attachments.css index 85dc7652d..8e3808ec5 100644 --- a/app/assets/stylesheets/attachments.css +++ b/app/assets/stylesheets/attachments.css @@ -3,8 +3,8 @@ block-size: auto; display: block; inline-size: fit-content; - position: relative; max-inline-size: 100%; + position: relative; progress { inline-size: 100%; @@ -35,8 +35,7 @@ @supports (field-sizing: content) { field-sizing: content; - inline-size: auto; - min-inline-size: 20ch; + inline-size: 100%; } } } diff --git a/app/assets/stylesheets/lexxy.css b/app/assets/stylesheets/lexxy.css index 8fb7658ee..053f626a9 100644 --- a/app/assets/stylesheets/lexxy.css +++ b/app/assets/stylesheets/lexxy.css @@ -120,6 +120,10 @@ margin-block: 1em; } + .lexxy-prompt-menu { + max-inline-size: min(35ch, calc(100% - var(--lexxy-prompt-offset-x))); + } + /* Content /* ------------------------------------------------------------------------ */ @@ -188,4 +192,29 @@ .attachment { margin-inline: 0; } + + .attachment-gallery { + .attachment { + display: inline-block; + inline-size: calc(33.333% - 0.8ch); + } + + &.attachment-gallery--2, + &.attachment-gallery--4 { + .attachment { + inline-size: calc(50% - 0.8ch); + } + } + } + + action-text-attachment[content-type^='application/vnd.actiontext'] { + lexxy-node-delete-button { + inset-inline-start: -0.25ch; + + .lexxy-floating-controls__group { + background-color: oklch(var(--lch-blue-dark)); + border-radius: 50%; + } + } + } } diff --git a/app/javascript/initializers/index.js b/app/javascript/initializers/index.js index 1d16ef205..d2c20451e 100644 --- a/app/javascript/initializers/index.js +++ b/app/javascript/initializers/index.js @@ -1,3 +1,4 @@ import "initializers/current" import "initializers/bridge/bridge_element" import "initializers/offline" +import "initializers/lexxy_markdown_paste" diff --git a/app/javascript/initializers/lexxy_markdown_paste.js b/app/javascript/initializers/lexxy_markdown_paste.js new file mode 100644 index 000000000..cf7600306 --- /dev/null +++ b/app/javascript/initializers/lexxy_markdown_paste.js @@ -0,0 +1,3 @@ +document.addEventListener("lexxy:insert-markdown", (event) => { + event.detail.addBlockSpacing() +}) diff --git a/test/system/smoke_test.rb b/test/system/smoke_test.rb index 31e8f723f..5af13f890 100644 --- a/test/system/smoke_test.rb +++ b/test/system/smoke_test.rb @@ -76,6 +76,38 @@ class SmokeTest < ApplicationSystemTestCase assert_no_selector "div##{dom_id(notification)}" end + test "markdown paste adds block spacing" do + sign_in_as(users(:david)) + + visit card_url(cards(:layout)) + find("lexxy-editor").click + paste_markdown("Hello\n\nWorld") + + within("lexxy-editor") do + assert_selector "p", text: "Hello" + assert_selector "p br", visible: :all + assert_selector "p", text: "World" + end + end + + test "markdown paste preserves line breaks" do + sign_in_as(users(:david)) + + visit card_url(cards(:layout)) + find("lexxy-editor").click + paste_markdown("Hello\nWorld") + + inner_html = find("lexxy-editor p", text: "Hello").native.property("innerHTML") + children = Nokogiri::HTML5.fragment(inner_html).children + assert_pattern do + children => [ + { name: "span", inner_html: "Hello" }, + { name: "br" }, + { name: "span", inner_html: "World" } + ] + end + end + test "dragging card to a new column" do sign_in_as(users(:david)) @@ -105,4 +137,12 @@ class SmokeTest < ApplicationSystemTestCase editor_element.set with page.execute_script("arguments[0].value = '#{with}'", editor_element) end + + def paste_markdown(markdown) + page.execute_script(<<~JS, markdown) + const dt = new DataTransfer(); + dt.setData("text/plain", arguments[0]); + document.activeElement.dispatchEvent(new ClipboardEvent("paste", { clipboardData: dt, bubbles: true })); + JS + end end