Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions packages/docs/fluent-editor/demos/collaborative-editing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ test('header collaborative-editing test', async () => {
await typeSync(p1, p2, 'Title')
const levels = [1, 2, 3, 4, 5, 6]
for (const lv of levels) {
await p1.locator('.ql-editor').click()
await p1.locator('.ql-editor').first().click()
await selectAll(p1)
if (lv <= 2) {
await p1.getByRole('button', { name: 'Normal' }).click()
await p1.getByRole('button', { name: `Heading ${lv}` }).click()
await p1.locator('.ql-toolbar .ql-picker.ql-header').click()
await p1.locator('.ql-toolbar').getByRole('button', { name: `Heading ${lv}` }).click()
}
else {
await p1.getByRole('button', { name: `Heading ${lv - 1}` }).click()
await p1.getByRole('button', { name: `Heading ${lv}` }).click()
await p1.locator('.ql-toolbar .ql-picker.ql-header').click()
await p1.locator('.ql-toolbar').getByRole('button', { name: `Heading ${lv}` }).click()
}
await expect.poll(() => headingMatched(p2, lv, 'Title')).toBeTruthy()
}
Expand All @@ -121,7 +121,7 @@ test('size collaborative-editing test', async () => {
if (next === current) {
continue
}
await p1.getByRole('button', { name: current }).click()
await p1.locator('.ql-toolbar .ql-size.ql-picker').click()
await p1.getByRole('button', { name: next }).click()

const sizeMatch = next.match(/\d+px/)
Expand All @@ -147,18 +147,18 @@ test('font collaborative-editing test', async () => {
await selectAll(p1)

await p1.getByRole('button', { name: 'Sans Serif' }).click()
await p1.getByRole('button', { name: 'serif', exact: true }).click()
await p1.getByRole('button', { name: '宋体', exact: true }).click()

await expect
.poll(async () => (await p2.locator('.ql-editor span[style*="font-family: serif"]').count()) > 0)
.poll(async () => (await p2.locator('.ql-editor span[style*="font-family: 宋体"]').count()) > 0)
.toBeTruthy()
})

test('line-height collaborative-editing test', async () => {
await typeSync(p1, p2, 'fdsafdsa')
await p1.getByRole('button', { name: '1', exact: true }).click()
await p1.getByRole('button', { name: '1.15' }).click()
await expect.poll(async () => (await p2.locator('.ql-editor p[style*="line-height: 1.15"]').count()) > 0).toBeTruthy()
await p1.locator('.ql-toolbar .ql-picker.ql-line-height').click()
await p1.getByRole('button', { name: '1.5' }).click()
await expect.poll(async () => (await p2.locator('.ql-editor p[style*="line-height: 1.5"]').count()) > 0).toBeTruthy()
})

const formatTypes = ['bold', 'italic', 'underline', 'strike']
Expand Down Expand Up @@ -287,7 +287,7 @@ test('formula collaborative-editing test', async () => {

test('table-up collaborative-editing test', async () => {
await p1.locator('.ql-table-up > .ql-picker-label').click()
await p1.locator('div:nth-child(29)').first().click()
await p1.locator('.table-up-select-box__item[data-row="2"][data-col="2"]').first().click()
await expect.poll(async () => (await p2.locator('.ql-editor div.ql-table-wrapper').count()) > 0).toBeTruthy()
})

Expand Down
11 changes: 10 additions & 1 deletion packages/docs/fluent-editor/demos/collaborative-editing.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<script setup lang="ts">
import type { EmojiMartData } from '@emoji-mart/data'
import type FluentEditor from '@opentiny/fluent-editor'
import type { Range } from '@opentiny/fluent-editor'
import data from '@emoji-mart/data'
import { computePosition } from '@floating-ui/dom'
import Html2Canvas from 'html2canvas'
import katex from 'katex'
import { onMounted, ref } from 'vue'
Expand Down Expand Up @@ -34,6 +37,7 @@ onMounted(async () => {
{ WebsocketProvider },
{ IndexeddbPersistence },
{ default: QuillCursors },
emojiMart,
] = await Promise.all([
import('@opentiny/fluent-editor'),
import('quill-table-up'),
Expand All @@ -43,6 +47,7 @@ onMounted(async () => {
import('y-websocket'),
import('y-indexeddb'),
import('quill-cursors'),
import('emoji-mart'),
])

if (!editorRef.value) return
Expand All @@ -63,7 +68,11 @@ onMounted(async () => {
modules: {
'toolbar': FULL_TOOLBAR,
'file': true,
'emoji': true,
'emoji': {
emojiData: data as EmojiMartData,
EmojiPicker: emojiMart.Picker,
emojiPickerPosition: computePosition,
},
'uploader': {
mimetypes: ['image/*'],
handler(range: Range, files: File[]) {
Expand Down
8 changes: 4 additions & 4 deletions packages/docs/fluent-editor/demos/file-upload.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ test('image-upload', async ({ page }) => {
// upload
await page.getByLabel('image').first().click()
await page.locator('.ql-toolbar input.ql-image').setInputFiles(path.join(baseUrl, 'public', 'logo.png'))
await expect(page.locator('.ql-editor').first().getByRole('img')).toBeVisible()
const imageElement = page.locator('.ql-editor').first().getByRole('img').first()
await expect(imageElement).toBeVisible()

// overlay
await page.locator('.ql-editor').first().getByRole('img').click()
await imageElement.click()
await expect(page.locator('.blot-formatter__overlay')).toBeVisible()

// zoom
const moveDistance = 100
const imageElement = page.locator('.ql-editor').first().getByRole('img')
const oldBox = await imageElement.boundingBox() as { x: number, y: number, width: number, height: number }
await page.mouse.move(oldBox.x, oldBox.y)
await page.mouse.down()
Expand All @@ -31,6 +31,6 @@ test('image-upload', async ({ page }) => {
expect(newBox.height + moveDistance).toEqual(oldBox.height)

// remove overlay
await page.mouse.click(newBox.x + newBox.width + 20, newBox.y + newBox.height + 20)
await page.mouse.click(newBox.x + newBox.width + 20, newBox.y + newBox.height / 2)
await expect(page.locator('.blot-formatter__overlay')).not.toBeVisible()
})
2 changes: 1 addition & 1 deletion packages/docs/fluent-editor/demos/file-upload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ onMounted(async () => {

<template>
<div ref="editorRef">
<img src="https://res-static.opentiny.design/tiny-vue-web-doc/3.27.0/static/images/mountain.png" />
<img src="https://res-static.opentiny.design/tiny-vue-web-doc/3.27.0/static/images/mountain.png">
</div>
<br>
</template>
10 changes: 5 additions & 5 deletions packages/docs/fluent-editor/demos/flow-chart.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ test.describe('FlowChart.vue', () => {
})

test('should have flow-chart button in toolbar', async ({ page }) => {
const toolbar = page.locator('.ql-toolbar')
const toolbar = page.locator('.ql-toolbar').first()
await expect(toolbar).toBeVisible()

const flowChartButton = toolbar.locator('.ql-flow-chart')
Expand All @@ -31,18 +31,18 @@ test.describe('FlowChart.vue', () => {
test('should contain initial flow chart nodes and edges', async ({ page }) => {
await page.waitForTimeout(2000)

const flowChartContainer = page.locator('.ql-flow-chart-item')
const flowChartContainer = page.locator('.ql-flow-chart-item').first()
await expect(flowChartContainer).toBeVisible()

const nodes = page.locator('.lf-node')
const nodes = flowChartContainer.locator('.lf-node')
await expect(nodes).toHaveCount(2)

const edges = page.locator('.lf-edge')
const edges = flowChartContainer.locator('.lf-edge')
await expect(edges).toHaveCount(1)
})

test('should activate flow-chart when button is clicked', async ({ page }) => {
const flowChartButton = page.locator('.ql-toolbar .ql-flow-chart')
const flowChartButton = page.locator('.ql-toolbar .ql-flow-chart').first()
await expect(flowChartButton).toBeVisible()

await flowChartButton.click()
Expand Down
38 changes: 18 additions & 20 deletions packages/docs/fluent-editor/demos/i18n-custom.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { EmojiMartData } from '@emoji-mart/data'
import type FluentEditor from '@opentiny/fluent-editor'

import type { I18N } from '@opentiny/fluent-editor'
import type { I18n } from '@opentiny/fluent-editor'
// 这里实际导入的是一个 json 文件,包含了 emoji-mart 所需的所有表情数据,类型是 EmojiMartData
import data from '@emoji-mart/data'
// computePosition 函数用于计算 emoji picker显示的位置
Expand All @@ -22,7 +22,7 @@ const lang = ref('zh-CN')
onMounted(async () => {
// ssr compat, reference: https://vitepress.dev/guide/ssr-compat#importing-in-mounted-hook
const [
{ default: FluentEditor, FULL_TOOLBAR, I18N, generateToolbarTip, generateTableUp },
{ default: FluentEditor, FULL_TOOLBAR, generateToolbarTip, generateTableUp },
{ defaultCustomSelect, TableMenuContextmenu, TableSelection, TableUp },
emojiMart,
] = await Promise.all([
Expand All @@ -34,20 +34,7 @@ onMounted(async () => {
if (!editorRef.value) return
FluentEditor.register({ 'modules/toolbar-tip': generateToolbarTip(QuillToolbarTip) }, true)
FluentEditor.register({ 'modules/table-up': generateTableUp(TableUp) }, true)
I18N.register(
{
'zh-CN': {
'replace bold': '替换粗体文本',
'replace italic': '替换斜体文本',
},
'en-US': {
'replace bold': 'Replace bold text',
'replace italic': 'Replace italic text',
},
},
// set false to add text to the existing language
false,
)

editor = new FluentEditor(editorRef.value, {
theme: 'snow',
modules: {
Expand All @@ -59,12 +46,23 @@ onMounted(async () => {
emojiPickerPosition: computePosition,
},
'i18n': {
lang: lang.value,
locale: lang.value,
messages: {
'zh-CN': {
'replace bold': '替换粗体文本',
'replace italic': '替换斜体文本',
},
'en-US': {
'replace bold': 'Replace bold text',
'replace italic': 'Replace italic text',
},
},
},
'toolbar-tip': {
tipTextMap: {
bold: '_i18n"replace bold"',
italic: '_i18n"replace italic"',
// 对应的工具 key 名对应配置的 i18n key 名
bold: 'replace bold',
italic: 'replace italic',
},
defaultTooltipOptions: {
tipHoverable: false,
Expand All @@ -82,7 +80,7 @@ onMounted(async () => {
})
function switchLanguage() {
lang.value = lang.value === 'zh-CN' ? 'en-US' : 'zh-CN';
(editor.getModule('i18n') as I18N).changeLanguage({ lang: lang.value })
(editor.getModule('i18n') as I18n).setLocale(lang.value)
}
</script>

Expand Down
6 changes: 3 additions & 3 deletions packages/docs/fluent-editor/demos/i18n.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { EmojiMartData } from '@emoji-mart/data'
import type FluentEditor from '@opentiny/fluent-editor'
import type { I18N } from '@opentiny/fluent-editor'
import type { I18n } from '@opentiny/fluent-editor'

// 这里实际导入的是一个 json 文件,包含了 emoji-mart 所需的所有表情数据,类型是 EmojiMartData
import data from '@emoji-mart/data'
Expand Down Expand Up @@ -45,7 +45,7 @@ onMounted(async () => {
emojiPickerPosition: computePosition,
},
'i18n': {
lang: lang.value,
locale: lang.value,
},
'toolbar-tip': {
defaultTooltipOptions: {
Expand All @@ -64,7 +64,7 @@ onMounted(async () => {
})
function switchLanguage() {
lang.value = lang.value === 'zh-CN' ? 'en-US' : 'zh-CN';
(editor.getModule('i18n') as I18N).changeLanguage({ lang: lang.value })
(editor.getModule('i18n') as I18n).setLocale(lang.value)
}
</script>

Expand Down
4 changes: 2 additions & 2 deletions packages/docs/fluent-editor/demos/mind-map.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ test.describe('MindMap.vue', () => {

test('should activate mind-map when button is clicked', async ({ page }) => {
const mindMapButton = page.locator('.ql-toolbar .ql-mind-map').first()
const mindMapCount = await page.locator('.ql-mind-map-item').count()
await expect(mindMapButton).toBeVisible()
await mindMapButton.click()
await page.waitForTimeout(500)
const editor = page.locator('.ql-editor')
await expect(editor).toBeVisible()
await expect(await page.locator('.ql-mind-map-item').count()).toBe(mindMapCount + 1)
})
})
61 changes: 56 additions & 5 deletions packages/docs/fluent-editor/demos/table-up-shortcut.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<script setup lang="ts">
import type FluentEditor from '@opentiny/fluent-editor'
import type { I18n } from '@opentiny/fluent-editor'
import katex from 'katex'
import { onMounted, ref } from 'vue'
import QuillToolbarTip from 'quill-toolbar-tip'
import { onMounted, ref, watch } from 'vue'
import 'quill-table-up/index.css'
import 'quill-table-up/table-creator.css'
import 'quill-toolbar-tip/dist/index.css'
import 'katex/dist/katex.min.css'

window.katex = katex
Expand All @@ -14,23 +17,52 @@ const editorRef = ref<HTMLElement>()
onMounted(async () => {
// ssr compat, reference: https://vitepress.dev/guide/ssr-compat#importing-in-mounted-hook
const [
{ default: FluentEditor, FULL_TOOLBAR, generateTableUp, generateTableUpShortKeyMenu },
{ createSelectBox, defaultCustomSelect, TableUp },
{
default: FluentEditor,
FULL_TOOLBAR,
generateTableUp,
generateTableUpShortKeyMenu,
generateToolbarTip,
},
{
createSelectBox,
defaultCustomSelect,
TableUp,
TableVirtualScrollbar,
TableAlign,
TableResizeLine,
TableResizeScale,
TableSelection,
TableMenuContextmenu,
},
] = await Promise.all([
import('@opentiny/fluent-editor'),
import('quill-table-up'),
])

FluentEditor.register({ 'modules/table-up': generateTableUp(TableUp) }, true)
FluentEditor.register({
'modules/table-up': generateTableUp(TableUp),
'modules/toolbar-tip': generateToolbarTip(QuillToolbarTip),
}, true)
const { tableUpConfig, tableUpKeyboardControl } = generateTableUpShortKeyMenu(createSelectBox)
tableUpConfig.title = '_i18n"table"'
tableUpConfig.title = function () {
return (this.quill.getModule('i18n') as I18n).t('table') as string
}
if (editorRef.value) {
editor = new FluentEditor(editorRef.value, {
theme: 'snow',
modules: {
'toolbar': FULL_TOOLBAR,
'table-up': {
customSelect: defaultCustomSelect,
modules: [
{ module: TableVirtualScrollbar },
{ module: TableAlign },
{ module: TableResizeLine },
{ module: TableResizeScale },
{ module: TableSelection },
{ module: TableMenuContextmenu },
],
},
'shortcut-key': {
menuItems: [tableUpConfig],
Expand All @@ -41,12 +73,31 @@ onMounted(async () => {
return result
},
},
'toolbar-tip': {
defaultTooltipOptions: {
tipHoverable: false,
},
},
},
})
}
})

const lang = ref('en-US')
watch(lang, (value) => {
(editor.getModule('i18n') as I18n).setLocale(value)
})
</script>

<template>
<label for="locale-select">Language:</label>
<select id="locale-select" v-model="lang">
<option value="en-US">
English
</option>
<option value="zh-CN">
中文
</option>
</select>
<div ref="editorRef" />
</template>
Loading
Loading