Skip to content

Commit 51d0fe7

Browse files
authored
fix(Link): paste URL with trailing question mark (#798)
1 parent 23c68ac commit 51d0fe7

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {EditorState, TextSelection} from 'prosemirror-state';
2+
import {builders} from 'prosemirror-test-builder';
3+
import {EditorView} from 'prosemirror-view';
4+
5+
import {dispatchPasteEvent} from '../../../../tests/dispatch-event';
6+
import {createMarkupChecker} from '../../../../tests/sameMarkup';
7+
import {ExtensionsManager} from '../../../core';
8+
import {LoggerFacet} from '../../../core/utils/logger';
9+
import {Logger2} from '../../../logger';
10+
import {BaseNode, BaseSchemaSpecs} from '../../base/specs';
11+
12+
import {LinkAttr, LinkSpecs, linkMarkName} from './LinkSpecs';
13+
import {linkPasteEnhance} from './paste-plugin';
14+
15+
const logger = new Logger2();
16+
const {
17+
schema,
18+
plugins,
19+
markupParser: parser,
20+
serializer,
21+
} = new ExtensionsManager({
22+
extensions: (builder) => {
23+
builder.use(BaseSchemaSpecs, {}).use(LinkSpecs);
24+
builder.addPlugin(linkPasteEnhance, builder.Priority.High);
25+
},
26+
logger,
27+
}).build();
28+
plugins.unshift(LoggerFacet.of(logger));
29+
30+
const {doc, p, lnk} = builders<'doc' | 'p' | 'lnk'>(schema, {
31+
doc: {nodeType: BaseNode.Doc},
32+
p: {nodeType: BaseNode.Paragraph},
33+
lnk: {markType: linkMarkName, [LinkAttr.Href]: 'http://example.com?'},
34+
});
35+
36+
const {same} = createMarkupChecker({parser, serializer});
37+
38+
describe('link paste plugin', () => {
39+
it('parser does not include trailing question mark in matchLinks', () => {
40+
const match = parser.matchLinks('http://example.com?');
41+
expect(match?.[0]?.raw).toBe('http://example.com');
42+
});
43+
44+
it('pastes url ending with question mark as link for selected text', () => {
45+
const startDoc = doc(p('<a>test text<b>'));
46+
const state = EditorState.create({
47+
schema,
48+
doc: startDoc,
49+
selection: TextSelection.create(startDoc, startDoc.tag.a, startDoc.tag.b),
50+
plugins,
51+
});
52+
const view = new EditorView(null, {state});
53+
dispatchPasteEvent(view, {'text/plain': 'http://example.com?'});
54+
expect(view.state.doc).toMatchNode(doc(p(lnk('test text'))));
55+
same('[test text](http://example.com?)', view.state.doc);
56+
});
57+
});

src/extensions/markdown/Link/paste-plugin.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ function getUrl(data: DataTransfer | null, parser: Parser): string | null {
8080
// TODO: should we process HTML here?
8181
const text = data.getData(DataTransferType.Text);
8282
const match = parser.matchLinks(text);
83-
if (match?.[0]?.raw === text) return match[0].url;
83+
if (match?.[0]) {
84+
const {raw, url} = match[0];
85+
if (raw === text) return url;
86+
if (text.endsWith('?') && raw + '?' === text && parser.validateLink(text)) {
87+
return parser.normalizeLink(text);
88+
}
89+
}
8490
return null;
8591
}

0 commit comments

Comments
 (0)