feat: add image resize support in articles (#14293)
This commit is contained in:
@@ -61,7 +61,7 @@ const handleChange = () => {
|
||||
<div class="flex flex-col gap-2 items-start">
|
||||
<div class="flex items-center justify-between w-full gap-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="text-heading-2 text-n-slate-12">
|
||||
<h3 class="text-heading-3 text-n-slate-12">
|
||||
{{ label }}
|
||||
</h3>
|
||||
<Label v-if="disabled" :label="disabledLabel" color="amber" compact />
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ArticleMarkdownTransformer,
|
||||
EditorState,
|
||||
Selection,
|
||||
imageResizeView,
|
||||
} from '@chatwoot/prosemirror-schema';
|
||||
import {
|
||||
suggestionsPlugin,
|
||||
@@ -235,6 +236,7 @@ export default {
|
||||
const tr = editorView.state.tr.replaceSelectionWith(tableNode);
|
||||
editorView.dispatch(tr.scrollIntoView());
|
||||
},
|
||||
imageUpload: () => this.openFileBrowser(),
|
||||
};
|
||||
|
||||
const command = commandMap[actionKey];
|
||||
@@ -332,6 +334,9 @@ export default {
|
||||
createEditorView() {
|
||||
editorView = new EditorView(this.$refs.editor, {
|
||||
state: state,
|
||||
nodeViews: {
|
||||
image: imageResizeView,
|
||||
},
|
||||
dispatchTransaction: tx => {
|
||||
state = state.apply(tx);
|
||||
editorView.updateState(state);
|
||||
|
||||
@@ -60,6 +60,12 @@ const EDITOR_ACTIONS = [
|
||||
icon: 'i-lucide-table',
|
||||
menuKey: 'insertTable',
|
||||
},
|
||||
{
|
||||
value: 'imageUpload',
|
||||
labelKey: 'SLASH_COMMANDS.IMAGE',
|
||||
icon: 'i-lucide-image',
|
||||
menuKey: 'imageUpload',
|
||||
},
|
||||
{
|
||||
value: 'strike',
|
||||
labelKey: 'SLASH_COMMANDS.STRIKETHROUGH',
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"CODE": "Code",
|
||||
"BULLET_LIST": "Bullet List",
|
||||
"ORDERED_LIST": "Ordered List",
|
||||
"TABLE": "Table"
|
||||
"TABLE": "Table",
|
||||
"IMAGE": "Image"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,31 @@ class CustomMarkdownRenderer < CommonMarker::HtmlRenderer
|
||||
super
|
||||
end
|
||||
|
||||
def image(node)
|
||||
src = escape_href(node.url)
|
||||
width = extract_image_width(src)
|
||||
plain do
|
||||
out(%(<img src="#{src}"))
|
||||
out(' alt="', :children, '"')
|
||||
out(%( title="#{escape_html(node.title)}")) if node.title.present?
|
||||
out(%( style="width: #{width}; max-width: 100%; height: auto;")) if width
|
||||
out(' />')
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def extract_image_width(src)
|
||||
query = URI.parse(src).query
|
||||
raw = query && CGI.parse(query)['cw_image_width']&.first
|
||||
return unless raw =~ /\A(\d+)px\z/
|
||||
|
||||
px = Regexp.last_match(1).to_i
|
||||
"#{px}px" if px.between?(1, 2000)
|
||||
rescue URI::InvalidURIError
|
||||
nil
|
||||
end
|
||||
|
||||
def surrounded_by_empty_lines?(node)
|
||||
prev_node_empty?(node.previous) && next_node_empty?(node.next)
|
||||
end
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@
|
||||
"@amplitude/analytics-browser": "^2.11.10",
|
||||
"@breezystack/lamejs": "^1.2.7",
|
||||
"@chatwoot/ninja-keys": "1.2.3",
|
||||
"@chatwoot/prosemirror-schema": "1.3.11",
|
||||
"@chatwoot/prosemirror-schema": "1.3.13",
|
||||
"@chatwoot/utils": "^0.0.52",
|
||||
"@formkit/core": "^1.7.2",
|
||||
"@formkit/vue": "^1.7.2",
|
||||
|
||||
Generated
+5
-5
@@ -26,8 +26,8 @@ importers:
|
||||
specifier: 1.2.3
|
||||
version: 1.2.3
|
||||
'@chatwoot/prosemirror-schema':
|
||||
specifier: 1.3.11
|
||||
version: 1.3.11
|
||||
specifier: 1.3.13
|
||||
version: 1.3.13
|
||||
'@chatwoot/utils':
|
||||
specifier: ^0.0.52
|
||||
version: 0.0.52
|
||||
@@ -459,8 +459,8 @@ packages:
|
||||
'@chatwoot/ninja-keys@1.2.3':
|
||||
resolution: {integrity: sha512-xM8d9P5ikDMZm2WbaCTk/TW5HFauylrU3cJ75fq5je6ixKwyhl/0kZbVN/vbbZN4+AUX/OaSIn6IJbtCgIF67g==}
|
||||
|
||||
'@chatwoot/prosemirror-schema@1.3.11':
|
||||
resolution: {integrity: sha512-+GptIqY73/EtojrhAKX4UKwZF7NUB47DMzgYxmx8Vu07DLKCGe+8JnbHJnR9oBy8p5sn5VOO1ihNf/4Pg2RzIQ==}
|
||||
'@chatwoot/prosemirror-schema@1.3.13':
|
||||
resolution: {integrity: sha512-T6FBUinMJbwDCD7975g8M/Tsn2+G3O2pTGIXdcLkMRpbAAC6mVdl4ZcZektlt5y/PVmPVqNHPsfee1XB/C3vAw==}
|
||||
|
||||
'@chatwoot/utils@0.0.52':
|
||||
resolution: {integrity: sha512-e57uVqyVW4tj1gql4YJPNMykqMJPkETn5Y9AmHdhc6Y7oxDXfRXBq27fZrrDadLkZdn5RYVCZjfIhXOumyYv2Q==}
|
||||
@@ -4993,7 +4993,7 @@ snapshots:
|
||||
hotkeys-js: 3.8.7
|
||||
lit: 2.2.6
|
||||
|
||||
'@chatwoot/prosemirror-schema@1.3.11':
|
||||
'@chatwoot/prosemirror-schema@1.3.13':
|
||||
dependencies:
|
||||
markdown-it-sup: 2.0.0
|
||||
prosemirror-commands: 1.7.1
|
||||
|
||||
@@ -257,4 +257,18 @@ describe CustomMarkdownRenderer do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#image' do
|
||||
it 'renders width in px with responsive cap and auto height' do
|
||||
markdown = ''
|
||||
expect(render_markdown(markdown)).to include(
|
||||
'style="width: 400px; max-width: 100%; height: auto;"'
|
||||
)
|
||||
end
|
||||
|
||||
it 'ignores a non-numeric width' do
|
||||
markdown = ''
|
||||
expect(render_markdown(markdown)).not_to include('style=')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user