feat: text editor & preview imporovments

This commit is contained in:
Joshua Shoemaker 2023-03-24 19:19:53 -05:00
parent c94d0ed78b
commit 01529b731c
12 changed files with 385 additions and 51 deletions

View File

@ -178,22 +178,19 @@ const DocumentRenderer = () => {
})
return <div className='relative'>
<div className='flex justify-between mt-2'>
<h1 className="text-2xl font-semibold text-gray-900">
{getSelectedDocument()?.name}
</h1>
<div>
<div className='flex justify-between align-top mb-2'>
<div className='flex align-top'>
<h1 className="text-xl font-semibold text-gray-900 inline-block mr-2">{getSelectedDocument()?.name}</h1>
<LanguageSelect shouldUpdateDocument defaultLanguage={selectedDocument?.defaultLanguage} />
<div className='flex justify-evenly items-center mt-2 mb-0'>
<MagnifyingGlassMinusIcon className='w-4 h-4' />
<input
id="zoomRange" type="range" min={zoomStep} max={maxZoomLevel} step={zoomStep}
value={zoomLevel} className="w-[calc(100%-50px)] h-2 bg-indigo-200 rounded-lg appearance-none cursor-pointer p-0"
onChange={(e) => { setZoomLevel(e.currentTarget.valueAsNumber) }}
/>
<MagnifyingGlassPlusIcon className='w-4 h-4' />
</div>
</div>
<div className='flex justify-evenly items-center'>
<MagnifyingGlassMinusIcon className='w-4 h-4' />
<input
id="zoomRange" type="range" min={zoomStep} max={maxZoomLevel} step={zoomStep}
value={zoomLevel} className="w-[calc(100%-50px)] h-2 bg-indigo-200 rounded-lg appearance-none cursor-pointer p-0"
onChange={(e) => { setZoomLevel(e.currentTarget.valueAsNumber) }}
/>
<MagnifyingGlassPlusIcon className='w-4 h-4' />
</div>
</div>
<div

View File

@ -41,10 +41,11 @@ const LanguageSelect = (props?: Props) => {
}, [selectedLanguage])
return <Combobox as="div" value={selectedLanguage} onChange={setSelectedLanguage}>
return <Combobox as="div" value={selectedLanguage} onChange={setSelectedLanguage} className='inline-block'>
<div className="inline-block relative">
<Combobox.Input
className="w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm"
style={{'maxWidth': '240px', 'height': '30px'}}
className="rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm"
onChange={(event) => setQuery(event.target.value)}
displayValue={(language: ipc.Language) => language?.displayName}
placeholder='Document Language'

View File

@ -1,13 +1,13 @@
'use client'
import React, { useRef, useState } from 'react'
import { XMarkIcon } from '@heroicons/react/20/solid'
import { useProject } from '../../../context/Project/provider'
import classNames from '../../../utils/classNames'
import { ArrowPathIcon } from '@heroicons/react/24/outline'
import { ArrowPathIcon, XMarkIcon } from '@heroicons/react/24/outline'
import { SidebarArea } from './types'
import { useSidebar } from './provider'
import onEnterHandler from '../../../utils/onEnterHandler'
import processImageArea from '../../../useCases/processImageArea'
const AreaLineItem = (props: { area: SidebarArea, documentId: string, index: number }) => {
@ -76,6 +76,11 @@ const AreaLineItem = (props: { area: SidebarArea, documentId: string, index: num
requestDeleteAreaById(areaId)
}
const handleReprocessAreaButtonClick = async () => {
const response = await processImageArea(props.documentId, props.area.id)
console.log(response)
}
return <li>
{selectedAreaId === props.area.id && isEditAreaNameInputShowing
? <input
@ -114,7 +119,7 @@ const AreaLineItem = (props: { area: SidebarArea, documentId: string, index: num
<ArrowPathIcon
className='w-6 h-5 mr-2 text-white hover:bg-white hover:text-gray-700 rounded-full p-0.5'
aria-hidden="true"
onClick={() => console.log('refresh')}
onClick={handleReprocessAreaButtonClick}
/>
<XMarkIcon
className='w-6 h-5 mr-2 text-white hover:bg-red-400 hover:text-gray-100 rounded-full p-0.5'

View File

@ -1,4 +1,5 @@
import { loader, DiffEditor } from '@monaco-editor/react'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
import { useEffect, useState } from 'react'
import { useProject } from '../../context/Project/provider'
import type { DiffOnMount } from '@monaco-editor/react/'
@ -6,7 +7,7 @@ import TextEditorButtons from './TextEditorButtons'
import createDiffEditorInteractions from '../../useCases/createDiffEditorInteractions'
import TextPreview from './TextPreview'
import createDebounce from '../../utils/createDebounce'
import LanguageSelect from './LanguageSelect'
import { MagnifyingGlassMinusIcon, MagnifyingGlassPlusIcon } from '@heroicons/react/24/outline'
loader.config({
paths: {
@ -17,6 +18,11 @@ loader.config({
let editorInteractions: ReturnType<typeof createDiffEditorInteractions>
const editorHeightOffset = 234
const fontSizeStep = 1
const maxFontSize = 36
let editorRefernce: monaco.editor.IStandaloneDiffEditor | null
const TextEditor = () => {
const { getSelectedDocument, getProcessedAreasByDocumentId, requestUpdateDocumentUserMarkdown, getUserMarkdownByDocumentId } = useProject()
const [editorHeight, setEditorHeight] = useState(window.innerHeight - editorHeightOffset)
@ -24,6 +30,7 @@ const TextEditor = () => {
const [isEditorReady, setIsEditorReady] = useState(false)
const [isPreviewOpen, setIsPreviewOpen] = useState(false)
const [modifiedEditorValue, setModifiedEditorValue] = useState('')
const [fontSize, setFontSize] = useState(16)
const selectedDocument = getSelectedDocument()
const selectedDocumentId = selectedDocument?.id || ''
@ -53,6 +60,7 @@ const TextEditor = () => {
setModifiedEditorValue(modifiedMarkdown)
}))
editorRefernce = editor
setIsEditorReady(true)
}
@ -76,12 +84,16 @@ const TextEditor = () => {
requestProcessedArea()
}, [selectedDocumentId, getProcessedAreasByDocumentId])
useEffect(() => {
editorRefernce?.updateOptions({ fontSize })
}, [fontSize, isEditorReady])
window.addEventListener('resize', () => {
setEditorHeight(window.innerHeight - editorHeightOffset)
})
return <div className='m-0 p-0 relative'>
<span className="flex z-0 rounded-md shadow-sm mb-2 mt-2 justify-between">
<span className="flex z-0 rounded-md shadow-sm mb-2 justify-between align-top">
{isEditorReady
? <>
<TextEditorButtons
@ -89,7 +101,18 @@ const TextEditor = () => {
togglePreview={() => setIsPreviewOpen(!isPreviewOpen)}
editorInteractions={editorInteractions}
/>
<LanguageSelect shouldUpdateDocument defaultLanguage={selectedDocument?.defaultLanguage} />
<div>
<div className='flex justify-evenly items-center mt-2 mb-0'>
<MagnifyingGlassMinusIcon className='w-4 h-4' />
<input
id="zoomRange" type="range" min={fontSizeStep} max={maxFontSize} step={fontSizeStep}
value={fontSize} className="w-[calc(100%-50px)] h-2 bg-indigo-200 rounded-lg appearance-none cursor-pointer p-0"
onChange={(e) => { setFontSize(e.currentTarget.valueAsNumber) }}
/>
<MagnifyingGlassPlusIcon className='w-4 h-4' />
</div>
</div>
</>
: ''
}

View File

@ -1,5 +1,4 @@
import { ListBulletIcon, MinusIcon } from '@heroicons/react/20/solid'
import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline'
import { Bars3BottomRightIcon, MinusIcon, ListBulletIcon, ChatBubbleLeftEllipsisIcon, EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline'
import createDiffEditorInteractions, { MarkdownOperator } from '../../useCases/createDiffEditorInteractions'
import classNames from '../../utils/classNames'
@ -124,6 +123,21 @@ const TextEditorButtons = (props: Props) => {
B
</button>
<button
type="button"
onClick={() => editorInteractions.insertMarkdownOperator(MarkdownOperator.QUOTE)}
className={classNames(
'text-sm relative inline-flex items-center border',
'border-gray-300 bg-white px-2 py-0 text-gray-700 hover:bg-gray-50',
'focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-1',
'focus:ring-indigo-500 font-extrabold',
)}>
<span className="sr-only">Quote</span>
<ChatBubbleLeftEllipsisIcon className="h-5 w-5" aria-hidden="true" />
</button>
<button
type="button"
onClick={() => editorInteractions.insertMarkdownOperator(MarkdownOperator.BULLET)}
@ -137,11 +151,26 @@ const TextEditorButtons = (props: Props) => {
<ListBulletIcon className="h-5 w-5" aria-hidden="true" />
</button>
<button
type="button"
onClick={() => editorInteractions.insertMarkdownOperator(MarkdownOperator.RIGHTALIGN)}
className={classNames(
'text-sm relative inline-flex items-center border',
'border-gray-300 bg-white px-2 py-0 text-gray-700 hover:bg-gray-50',
'focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-1',
'focus:ring-indigo-500 italic',
)}>
<span className="sr-only">Right Align</span>
<Bars3BottomRightIcon className="h-5 w-5" aria-hidden="true" />
</button>
<button
type="button"
onClick={() => editorInteractions.insertMarkdownOperator(MarkdownOperator.DIVIDER)}
className={classNames(
'text-sm relative inline-flex items-center border',
'text-sm relative inline-flex items-center rounded-r-md border',
'border-gray-300 bg-white px-2 py-0 text-gray-700 hover:bg-gray-50',
'focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-1',
'focus:ring-indigo-500 italic',
@ -150,7 +179,6 @@ const TextEditorButtons = (props: Props) => {
<MinusIcon className="h-5 w-5" aria-hidden="true" />
</button>
</span>
}

View File

@ -1,12 +1,14 @@
import { ReactMarkdown } from 'react-markdown/lib/react-markdown'
import rehypeRaw from 'rehype-raw'
type Props = { markdown: string, height: number }
const TextPreview = (props: Props) => (
<div
className='absolute w-[calc(50%-14px)] top-[46px] bg-white overflow-y-scroll p-4 m-0'
className='absolute w-[calc(50%-14px)] top-[38px] bg-white overflow-y-scroll p-4 m-0'
style={{ 'height': `${props.height}px` }}>
<ReactMarkdown
rehypePlugins={[rehypeRaw]}
components={{
h1: ({ node, ...props }) => <h1 {...props} className='font-black text-2xl' />,
h2: ({ node, ...props }) => <h2 {...props} className='font-extrabold text-xl' />,
@ -18,6 +20,7 @@ const TextPreview = (props: Props) => (
ol: ({ node, ...props }) => <ol {...props} className='list-decimal list-inside ml-2' />,
em: ({ node, ...props }) => <em {...props} className='italic font-light' />,
p: ({ node, ...props }) => <p {...props} className='text-base mb-2' />,
blockquote: ({ node, ...props }) => <blockquote {...props} className='text-base mb-2 block p-3 bg-slate-50 italic' />,
}}
>
{props.markdown}

View File

@ -16,6 +16,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^8.0.5",
"rehype-raw": "^6.1.1",
"tesseract.js": "^4.0.2",
"uuid": "^9.0.0"
},
@ -753,6 +754,11 @@
"integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
"dev": true
},
"node_modules/@types/parse5": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
"integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g=="
},
"node_modules/@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@ -2518,6 +2524,75 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hast-util-from-parse5": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
"integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==",
"dependencies": {
"@types/hast": "^2.0.0",
"@types/unist": "^2.0.0",
"hastscript": "^7.0.0",
"property-information": "^6.0.0",
"vfile": "^5.0.0",
"vfile-location": "^4.0.0",
"web-namespaces": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-parse-selector": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz",
"integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==",
"dependencies": {
"@types/hast": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-raw": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz",
"integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==",
"dependencies": {
"@types/hast": "^2.0.0",
"@types/parse5": "^6.0.0",
"hast-util-from-parse5": "^7.0.0",
"hast-util-to-parse5": "^7.0.0",
"html-void-elements": "^2.0.0",
"parse5": "^6.0.0",
"unist-util-position": "^4.0.0",
"unist-util-visit": "^4.0.0",
"vfile": "^5.0.0",
"web-namespaces": "^2.0.0",
"zwitch": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-to-parse5": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz",
"integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==",
"dependencies": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0",
"web-namespaces": "^2.0.0",
"zwitch": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-whitespace": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz",
@ -2527,6 +2602,31 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/hastscript": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz",
"integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==",
"dependencies": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"hast-util-parse-selector": "^3.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/html-void-elements": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
"integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@ -3937,6 +4037,11 @@
"node": ">=6"
}
},
"node_modules/parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -4299,6 +4404,20 @@
"url": "https://github.com/sponsors/mysticatea"
}
},
"node_modules/rehype-raw": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz",
"integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==",
"dependencies": {
"@types/hast": "^2.0.0",
"hast-util-raw": "^7.2.0",
"unified": "^10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark-parse": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz",
@ -5059,6 +5178,19 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/vfile-location": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz",
"integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==",
"dependencies": {
"@types/unist": "^2.0.0",
"vfile": "^5.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/vfile-message": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.3.tgz",
@ -5077,6 +5209,15 @@
"resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.3.0.tgz",
"integrity": "sha512-w9datO3OReMouWgKOelvu1CozmLK/VbkXOtlzNTanBJpR0uBHyUwS3EYdXf5vBPoHKYS0lpuYo91rpqMNIZM9g=="
},
"node_modules/web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
"integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
@ -5174,6 +5315,15 @@
"engines": {
"node": "*"
}
},
"node_modules/zwitch": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
"integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
}
},
"dependencies": {
@ -5657,6 +5807,11 @@
"integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
"dev": true
},
"@types/parse5": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
"integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g=="
},
"@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@ -6919,11 +7074,81 @@
"has-symbols": "^1.0.2"
}
},
"hast-util-from-parse5": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
"integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==",
"requires": {
"@types/hast": "^2.0.0",
"@types/unist": "^2.0.0",
"hastscript": "^7.0.0",
"property-information": "^6.0.0",
"vfile": "^5.0.0",
"vfile-location": "^4.0.0",
"web-namespaces": "^2.0.0"
}
},
"hast-util-parse-selector": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz",
"integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==",
"requires": {
"@types/hast": "^2.0.0"
}
},
"hast-util-raw": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz",
"integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==",
"requires": {
"@types/hast": "^2.0.0",
"@types/parse5": "^6.0.0",
"hast-util-from-parse5": "^7.0.0",
"hast-util-to-parse5": "^7.0.0",
"html-void-elements": "^2.0.0",
"parse5": "^6.0.0",
"unist-util-position": "^4.0.0",
"unist-util-visit": "^4.0.0",
"vfile": "^5.0.0",
"web-namespaces": "^2.0.0",
"zwitch": "^2.0.0"
}
},
"hast-util-to-parse5": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz",
"integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==",
"requires": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0",
"web-namespaces": "^2.0.0",
"zwitch": "^2.0.0"
}
},
"hast-util-whitespace": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz",
"integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng=="
},
"hastscript": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz",
"integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==",
"requires": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"hast-util-parse-selector": "^3.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0"
}
},
"html-void-elements": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
"integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A=="
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@ -7799,6 +8024,11 @@
"callsites": "^3.0.0"
}
},
"parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -8022,6 +8252,16 @@
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg=="
},
"rehype-raw": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz",
"integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==",
"requires": {
"@types/hast": "^2.0.0",
"hast-util-raw": "^7.2.0",
"unified": "^10.0.0"
}
},
"remark-parse": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz",
@ -8551,6 +8791,15 @@
"vfile-message": "^3.0.0"
}
},
"vfile-location": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz",
"integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==",
"requires": {
"@types/unist": "^2.0.0",
"vfile": "^5.0.0"
}
},
"vfile-message": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.3.tgz",
@ -8565,6 +8814,11 @@
"resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.3.0.tgz",
"integrity": "sha512-w9datO3OReMouWgKOelvu1CozmLK/VbkXOtlzNTanBJpR0uBHyUwS3EYdXf5vBPoHKYS0lpuYo91rpqMNIZM9g=="
},
"web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
"integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
@ -8635,6 +8889,11 @@
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz",
"integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w=="
},
"zwitch": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
"integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="
}
}
}

View File

@ -21,6 +21,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^8.0.5",
"rehype-raw": "^6.1.1",
"tesseract.js": "^4.0.2",
"uuid": "^9.0.0"
},

View File

@ -1 +1 @@
db04e8c6f18963bc94c89200059f2f38
e8bab26469d3f6b725d33cef9359048b

View File

@ -10,7 +10,9 @@ export enum MarkdownOperator {
ITALLICS = '_',
BOLD = '**',
BULLET = '* ',
DIVIDER = '\n\n---\n'
DIVIDER = '\n\n---\n',
QUOTE = '> ',
RIGHTALIGN = 'htmlRightAlign' // Not a real operator
}
const wrapperOperators = [
@ -18,6 +20,16 @@ const wrapperOperators = [
MarkdownOperator.BOLD
]
const htmlWrappers = [
MarkdownOperator.RIGHTALIGN
]
const getHtmlWrappedText = (text: string, htmlWrapper: (typeof htmlWrappers)[number]) => {
if (htmlWrapper === MarkdownOperator.RIGHTALIGN) {
return `<span style="text-align:right">\n\n${text}\n\n</span>\n`
}
}
const createDiffEditorInteractions = (editor: monaco.editor.IStandaloneDiffEditor) => {
const modifiedEditor = editor.getModifiedEditor()
@ -51,14 +63,16 @@ const createDiffEditorInteractions = (editor: monaco.editor.IStandaloneDiffEdito
}
newText = `${operator}`
} else if (wrapperOperators.includes(operator)) {
} else if (wrapperOperators.includes(operator) || htmlWrappers.includes(operator)) {
if (!doesSelectionHaveRange && wordAtStartPosition) range = {
startLineNumber,
startColumn: wordAtStartPosition.startColumn,
endLineNumber,
endColumn: wordAtStartPosition.endColumn
}
newText = `${operator}${modifiedEditor.getModel()?.getValueInRange(range)}${operator}`
if (htmlWrappers.includes(operator)) {
newText = getHtmlWrappedText(modifiedEditor.getModel()?.getValueInRange(range) || '', operator) || ''
} else newText = `${operator}${modifiedEditor.getModel()?.getValueInRange(range)}${operator}`
} else {
range = {
startLineNumber,

View File

@ -10,6 +10,8 @@ const processImageArea = async (documentId: string, areaId: string) => {
const processLanguage = foundDocument.defaultLanguage.processCode
if (!processLanguage) return console.error('No process language selected')
const { path } = foundDocument
const imageData = await loadImage(path)
@ -31,6 +33,7 @@ const processImageArea = async (documentId: string, areaId: string) => {
const addProcessesAreaRequest = await RequestAddProcessedArea(new ipc.ProcessedArea({
id: foundArea.id,
documentId,
order: foundArea.order,
fullText: result.data.text,
lines: result.data.lines.map((l: any) => new ipc.ProcessedLine({
fullText: l.text,

View File

@ -139,32 +139,32 @@ func deserializeProcessedArea(area ProcessedArea) document.ProcessedArea {
return document.ProcessedArea{
Id: area.Id,
DocumentId: area.DocumentId,
Order: area.Order,
FullText: area.FullText,
Lines: lines,
}
}
func (c *Channel) RequestAddProcessedArea(area ProcessedArea) ProcessedArea {
var currentAreaIds []string
processedAreasCollection := document.GetProcessedAreaCollection()
for _, a := range processedAreasCollection.Areas {
currentAreaIds = append(currentAreaIds, a.Id)
}
areaAlreadyExists := false
for _, areaId := range currentAreaIds {
if area.Id == areaId {
areaAlreadyExists = true
func (c *Channel) RequestAddProcessedArea(processedArea ProcessedArea) ProcessedArea {
doesAreaAlreadyExist := false
processedAreasOfDocument := document.GetProcessedAreaCollection().GetAreasByDocumentId(processedArea.DocumentId)
for _, a := range processedAreasOfDocument {
if a.Order == processedArea.Order {
doesAreaAlreadyExist = true
break
}
}
if !areaAlreadyExists {
processedArea := deserializeProcessedArea(area)
currentAreasOfDocument := processedAreasCollection.GetAreasByDocumentId(area.DocumentId)
processedArea.Order = len(currentAreasOfDocument)
document.GetProcessedAreaCollection().AddProcessedArea(processedArea)
deserializedProcessedArea := deserializeProcessedArea(processedArea)
if doesAreaAlreadyExist {
storedProcessedArea := document.GetProcessedAreaCollection().GetAreaById(processedArea.Id)
if storedProcessedArea.Id != "" {
storedProcessedArea = &deserializedProcessedArea
}
} else {
document.GetProcessedAreaCollection().AddProcessedArea((deserializedProcessedArea))
}
return area
return processedArea
}