feat(copilot): enhance OCR handling with inline tags and document serializer
- Replace HTML comment OCR metadata with inline `<OCR:...>` tags - Implement serializer-based markdown conversion for prefix/suffix content - Add extractTextFromOCR utility function for text extraction - Enable Table, Diagram, and ListCheck features in MilkdownEditor - Add periodic debug logging for document state analysis
This commit is contained in:
@@ -99,7 +99,7 @@
|
||||
import { onMounted, onUnmounted, ref, computed } from 'vue'
|
||||
import { replaceAll } from '@milkdown/kit/utils'
|
||||
import { Crepe } from '@milkdown/crepe'
|
||||
import { editorViewCtx } from '@milkdown/kit/core'
|
||||
import { editorViewCtx, serializerCtx } from '@milkdown/kit/core'
|
||||
import { copilotPlugin, copilotConfigCtx, copilotGhostMark, setCopilotEnabled, COPILOT_PLUGIN_KEY, SIZE_LIMIT, checkSizeLimit } from '../plugins/copilotPlugin'
|
||||
import { fetchSuggestion } from '../utils/api.js'
|
||||
import { DEBUG, OCR_URL } from '../utils/config.js'
|
||||
@@ -124,6 +124,7 @@ const aiButtonLabel = computed(() => {
|
||||
|
||||
let crepe = null
|
||||
let markdownSyncTimer = null
|
||||
let debugLogTimer = null
|
||||
const objectUrls = new Set()
|
||||
const IMAGE_NODE_TYPES = new Set(['image', 'image-block', 'imageBlock'])
|
||||
|
||||
@@ -199,6 +200,57 @@ const scheduleMarkdownSync = () => {
|
||||
}, 120)
|
||||
}
|
||||
|
||||
const logDebugInfo = async () => {
|
||||
if (!crepe) return
|
||||
try {
|
||||
const markdown = await crepe.getMarkdown()
|
||||
crepe.editor.action((ctx) => {
|
||||
const view = ctx.get(editorViewCtx)
|
||||
const schema = view.state.schema
|
||||
const { from, to } = view.state.selection
|
||||
const serializer = ctx.get(serializerCtx)
|
||||
let prefixMarkdown = '', suffixMarkdown = ''
|
||||
|
||||
try {
|
||||
// Prefix: 使用 slice 创建文档节点
|
||||
const prefixSlice = view.state.doc.slice(0, from)
|
||||
if (prefixSlice.content.size > 0) {
|
||||
const prefixDoc = schema.topNodeType.createAndFill(undefined, prefixSlice.content)
|
||||
if (prefixDoc) {
|
||||
prefixMarkdown = serializer(prefixDoc)
|
||||
}
|
||||
}
|
||||
if (!prefixMarkdown) {
|
||||
prefixMarkdown = view.state.doc.textBetween(0, from, '\n', '\n')
|
||||
}
|
||||
|
||||
// Suffix
|
||||
const suffixSlice = view.state.doc.slice(to)
|
||||
if (suffixSlice.content.size > 0) {
|
||||
const suffixDoc = schema.topNodeType.createAndFill(undefined, suffixSlice.content)
|
||||
if (suffixDoc) {
|
||||
suffixMarkdown = serializer(suffixDoc)
|
||||
}
|
||||
}
|
||||
if (!suffixMarkdown) {
|
||||
suffixMarkdown = view.state.doc.textBetween(to, view.state.doc.content.size, '\n', '\n')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[Debug] Serializer error:', e)
|
||||
prefixMarkdown = view.state.doc.textBetween(0, from, '\n', '\n')
|
||||
suffixMarkdown = view.state.doc.textBetween(to, view.state.doc.content.size, '\n', '\n')
|
||||
}
|
||||
console.log('[Debug] ===== Document State =====')
|
||||
console.log('[Debug] PREFIX:', prefixMarkdown)
|
||||
console.log('[Debug] SUFFIX:', suffixMarkdown)
|
||||
console.log('[Debug] FULL MARKDOWN:', markdown)
|
||||
console.log('[Debug] ==========================')
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('[Debug] Log failed:', e)
|
||||
}
|
||||
}
|
||||
|
||||
const clearCurrentSuggestion = (view) => {
|
||||
const state = COPILOT_PLUGIN_KEY.getState(view.state)
|
||||
if (state?.suggestion && state.from < state.to) {
|
||||
@@ -261,6 +313,9 @@ onMounted(async () => {
|
||||
features: {
|
||||
[Crepe.Feature.Latex]: true,
|
||||
[Crepe.Feature.ImageBlock]: true,
|
||||
[Crepe.Feature.Table]: true,
|
||||
[Crepe.Feature.Diagram]: true,
|
||||
[Crepe.Feature.ListCheck]: true,
|
||||
},
|
||||
featureConfigs: {
|
||||
[Crepe.Feature.Latex]: {
|
||||
@@ -308,6 +363,7 @@ onMounted(async () => {
|
||||
refreshSizeAndLimit(ctx)
|
||||
})
|
||||
scheduleMarkdownSync()
|
||||
debugLogTimer = setInterval(logDebugInfo, 20000)
|
||||
|
||||
if (DEBUG) console.log('[Debug] Crepe editor created with copilot plugin')
|
||||
})
|
||||
@@ -418,6 +474,10 @@ onUnmounted(() => {
|
||||
clearTimeout(markdownSyncTimer)
|
||||
markdownSyncTimer = null
|
||||
}
|
||||
if (debugLogTimer) {
|
||||
clearInterval(debugLogTimer)
|
||||
debugLogTimer = null
|
||||
}
|
||||
|
||||
for (const url of Array.from(objectUrls)) {
|
||||
revokeObjectUrl(url)
|
||||
|
||||
Reference in New Issue
Block a user