1/*
2 * code.ts
3 *
4 * Copyright (C) 2021 by RStudio, PBC
5 *
6 * Unless you have received this program directly from RStudio pursuant
7 * to the terms of a commercial license agreement with RStudio, then
8 * this program is licensed to you under the terms of version 3 of the
9 * GNU Affero General Public License. This program is distributed WITHOUT
10 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13 *
14 */
15
16import { Plugin, PluginKey } from 'prosemirror-state';
17
18import { CodeViewOptions, canInsertNodeAtPos } from './node';
19import { ResolvedPos, Slice, Fragment } from 'prosemirror-model';
20
21export const kCodeAttr = 0;
22export const kCodeText = 1;
23
24export function codeNodeSpec() {
25  return {
26    content: 'text*',
27    group: 'block',
28    marks: '',
29    code: true,
30    defining: true,
31    isolating: true,
32  };
33}
34
35export function codeViewClipboardPlugin(codeViews: { [key: string]: CodeViewOptions }) {
36  return new Plugin({
37    key: new PluginKey('code-view-clipboard'),
38    props: {
39      clipboardTextParser: (text: string, $context: ResolvedPos): any => {
40        // see if any of the code views want to handle this text
41        for (const codeViewType of Object.keys(codeViews)) {
42          const codeView = codeViews[codeViewType];
43          if (codeView.createFromPastePattern && codeView.createFromPastePattern.test(text)) {
44            const schema = $context.node().type.schema;
45            const nodeType = schema.nodes[codeViewType];
46            if (canInsertNodeAtPos($context, nodeType)) {
47              const textNode = schema.text(text);
48              const codeNode = nodeType.createAndFill({}, textNode);
49              return new Slice(Fragment.from(codeNode), 0, 0);
50            }
51          }
52        }
53        return null;
54      },
55    },
56  });
57}
58