From a3d001569398ce423dc01448323c6f9fde938a87 Mon Sep 17 00:00:00 2001 From: Manuel Leduc Date: Mon, 23 Dec 2024 15:27:37 +0100 Subject: [PATCH] CRISTAL-194: Support for images edition (#529) --- core/attachments/attachments-ui/package.json | 3 + .../attachments-ui/src/vue/AttachmentsTab.vue | 24 +- .../src/vue/AttachmentsTable.vue | 22 +- .../authentication-nextcloud/package.json | 40 ++ .../authentication-nextcloud/src/index.ts | 25 ++ .../authentication-nextcloud/tsconfig.json | 12 + .../authentication-nextcloud/tsdoc.json | 4 + .../authentication-nextcloud/vite.config.ts | 23 ++ core/backends/backend-nextcloud/package.json | 1 + .../backend-nextcloud/src/nextcloudStorage.ts | 5 +- core/document/document-api/package.json | 1 + core/document/document-api/src/index.ts | 15 + core/document/document-default/package.json | 2 + .../src/defaultDocumentService.ts | 52 ++- .../src/linkSuggestService.ts | 11 +- .../link-suggest-nextcloud/package.json | 1 + .../src/nextcloudLinkSuggestService.ts | 7 +- .../link-suggest-xwiki/package.json | 3 + .../src/components/componentsInit.ts | 177 ++++++--- core/markdown/markdown-api/package.json | 43 +++ core/markdown/markdown-api/src/index.ts | 23 ++ .../markdown-api/src/markdownRenderer.ts | 33 ++ core/markdown/markdown-api/tsconfig.json | 12 + core/markdown/markdown-api/tsdoc.json | 4 + core/markdown/markdown-api/vite.config.ts | 23 ++ core/markdown/markdown-default/package.json | 53 +++ core/markdown/markdown-default/src/index.ts | 76 ++++ .../src/parseInternalImages.ts | 135 +++++++ .../src/parseInternalLinks.ts | 135 +++++++ core/markdown/markdown-default/tsconfig.json | 12 + core/markdown/markdown-default/tsdoc.json | 4 + core/markdown/markdown-default/vite.config.ts | 23 ++ core/model/model-api/src/index.ts | 8 +- .../src/DefaultClickListener.ts | 3 + .../src/modelReferenceParser.ts | 8 +- .../src/filesystemModelReferenceParser.ts | 31 +- .../src/nextcloudModelReferenceParser.ts | 34 +- .../src/nextcloudModelReferenceSerializer.ts | 2 +- .../model-reference-xwiki/package.json | 9 +- .../xWikiModelReferenceParser.test.ts | 103 ++++++ ...st.ts => xWikiModelReferenceSerializer.ts} | 2 +- .../src/xWikiModelReferenceParser.ts | 59 ++- .../src/xWikiModelReferenceSerializer.ts | 2 +- .../src/filesystemRemoteURLSerializer.ts | 30 +- .../model-remote-url-nextcloud/package.json | 2 + .../src/nextcloudRemoteURLParser.ts | 61 +++- .../src/nextcloudRemoteURLSerializer.ts | 41 ++- .../src/xWikiRemoteURLSerializer.ts | 52 ++- .../navigation-tree-nextcloud/package.json | 1 + .../src/components/componentsInit.ts | 5 +- .../tiptap-extension-image/package.json | 63 ++++ .../src/CristalTiptapImage.ts | 99 +++++ .../tiptap-extension-image/src/ImageInsert.ts | 29 ++ .../tiptap-extension-image/src/index.ts | 24 ++ .../src/vue/ImageInsertView.vue | 269 ++++++++++++++ .../src/vue/ImageView.vue | 148 ++++++++ .../tiptap-extension-image/tsconfig.json | 13 + .../tiptap-extension-image/vite.config.ts | 23 ++ .../tiptap-link-suggest-ui/package.json | 48 +++ .../tiptap-link-suggest-ui/src/index.ts | 22 ++ .../src/vue/LinkSuggestItem.vue | 37 ++ .../tiptap-link-suggest-ui/tsconfig.json | 13 + .../tiptap-link-suggest-ui/vite.config.ts | 23 ++ editors/tiptap/package.json | 7 +- .../src/components/extensions/bubble-menu.ts | 126 ++----- .../bubble-menu/BubbleMenuAction.ts | 40 ++ .../extensions/bubble-menu/image-actions.ts | 56 +++ .../extensions/bubble-menu/text-actions.ts | 110 ++++++ .../src/components/extensions/link-suggest.ts | 35 +- .../tiptap/src/components/extensions/slash.ts | 19 + editors/tiptap/src/extensions/link.ts | 74 ++-- editors/tiptap/src/extensions/markdown.ts | 152 ++------ editors/tiptap/src/vue/c-edit-tiptap.vue | 189 ++++++---- .../tiptap/src/vue/c-tiptap-bubble-menu.vue | 48 ++- editors/tiptap/src/vue/c-tiptap-link-edit.vue | 16 +- .../tiptap/src/vue/c-tiptap-link-suggest.vue | 23 +- .../link-suggest-filesystem/package.json | 52 +++ .../src/components/componentsInit.ts | 34 ++ .../filesystemLinkSuggestService.ts | 100 +++++ .../link-suggest-filesystem/src/index.ts | 23 ++ .../link-suggest-filesystem/tsconfig.json | 12 + .../link-suggest-filesystem/tsdoc.json | 4 + .../link-suggest-filesystem/vite.config.ts | 23 ++ electron/renderer/package.json | 1 + electron/renderer/src/index.ts | 2 + electron/storage/package.json | 2 + electron/storage/src/electron/main/index.ts | 143 +++++++- .../storage/src/electron/preload/apiTypes.ts | 20 + .../storage/src/electron/preload/index.ts | 14 + lib/package.json | 1 + lib/src/staticBuild.ts | 2 + pnpm-lock.yaml | 341 +++++++++++++++--- pnpm-workspace.yaml | 3 + .../src/components/MarkdownToHTMLConverter.ts | 5 + skin/package.json | 4 +- skin/src/vue/__tests__/c-content.test.ts | 39 +- skin/src/vue/c-content.vue | 31 +- 97 files changed, 3440 insertions(+), 579 deletions(-) create mode 100644 core/authentication/authentication-nextcloud/package.json create mode 100644 core/authentication/authentication-nextcloud/src/index.ts create mode 100644 core/authentication/authentication-nextcloud/tsconfig.json create mode 100644 core/authentication/authentication-nextcloud/tsdoc.json create mode 100644 core/authentication/authentication-nextcloud/vite.config.ts create mode 100644 core/markdown/markdown-api/package.json create mode 100644 core/markdown/markdown-api/src/index.ts create mode 100644 core/markdown/markdown-api/src/markdownRenderer.ts create mode 100644 core/markdown/markdown-api/tsconfig.json create mode 100644 core/markdown/markdown-api/tsdoc.json create mode 100644 core/markdown/markdown-api/vite.config.ts create mode 100644 core/markdown/markdown-default/package.json create mode 100644 core/markdown/markdown-default/src/index.ts create mode 100644 core/markdown/markdown-default/src/parseInternalImages.ts create mode 100644 core/markdown/markdown-default/src/parseInternalLinks.ts create mode 100644 core/markdown/markdown-default/tsconfig.json create mode 100644 core/markdown/markdown-default/tsdoc.json create mode 100644 core/markdown/markdown-default/vite.config.ts create mode 100644 core/model/model-reference/model-reference-xwiki/src/__tests__/xWikiModelReferenceParser.test.ts rename core/model/model-reference/model-reference-xwiki/src/__tests__/{defaultLocalURLSerializer.test.ts => xWikiModelReferenceSerializer.ts} (98%) create mode 100644 core/tiptap-extensions/tiptap-extension-image/package.json create mode 100644 core/tiptap-extensions/tiptap-extension-image/src/CristalTiptapImage.ts create mode 100644 core/tiptap-extensions/tiptap-extension-image/src/ImageInsert.ts create mode 100644 core/tiptap-extensions/tiptap-extension-image/src/index.ts create mode 100644 core/tiptap-extensions/tiptap-extension-image/src/vue/ImageInsertView.vue create mode 100644 core/tiptap-extensions/tiptap-extension-image/src/vue/ImageView.vue create mode 100644 core/tiptap-extensions/tiptap-extension-image/tsconfig.json create mode 100644 core/tiptap-extensions/tiptap-extension-image/vite.config.ts create mode 100644 core/tiptap-extensions/tiptap-link-suggest-ui/package.json create mode 100644 core/tiptap-extensions/tiptap-link-suggest-ui/src/index.ts create mode 100644 core/tiptap-extensions/tiptap-link-suggest-ui/src/vue/LinkSuggestItem.vue create mode 100644 core/tiptap-extensions/tiptap-link-suggest-ui/tsconfig.json create mode 100644 core/tiptap-extensions/tiptap-link-suggest-ui/vite.config.ts create mode 100644 editors/tiptap/src/components/extensions/bubble-menu/BubbleMenuAction.ts create mode 100644 editors/tiptap/src/components/extensions/bubble-menu/image-actions.ts create mode 100644 editors/tiptap/src/components/extensions/bubble-menu/text-actions.ts create mode 100644 electron/link-suggest/link-suggest-filesystem/package.json create mode 100644 electron/link-suggest/link-suggest-filesystem/src/components/componentsInit.ts create mode 100644 electron/link-suggest/link-suggest-filesystem/src/components/filesystemLinkSuggestService.ts create mode 100644 electron/link-suggest/link-suggest-filesystem/src/index.ts create mode 100644 electron/link-suggest/link-suggest-filesystem/tsconfig.json create mode 100644 electron/link-suggest/link-suggest-filesystem/tsdoc.json create mode 100644 electron/link-suggest/link-suggest-filesystem/vite.config.ts diff --git a/core/attachments/attachments-ui/package.json b/core/attachments/attachments-ui/package.json index 911c88a75..ae69ea305 100644 --- a/core/attachments/attachments-ui/package.json +++ b/core/attachments/attachments-ui/package.json @@ -26,11 +26,14 @@ "@xwiki/cristal-api": "workspace:*", "@xwiki/cristal-attachments-api": "workspace:*", "@xwiki/cristal-date-ui": "workspace:*", + "@xwiki/cristal-document-api": "workspace:*", "@xwiki/cristal-dsapi": "workspace:*", "@xwiki/cristal-extra-tabs-api": "workspace:*", "@xwiki/cristal-file-preview-ui": "workspace:*", "@xwiki/cristal-info-actions-api": "workspace:*", + "@xwiki/cristal-model-api": "workspace:*", "@xwiki/cristal-model-click-listener": "workspace:*", + "@xwiki/cristal-model-reference-api": "workspace:*", "@xwiki/cristal-uiextension-api": "workspace:*", "@xwiki/cristal-user-ui": "workspace:*", "inversify": "6.2.0", diff --git a/core/attachments/attachments-ui/src/vue/AttachmentsTab.vue b/core/attachments/attachments-ui/src/vue/AttachmentsTab.vue index 9a14b1b0e..cd6b3db4b 100644 --- a/core/attachments/attachments-ui/src/vue/AttachmentsTab.vue +++ b/core/attachments/attachments-ui/src/vue/AttachmentsTab.vue @@ -23,6 +23,7 @@ import AttachmentsTable from "./AttachmentsTable.vue"; import { AlertsService } from "@xwiki/cristal-alerts-api"; import { CristalApp } from "@xwiki/cristal-api"; import { AttachmentsService } from "@xwiki/cristal-attachments-api"; +import { DocumentService } from "@xwiki/cristal-document-api"; import { inject, ref, watch } from "vue"; import { useRoute } from "vue-router"; @@ -31,6 +32,10 @@ const attachmentsService = cristal .getContainer() .get("AttachmentsService")!; +const documentService = cristal + .getContainer() + .get("DocumentService")!; + const attachments = attachmentsService.list(); const isLoading = attachmentsService.isLoading(); const errorMessage = attachmentsService.getError(); @@ -38,14 +43,14 @@ const isUploading = attachmentsService.isUploading(); // Watch for route change to refresh the tab when a user visits a new page. const route = useRoute(); + +function getCurrentPageReference() { + return documentService.getCurrentDocumentReferenceString().value ?? ""; +} + watch( () => route.params.page, - () => - attachmentsService.refresh( - (route.params.page as string) || - cristal.getCurrentPage() || - "Main.WebHome", - ), + () => attachmentsService.refresh(getCurrentPageReference()), { immediate: true }, ); @@ -57,12 +62,7 @@ const alertsService = cristal async function upload(files: File[]) { try { - await attachmentsService.upload( - (route.params.page as string) || - cristal.getCurrentPage() || - ("Main.WebHome" as string), - files, - ); + await attachmentsService.upload(getCurrentPageReference(), files); attachmentUpload.value?.reset(); } catch (e) { if (e instanceof Error) { diff --git a/core/attachments/attachments-ui/src/vue/AttachmentsTable.vue b/core/attachments/attachments-ui/src/vue/AttachmentsTable.vue index 00d0c6698..5dbefb44b 100644 --- a/core/attachments/attachments-ui/src/vue/AttachmentsTable.vue +++ b/core/attachments/attachments-ui/src/vue/AttachmentsTable.vue @@ -3,6 +3,8 @@ import messages from "../translations"; import { Attachment } from "@xwiki/cristal-attachments-api"; import { Date } from "@xwiki/cristal-date-ui"; import { FileSize } from "@xwiki/cristal-file-preview-ui"; +import { AttachmentReference, EntityType } from "@xwiki/cristal-model-api"; +import { ModelReferenceParserProvider } from "@xwiki/cristal-model-reference-api"; import { User } from "@xwiki/cristal-user-ui"; import { computed, inject } from "vue"; import { useI18n } from "vue-i18n"; @@ -21,6 +23,10 @@ const props = defineProps<{ const cristal = inject("cristal")!; const listener = cristal.getContainer().get("ClickListener"); +const modelReferenceParser = cristal + .getContainer() + .get("ModelReferenceParserProvider") + .get()!; function attachmentPreview(url: string, event: Event) { event.preventDefault(); @@ -35,6 +41,19 @@ const hasAuthor = computed(() => { .length > 0 ); }); + +function attachmentName(name: string) { + try { + return ( + modelReferenceParser.parse( + name, + EntityType.ATTACHMENT, + ) as AttachmentReference + ).name; + } catch { + return ""; + } +}