@pod-os/elements 0.30.2-rc.8724051.0 → 0.30.2-rc.94c5dad.0
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/dist/cjs/elements.cjs.js +1 -1
- package/dist/cjs/ion-icon_33.cjs.entry.js +1 -2
- package/dist/cjs/ion-icon_33.cjs.entry.js.map +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/pos-document.cjs.entry.js +9 -6
- package/dist/cjs/pos-document.cjs.entry.js.map +1 -1
- package/dist/cjs/pos-markdown-document.cjs.entry.js +13481 -14042
- package/dist/cjs/pos-markdown-document.cjs.entry.js.map +1 -1
- package/dist/collection/components/pos-document/pos-document.js +10 -7
- package/dist/collection/components/pos-document/pos-document.js.map +1 -1
- package/dist/collection/components/pos-markdown-document/pos-markdown-document.css +17 -0
- package/dist/collection/components/pos-markdown-document/pos-markdown-document.js +33 -25
- package/dist/collection/components/pos-markdown-document/pos-markdown-document.js.map +1 -1
- package/dist/collection/components/pos-markdown-document/rich-editor/PosImageNode.js +25 -21
- package/dist/collection/components/pos-markdown-document/rich-editor/PosImageNode.js.map +1 -1
- package/dist/collection/components/pos-markdown-document/rich-editor/PosRichLinkMark.js +20 -16
- package/dist/collection/components/pos-markdown-document/rich-editor/PosRichLinkMark.js.map +1 -1
- package/dist/collection/components/pos-markdown-document/rich-editor/RichEditor.js +10 -24
- package/dist/collection/components/pos-markdown-document/rich-editor/RichEditor.js.map +1 -1
- package/dist/components/pos-app2.js +1 -2
- package/dist/components/pos-app2.js.map +1 -1
- package/dist/components/pos-document2.js +10 -7
- package/dist/components/pos-document2.js.map +1 -1
- package/dist/components/pos-markdown-document2.js +13483 -14044
- package/dist/components/pos-markdown-document2.js.map +1 -1
- package/dist/elements/elements.esm.js +1 -1
- package/dist/elements/elements.esm.js.map +1 -1
- package/dist/elements/p-08f92489.entry.js +2 -0
- package/dist/elements/p-08f92489.entry.js.map +1 -0
- package/dist/elements/p-4f8297e8.entry.js +2 -0
- package/dist/elements/p-4f8297e8.entry.js.map +1 -0
- package/dist/elements/{p-411c85a4.entry.js → p-c9ba983f.entry.js} +2 -2
- package/dist/elements/p-c9ba983f.entry.js.map +1 -0
- package/dist/esm/elements.js +1 -1
- package/dist/esm/ion-icon_33.entry.js +1 -2
- package/dist/esm/ion-icon_33.entry.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/pos-document.entry.js +9 -6
- package/dist/esm/pos-document.entry.js.map +1 -1
- package/dist/esm/pos-markdown-document.entry.js +13481 -14042
- package/dist/esm/pos-markdown-document.entry.js.map +1 -1
- package/dist/types/components/pos-document/pos-document.d.ts +1 -1
- package/dist/types/components/pos-markdown-document/pos-markdown-document.d.ts +5 -5
- package/dist/types/components/pos-markdown-document/rich-editor/PosImageNode.d.ts +2 -0
- package/dist/types/components/pos-markdown-document/rich-editor/PosRichLinkMark.d.ts +2 -0
- package/dist/types/components/pos-markdown-document/rich-editor/RichEditor.d.ts +1 -9
- package/dist/types/components.d.ts +4 -4
- package/package.json +9 -11
- package/dist/collection/components/pos-markdown-document/html2markdown.js +0 -10
- package/dist/collection/components/pos-markdown-document/html2markdown.js.map +0 -1
- package/dist/collection/components/pos-markdown-document/markdown2html.js +0 -5
- package/dist/collection/components/pos-markdown-document/markdown2html.js.map +0 -1
- package/dist/collection/components/pos-markdown-document/sanitize.js +0 -10
- package/dist/collection/components/pos-markdown-document/sanitize.js.map +0 -1
- package/dist/elements/p-411c85a4.entry.js.map +0 -1
- package/dist/elements/p-581ed3ee.entry.js +0 -3
- package/dist/elements/p-581ed3ee.entry.js.map +0 -1
- package/dist/elements/p-ff3f95dc.entry.js +0 -2
- package/dist/elements/p-ff3f95dc.entry.js.map +0 -1
- package/dist/types/components/pos-markdown-document/html2markdown.d.ts +0 -1
- package/dist/types/components/pos-markdown-document/markdown2html.d.ts +0 -1
- package/dist/types/components/pos-markdown-document/sanitize.d.ts +0 -4
|
@@ -3,7 +3,7 @@ import session from "../../store/session";
|
|
|
3
3
|
import { BrokenFile } from "../broken-file/BrokenFile";
|
|
4
4
|
export class PosDocument {
|
|
5
5
|
constructor() {
|
|
6
|
-
this.
|
|
6
|
+
this.saveStatus = 'idle';
|
|
7
7
|
this.loading = true;
|
|
8
8
|
this.isEditable = false;
|
|
9
9
|
this.setOs = async (os) => {
|
|
@@ -17,16 +17,19 @@ export class PosDocument {
|
|
|
17
17
|
async handleDocumentModified(event) {
|
|
18
18
|
const { file, newContent } = event.detail;
|
|
19
19
|
try {
|
|
20
|
-
this.
|
|
20
|
+
this.saveStatus = 'saving';
|
|
21
21
|
const response = await this.os.files().putFile(file, newContent);
|
|
22
|
-
if (
|
|
23
|
-
this.
|
|
22
|
+
if (response.ok) {
|
|
23
|
+
this.saveStatus = 'idle';
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.saveStatus = 'failed';
|
|
24
27
|
const error = new Error(`Failed to save file: ${response.status} ${response.statusText}`);
|
|
25
28
|
this.errorEmitter.emit(error);
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
catch (error) {
|
|
29
|
-
this.
|
|
32
|
+
this.saveStatus = 'failed';
|
|
30
33
|
this.errorEmitter.emit(error);
|
|
31
34
|
}
|
|
32
35
|
}
|
|
@@ -63,7 +66,7 @@ export class PosDocument {
|
|
|
63
66
|
return h(BrokenFile, { file: this.brokenFile });
|
|
64
67
|
}
|
|
65
68
|
if (this.file.blob().type === 'text/markdown') {
|
|
66
|
-
return (h("pos-markdown-document", { editable: this.isEditable,
|
|
69
|
+
return (h("pos-markdown-document", { editable: this.isEditable, saveStatus: this.saveStatus, file: this.file }));
|
|
67
70
|
}
|
|
68
71
|
else {
|
|
69
72
|
return h("iframe", { src: URL.createObjectURL(this.file.blob()) });
|
|
@@ -129,7 +132,7 @@ export class PosDocument {
|
|
|
129
132
|
"file": {},
|
|
130
133
|
"brokenFile": {},
|
|
131
134
|
"error": {},
|
|
132
|
-
"
|
|
135
|
+
"saveStatus": {},
|
|
133
136
|
"loading": {},
|
|
134
137
|
"isEditable": {}
|
|
135
138
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pos-document.js","sourceRoot":"","sources":["../../../../src/components/pos-document/pos-document.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAgB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC9F,OAAO,OAAO,MAAM,qBAAqB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAOvD,MAAM,OAAO,WAAW;IALxB;QAsBU,
|
|
1
|
+
{"version":3,"file":"pos-document.js","sourceRoot":"","sources":["../../../../src/components/pos-document/pos-document.tsx"],"names":[],"mappings":"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","sourcesContent":["import { PodOS, BrokenFile as BrokenFileData, SolidFile } from '@pod-os/core';\nimport { Component, Event, EventEmitter, h, Listen, Prop, State, Watch } from '@stencil/core';\nimport session from '../../store/session';\nimport { BrokenFile } from '../broken-file/BrokenFile';\n\n@Component({\n tag: 'pos-document',\n styleUrl: 'pos-document.css',\n shadow: true,\n})\nexport class PosDocument {\n @Prop() src: string;\n\n @Prop() alt: string;\n\n @State() os: PodOS;\n\n @State()\n private file: SolidFile;\n\n @State()\n private brokenFile: BrokenFileData;\n\n @State()\n private error: Error;\n\n @State()\n private saveStatus: 'idle' | 'saving' | 'failed' = 'idle';\n\n @State()\n private loading: boolean = true;\n\n @State()\n private isEditable: boolean = false;\n\n @Event({ eventName: 'pod-os:init' }) initializeOsEmitter: EventEmitter;\n\n /**\n * Indicates that the resource given in `src` property has been loaded.\n */\n @Event({ eventName: 'pod-os:resource-loaded' }) resourceLoadedEmitter: EventEmitter<string>;\n\n /**\n * Emitted when an error occurs during file operations.\n */\n @Event({ eventName: 'pod-os:error' }) errorEmitter: EventEmitter<Error>;\n\n componentWillLoad() {\n session.onChange('isLoggedIn', () => this.fetchBlob());\n this.initializeOsEmitter.emit(this.setOs);\n }\n\n setOs = async (os: PodOS) => {\n this.os = os;\n };\n\n @Listen('pod-os:document-modified')\n async handleDocumentModified(event: CustomEvent) {\n const { file, newContent } = event.detail;\n try {\n this.saveStatus = 'saving';\n const response = await this.os.files().putFile(file, newContent);\n if (response.ok) {\n this.saveStatus = 'idle';\n } else {\n this.saveStatus = 'failed';\n const error = new Error(`Failed to save file: ${response.status} ${response.statusText}`);\n this.errorEmitter.emit(error);\n }\n } catch (error) {\n this.saveStatus = 'failed';\n this.errorEmitter.emit(error);\n }\n }\n\n @Watch('os')\n @Watch('src')\n async fetchBlob() {\n try {\n this.loading = true;\n const file = await this.os.files().fetchFile(this.src);\n const thing = this.os.store.get(this.src);\n this.isEditable = thing?.editable;\n this.resourceLoadedEmitter.emit(this.src);\n if (file.blob()) {\n this.file = file;\n this.error = null;\n } else {\n this.brokenFile = file as BrokenFileData;\n }\n } catch (err) {\n this.error = err;\n } finally {\n this.loading = false;\n }\n }\n\n render() {\n if (this.loading) {\n return <ion-skeleton-text animated={true}></ion-skeleton-text>;\n }\n if (this.error) {\n return <div class=\"error\">{this.error.message}</div>;\n }\n if (this.brokenFile) {\n return <BrokenFile file={this.brokenFile} />;\n }\n if (this.file.blob().type === 'text/markdown') {\n return (\n <pos-markdown-document\n editable={this.isEditable}\n saveStatus={this.saveStatus}\n file={this.file}\n ></pos-markdown-document>\n );\n } else {\n return <iframe src={URL.createObjectURL(this.file.blob())}></iframe>;\n }\n }\n}\n"]}
|
|
@@ -67,6 +67,10 @@
|
|
|
67
67
|
&.error {
|
|
68
68
|
animation: error-flash 2s ease infinite;
|
|
69
69
|
}
|
|
70
|
+
|
|
71
|
+
&.saving {
|
|
72
|
+
animation: saving-flash 2s ease infinite;
|
|
73
|
+
}
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
76
|
|
|
@@ -133,3 +137,16 @@
|
|
|
133
137
|
opacity: 0;
|
|
134
138
|
}
|
|
135
139
|
}
|
|
140
|
+
|
|
141
|
+
@keyframes saving-flash {
|
|
142
|
+
0% {
|
|
143
|
+
opacity: 0;
|
|
144
|
+
}
|
|
145
|
+
50% {
|
|
146
|
+
opacity: 1;
|
|
147
|
+
color: var(--pos-primary-color);
|
|
148
|
+
}
|
|
149
|
+
100% {
|
|
150
|
+
opacity: 0;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
|
-
import { sanitize } from "./sanitize";
|
|
3
2
|
import { RichEditor } from "./rich-editor";
|
|
4
3
|
import "./shoelace";
|
|
5
4
|
import { map, Subject, takeUntil, tap } from "rxjs";
|
|
6
|
-
import { html2markdown } from "./html2markdown";
|
|
7
|
-
import { markdown2html } from "./markdown2html";
|
|
8
5
|
export class PosMarkdownDocument {
|
|
9
6
|
constructor() {
|
|
10
7
|
/**
|
|
11
|
-
*
|
|
8
|
+
* Current save status
|
|
12
9
|
*/
|
|
13
|
-
this.
|
|
10
|
+
this.saveStatus = 'idle';
|
|
14
11
|
/**
|
|
15
12
|
* Whether the current user has the permission to edit the file
|
|
16
13
|
*/
|
|
@@ -20,18 +17,16 @@ export class PosMarkdownDocument {
|
|
|
20
17
|
this.disconnected$ = new Subject();
|
|
21
18
|
}
|
|
22
19
|
async componentWillLoad() {
|
|
23
|
-
|
|
24
|
-
const html = await markdown2html(markdown);
|
|
25
|
-
this.sanitizedHtml = sanitize(html);
|
|
20
|
+
this.markdown = await this.file.blob().text();
|
|
26
21
|
}
|
|
27
22
|
componentDidLoad() {
|
|
28
|
-
this.editor = new RichEditor(this.editorEl, this.
|
|
23
|
+
this.editor = new RichEditor(this.editorEl, this.markdown, this.file.url);
|
|
29
24
|
this.editor.onUpdate(() => {
|
|
30
|
-
this.isModified =
|
|
25
|
+
this.isModified = true;
|
|
31
26
|
});
|
|
32
27
|
this.editor
|
|
33
28
|
.observeChanges()
|
|
34
|
-
.pipe(takeUntil(this.disconnected$), map(changes =>
|
|
29
|
+
.pipe(takeUntil(this.disconnected$), map(changes => changes.content), tap(markdown => {
|
|
35
30
|
this.isModified = false;
|
|
36
31
|
this.documentModified.emit({
|
|
37
32
|
file: this.file,
|
|
@@ -47,27 +42,30 @@ export class PosMarkdownDocument {
|
|
|
47
42
|
/**
|
|
48
43
|
* Switch to editing mode
|
|
49
44
|
*/
|
|
50
|
-
startEditing() {
|
|
45
|
+
async startEditing() {
|
|
51
46
|
this.editor.startEditing();
|
|
52
47
|
this.isEditing = true;
|
|
53
48
|
}
|
|
54
49
|
/**
|
|
55
50
|
* Switch to view mode
|
|
56
51
|
*/
|
|
57
|
-
stopEditing() {
|
|
52
|
+
async stopEditing() {
|
|
58
53
|
this.editor.stopEditing();
|
|
59
54
|
this.isEditing = false;
|
|
60
55
|
}
|
|
61
56
|
render() {
|
|
62
|
-
return (h("article", { key: '
|
|
57
|
+
return (h("article", { key: '99e920a07dfbde44c65415fac345ce183b4a6be3' }, this.editable ? (h("header", null, this.isEditing ? this.getStatus() : null, this.isEditing ? (h("button", { onClick: () => this.stopEditing() }, h("sl-icon", { name: "eye" }), "View")) : (h("button", { onClick: () => this.startEditing() }, h("sl-icon", { name: "pencil-square" }), "Edit")))) : null, h("div", { key: '8407b452e5a17be4e1db7a61621787ddc76bd279', class: "content", ref: el => (this.editorEl = el) })));
|
|
63
58
|
}
|
|
64
59
|
getStatus() {
|
|
65
60
|
if (this.isModified) {
|
|
66
61
|
return h(Status, { status: "pending", message: "pending changes", icon: "clock-history" });
|
|
67
62
|
}
|
|
68
|
-
if (this.
|
|
63
|
+
if (this.saveStatus === 'failed') {
|
|
69
64
|
return h(Status, { status: "error", message: "saving failed", icon: "x-octagon" });
|
|
70
65
|
}
|
|
66
|
+
if (this.saveStatus === 'saving') {
|
|
67
|
+
return h(Status, { status: "saving", message: "saving changes", icon: "cloud-upload" });
|
|
68
|
+
}
|
|
71
69
|
return h(Status, { status: "success", message: "all saved", icon: "check2-circle" });
|
|
72
70
|
}
|
|
73
71
|
static get is() { return "pos-markdown-document"; }
|
|
@@ -107,25 +105,25 @@ export class PosMarkdownDocument {
|
|
|
107
105
|
"getter": false,
|
|
108
106
|
"setter": false
|
|
109
107
|
},
|
|
110
|
-
"
|
|
111
|
-
"type": "
|
|
108
|
+
"saveStatus": {
|
|
109
|
+
"type": "string",
|
|
112
110
|
"mutable": false,
|
|
113
111
|
"complexType": {
|
|
114
|
-
"original": "
|
|
115
|
-
"resolved": "
|
|
112
|
+
"original": "'idle' | 'saving' | 'failed'",
|
|
113
|
+
"resolved": "\"failed\" | \"idle\" | \"saving\"",
|
|
116
114
|
"references": {}
|
|
117
115
|
},
|
|
118
116
|
"required": false,
|
|
119
117
|
"optional": false,
|
|
120
118
|
"docs": {
|
|
121
119
|
"tags": [],
|
|
122
|
-
"text": "
|
|
120
|
+
"text": "Current save status"
|
|
123
121
|
},
|
|
124
122
|
"getter": false,
|
|
125
123
|
"setter": false,
|
|
126
|
-
"attribute": "
|
|
124
|
+
"attribute": "save-status",
|
|
127
125
|
"reflect": false,
|
|
128
|
-
"defaultValue": "
|
|
126
|
+
"defaultValue": "'idle'"
|
|
129
127
|
},
|
|
130
128
|
"editable": {
|
|
131
129
|
"type": "boolean",
|
|
@@ -151,7 +149,7 @@ export class PosMarkdownDocument {
|
|
|
151
149
|
}
|
|
152
150
|
static get states() {
|
|
153
151
|
return {
|
|
154
|
-
"
|
|
152
|
+
"markdown": {},
|
|
155
153
|
"isModified": {},
|
|
156
154
|
"isEditing": {}
|
|
157
155
|
};
|
|
@@ -185,7 +183,12 @@ export class PosMarkdownDocument {
|
|
|
185
183
|
"complexType": {
|
|
186
184
|
"signature": "() => Promise<void>",
|
|
187
185
|
"parameters": [],
|
|
188
|
-
"references": {
|
|
186
|
+
"references": {
|
|
187
|
+
"Promise": {
|
|
188
|
+
"location": "global",
|
|
189
|
+
"id": "global::Promise"
|
|
190
|
+
}
|
|
191
|
+
},
|
|
189
192
|
"return": "Promise<void>"
|
|
190
193
|
},
|
|
191
194
|
"docs": {
|
|
@@ -197,7 +200,12 @@ export class PosMarkdownDocument {
|
|
|
197
200
|
"complexType": {
|
|
198
201
|
"signature": "() => Promise<void>",
|
|
199
202
|
"parameters": [],
|
|
200
|
-
"references": {
|
|
203
|
+
"references": {
|
|
204
|
+
"Promise": {
|
|
205
|
+
"location": "global",
|
|
206
|
+
"id": "global::Promise"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
201
209
|
"return": "Promise<void>"
|
|
202
210
|
},
|
|
203
211
|
"docs": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pos-markdown-document.js","sourceRoot":"","sources":["../../../../src/components/pos-markdown-document/pos-markdown-document.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AAEvF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"pos-markdown-document.js","sourceRoot":"","sources":["../../../../src/components/pos-markdown-document/pos-markdown-document.tsx"],"names":[],"mappings":"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","sourcesContent":["import { SolidFile } from '@pod-os/core';\nimport { Component, h, Method, Prop, State, Event, EventEmitter } from '@stencil/core';\n\nimport { RichEditor } from './rich-editor';\n\nimport './shoelace';\nimport { map, Subject, takeUntil, tap } from 'rxjs';\n\ninterface ModifiedFile {\n file: SolidFile;\n newContent: string;\n}\n\n@Component({\n tag: 'pos-markdown-document',\n styleUrls: ['pos-markdown-document.css', '../../apps/styles/article-card.css'],\n shadow: true,\n})\nexport class PosMarkdownDocument {\n /**\n * The file to show / edit\n */\n @Prop()\n file: SolidFile;\n\n /**\n * Current save status\n */\n @Prop()\n saveStatus: 'idle' | 'saving' | 'failed' = 'idle';\n\n /**\n * Whether the current user has the permission to edit the file\n */\n @Prop()\n editable: boolean = false;\n\n @State()\n private markdown: string;\n\n private editorEl: HTMLElement;\n\n @State()\n private isModified: boolean = false;\n\n private editor: RichEditor;\n\n @State()\n private isEditing: boolean = false;\n\n /**\n * Event emitted when the document has been modified\n */\n @Event({ eventName: 'pod-os:document-modified' })\n documentModified: EventEmitter<ModifiedFile>;\n\n private readonly disconnected$ = new Subject<void>();\n\n async componentWillLoad() {\n this.markdown = await this.file.blob().text();\n }\n\n componentDidLoad() {\n this.editor = new RichEditor(this.editorEl, this.markdown, this.file.url);\n this.editor.onUpdate(() => {\n this.isModified = true;\n });\n this.editor\n .observeChanges()\n .pipe(\n takeUntil(this.disconnected$),\n map(changes => changes.content),\n tap(markdown => {\n this.isModified = false;\n this.documentModified.emit({\n file: this.file,\n newContent: markdown,\n });\n }),\n )\n .subscribe();\n }\n\n disconnectedCallback() {\n this.disconnected$.next();\n this.disconnected$.unsubscribe();\n }\n\n /**\n * Switch to editing mode\n */\n @Method()\n async startEditing() {\n this.editor.startEditing();\n this.isEditing = true;\n }\n\n /**\n * Switch to view mode\n */\n @Method()\n async stopEditing() {\n this.editor.stopEditing();\n this.isEditing = false;\n }\n\n render() {\n return (\n <article>\n {this.editable ? (\n <header>\n {this.isEditing ? this.getStatus() : null}\n {this.isEditing ? (\n <button onClick={() => this.stopEditing()}>\n <sl-icon name=\"eye\"></sl-icon>\n View\n </button>\n ) : (\n <button onClick={() => this.startEditing()}>\n <sl-icon name=\"pencil-square\"></sl-icon>\n Edit\n </button>\n )}\n </header>\n ) : null}\n <div class=\"content\" ref={el => (this.editorEl = el)}></div>\n </article>\n );\n }\n\n private getStatus() {\n if (this.isModified) {\n return <Status status=\"pending\" message=\"pending changes\" icon=\"clock-history\"></Status>;\n }\n if (this.saveStatus === 'failed') {\n return <Status status=\"error\" message=\"saving failed\" icon=\"x-octagon\"></Status>;\n }\n if (this.saveStatus === 'saving') {\n return <Status status=\"saving\" message=\"saving changes\" icon=\"cloud-upload\"></Status>;\n }\n return <Status status=\"success\" message=\"all saved\" icon=\"check2-circle\"></Status>;\n }\n}\n\nfunction Status({ status, icon, message }) {\n return (\n <span\n class={{\n status: true,\n [status]: true,\n }}\n role=\"status\"\n aria-live=\"polite\"\n aria-labelledby=\"status-message\"\n >\n <sl-icon name={icon} aria-hidden=\"true\"></sl-icon>\n <span id=\"status-message\">{message}</span>\n </span>\n );\n}\n"]}
|
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
import Image from "@tiptap/extension-image";
|
|
2
|
+
const allowedProtocols = new Set(['http:', 'https:']);
|
|
3
|
+
export const createNodeView = baseUrl => ({ HTMLAttributes }) => {
|
|
4
|
+
const container = document.createElement('pos-image');
|
|
5
|
+
const uri = new URL(HTMLAttributes.src, baseUrl);
|
|
6
|
+
if (allowedProtocols.has(uri.protocol)) {
|
|
7
|
+
container.setAttribute('src', uri.toString());
|
|
8
|
+
}
|
|
9
|
+
let attrsToKeep = ['alt', 'title'];
|
|
10
|
+
for (const attr of attrsToKeep) {
|
|
11
|
+
if (HTMLAttributes[attr]) {
|
|
12
|
+
container.setAttribute(attr, HTMLAttributes[attr]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
dom: container,
|
|
17
|
+
/**
|
|
18
|
+
* ignoreMutation because:
|
|
19
|
+
* - `pos-image` handles its own internal DOM updates
|
|
20
|
+
* - We don't want the editor to interfere with the component's internal structure
|
|
21
|
+
* - The component content shouldn't trigger editor updates
|
|
22
|
+
*/
|
|
23
|
+
ignoreMutation: () => true,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
2
26
|
export const PosImageNode = (baseUrl) => Image.extend({
|
|
3
27
|
addNodeView() {
|
|
4
|
-
return (
|
|
5
|
-
const container = document.createElement('pos-image');
|
|
6
|
-
const uri = new URL(HTMLAttributes.src, baseUrl);
|
|
7
|
-
container.setAttribute('src', uri.toString());
|
|
8
|
-
let attrsToKeep = ['alt', 'title'];
|
|
9
|
-
for (const attr of attrsToKeep) {
|
|
10
|
-
if (HTMLAttributes[attr]) {
|
|
11
|
-
container.setAttribute(attr, HTMLAttributes[attr]);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return {
|
|
15
|
-
dom: container,
|
|
16
|
-
/**
|
|
17
|
-
* ignoreMutation because:
|
|
18
|
-
* - `pos-image` handles its own internal DOM updates
|
|
19
|
-
* - We don't want the editor to interfere with the component's internal structure
|
|
20
|
-
* - The component content shouldn't trigger editor updates
|
|
21
|
-
*/
|
|
22
|
-
ignoreMutation: () => true,
|
|
23
|
-
};
|
|
24
|
-
};
|
|
28
|
+
return createNodeView(baseUrl);
|
|
25
29
|
},
|
|
26
30
|
});
|
|
27
31
|
//# sourceMappingURL=PosImageNode.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PosImageNode.js","sourceRoot":"","sources":["../../../../../src/components/pos-markdown-document/rich-editor/PosImageNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"PosImageNode.js","sourceRoot":"","sources":["../../../../../src/components/pos-markdown-document/rich-editor/PosImageNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,yBAAyB,CAAC;AAG5C,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEtD,MAAM,CAAC,MAAM,cAAc,GACzB,OAAO,CAAC,EAAE,CACV,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE;IACrB,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAEtD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjD,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,WAAW,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,EAAE,SAAS;QACd;;;;;WAKG;QACH,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;KAC3B,CAAC;AACJ,CAAC,CAAC;AAEJ,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAe,EAAE,EAAE,CAC9C,KAAK,CAAC,MAAM,CAAC;IACX,WAAW;QACT,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;CACF,CAAC,CAAC","sourcesContent":["import Image from '@tiptap/extension-image';\nimport { NodeViewRenderer } from '@tiptap/core';\n\nconst allowedProtocols = new Set(['http:', 'https:']);\n\nexport const createNodeView: (baseUrl: string) => NodeViewRenderer =\n baseUrl =>\n ({ HTMLAttributes }) => {\n const container = document.createElement('pos-image');\n\n const uri = new URL(HTMLAttributes.src, baseUrl);\n if (allowedProtocols.has(uri.protocol)) {\n container.setAttribute('src', uri.toString());\n }\n let attrsToKeep = ['alt', 'title'];\n for (const attr of attrsToKeep) {\n if (HTMLAttributes[attr]) {\n container.setAttribute(attr, HTMLAttributes[attr]);\n }\n }\n\n return {\n dom: container,\n /**\n * ignoreMutation because:\n * - `pos-image` handles its own internal DOM updates\n * - We don't want the editor to interfere with the component's internal structure\n * - The component content shouldn't trigger editor updates\n */\n ignoreMutation: () => true,\n };\n };\n\nexport const PosImageNode = (baseUrl: string) =>\n Image.extend({\n addNodeView() {\n return createNodeView(baseUrl);\n },\n });\n"]}
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import Link from "@tiptap/extension-link";
|
|
2
|
+
const allowedProtocols = new Set(['http:', 'https:', 'mailto:', 'tel:']);
|
|
3
|
+
export const createMarkViewRenderer = baseUrl => ({ HTMLAttributes }) => {
|
|
4
|
+
const container = document.createElement('pos-rich-link');
|
|
5
|
+
const uri = new URL(HTMLAttributes.href, baseUrl);
|
|
6
|
+
if (allowedProtocols.has(uri.protocol)) {
|
|
7
|
+
container.setAttribute('uri', uri.toString());
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
dom: container,
|
|
11
|
+
contentDOM: container,
|
|
12
|
+
/**
|
|
13
|
+
* ignoreMutation because:
|
|
14
|
+
* - `pos-rich-link` handles its own internal DOM updates
|
|
15
|
+
* - We don't want the editor to interfere with the component's internal structure
|
|
16
|
+
* - The component content shouldn't trigger editor updates
|
|
17
|
+
*/
|
|
18
|
+
ignoreMutation: () => true,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
2
21
|
export const PosRichLinkMark = (baseUrl) => Link.extend({
|
|
3
22
|
addMarkView() {
|
|
4
|
-
return (
|
|
5
|
-
const container = document.createElement('pos-rich-link');
|
|
6
|
-
const uri = new URL(HTMLAttributes.href, baseUrl);
|
|
7
|
-
container.setAttribute('uri', uri.toString());
|
|
8
|
-
return {
|
|
9
|
-
dom: container,
|
|
10
|
-
contentDOM: container,
|
|
11
|
-
/**
|
|
12
|
-
* ignoreMutation because:
|
|
13
|
-
* - `pos-rich-link` handles its own internal DOM updates
|
|
14
|
-
* - We don't want the editor to interfere with the component's internal structure
|
|
15
|
-
* - The component content shouldn't trigger editor updates
|
|
16
|
-
*/
|
|
17
|
-
ignoreMutation: () => true,
|
|
18
|
-
};
|
|
19
|
-
};
|
|
23
|
+
return createMarkViewRenderer(baseUrl);
|
|
20
24
|
},
|
|
21
25
|
});
|
|
22
26
|
//# sourceMappingURL=PosRichLinkMark.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PosRichLinkMark.js","sourceRoot":"","sources":["../../../../../src/components/pos-markdown-document/rich-editor/PosRichLinkMark.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"PosRichLinkMark.js","sourceRoot":"","sources":["../../../../../src/components/pos-markdown-document/rich-editor/PosRichLinkMark.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,wBAAwB,CAAC;AAG1C,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAEzE,MAAM,CAAC,MAAM,sBAAsB,GACjC,OAAO,CAAC,EAAE,CACV,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE;IACrB,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,OAAO;QACL,GAAG,EAAE,SAAS;QACd,UAAU,EAAE,SAAS;QACrB;;;;;WAKG;QACH,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;KAC3B,CAAC;AACJ,CAAC,CAAC;AAEJ,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAe,EAAE,EAAE,CACjD,IAAI,CAAC,MAAM,CAAC;IACV,WAAW;QACT,OAAO,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;CACF,CAAC,CAAC","sourcesContent":["import Link from '@tiptap/extension-link';\nimport { MarkViewRenderer } from '@tiptap/core';\n\nconst allowedProtocols = new Set(['http:', 'https:', 'mailto:', 'tel:']);\n\nexport const createMarkViewRenderer: (baseUrl: string) => MarkViewRenderer =\n baseUrl =>\n ({ HTMLAttributes }) => {\n const container = document.createElement('pos-rich-link');\n const uri = new URL(HTMLAttributes.href, baseUrl);\n if (allowedProtocols.has(uri.protocol)) {\n container.setAttribute('uri', uri.toString());\n }\n\n return {\n dom: container,\n contentDOM: container,\n /**\n * ignoreMutation because:\n * - `pos-rich-link` handles its own internal DOM updates\n * - We don't want the editor to interfere with the component's internal structure\n * - The component content shouldn't trigger editor updates\n */\n ignoreMutation: () => true,\n };\n };\n\nexport const PosRichLinkMark = (baseUrl: string) =>\n Link.extend({\n addMarkView() {\n return createMarkViewRenderer(baseUrl);\n },\n });\n"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Editor } from "@tiptap/core";
|
|
2
|
+
import { Markdown } from "@tiptap/markdown";
|
|
2
3
|
import StarterKit from "@tiptap/starter-kit";
|
|
3
4
|
import { PosImageNode } from "./PosImageNode";
|
|
4
5
|
import { PosRichLinkMark } from "./PosRichLinkMark";
|
|
5
|
-
import { Subject
|
|
6
|
+
import { Subject } from "rxjs";
|
|
6
7
|
import { debounceTime } from "rxjs/operators";
|
|
7
8
|
export class RichEditor {
|
|
8
9
|
/**
|
|
@@ -11,26 +12,16 @@ export class RichEditor {
|
|
|
11
12
|
* @param baseUrl Base URL for relative links and relative image src
|
|
12
13
|
*/
|
|
13
14
|
constructor(target, content, baseUrl) {
|
|
14
|
-
/**
|
|
15
|
-
* Whether the editor has been modified since the latest changes have been observed
|
|
16
|
-
* @private
|
|
17
|
-
*/
|
|
18
|
-
this.modified = false;
|
|
19
|
-
this.editingJustChanged = false;
|
|
20
15
|
this.modifications = new Subject();
|
|
21
16
|
this.editor = new Editor({
|
|
22
17
|
element: target,
|
|
23
|
-
extensions: [StarterKit.configure({ link: false }), PosImageNode(baseUrl), PosRichLinkMark(baseUrl)],
|
|
24
|
-
content: content
|
|
18
|
+
extensions: [Markdown, StarterKit.configure({ link: false }), PosImageNode(baseUrl), PosRichLinkMark(baseUrl)],
|
|
19
|
+
content: content,
|
|
20
|
+
contentType: 'markdown',
|
|
25
21
|
editable: false,
|
|
26
22
|
});
|
|
27
23
|
this.editor.on('update', () => {
|
|
28
|
-
|
|
29
|
-
this.editingJustChanged = false;
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
this.modified = true;
|
|
33
|
-
this.modifications.next({ content: this.editor.getHTML() });
|
|
24
|
+
this.modifications.next({ content: this.editor.getMarkdown() });
|
|
34
25
|
});
|
|
35
26
|
}
|
|
36
27
|
onUpdate(callback) {
|
|
@@ -40,26 +31,21 @@ export class RichEditor {
|
|
|
40
31
|
return this.editor.isEditable;
|
|
41
32
|
}
|
|
42
33
|
startEditing() {
|
|
43
|
-
this.
|
|
44
|
-
this.editor.setEditable(true);
|
|
34
|
+
this.editor.setEditable(true, false);
|
|
45
35
|
this.editor.commands.focus();
|
|
46
36
|
}
|
|
47
37
|
stopEditing() {
|
|
48
|
-
this.
|
|
49
|
-
this.editor.setEditable(false);
|
|
50
|
-
}
|
|
51
|
-
isModified() {
|
|
52
|
-
return this.modified;
|
|
38
|
+
this.editor.setEditable(false, false);
|
|
53
39
|
}
|
|
54
40
|
getContent() {
|
|
55
|
-
return this.editor.
|
|
41
|
+
return this.editor.getMarkdown();
|
|
56
42
|
}
|
|
57
43
|
/**
|
|
58
44
|
* Provides an observable that communicates the latest editor content after changes have settled
|
|
59
45
|
* @param debounce - time (in millisecond) that has to pass without further modifications, until the changes are communicated
|
|
60
46
|
*/
|
|
61
47
|
observeChanges(debounce = 1000) {
|
|
62
|
-
return this.modifications.pipe(debounceTime(debounce)
|
|
48
|
+
return this.modifications.pipe(debounceTime(debounce));
|
|
63
49
|
}
|
|
64
50
|
}
|
|
65
51
|
//# sourceMappingURL=RichEditor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichEditor.js","sourceRoot":"","sources":["../../../../../src/components/pos-markdown-document/rich-editor/RichEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"RichEditor.js","sourceRoot":"","sources":["../../../../../src/components/pos-markdown-document/rich-editor/RichEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,OAAO,UAAU;IAKrB;;;;OAIG;IACH,YAAY,MAAmB,EAAE,OAAe,EAAE,OAAe;QAPhD,kBAAa,GAAG,IAAI,OAAO,EAAuB,CAAC;QAQlE,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC;YACvB,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;YAC9G,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,UAAU;YACvB,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC5B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,QAAoB;QAC3B,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IAChC,CAAC;IAED,YAAY;QACV,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,WAAmB,IAAI;QACpC,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzD,CAAC;CACF","sourcesContent":["import { Editor } from '@tiptap/core';\nimport { Markdown } from '@tiptap/markdown';\nimport StarterKit from '@tiptap/starter-kit';\nimport { PosImageNode } from './PosImageNode';\nimport { PosRichLinkMark } from './PosRichLinkMark';\nimport { Subject } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\n\nexport class RichEditor {\n private readonly editor: Editor;\n\n private readonly modifications = new Subject<{ content: string }>();\n\n /**\n * @param target The element to render to\n * @param content The content to show in the editor\n * @param baseUrl Base URL for relative links and relative image src\n */\n constructor(target: HTMLElement, content: string, baseUrl: string) {\n this.editor = new Editor({\n element: target,\n extensions: [Markdown, StarterKit.configure({ link: false }), PosImageNode(baseUrl), PosRichLinkMark(baseUrl)],\n content: content,\n contentType: 'markdown',\n editable: false,\n });\n this.editor.on('update', () => {\n this.modifications.next({ content: this.editor.getMarkdown() });\n });\n }\n\n onUpdate(callback: () => void) {\n this.editor.on('update', callback);\n }\n\n isEditable() {\n return this.editor.isEditable;\n }\n\n startEditing() {\n this.editor.setEditable(true, false);\n this.editor.commands.focus();\n }\n\n stopEditing() {\n this.editor.setEditable(false, false);\n }\n\n getContent() {\n return this.editor.getMarkdown();\n }\n\n /**\n * Provides an observable that communicates the latest editor content after changes have settled\n * @param debounce - time (in millisecond) that has to pass without further modifications, until the changes are communicated\n */\n observeChanges(debounce: number = 1000) {\n return this.modifications.pipe(debounceTime(debounce));\n }\n}\n"]}
|