@fluentui-copilot/chat-input-plugins 0.3.1 → 0.3.3
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.
- package/CHANGELOG.json +45 -1
- package/CHANGELOG.md +21 -2
- package/dist/index.d.ts +1 -0
- package/lib/BasicFunctionality/SentinelNode.js +3 -0
- package/lib/BasicFunctionality/SentinelNode.js.map +1 -1
- package/lib/PasteUnfurling/PasteUnfurling.base.js +8 -5
- package/lib/PasteUnfurling/PasteUnfurling.base.js.map +1 -1
- package/lib/PasteUnfurling/PasteUnfurlingTestUtils.js +163 -0
- package/lib/PasteUnfurling/PasteUnfurlingTestUtils.js.map +1 -0
- package/lib-commonjs/BasicFunctionality/SentinelNode.js +3 -0
- package/lib-commonjs/BasicFunctionality/SentinelNode.js.map +1 -1
- package/lib-commonjs/PasteUnfurling/PasteUnfurling.base.js +8 -5
- package/lib-commonjs/PasteUnfurling/PasteUnfurling.base.js.map +1 -1
- package/lib-commonjs/PasteUnfurling/PasteUnfurlingTestUtils.js +197 -0
- package/lib-commonjs/PasteUnfurling/PasteUnfurlingTestUtils.js.map +1 -0
- package/package.json +2 -2
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,51 @@
|
|
|
2
2
|
"name": "@fluentui-copilot/chat-input-plugins",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Tue, 10 Dec 2024 20:20:52 GMT",
|
|
6
|
+
"tag": "@fluentui-copilot/chat-input-plugins_v0.3.3",
|
|
7
|
+
"version": "0.3.3",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"author": "owcampbe@microsoft.com",
|
|
12
|
+
"package": "@fluentui-copilot/chat-input-plugins",
|
|
13
|
+
"commit": "edf4a5e558c8f6f3fb45451a9557832c059d4e5a",
|
|
14
|
+
"comment": "chore: Add importJSON implementation for SentinelNode."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"author": "owcampbe@microsoft.com",
|
|
18
|
+
"package": "@fluentui-copilot/chat-input-plugins",
|
|
19
|
+
"commit": "b4a502d9b602517a583dd25b14d651828270fc1d",
|
|
20
|
+
"comment": "chore: Add paste unfurling tests."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"none": [
|
|
24
|
+
{
|
|
25
|
+
"author": "owcampbe@microsoft.com",
|
|
26
|
+
"package": "@fluentui-copilot/chat-input-plugins",
|
|
27
|
+
"commit": "c5ad8962a0e32fedd5d915d15107f0e1398b7aae",
|
|
28
|
+
"comment": "chore: Applying package updates."
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"date": "Wed, 20 Nov 2024 23:38:56 GMT",
|
|
35
|
+
"tag": "@fluentui-copilot/chat-input-plugins_v0.3.2",
|
|
36
|
+
"version": "0.3.2",
|
|
37
|
+
"comments": {
|
|
38
|
+
"patch": [
|
|
39
|
+
{
|
|
40
|
+
"author": "owcampbe@microsoft.com",
|
|
41
|
+
"package": "@fluentui-copilot/chat-input-plugins",
|
|
42
|
+
"commit": "0b973dffa7a48e7ea5f2ebca45c1992f83c20b12",
|
|
43
|
+
"comment": "chore: Fix Paste Unfurling default handlers."
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"date": "Thu, 31 Oct 2024 17:41:08 GMT",
|
|
6
50
|
"tag": "@fluentui-copilot/chat-input-plugins_v0.3.1",
|
|
7
51
|
"version": "0.3.1",
|
|
8
52
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
# Change Log - @fluentui-copilot/chat-input-plugins
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Tue, 10 Dec 2024 20:20:52 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## [0.3.3](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/chat-input-plugins_v0.3.3)
|
|
8
|
+
|
|
9
|
+
Tue, 10 Dec 2024 20:20:52 GMT
|
|
10
|
+
[Compare changes](https://github.com/microsoft/fluentai/compare/@fluentui-copilot/chat-input-plugins_v0.3.2..@fluentui-copilot/chat-input-plugins_v0.3.3)
|
|
11
|
+
|
|
12
|
+
### Patches
|
|
13
|
+
|
|
14
|
+
- chore: Add importJSON implementation for SentinelNode. ([PR #2438](https://github.com/microsoft/fluentai/pull/2438) by owcampbe@microsoft.com)
|
|
15
|
+
- chore: Add paste unfurling tests. ([PR #2417](https://github.com/microsoft/fluentai/pull/2417) by owcampbe@microsoft.com)
|
|
16
|
+
|
|
17
|
+
## [0.3.2](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/chat-input-plugins_v0.3.2)
|
|
18
|
+
|
|
19
|
+
Wed, 20 Nov 2024 23:38:56 GMT
|
|
20
|
+
[Compare changes](https://github.com/microsoft/fluentai/compare/@fluentui-copilot/chat-input-plugins_v0.3.1..@fluentui-copilot/chat-input-plugins_v0.3.2)
|
|
21
|
+
|
|
22
|
+
### Patches
|
|
23
|
+
|
|
24
|
+
- chore: Fix Paste Unfurling default handlers. ([PR #2408](https://github.com/microsoft/fluentai/pull/2408) by owcampbe@microsoft.com)
|
|
25
|
+
|
|
7
26
|
## [0.3.1](https://github.com/microsoft/fluentai/tree/@fluentui-copilot/chat-input-plugins_v0.3.1)
|
|
8
27
|
|
|
9
|
-
Thu, 31 Oct 2024 17:
|
|
28
|
+
Thu, 31 Oct 2024 17:41:08 GMT
|
|
10
29
|
[Compare changes](https://github.com/microsoft/fluentai/compare/@fluentui-copilot/chat-input-plugins_v0.3.0..@fluentui-copilot/chat-input-plugins_v0.3.1)
|
|
11
30
|
|
|
12
31
|
### Patches
|
package/dist/index.d.ts
CHANGED
|
@@ -188,6 +188,7 @@ export declare class SentinelNode extends TextNode {
|
|
|
188
188
|
createDOM(config: EditorConfig): HTMLElement;
|
|
189
189
|
isToken(): boolean;
|
|
190
190
|
exportJSON(): SerializedTextNode;
|
|
191
|
+
static importJSON(serializedNode: SerializedTextNode): SentinelNode;
|
|
191
192
|
}
|
|
192
193
|
|
|
193
194
|
export { }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["SentinelNode.ts"],"sourcesContent":["import type { EditorConfig, LexicalNode, NodeKey, SerializedTextNode } from '@fluentui-copilot/text-editor';\nimport { TextNode } from '@fluentui-copilot/text-editor';\n\n// 2 zero width characters will not be visible in the editor.\n// \\u200b is the zero width space character which can allow line wrapping in a word\n// \\u200c is the zero width non-joiner character which prevents ligatures from connecting the two surrounding characters\n// These two characters together are a no-op and should not be present together in any legitimate user input.\nexport const SENTINEL_VALUE = '\\u200b\\u200c';\n\nexport class SentinelNode extends TextNode {\n constructor(key?: NodeKey) {\n super(SENTINEL_VALUE, key);\n }\n\n static getType() {\n return 'sentinel';\n }\n static clone(node: SentinelNode) {\n return new SentinelNode(node.__key);\n }\n\n createDOM(config: EditorConfig): HTMLElement {\n const element = super.createDOM(config);\n element.ariaHidden = 'true';\n return element;\n }\n\n isToken() {\n return true;\n }\n\n exportJSON(): SerializedTextNode {\n return {\n ...super.exportJSON(),\n type: 'sentinel',\n version: 1,\n };\n }\n}\n\nexport function $createSentinelNode(key?: NodeKey) {\n return new SentinelNode(key);\n}\n\nexport function $isSentinelNode(node: LexicalNode | null): node is SentinelNode {\n return node instanceof SentinelNode;\n}\n"],"names":["TextNode","SENTINEL_VALUE","SentinelNode","getType","clone","node","__key","createDOM","config","element","ariaHidden","isToken","exportJSON","type","version","
|
|
1
|
+
{"version":3,"sources":["SentinelNode.ts"],"sourcesContent":["import type { EditorConfig, LexicalNode, NodeKey, SerializedTextNode } from '@fluentui-copilot/text-editor';\nimport { TextNode } from '@fluentui-copilot/text-editor';\n\n// 2 zero width characters will not be visible in the editor.\n// \\u200b is the zero width space character which can allow line wrapping in a word\n// \\u200c is the zero width non-joiner character which prevents ligatures from connecting the two surrounding characters\n// These two characters together are a no-op and should not be present together in any legitimate user input.\nexport const SENTINEL_VALUE = '\\u200b\\u200c';\n\nexport class SentinelNode extends TextNode {\n constructor(key?: NodeKey) {\n super(SENTINEL_VALUE, key);\n }\n\n static getType() {\n return 'sentinel';\n }\n static clone(node: SentinelNode) {\n return new SentinelNode(node.__key);\n }\n\n createDOM(config: EditorConfig): HTMLElement {\n const element = super.createDOM(config);\n element.ariaHidden = 'true';\n return element;\n }\n\n isToken() {\n return true;\n }\n\n exportJSON(): SerializedTextNode {\n return {\n ...super.exportJSON(),\n type: 'sentinel',\n version: 1,\n };\n }\n\n static importJSON(serializedNode: SerializedTextNode): SentinelNode {\n return $createSentinelNode();\n }\n}\n\nexport function $createSentinelNode(key?: NodeKey) {\n return new SentinelNode(key);\n}\n\nexport function $isSentinelNode(node: LexicalNode | null): node is SentinelNode {\n return node instanceof SentinelNode;\n}\n"],"names":["TextNode","SENTINEL_VALUE","SentinelNode","getType","clone","node","__key","createDOM","config","element","ariaHidden","isToken","exportJSON","type","version","importJSON","serializedNode","$createSentinelNode","constructor","key","$isSentinelNode"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AACA,SAASA,QAAQ,QAAQ,gCAAgC;AAEzD,6DAA6D;AAC7D,mFAAmF;AACnF,wHAAwH;AACxH,6GAA6G;AAC7G,OAAO,MAAMC,iBAAiB,eAAe;AAE7C,OAAO,MAAMC,qBAAqBF;IAKhC,OAAOG,UAAU;QACf,OAAO;IACT;IACA,OAAOC,MAAMC,IAAkB,EAAE;QAC/B,OAAO,IAAIH,aAAaG,KAAKC,KAAK;IACpC;IAEAC,UAAUC,MAAoB,EAAe;QAC3C,MAAMC,UAAU,KAAK,CAACF,UAAUC;QAChCC,QAAQC,UAAU,GAAG;QACrB,OAAOD;IACT;IAEAE,UAAU;QACR,OAAO;IACT;IAEAC,aAAiC;QAC/B,OAAO;YACL,GAAG,KAAK,CAACA,YAAY;YACrBC,MAAM;YACNC,SAAS;QACX;IACF;IAEA,OAAOC,WAAWC,cAAkC,EAAgB;QAClE,OAAOC;IACT;IA/BAC,YAAYC,GAAa,CAAE;QACzB,KAAK,CAAClB,gBAAgBkB;IACxB;AA8BF;AAEA,OAAO,SAASF,oBAAoBE,GAAa;IAC/C,OAAO,IAAIjB,aAAaiB;AAC1B;AAEA,OAAO,SAASC,gBAAgBf,IAAwB;IACtD,OAAOA,gBAAgBH;AACzB"}
|
|
@@ -46,12 +46,15 @@ export function registerPasteUnfurlingPlugin(editor, props) {
|
|
|
46
46
|
const commandsMap = editor._commands;
|
|
47
47
|
const defaultEditorListeners = (_commandsMap_get = commandsMap.get(PASTE_COMMAND)) === null || _commandsMap_get === void 0 ? void 0 : _commandsMap_get[COMMAND_PRIORITY_EDITOR];
|
|
48
48
|
if (defaultEditorListeners) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
// After the promises have resolved, we're not guaranteed to be in the same update state as the original command
|
|
50
|
+
editor.update(() => {
|
|
51
|
+
for (const listener of defaultEditorListeners) {
|
|
52
|
+
const defaultHandled = listener(event, editor);
|
|
53
|
+
if (defaultHandled) {
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
53
56
|
}
|
|
54
|
-
}
|
|
57
|
+
});
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["PasteUnfurling.base.ts"],"sourcesContent":["import type { LexicalEditor } from '@fluentui-copilot/text-editor';\nimport {\n COMMAND_PRIORITY_EDITOR,\n COMMAND_PRIORITY_LOW,\n PASTE_COMMAND,\n $insertNodes,\n $createTextNode,\n} from '@fluentui-copilot/text-editor';\nimport type {\n PasteUnfurlingPluginBaseProps,\n PasteUnfurlingTransformedPart,\n PasteUnfurlingTransformResult,\n} from './PasteUnfurling.types';\n\nfunction unhandledPart(part: never): never {\n throw new Error(`Unhandled part: ${part}`);\n}\n\nexport function registerPasteUnfurlingPlugin<ExtraDataType, NodePropsType>(\n editor: LexicalEditor,\n props: PasteUnfurlingPluginBaseProps<ExtraDataType, NodePropsType>,\n): () => void {\n const { entityPluginId, transforms, $createEntityNode } = props;\n\n function insertParts(parts: PasteUnfurlingTransformedPart<ExtraDataType, NodePropsType>[]) {\n editor.update(() => {\n const nodes = parts.map(part => {\n switch (part.type) {\n case 'entity':\n return $createEntityNode(entityPluginId, part.value.text, part.value.data, part.value.entityProps);\n case 'text':\n return $createTextNode(part.value);\n }\n return unhandledPart(part);\n });\n $insertNodes(nodes);\n });\n }\n\n function handlePaste(event: ClipboardEvent): boolean {\n const transformPromises: Promise<PasteUnfurlingTransformResult<ExtraDataType, NodePropsType>>[] = [];\n\n for (const transform of transforms) {\n transformPromises.push(Promise.resolve(transform(event, editor)));\n }\n\n Promise.allSettled(transformPromises).then(results => {\n let handledPaste = false;\n\n for (const result of results) {\n if (result.status === 'fulfilled') {\n const transformResult = result.value;\n if (transformResult.transformedParts) {\n insertParts(transformResult.transformedParts);\n }\n\n if (transformResult.handled) {\n handledPaste = true;\n break;\n }\n }\n }\n\n if (!handledPaste) {\n const commandsMap = editor._commands;\n const defaultEditorListeners = commandsMap.get(PASTE_COMMAND)?.[COMMAND_PRIORITY_EDITOR];\n if (defaultEditorListeners) {\n for (const listener of defaultEditorListeners) {\n
|
|
1
|
+
{"version":3,"sources":["PasteUnfurling.base.ts"],"sourcesContent":["import type { LexicalEditor } from '@fluentui-copilot/text-editor';\nimport {\n COMMAND_PRIORITY_EDITOR,\n COMMAND_PRIORITY_LOW,\n PASTE_COMMAND,\n $insertNodes,\n $createTextNode,\n} from '@fluentui-copilot/text-editor';\nimport type {\n PasteUnfurlingPluginBaseProps,\n PasteUnfurlingTransformedPart,\n PasteUnfurlingTransformResult,\n} from './PasteUnfurling.types';\n\nfunction unhandledPart(part: never): never {\n throw new Error(`Unhandled part: ${part}`);\n}\n\nexport function registerPasteUnfurlingPlugin<ExtraDataType, NodePropsType>(\n editor: LexicalEditor,\n props: PasteUnfurlingPluginBaseProps<ExtraDataType, NodePropsType>,\n): () => void {\n const { entityPluginId, transforms, $createEntityNode } = props;\n\n function insertParts(parts: PasteUnfurlingTransformedPart<ExtraDataType, NodePropsType>[]) {\n editor.update(() => {\n const nodes = parts.map(part => {\n switch (part.type) {\n case 'entity':\n return $createEntityNode(entityPluginId, part.value.text, part.value.data, part.value.entityProps);\n case 'text':\n return $createTextNode(part.value);\n }\n return unhandledPart(part);\n });\n $insertNodes(nodes);\n });\n }\n\n function handlePaste(event: ClipboardEvent): boolean {\n const transformPromises: Promise<PasteUnfurlingTransformResult<ExtraDataType, NodePropsType>>[] = [];\n\n for (const transform of transforms) {\n transformPromises.push(Promise.resolve(transform(event, editor)));\n }\n\n Promise.allSettled(transformPromises).then(results => {\n let handledPaste = false;\n\n for (const result of results) {\n if (result.status === 'fulfilled') {\n const transformResult = result.value;\n if (transformResult.transformedParts) {\n insertParts(transformResult.transformedParts);\n }\n\n if (transformResult.handled) {\n handledPaste = true;\n break;\n }\n }\n }\n\n if (!handledPaste) {\n const commandsMap = editor._commands;\n const defaultEditorListeners = commandsMap.get(PASTE_COMMAND)?.[COMMAND_PRIORITY_EDITOR];\n if (defaultEditorListeners) {\n // After the promises have resolved, we're not guaranteed to be in the same update state as the original command\n editor.update(() => {\n for (const listener of defaultEditorListeners) {\n const defaultHandled = listener(event, editor);\n if (defaultHandled) {\n break;\n }\n }\n });\n }\n }\n });\n\n return true;\n }\n\n return editor.registerCommand(PASTE_COMMAND, handlePaste, COMMAND_PRIORITY_LOW);\n}\n"],"names":["COMMAND_PRIORITY_EDITOR","COMMAND_PRIORITY_LOW","PASTE_COMMAND","$insertNodes","$createTextNode","unhandledPart","part","Error","registerPasteUnfurlingPlugin","editor","props","entityPluginId","transforms","$createEntityNode","insertParts","parts","update","nodes","map","type","value","text","data","entityProps","handlePaste","event","transformPromises","transform","push","Promise","resolve","allSettled","then","results","handledPaste","result","status","transformResult","transformedParts","handled","commandsMap","_commands","defaultEditorListeners","get","listener","defaultHandled","registerCommand"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AACA,SACEA,uBAAuB,EACvBC,oBAAoB,EACpBC,aAAa,EACbC,YAAY,EACZC,eAAe,QACV,gCAAgC;AAOvC,SAASC,cAAcC,IAAW;IAChC,MAAM,IAAIC,MAAM,CAAC,gBAAgB,EAAED,KAAK,CAAC;AAC3C;AAEA,OAAO,SAASE,6BACdC,MAAqB,EACrBC,KAAkE;IAElE,MAAM,EAAEC,cAAc,EAAEC,UAAU,EAAEC,iBAAiB,EAAE,GAAGH;IAE1D,SAASI,YAAYC,KAAoE;QACvFN,OAAOO,MAAM,CAAC;YACZ,MAAMC,QAAQF,MAAMG,GAAG,CAACZ,CAAAA;gBACtB,OAAQA,KAAKa,IAAI;oBACf,KAAK;wBACH,OAAON,kBAAkBF,gBAAgBL,KAAKc,KAAK,CAACC,IAAI,EAAEf,KAAKc,KAAK,CAACE,IAAI,EAAEhB,KAAKc,KAAK,CAACG,WAAW;oBACnG,KAAK;wBACH,OAAOnB,gBAAgBE,KAAKc,KAAK;gBACrC;gBACA,OAAOf,cAAcC;YACvB;YACAH,aAAac;QACf;IACF;IAEA,SAASO,YAAYC,KAAqB;QACxC,MAAMC,oBAA4F,EAAE;QAEpG,KAAK,MAAMC,aAAaf,WAAY;YAClCc,kBAAkBE,IAAI,CAACC,QAAQC,OAAO,CAACH,UAAUF,OAAOhB;QAC1D;QAEAoB,QAAQE,UAAU,CAACL,mBAAmBM,IAAI,CAACC,CAAAA;YACzC,IAAIC,eAAe;YAEnB,KAAK,MAAMC,UAAUF,QAAS;gBAC5B,IAAIE,OAAOC,MAAM,KAAK,aAAa;oBACjC,MAAMC,kBAAkBF,OAAOf,KAAK;oBACpC,IAAIiB,gBAAgBC,gBAAgB,EAAE;wBACpCxB,YAAYuB,gBAAgBC,gBAAgB;oBAC9C;oBAEA,IAAID,gBAAgBE,OAAO,EAAE;wBAC3BL,eAAe;wBACf;oBACF;gBACF;YACF;YAEA,IAAI,CAACA,cAAc;oBAEcM;gBAD/B,MAAMA,cAAc/B,OAAOgC,SAAS;gBACpC,MAAMC,0BAAyBF,mBAAAA,YAAYG,GAAG,CAACzC,4BAAhBsC,uCAAAA,gBAAgC,CAACxC,wBAAwB;gBACxF,IAAI0C,wBAAwB;oBAC1B,gHAAgH;oBAChHjC,OAAOO,MAAM,CAAC;wBACZ,KAAK,MAAM4B,YAAYF,uBAAwB;4BAC7C,MAAMG,iBAAiBD,SAASnB,OAAOhB;4BACvC,IAAIoC,gBAAgB;gCAClB;4BACF;wBACF;oBACF;gBACF;YACF;QACF;QAEA,OAAO;IACT;IAEA,OAAOpC,OAAOqC,eAAe,CAAC5C,eAAesB,aAAavB;AAC5D"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
import { TextNode } from '@fluentui-copilot/text-editor';
|
|
3
|
+
export class MockClipboardEvent extends Event {
|
|
4
|
+
constructor(...args) {
|
|
5
|
+
super(...args);
|
|
6
|
+
_define_property(this, "clipboardData", null);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function createPasteEvent(data) {
|
|
10
|
+
const event = new MockClipboardEvent('paste');
|
|
11
|
+
event.clipboardData = {
|
|
12
|
+
types: [data.map(({
|
|
13
|
+
mimeType
|
|
14
|
+
}) => mimeType)],
|
|
15
|
+
getData: format => {
|
|
16
|
+
const item = data.find(({
|
|
17
|
+
mimeType
|
|
18
|
+
}) => mimeType === format);
|
|
19
|
+
if (item) {
|
|
20
|
+
return item.value;
|
|
21
|
+
}
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
return event;
|
|
26
|
+
}
|
|
27
|
+
export class MockEntityNode extends TextNode {
|
|
28
|
+
static getType() {
|
|
29
|
+
return 'mockEntity';
|
|
30
|
+
}
|
|
31
|
+
constructor(text, url) {
|
|
32
|
+
super(text);
|
|
33
|
+
_define_property(this, "url", void 0);
|
|
34
|
+
this.url = url;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function $createMockEntityNode(text, url) {
|
|
38
|
+
return new MockEntityNode(text, url);
|
|
39
|
+
}
|
|
40
|
+
export function $isMockEntityNode(node) {
|
|
41
|
+
return node instanceof MockEntityNode;
|
|
42
|
+
}
|
|
43
|
+
export const parseLinkPreview = event => {
|
|
44
|
+
let previewData;
|
|
45
|
+
try {
|
|
46
|
+
var _event_clipboardData;
|
|
47
|
+
const previewDataString = (_event_clipboardData = event.clipboardData) === null || _event_clipboardData === void 0 ? void 0 : _event_clipboardData.getData('text/link-preview');
|
|
48
|
+
if (previewDataString === undefined || previewDataString === '') {
|
|
49
|
+
return {
|
|
50
|
+
handled: false
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
previewData = JSON.parse(previewDataString);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
return {
|
|
56
|
+
handled: false
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const title = previewData.title;
|
|
60
|
+
const url = previewData.url;
|
|
61
|
+
if (!title || !url) {
|
|
62
|
+
return {
|
|
63
|
+
handled: false
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
handled: true,
|
|
68
|
+
transformedParts: [{
|
|
69
|
+
type: 'entity',
|
|
70
|
+
value: {
|
|
71
|
+
text: title,
|
|
72
|
+
data: {
|
|
73
|
+
url
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}]
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
const urlRegex = /(\b(?:https?):\/\/[^\s]+)/gi;
|
|
80
|
+
export const parseLink = event => {
|
|
81
|
+
var _event_clipboardData;
|
|
82
|
+
const text = (_event_clipboardData = event.clipboardData) === null || _event_clipboardData === void 0 ? void 0 : _event_clipboardData.getData('text/plain');
|
|
83
|
+
if (!text) {
|
|
84
|
+
return {
|
|
85
|
+
handled: false
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const parts = text.split(urlRegex);
|
|
89
|
+
// If an entity was found, parts will be at least 3 elements long
|
|
90
|
+
if (parts.length < 3) {
|
|
91
|
+
return {
|
|
92
|
+
handled: false
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const transformedParts = parts.map((str, i) => {
|
|
96
|
+
if (i % 2 === 0) {
|
|
97
|
+
return {
|
|
98
|
+
type: 'text',
|
|
99
|
+
value: str
|
|
100
|
+
};
|
|
101
|
+
} else {
|
|
102
|
+
return {
|
|
103
|
+
type: 'entity',
|
|
104
|
+
value: {
|
|
105
|
+
text: str,
|
|
106
|
+
data: {
|
|
107
|
+
url: str
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}) // Filter out all the nulls for empty strings
|
|
113
|
+
.filter(node => node !== null);
|
|
114
|
+
return {
|
|
115
|
+
handled: true,
|
|
116
|
+
transformedParts
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
// A transform can be async in case it needs to fetch data from a server.
|
|
120
|
+
export const parseEntity = async event => {
|
|
121
|
+
var _event_clipboardData;
|
|
122
|
+
const text = (_event_clipboardData = event.clipboardData) === null || _event_clipboardData === void 0 ? void 0 : _event_clipboardData.getData('text/plain');
|
|
123
|
+
if (!text) {
|
|
124
|
+
return {
|
|
125
|
+
handled: false
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Assume entities come in the syntax <entity>title</entity>
|
|
129
|
+
const re = /<entity[^>]*>([^<]*)<\/entity>/g;
|
|
130
|
+
const parts = text.split(re);
|
|
131
|
+
// If an entity was found, parts will be at least 3 elements long
|
|
132
|
+
if (parts.length < 3) {
|
|
133
|
+
return {
|
|
134
|
+
handled: false
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// Even elements are text, odd elements are entities
|
|
138
|
+
// ["", entity, "", entity, "", ...]
|
|
139
|
+
const transformedParts = parts.map((str, i) => {
|
|
140
|
+
if (i % 2 === 0) {
|
|
141
|
+
return {
|
|
142
|
+
type: 'text',
|
|
143
|
+
value: str
|
|
144
|
+
};
|
|
145
|
+
} else {
|
|
146
|
+
return {
|
|
147
|
+
type: 'entity',
|
|
148
|
+
value: {
|
|
149
|
+
text: str,
|
|
150
|
+
data: {
|
|
151
|
+
url: str
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}) // Filter out all the nulls for empty strings
|
|
157
|
+
.filter(node => node !== null);
|
|
158
|
+
return {
|
|
159
|
+
handled: true,
|
|
160
|
+
transformedParts
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
//# sourceMappingURL=PasteUnfurlingTestUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["PasteUnfurlingTestUtils.ts"],"sourcesContent":["import type { LexicalNode } from '@fluentui-copilot/text-editor';\nimport { TextNode } from '@fluentui-copilot/text-editor';\nimport type { PasteUnfurlingTransformedPart, PasteUnfurlingTransformResult } from '..';\n\nexport class MockClipboardEvent extends Event implements ClipboardEvent {\n clipboardData: DataTransfer | null = null;\n}\n\nexport function createPasteEvent(data: { mimeType: string; value: string }[]) {\n const event = new MockClipboardEvent('paste');\n\n event.clipboardData = {\n types: [data.map(({ mimeType }) => mimeType)],\n getData: (format: string) => {\n const item = data.find(({ mimeType }) => mimeType === format);\n if (item) {\n return item.value;\n }\n return '';\n },\n } as unknown as DataTransfer;\n\n return event;\n}\n\nexport class MockEntityNode extends TextNode {\n url: string;\n\n constructor(text: string, url: string) {\n super(text);\n this.url = url;\n }\n\n static getType(): string {\n return 'mockEntity';\n }\n}\n\nexport type ExtraDataType = { url: string };\n\nexport function $createMockEntityNode(text: string, url: string): MockEntityNode {\n return new MockEntityNode(text, url);\n}\n\nexport function $isMockEntityNode(node: LexicalNode | null | undefined): node is MockEntityNode {\n return node instanceof MockEntityNode;\n}\n\nexport const parseLinkPreview = (event: ClipboardEvent): PasteUnfurlingTransformResult<ExtraDataType, {}> => {\n let previewData;\n try {\n const previewDataString = event.clipboardData?.getData('text/link-preview');\n if (previewDataString === undefined || previewDataString === '') {\n return { handled: false };\n }\n\n previewData = JSON.parse(previewDataString);\n } catch (e) {\n return { handled: false };\n }\n\n const title: string | undefined = previewData.title;\n const url: string | undefined = previewData.url;\n if (!title || !url) {\n return { handled: false };\n }\n\n return {\n handled: true,\n transformedParts: [{ type: 'entity', value: { text: title, data: { url } } }],\n };\n};\nconst urlRegex = /(\\b(?:https?):\\/\\/[^\\s]+)/gi;\n\nexport const parseLink = (event: ClipboardEvent): PasteUnfurlingTransformResult<ExtraDataType, {}> => {\n const text = event.clipboardData?.getData('text/plain');\n if (!text) {\n return {\n handled: false,\n };\n }\n\n const parts = text.split(urlRegex);\n // If an entity was found, parts will be at least 3 elements long\n if (parts.length < 3) {\n return { handled: false };\n }\n const transformedParts = parts\n .map((str, i) => {\n if (i % 2 === 0) {\n return { type: 'text', value: str };\n } else {\n return {\n type: 'entity',\n value: { text: str, data: { url: str } },\n };\n }\n })\n // Filter out all the nulls for empty strings\n .filter(node => node !== null) as PasteUnfurlingTransformedPart<ExtraDataType, {}>[];\n\n return { handled: true, transformedParts };\n};\n\n// A transform can be async in case it needs to fetch data from a server.\nexport const parseEntity = async (event: ClipboardEvent): Promise<PasteUnfurlingTransformResult<ExtraDataType, {}>> => {\n const text = event.clipboardData?.getData('text/plain');\n if (!text) {\n return {\n handled: false,\n };\n }\n\n // Assume entities come in the syntax <entity>title</entity>\n const re = /<entity[^>]*>([^<]*)<\\/entity>/g;\n const parts = text.split(re);\n // If an entity was found, parts will be at least 3 elements long\n if (parts.length < 3) {\n return { handled: false };\n }\n\n // Even elements are text, odd elements are entities\n // [\"\", entity, \"\", entity, \"\", ...]\n const transformedParts = parts\n .map((str, i) => {\n if (i % 2 === 0) {\n return { type: 'text', value: str };\n } else {\n return {\n type: 'entity',\n value: { text: str, data: { url: str } },\n };\n }\n })\n // Filter out all the nulls for empty strings\n .filter(node => node !== null) as PasteUnfurlingTransformedPart<ExtraDataType, {}>[];\n\n return { handled: true, transformedParts };\n};\n"],"names":["TextNode","MockClipboardEvent","Event","clipboardData","createPasteEvent","data","event","types","map","mimeType","getData","format","item","find","value","MockEntityNode","getType","constructor","text","url","$createMockEntityNode","$isMockEntityNode","node","parseLinkPreview","previewData","previewDataString","undefined","handled","JSON","parse","e","title","transformedParts","type","urlRegex","parseLink","parts","split","length","str","i","filter","parseEntity","re"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["SentinelNode.ts"],"sourcesContent":["import type { EditorConfig, LexicalNode, NodeKey, SerializedTextNode } from '@fluentui-copilot/text-editor';\nimport { TextNode } from '@fluentui-copilot/text-editor';\n\n// 2 zero width characters will not be visible in the editor.\n// \\u200b is the zero width space character which can allow line wrapping in a word\n// \\u200c is the zero width non-joiner character which prevents ligatures from connecting the two surrounding characters\n// These two characters together are a no-op and should not be present together in any legitimate user input.\nexport const SENTINEL_VALUE = '\\u200b\\u200c';\n\nexport class SentinelNode extends TextNode {\n constructor(key?: NodeKey) {\n super(SENTINEL_VALUE, key);\n }\n\n static getType() {\n return 'sentinel';\n }\n static clone(node: SentinelNode) {\n return new SentinelNode(node.__key);\n }\n\n createDOM(config: EditorConfig): HTMLElement {\n const element = super.createDOM(config);\n element.ariaHidden = 'true';\n return element;\n }\n\n isToken() {\n return true;\n }\n\n exportJSON(): SerializedTextNode {\n return {\n ...super.exportJSON(),\n type: 'sentinel',\n version: 1,\n };\n }\n}\n\nexport function $createSentinelNode(key?: NodeKey) {\n return new SentinelNode(key);\n}\n\nexport function $isSentinelNode(node: LexicalNode | null): node is SentinelNode {\n return node instanceof SentinelNode;\n}\n"],"names":["$createSentinelNode","$isSentinelNode","SENTINEL_VALUE","SentinelNode","TextNode","getType","clone","node","__key","createDOM","config","element","ariaHidden","isToken","exportJSON","type","version","constructor","key"],"rangeMappings":"
|
|
1
|
+
{"version":3,"sources":["SentinelNode.ts"],"sourcesContent":["import type { EditorConfig, LexicalNode, NodeKey, SerializedTextNode } from '@fluentui-copilot/text-editor';\nimport { TextNode } from '@fluentui-copilot/text-editor';\n\n// 2 zero width characters will not be visible in the editor.\n// \\u200b is the zero width space character which can allow line wrapping in a word\n// \\u200c is the zero width non-joiner character which prevents ligatures from connecting the two surrounding characters\n// These two characters together are a no-op and should not be present together in any legitimate user input.\nexport const SENTINEL_VALUE = '\\u200b\\u200c';\n\nexport class SentinelNode extends TextNode {\n constructor(key?: NodeKey) {\n super(SENTINEL_VALUE, key);\n }\n\n static getType() {\n return 'sentinel';\n }\n static clone(node: SentinelNode) {\n return new SentinelNode(node.__key);\n }\n\n createDOM(config: EditorConfig): HTMLElement {\n const element = super.createDOM(config);\n element.ariaHidden = 'true';\n return element;\n }\n\n isToken() {\n return true;\n }\n\n exportJSON(): SerializedTextNode {\n return {\n ...super.exportJSON(),\n type: 'sentinel',\n version: 1,\n };\n }\n\n static importJSON(serializedNode: SerializedTextNode): SentinelNode {\n return $createSentinelNode();\n }\n}\n\nexport function $createSentinelNode(key?: NodeKey) {\n return new SentinelNode(key);\n}\n\nexport function $isSentinelNode(node: LexicalNode | null): node is SentinelNode {\n return node instanceof SentinelNode;\n}\n"],"names":["$createSentinelNode","$isSentinelNode","SENTINEL_VALUE","SentinelNode","TextNode","getType","clone","node","__key","createDOM","config","element","ariaHidden","isToken","exportJSON","type","version","importJSON","serializedNode","constructor","key"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;;;;;;;;IA4CgBA,mBAAAA;eAAAA;;IAIAC,eAAAA;eAAAA;;IAzCHC,cAAAA;eAAAA;;IAEAC,YAAAA;eAAAA;;;4BARY;AAMlB,MAAMD,iBAAiB;AAEvB,MAAMC,qBAAqBC,oBAAAA;WAKhCC,UAAOA;eACL;;WAEFC,MAAOA,IAAMC,EAAkB;eAC7B,IAAOJ,aAAIA,KAAaI,KAAKC;;cAG/BC,MAAUC,EAAoB;cAC5BC,UAAMA,KAAU,CAAAF,UAAMA;gBACtBE,UAAQC,GAAAA;eACRD;;cAGFE;eACE;;iBAGFC;eACE;oBACE,CAAGA,YAAMA;kBACTC;qBACAC;;;WAIJC,WAAOA,cAAWC,EAAkC;eAClDlB;;gBA9BFmB,GAAYC,CAAa;aACvB,CAAAlB,gBAAMA;;AA+BV;AAEO,SAASF,oBAAoBoB,GAAa;WAC/C,IAAOjB,aAAIA;AACb;AAEO,SAASF,gBAAgBM,IAAwB;WACtDA,gBAAOA;AACT"}
|
|
@@ -52,12 +52,15 @@ function registerPasteUnfurlingPlugin(editor, props) {
|
|
|
52
52
|
const commandsMap = editor._commands;
|
|
53
53
|
const defaultEditorListeners = (_commandsMap_get = commandsMap.get(_texteditor.PASTE_COMMAND)) === null || _commandsMap_get === void 0 ? void 0 : _commandsMap_get[_texteditor.COMMAND_PRIORITY_EDITOR];
|
|
54
54
|
if (defaultEditorListeners) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
// After the promises have resolved, we're not guaranteed to be in the same update state as the original command
|
|
56
|
+
editor.update(()=>{
|
|
57
|
+
for (const listener of defaultEditorListeners){
|
|
58
|
+
const defaultHandled = listener(event, editor);
|
|
59
|
+
if (defaultHandled) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
59
62
|
}
|
|
60
|
-
}
|
|
63
|
+
});
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["PasteUnfurling.base.ts"],"sourcesContent":["import type { LexicalEditor } from '@fluentui-copilot/text-editor';\nimport {\n COMMAND_PRIORITY_EDITOR,\n COMMAND_PRIORITY_LOW,\n PASTE_COMMAND,\n $insertNodes,\n $createTextNode,\n} from '@fluentui-copilot/text-editor';\nimport type {\n PasteUnfurlingPluginBaseProps,\n PasteUnfurlingTransformedPart,\n PasteUnfurlingTransformResult,\n} from './PasteUnfurling.types';\n\nfunction unhandledPart(part: never): never {\n throw new Error(`Unhandled part: ${part}`);\n}\n\nexport function registerPasteUnfurlingPlugin<ExtraDataType, NodePropsType>(\n editor: LexicalEditor,\n props: PasteUnfurlingPluginBaseProps<ExtraDataType, NodePropsType>,\n): () => void {\n const { entityPluginId, transforms, $createEntityNode } = props;\n\n function insertParts(parts: PasteUnfurlingTransformedPart<ExtraDataType, NodePropsType>[]) {\n editor.update(() => {\n const nodes = parts.map(part => {\n switch (part.type) {\n case 'entity':\n return $createEntityNode(entityPluginId, part.value.text, part.value.data, part.value.entityProps);\n case 'text':\n return $createTextNode(part.value);\n }\n return unhandledPart(part);\n });\n $insertNodes(nodes);\n });\n }\n\n function handlePaste(event: ClipboardEvent): boolean {\n const transformPromises: Promise<PasteUnfurlingTransformResult<ExtraDataType, NodePropsType>>[] = [];\n\n for (const transform of transforms) {\n transformPromises.push(Promise.resolve(transform(event, editor)));\n }\n\n Promise.allSettled(transformPromises).then(results => {\n let handledPaste = false;\n\n for (const result of results) {\n if (result.status === 'fulfilled') {\n const transformResult = result.value;\n if (transformResult.transformedParts) {\n insertParts(transformResult.transformedParts);\n }\n\n if (transformResult.handled) {\n handledPaste = true;\n break;\n }\n }\n }\n\n if (!handledPaste) {\n const commandsMap = editor._commands;\n const defaultEditorListeners = commandsMap.get(PASTE_COMMAND)?.[COMMAND_PRIORITY_EDITOR];\n if (defaultEditorListeners) {\n for (const listener of defaultEditorListeners) {\n
|
|
1
|
+
{"version":3,"sources":["PasteUnfurling.base.ts"],"sourcesContent":["import type { LexicalEditor } from '@fluentui-copilot/text-editor';\nimport {\n COMMAND_PRIORITY_EDITOR,\n COMMAND_PRIORITY_LOW,\n PASTE_COMMAND,\n $insertNodes,\n $createTextNode,\n} from '@fluentui-copilot/text-editor';\nimport type {\n PasteUnfurlingPluginBaseProps,\n PasteUnfurlingTransformedPart,\n PasteUnfurlingTransformResult,\n} from './PasteUnfurling.types';\n\nfunction unhandledPart(part: never): never {\n throw new Error(`Unhandled part: ${part}`);\n}\n\nexport function registerPasteUnfurlingPlugin<ExtraDataType, NodePropsType>(\n editor: LexicalEditor,\n props: PasteUnfurlingPluginBaseProps<ExtraDataType, NodePropsType>,\n): () => void {\n const { entityPluginId, transforms, $createEntityNode } = props;\n\n function insertParts(parts: PasteUnfurlingTransformedPart<ExtraDataType, NodePropsType>[]) {\n editor.update(() => {\n const nodes = parts.map(part => {\n switch (part.type) {\n case 'entity':\n return $createEntityNode(entityPluginId, part.value.text, part.value.data, part.value.entityProps);\n case 'text':\n return $createTextNode(part.value);\n }\n return unhandledPart(part);\n });\n $insertNodes(nodes);\n });\n }\n\n function handlePaste(event: ClipboardEvent): boolean {\n const transformPromises: Promise<PasteUnfurlingTransformResult<ExtraDataType, NodePropsType>>[] = [];\n\n for (const transform of transforms) {\n transformPromises.push(Promise.resolve(transform(event, editor)));\n }\n\n Promise.allSettled(transformPromises).then(results => {\n let handledPaste = false;\n\n for (const result of results) {\n if (result.status === 'fulfilled') {\n const transformResult = result.value;\n if (transformResult.transformedParts) {\n insertParts(transformResult.transformedParts);\n }\n\n if (transformResult.handled) {\n handledPaste = true;\n break;\n }\n }\n }\n\n if (!handledPaste) {\n const commandsMap = editor._commands;\n const defaultEditorListeners = commandsMap.get(PASTE_COMMAND)?.[COMMAND_PRIORITY_EDITOR];\n if (defaultEditorListeners) {\n // After the promises have resolved, we're not guaranteed to be in the same update state as the original command\n editor.update(() => {\n for (const listener of defaultEditorListeners) {\n const defaultHandled = listener(event, editor);\n if (defaultHandled) {\n break;\n }\n }\n });\n }\n }\n });\n\n return true;\n }\n\n return editor.registerCommand(PASTE_COMMAND, handlePaste, COMMAND_PRIORITY_LOW);\n}\n"],"names":["registerPasteUnfurlingPlugin","unhandledPart","part","Error","editor","props","entityPluginId","insertParts","nodes","parts","map","$createEntityNode","$insertNodes","transformPromises","handlePaste","event","Promise","transform","handledPaste","result","results","transformResult","handled","transformedParts","defaultEditorListeners","update","_commands","listener","get","PASTE_COMMAND","_commandsMap_get","COMMAND_PRIORITY_EDITOR","defaultHandled"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAkBgBA;;;eAAAA;;;4BAXT;AAOP,SAASC,cAAcC,IAAW;UAChC,IAAMC,MAAIA,CAAAA,gBAAO,EAAgBD,KAAEA,CAAAA;AACrC;AAEO,SAASF,6BACdI,MAAqB,EACrBC,KAAkE;UAElE,EAEAC,cAASC,YACPH,mBACQI;yBAEFC,KAAK;;0BAELA,MAAKC,GAAA,CAAAR,CAAAA;gCACH;;+BAEJS,kBAAqBT,gBAAAA,KAAAA,KAAAA,CAAAA,IAAAA,EAAAA,KAAAA,KAAAA,CAAAA,IAAAA,EAAAA,KAAAA,KAAAA,CAAAA,WAAAA;yBACvB;wBACAU,OAAAA,IAAAA,2BAAaJ,EAAAA,KAAAA,KAAAA;gBACf;gBACF,OAAAP,cAAAC;YAEA;wCACQW,EAAAA;;;aAINC,YAAAC,KAAA;cAEAC,oBAAmBH,EAAAA;mBACjBI,aAAIC,WAAe;8BAERC,IAAAA,CAAAA,QAAUC,OAAS,CAAAH,UAAAF,OAAAX;;0BAE1B,CAAAS,mBAAMQ,IAAkBF,CAAAA,CAAAA;+BACpBE;iCACFd,QAAYc;iCACd,KAAA,aAAA;4CAEIA,OAAgBC,KAAAA;wCAClBJ,gBAAe,EAAA;oCACfG,gBAAAE,gBAAA;;wCAEJD,OAAA,EAAA;wBACFJ,eAAA;wBAEA;;;;+BAGMM;;oCAEKC,OAAOC,SAAA;+CACDC,CAAAA,mBAAYH,YAAwBI,GAAA,CAAAC,yBAAA,CAAA,MAAA,QAAAC,qBAAA,KAAA,IAAA,KAAA,IAAAA,gBAAA,CAAAC,mCAAA,CAAA;4CACvCC;oIACc;;+CAEpBR,uBAAA;mDACFG,SAAAZ,OAAAX;gDACF;gCACF;4BACF;wBACF;oBAEA;gBACF;YAEA;QACF"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: all[name]
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
$createMockEntityNode: function() {
|
|
13
|
+
return $createMockEntityNode;
|
|
14
|
+
},
|
|
15
|
+
$isMockEntityNode: function() {
|
|
16
|
+
return $isMockEntityNode;
|
|
17
|
+
},
|
|
18
|
+
MockClipboardEvent: function() {
|
|
19
|
+
return MockClipboardEvent;
|
|
20
|
+
},
|
|
21
|
+
MockEntityNode: function() {
|
|
22
|
+
return MockEntityNode;
|
|
23
|
+
},
|
|
24
|
+
createPasteEvent: function() {
|
|
25
|
+
return createPasteEvent;
|
|
26
|
+
},
|
|
27
|
+
parseEntity: function() {
|
|
28
|
+
return parseEntity;
|
|
29
|
+
},
|
|
30
|
+
parseLink: function() {
|
|
31
|
+
return parseLink;
|
|
32
|
+
},
|
|
33
|
+
parseLinkPreview: function() {
|
|
34
|
+
return parseLinkPreview;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const _define_property = require("@swc/helpers/_/_define_property");
|
|
38
|
+
const _texteditor = require("@fluentui-copilot/text-editor");
|
|
39
|
+
class MockClipboardEvent extends Event {
|
|
40
|
+
constructor(...args){
|
|
41
|
+
super(...args);
|
|
42
|
+
(0, _define_property._)(this, "clipboardData", null);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function createPasteEvent(data) {
|
|
46
|
+
const event = new MockClipboardEvent('paste');
|
|
47
|
+
event.clipboardData = {
|
|
48
|
+
types: [
|
|
49
|
+
data.map(({ mimeType })=>mimeType)
|
|
50
|
+
],
|
|
51
|
+
getData: (format)=>{
|
|
52
|
+
const item = data.find(({ mimeType })=>mimeType === format);
|
|
53
|
+
if (item) {
|
|
54
|
+
return item.value;
|
|
55
|
+
}
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return event;
|
|
60
|
+
}
|
|
61
|
+
class MockEntityNode extends _texteditor.TextNode {
|
|
62
|
+
static getType() {
|
|
63
|
+
return 'mockEntity';
|
|
64
|
+
}
|
|
65
|
+
constructor(text, url){
|
|
66
|
+
super(text);
|
|
67
|
+
(0, _define_property._)(this, "url", void 0);
|
|
68
|
+
this.url = url;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function $createMockEntityNode(text, url) {
|
|
72
|
+
return new MockEntityNode(text, url);
|
|
73
|
+
}
|
|
74
|
+
function $isMockEntityNode(node) {
|
|
75
|
+
return node instanceof MockEntityNode;
|
|
76
|
+
}
|
|
77
|
+
const parseLinkPreview = (event)=>{
|
|
78
|
+
let previewData;
|
|
79
|
+
try {
|
|
80
|
+
var _event_clipboardData;
|
|
81
|
+
const previewDataString = (_event_clipboardData = event.clipboardData) === null || _event_clipboardData === void 0 ? void 0 : _event_clipboardData.getData('text/link-preview');
|
|
82
|
+
if (previewDataString === undefined || previewDataString === '') {
|
|
83
|
+
return {
|
|
84
|
+
handled: false
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
previewData = JSON.parse(previewDataString);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
return {
|
|
90
|
+
handled: false
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const title = previewData.title;
|
|
94
|
+
const url = previewData.url;
|
|
95
|
+
if (!title || !url) {
|
|
96
|
+
return {
|
|
97
|
+
handled: false
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
handled: true,
|
|
102
|
+
transformedParts: [
|
|
103
|
+
{
|
|
104
|
+
type: 'entity',
|
|
105
|
+
value: {
|
|
106
|
+
text: title,
|
|
107
|
+
data: {
|
|
108
|
+
url
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
const urlRegex = /(\b(?:https?):\/\/[^\s]+)/gi;
|
|
116
|
+
const parseLink = (event)=>{
|
|
117
|
+
var _event_clipboardData;
|
|
118
|
+
const text = (_event_clipboardData = event.clipboardData) === null || _event_clipboardData === void 0 ? void 0 : _event_clipboardData.getData('text/plain');
|
|
119
|
+
if (!text) {
|
|
120
|
+
return {
|
|
121
|
+
handled: false
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const parts = text.split(urlRegex);
|
|
125
|
+
// If an entity was found, parts will be at least 3 elements long
|
|
126
|
+
if (parts.length < 3) {
|
|
127
|
+
return {
|
|
128
|
+
handled: false
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const transformedParts = parts.map((str, i)=>{
|
|
132
|
+
if (i % 2 === 0) {
|
|
133
|
+
return {
|
|
134
|
+
type: 'text',
|
|
135
|
+
value: str
|
|
136
|
+
};
|
|
137
|
+
} else {
|
|
138
|
+
return {
|
|
139
|
+
type: 'entity',
|
|
140
|
+
value: {
|
|
141
|
+
text: str,
|
|
142
|
+
data: {
|
|
143
|
+
url: str
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}) // Filter out all the nulls for empty strings
|
|
149
|
+
.filter((node)=>node !== null);
|
|
150
|
+
return {
|
|
151
|
+
handled: true,
|
|
152
|
+
transformedParts
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
const parseEntity = async (event)=>{
|
|
156
|
+
var _event_clipboardData;
|
|
157
|
+
const text = (_event_clipboardData = event.clipboardData) === null || _event_clipboardData === void 0 ? void 0 : _event_clipboardData.getData('text/plain');
|
|
158
|
+
if (!text) {
|
|
159
|
+
return {
|
|
160
|
+
handled: false
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// Assume entities come in the syntax <entity>title</entity>
|
|
164
|
+
const re = /<entity[^>]*>([^<]*)<\/entity>/g;
|
|
165
|
+
const parts = text.split(re);
|
|
166
|
+
// If an entity was found, parts will be at least 3 elements long
|
|
167
|
+
if (parts.length < 3) {
|
|
168
|
+
return {
|
|
169
|
+
handled: false
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
// Even elements are text, odd elements are entities
|
|
173
|
+
// ["", entity, "", entity, "", ...]
|
|
174
|
+
const transformedParts = parts.map((str, i)=>{
|
|
175
|
+
if (i % 2 === 0) {
|
|
176
|
+
return {
|
|
177
|
+
type: 'text',
|
|
178
|
+
value: str
|
|
179
|
+
};
|
|
180
|
+
} else {
|
|
181
|
+
return {
|
|
182
|
+
type: 'entity',
|
|
183
|
+
value: {
|
|
184
|
+
text: str,
|
|
185
|
+
data: {
|
|
186
|
+
url: str
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}) // Filter out all the nulls for empty strings
|
|
192
|
+
.filter((node)=>node !== null);
|
|
193
|
+
return {
|
|
194
|
+
handled: true,
|
|
195
|
+
transformedParts
|
|
196
|
+
};
|
|
197
|
+
}; //# sourceMappingURL=PasteUnfurlingTestUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["PasteUnfurlingTestUtils.ts"],"sourcesContent":["import type { LexicalNode } from '@fluentui-copilot/text-editor';\nimport { TextNode } from '@fluentui-copilot/text-editor';\nimport type { PasteUnfurlingTransformedPart, PasteUnfurlingTransformResult } from '..';\n\nexport class MockClipboardEvent extends Event implements ClipboardEvent {\n clipboardData: DataTransfer | null = null;\n}\n\nexport function createPasteEvent(data: { mimeType: string; value: string }[]) {\n const event = new MockClipboardEvent('paste');\n\n event.clipboardData = {\n types: [data.map(({ mimeType }) => mimeType)],\n getData: (format: string) => {\n const item = data.find(({ mimeType }) => mimeType === format);\n if (item) {\n return item.value;\n }\n return '';\n },\n } as unknown as DataTransfer;\n\n return event;\n}\n\nexport class MockEntityNode extends TextNode {\n url: string;\n\n constructor(text: string, url: string) {\n super(text);\n this.url = url;\n }\n\n static getType(): string {\n return 'mockEntity';\n }\n}\n\nexport type ExtraDataType = { url: string };\n\nexport function $createMockEntityNode(text: string, url: string): MockEntityNode {\n return new MockEntityNode(text, url);\n}\n\nexport function $isMockEntityNode(node: LexicalNode | null | undefined): node is MockEntityNode {\n return node instanceof MockEntityNode;\n}\n\nexport const parseLinkPreview = (event: ClipboardEvent): PasteUnfurlingTransformResult<ExtraDataType, {}> => {\n let previewData;\n try {\n const previewDataString = event.clipboardData?.getData('text/link-preview');\n if (previewDataString === undefined || previewDataString === '') {\n return { handled: false };\n }\n\n previewData = JSON.parse(previewDataString);\n } catch (e) {\n return { handled: false };\n }\n\n const title: string | undefined = previewData.title;\n const url: string | undefined = previewData.url;\n if (!title || !url) {\n return { handled: false };\n }\n\n return {\n handled: true,\n transformedParts: [{ type: 'entity', value: { text: title, data: { url } } }],\n };\n};\nconst urlRegex = /(\\b(?:https?):\\/\\/[^\\s]+)/gi;\n\nexport const parseLink = (event: ClipboardEvent): PasteUnfurlingTransformResult<ExtraDataType, {}> => {\n const text = event.clipboardData?.getData('text/plain');\n if (!text) {\n return {\n handled: false,\n };\n }\n\n const parts = text.split(urlRegex);\n // If an entity was found, parts will be at least 3 elements long\n if (parts.length < 3) {\n return { handled: false };\n }\n const transformedParts = parts\n .map((str, i) => {\n if (i % 2 === 0) {\n return { type: 'text', value: str };\n } else {\n return {\n type: 'entity',\n value: { text: str, data: { url: str } },\n };\n }\n })\n // Filter out all the nulls for empty strings\n .filter(node => node !== null) as PasteUnfurlingTransformedPart<ExtraDataType, {}>[];\n\n return { handled: true, transformedParts };\n};\n\n// A transform can be async in case it needs to fetch data from a server.\nexport const parseEntity = async (event: ClipboardEvent): Promise<PasteUnfurlingTransformResult<ExtraDataType, {}>> => {\n const text = event.clipboardData?.getData('text/plain');\n if (!text) {\n return {\n handled: false,\n };\n }\n\n // Assume entities come in the syntax <entity>title</entity>\n const re = /<entity[^>]*>([^<]*)<\\/entity>/g;\n const parts = text.split(re);\n // If an entity was found, parts will be at least 3 elements long\n if (parts.length < 3) {\n return { handled: false };\n }\n\n // Even elements are text, odd elements are entities\n // [\"\", entity, \"\", entity, \"\", ...]\n const transformedParts = parts\n .map((str, i) => {\n if (i % 2 === 0) {\n return { type: 'text', value: str };\n } else {\n return {\n type: 'entity',\n value: { text: str, data: { url: str } },\n };\n }\n })\n // Filter out all the nulls for empty strings\n .filter(node => node !== null) as PasteUnfurlingTransformedPart<ExtraDataType, {}>[];\n\n return { handled: true, transformedParts };\n};\n"],"names":["$createMockEntityNode","$isMockEntityNode","MockClipboardEvent","MockEntityNode","createPasteEvent","parseEntity","parseLink","parseLinkPreview","Event","clipboardData","data","event","types","map","mimeType","getData","item","find","value","TextNode","getType","constructor","url","text","_define_property","node","_event_clipboardData","undefined","previewDataString","handled","JSON","parse","title","previewData","transformedParts","urlRegex","parts","split","length","str","i","filter","re"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;;;;;;;;IA0CAA,qBAAA;eAAAA;;IAIAC,iBAAA;eAAAA;;IA1CaC,kBAAAA;eAAAA;;IA8BTC,cAAO;eAAPA;;IA1BYC,gBAAAA;eAAAA;;IAiGHC,WAAAA;eAAAA;;IA/BAC,SAAAA;eAAAA;;IAxBPC,gBAAA;eAAAA;;;;4BAjDmB;AAGlB,MAAML,2BAA2BM;;;8BACtCC,EAAAA,IAAAA,EAAAA,iBAAAA;;AACF;AAEO,SAASL,iBAAiBM,IAA2C;UAC1EC,QAAMA,IAAQT,mBAAIA;UAElBS,aAAMF,GAAa;eACjBG;YAAAA,KAAOC,GAAA,CAAA,CAAA,UAACH,KAAqCI;SAAA;iBAC7CC,CAAAA;kBACEC,OAAMA,KAAAA,IAAON,CAAAA,CAAKO,UACdD,kBACKA;sBACT;uBACAA,KAAOE,KAAA;;YAEX,OAAA;QAEA;IACF;IAEA,OAAOP;;MASHR,uBAAOgB,oBAAA;WACTC,UAAA;QAPAC,OAAAA;;gBAFAC,IAAAA,EAAAA,GAAAA,CAAAA;aAIE,CAAAC;QACFC,IAAAA,kBAAA,EAAA,IAAA,EAAA,OAAA,KAAA;QAKF,IAAA,CAAAF,GAAA,GAAAA;IAIA;;AAEA,SAAAtB,sBAAAuB,IAAA,EAAAD,GAAA;IAEA,OAAO,IAAAnB,eAASF,MAAkBwB;;AAElC,SAAAxB,kBAAAwB,IAAA;IAEA,OAAOA,gBAAMlB;;AAEX,MAAIA,mBAAAI,CAAAA;;;YAEFe;kCACS,AAAAA,CAAAA,uBAAAf,MAAAF,aAAA,MAAA,QAAAiB,yBAAA,KAAA,IAAA,KAAA,IAAAA,qBAAAX,OAAA,CAAA;kCAAWY,aAAAC,sBAAA,IAAA;mBAAM;gBAC1BC,SAAA;;QAGF;sBACSC,KAAAC,KAAA,CAAAH;gBAAEC;eAAe;YAC1BA,SAAA;QAEA;;UAEIG,QAACA,YAAeA,KAAA;UAClBV,MAAAW,YAAOX,GAAA;kBAAEO,CAAAA,KAAS;eAAM;YAC1BA,SAAA;QAEA;;WAEEK;iBAAmB;0BAAQ;YAAA;;;;;;;;;;;AAE/B;AACA,MAAMC,WAAW;AAEV,MAAM7B,YAAYK,CAAAA;;UACvBY,OAAMA,CAAAA,uBAAOZ,MAAAA,aAAMF,MAAa,QAAAiB,yBAAnBf,KAAAA,IAAAA,KAAAA,IAAAA,qBAAAA,OAAqBI,CAAAA;QAClC,CAAAQ,MAAKA;eACH;qBACEM;;;UAIJO,QAAMA,KAAQb,KAAKc,CAAAA;qEACnB;QACAD,MAAIA,MAAME,GAAM,GAAG;eACjB;qBAAST;;;UAEXK,mBAAMA,MAAmBE,GACtBvB,CAAAA,CAAG0B,KAAEA;YACJC,IAAIA,MAAI,GAAA;mBACN;;;;eACF;mBACE;;;;;;;;;;OAKJ,6CACA;WACCC,CAAAA,CAAAA,OAAOhB,SAAQA;WAElB;iBAASI;;;AACX;AAGO,MAAMxB,cAAc,OAAAM;;UACzBY,OAAMA,CAAAA,uBAAOZ,MAAAA,aAAMF,MAAa,QAAAiB,yBAAnBf,KAAAA,IAAAA,KAAAA,IAAAA,qBAAAA,OAAqBI,CAAAA;QAClC,CAAAQ,MAAKA;eACH;qBACEM;;;gEAIJ;UACAa,KAAMA;UACNN,QAAMA,KAAQb,KAAKc,CAAAA;qEACnB;QACAD,MAAIA,MAAME,GAAM,GAAG;eACjB;qBAAST;;;wDAGX;wCACA;UACAK,mBAAMA,MAAmBE,GACtBvB,CAAAA,CAAG0B,KAAEA;YACJC,IAAIA,MAAI,GAAA;mBACN;;;;eACF;mBACE;;;;;;;;;;OAKJ,6CACA;WACCC,CAAAA,CAAAA,OAAOhB,SAAQA;WAElB;iBAASI;;;AACX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluentui-copilot/chat-input-plugins",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "A Fluent AI package for non-react specific chat input plugins.",
|
|
5
5
|
"main": "lib-commonjs/index.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@fluentui-copilot/text-editor": "^0.2.
|
|
15
|
+
"@fluentui-copilot/text-editor": "^0.2.1",
|
|
16
16
|
"@swc/helpers": "^0.5.1"
|
|
17
17
|
},
|
|
18
18
|
"beachball": {
|