From 0acc0f76898be15e4e26b4a27853feeb10ca43a0 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Wed, 30 Nov 2022 06:47:24 +0800 Subject: [PATCH] feat(editor): select language --- .vscode/settings.json | 3 +- components/publish/PublishWidget.vue | 2 +- components/tiptap/TiptapCodeBlock.vue | 35 ++++++++++++++++++++ composables/tiptap.ts | 16 +++++++--- package.json | 2 ++ pnpm-lock.yaml | 46 +++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 components/tiptap/TiptapCodeBlock.vue diff --git a/.vscode/settings.json b/.vscode/settings.json index 2d7c6e2e..0987a409 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,7 +10,8 @@ "cSpell.words": [ "masto", "Nuxtodon", - "unmute" + "unmute", + "unstorage" ], "i18n-ally.localesPaths": [ "locales" diff --git a/components/publish/PublishWidget.vue b/components/publish/PublishWidget.vue index 5f7f941e..c3893251 100644 --- a/components/publish/PublishWidget.vue +++ b/components/publish/PublishWidget.vue @@ -30,7 +30,7 @@ const { editor } = useTiptap({ get: () => draft.params.status, set: newVal => draft.params.status = newVal, }), - placeholder: draft.placeholder, + placeholder: computed(() => draft.placeholder), autofocus: shouldExpanded, onSubmit: publish, onFocus() { isExpanded = true }, diff --git a/components/tiptap/TiptapCodeBlock.vue b/components/tiptap/TiptapCodeBlock.vue new file mode 100644 index 00000000..1c59f1d2 --- /dev/null +++ b/components/tiptap/TiptapCodeBlock.vue @@ -0,0 +1,35 @@ + + + diff --git a/composables/tiptap.ts b/composables/tiptap.ts index a3e294ef..57fa5e23 100644 --- a/composables/tiptap.ts +++ b/composables/tiptap.ts @@ -1,23 +1,24 @@ -import { Extension, useEditor } from '@tiptap/vue-3' +import { Extension, VueNodeViewRenderer, useEditor } from '@tiptap/vue-3' import Placeholder from '@tiptap/extension-placeholder' import Document from '@tiptap/extension-document' import Paragraph from '@tiptap/extension-paragraph' import Text from '@tiptap/extension-text' import Mention from '@tiptap/extension-mention' -import CodeBlock from '@tiptap/extension-code-block' import CharacterCount from '@tiptap/extension-character-count' import HardBreak from '@tiptap/extension-hard-break' import Bold from '@tiptap/extension-bold' import Italic from '@tiptap/extension-italic' import Code from '@tiptap/extension-code' import { Plugin } from 'prosemirror-state' +import CodeBlock from '@tiptap/extension-code-block' import type { Ref } from 'vue' import { HashSuggestion, MentionSuggestion } from './tiptap/suggestion' +import TiptapCodeBlock from '~/components/tiptap/TiptapCodeBlock.vue' export interface UseTiptapOptions { content: Ref - placeholder: string + placeholder: Ref onSubmit: () => void onFocus: () => void onPaste: (event: ClipboardEvent) => void @@ -50,12 +51,17 @@ export function useTiptap(options: UseTiptapOptions) { suggestion: HashSuggestion, }), Placeholder.configure({ - placeholder, + placeholder: placeholder.value, }), CharacterCount.configure({ limit: characterLimit.value, }), - CodeBlock, + CodeBlock + .extend({ + addNodeView() { + return VueNodeViewRenderer(TiptapCodeBlock) + }, + }), Extension.create({ name: 'api', addKeyboardShortcuts() { diff --git a/package.json b/package.json index 2f0ccd98..bd6494da 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@pinia/nuxt": "^0.4.5", "@tiptap/extension-character-count": "2.0.0-beta.204", "@tiptap/extension-code-block": "2.0.0-beta.204", + "@tiptap/extension-code-block-lowlight": "2.0.0-beta.204", "@tiptap/extension-mention": "2.0.0-beta.204", "@tiptap/extension-paragraph": "2.0.0-beta.204", "@tiptap/extension-placeholder": "2.0.0-beta.204", @@ -55,6 +56,7 @@ "fuse.js": "^6.6.2", "js-yaml": "^4.1.0", "lint-staged": "^13.0.4", + "lowlight": "^2.8.0", "lru-cache": "^7.14.1", "masto": "^4.7.0-rc1", "nuxt": "^3.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4ce7011d..29815a44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,7 @@ specifiers: '@pinia/nuxt': ^0.4.5 '@tiptap/extension-character-count': 2.0.0-beta.204 '@tiptap/extension-code-block': 2.0.0-beta.204 + '@tiptap/extension-code-block-lowlight': 2.0.0-beta.204 '@tiptap/extension-mention': 2.0.0-beta.204 '@tiptap/extension-paragraph': 2.0.0-beta.204 '@tiptap/extension-placeholder': 2.0.0-beta.204 @@ -39,6 +40,7 @@ specifiers: fuse.js: ^6.6.2 js-yaml: ^4.1.0 lint-staged: ^13.0.4 + lowlight: ^2.8.0 lru-cache: ^7.14.1 masto: ^4.7.0-rc1 nuxt: ^3.0.0 @@ -72,6 +74,7 @@ devDependencies: '@pinia/nuxt': 0.4.5_typescript@4.9.3 '@tiptap/extension-character-count': 2.0.0-beta.204 '@tiptap/extension-code-block': 2.0.0-beta.204 + '@tiptap/extension-code-block-lowlight': 2.0.0-beta.204_czakdrv4w4d5ggkubz4l2tz4ny '@tiptap/extension-mention': 2.0.0-beta.204_ggkstofzpnfxkp3gzsos4mewvi '@tiptap/extension-paragraph': 2.0.0-beta.204 '@tiptap/extension-placeholder': 2.0.0-beta.204 @@ -99,6 +102,7 @@ devDependencies: fuse.js: 6.6.2 js-yaml: 4.1.0 lint-staged: 13.0.4 + lowlight: 2.8.0 lru-cache: 7.14.1 masto: 4.7.0-rc1 nuxt: 3.0.0_hsf322ms6xhhd4b5ne6lb74y4a @@ -1331,6 +1335,18 @@ packages: prosemirror-state: 1.4.2 dev: true + /@tiptap/extension-code-block-lowlight/2.0.0-beta.204_czakdrv4w4d5ggkubz4l2tz4ny: + resolution: {integrity: sha512-6n2RWlMv7V3NANK+5UfxOMaK83ps8BucleQ/XdNcZuj/glTZco8Z+2E+kazW92c4IFrSgteriYg5ZqC2NBYXrg==} + peerDependencies: + '@tiptap/core': ^2.0.0-beta.193 + '@tiptap/extension-code-block': ^2.0.0-beta.193 + dependencies: + '@tiptap/extension-code-block': 2.0.0-beta.204 + prosemirror-model: 1.18.3 + prosemirror-state: 1.4.2 + prosemirror-view: 1.29.1 + dev: true + /@tiptap/extension-code-block/2.0.0-beta.204: resolution: {integrity: sha512-IIkZsBT7rxhK7yHnM2LRQfS6i+HNQxU+E6tRtPYF40YSg1xMZSC/xDy0k+NEU/xM6ZVesRofW3voB6svFPPDtw==} peerDependencies: @@ -1578,6 +1594,12 @@ packages: '@types/node': 18.11.9 dev: true + /@types/hast/2.3.4: + resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} + dependencies: + '@types/unist': 2.0.6 + dev: true + /@types/js-yaml/4.0.5: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} dev: true @@ -4337,6 +4359,12 @@ packages: reusify: 1.0.4 dev: true + /fault/2.0.1: + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + dependencies: + format: 0.2.2 + dev: true + /fetch-blob/3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -4447,6 +4475,11 @@ packages: mime-types: 2.1.35 dev: true + /format/0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + dev: true + /formdata-polyfill/4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} @@ -4770,6 +4803,11 @@ packages: tslib: 2.4.1 dev: true + /highlight.js/11.7.0: + resolution: {integrity: sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ==} + engines: {node: '>=12.0.0'} + dev: true + /hookable/5.4.2: resolution: {integrity: sha512-6rOvaUiNKy9lET1X0ECnyZ5O5kSV0PJbtA5yZUgdEF7fGJEVwSLSislltyt7nFwVVALYHQJtfGeAR2Y0A0uJkg==} dev: true @@ -5481,6 +5519,14 @@ packages: tslib: 2.4.1 dev: true + /lowlight/2.8.0: + resolution: {integrity: sha512-WeExw1IKEkel9ZcYwzpvcFzORIB0IlleTcxJYoEuUgHASuYe/OBYbV6ym/AetG7unNVCBU/SXpgTgs2nT93mhg==} + dependencies: + '@types/hast': 2.3.4 + fault: 2.0.1 + highlight.js: 11.7.0 + dev: true + /lru-cache/6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'}