mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-11 23:54:57 +00:00
Move AI provider usage to the backend (#18562)
GitOrigin-RevId: 4f66c6576571c4fbb7381d8d0e34f2e468d6f34f
This commit is contained in:
parent
e36de5a62d
commit
b9a8a7f7ec
18 changed files with 147 additions and 141 deletions
132
package-lock.json
generated
132
package-lock.json
generated
|
@ -14708,17 +14708,6 @@
|
|||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agentkeepalive": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
|
||||
"integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
|
||||
"dependencies": {
|
||||
"humanize-ms": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aggregate-error": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
||||
|
@ -21858,6 +21847,14 @@
|
|||
"resolved": "https://registry.npmjs.org/events-listener/-/events-listener-1.1.0.tgz",
|
||||
"integrity": "sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g=="
|
||||
},
|
||||
"node_modules/eventsource-parser": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz",
|
||||
"integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==",
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/execa": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||
|
@ -25275,14 +25272,6 @@
|
|||
"node": ">=8.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/humanize-ms": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
||||
"integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
|
||||
"dependencies": {
|
||||
"ms": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
|
@ -28840,23 +28829,6 @@
|
|||
"micromark-util-types": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-extension-gfm-table": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz",
|
||||
"integrity": "sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"devlop": "^1.0.0",
|
||||
"micromark-factory-space": "^2.0.0",
|
||||
"micromark-util-character": "^2.0.0",
|
||||
"micromark-util-symbol": "^2.0.0",
|
||||
"micromark-util-types": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark-factory-destination": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz",
|
||||
|
@ -30897,32 +30869,6 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/openai": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/openai/-/openai-4.36.0.tgz",
|
||||
"integrity": "sha512-AtYrhhWY64LhB9P6f3H0nV8nTSaQJ89mWPnfNU5CnYg81zlYaV8nkyO+aTNfprdqP/9xv10woNNUgefXINT4Dg==",
|
||||
"dependencies": {
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/node-fetch": "^2.6.4",
|
||||
"abort-controller": "^3.0.0",
|
||||
"agentkeepalive": "^4.2.1",
|
||||
"form-data-encoder": "1.7.2",
|
||||
"formdata-node": "^4.3.2",
|
||||
"node-fetch": "^2.6.7",
|
||||
"web-streams-polyfill": "^3.2.1"
|
||||
},
|
||||
"bin": {
|
||||
"openai": "bin/cli"
|
||||
}
|
||||
},
|
||||
"node_modules/openai/node_modules/web-streams-polyfill": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/openapi3-ts": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-3.1.2.tgz",
|
||||
|
@ -44630,6 +44576,7 @@
|
|||
"east": "^2.0.2",
|
||||
"ejs": "^3.1.10",
|
||||
"email-addresses": "^5.0.0",
|
||||
"eventsource-parser": "^1.1.2",
|
||||
"express": "^4.19.2",
|
||||
"express-bearer-token": "^2.4.0",
|
||||
"express-http-proxy": "^1.6.0",
|
||||
|
@ -44661,7 +44608,6 @@
|
|||
"nodemailer": "^6.7.0",
|
||||
"nodemailer-ses-transport": "^1.5.1",
|
||||
"on-headers": "^1.0.2",
|
||||
"openai": "^4.36.0",
|
||||
"otplib": "^12.0.1",
|
||||
"p-limit": "^2.3.0",
|
||||
"p-props": "4.0.0",
|
||||
|
@ -44833,7 +44779,6 @@
|
|||
"mathjax": "^3.2.2",
|
||||
"mensch": "^0.3.4",
|
||||
"micromark": "^4.0.0",
|
||||
"micromark-extension-gfm-table": "^2.0.0",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
"mocha": "^10.2.0",
|
||||
"mocha-each": "^2.0.1",
|
||||
|
@ -53295,6 +53240,7 @@
|
|||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"events": "^3.3.0",
|
||||
"eventsource-parser": "^1.1.2",
|
||||
"expose-loader": "^4.1.0",
|
||||
"express": "^4.19.2",
|
||||
"express-bearer-token": "^2.4.0",
|
||||
|
@ -53331,7 +53277,6 @@
|
|||
"mensch": "^0.3.4",
|
||||
"method-override": "^2.3.3",
|
||||
"micromark": "^4.0.0",
|
||||
"micromark-extension-gfm-table": "^2.0.0",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
"minimatch": "^7.4.2",
|
||||
"minimist": "^1.2.7",
|
||||
|
@ -53349,7 +53294,6 @@
|
|||
"nodemailer-ses-transport": "^1.5.1",
|
||||
"nvd3": "^1.8.6",
|
||||
"on-headers": "^1.0.2",
|
||||
"openai": "^4.36.0",
|
||||
"otplib": "^12.0.1",
|
||||
"p-limit": "^2.3.0",
|
||||
"p-props": "4.0.0",
|
||||
|
@ -59198,14 +59142,6 @@
|
|||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"agentkeepalive": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
|
||||
"integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
|
||||
"requires": {
|
||||
"humanize-ms": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"aggregate-error": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
||||
|
@ -64617,6 +64553,11 @@
|
|||
"resolved": "https://registry.npmjs.org/events-listener/-/events-listener-1.1.0.tgz",
|
||||
"integrity": "sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g=="
|
||||
},
|
||||
"eventsource-parser": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz",
|
||||
"integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA=="
|
||||
},
|
||||
"execa": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||
|
@ -67268,14 +67209,6 @@
|
|||
"integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
|
||||
"dev": true
|
||||
},
|
||||
"humanize-ms": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
||||
"integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
|
||||
"requires": {
|
||||
"ms": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
|
@ -70942,19 +70875,6 @@
|
|||
"micromark-util-types": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"micromark-extension-gfm-table": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz",
|
||||
"integrity": "sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"devlop": "^1.0.0",
|
||||
"micromark-factory-space": "^2.0.0",
|
||||
"micromark-util-character": "^2.0.0",
|
||||
"micromark-util-symbol": "^2.0.0",
|
||||
"micromark-util-types": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"micromark-factory-destination": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz",
|
||||
|
@ -72380,28 +72300,6 @@
|
|||
"is-wsl": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"openai": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/openai/-/openai-4.36.0.tgz",
|
||||
"integrity": "sha512-AtYrhhWY64LhB9P6f3H0nV8nTSaQJ89mWPnfNU5CnYg81zlYaV8nkyO+aTNfprdqP/9xv10woNNUgefXINT4Dg==",
|
||||
"requires": {
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/node-fetch": "^2.6.4",
|
||||
"abort-controller": "^3.0.0",
|
||||
"agentkeepalive": "^4.2.1",
|
||||
"form-data-encoder": "1.7.2",
|
||||
"formdata-node": "^4.3.2",
|
||||
"node-fetch": "^2.6.7",
|
||||
"web-streams-polyfill": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"web-streams-polyfill": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"openapi3-ts": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-3.1.2.tgz",
|
||||
|
|
|
@ -670,6 +670,7 @@ const _ProjectController = {
|
|||
debugPdfDetach,
|
||||
showSymbolPalette,
|
||||
symbolPaletteAvailable: Features.hasFeature('symbol-palette'),
|
||||
showAiErrorAssistant: user.alphaProgram, // TODO: labs experiment
|
||||
detachRole,
|
||||
metadata: { viewport: false },
|
||||
showUpgradePrompt,
|
||||
|
|
|
@ -8,6 +8,7 @@ const VALID_KEYS = [
|
|||
'writefull-integration',
|
||||
'writefull-oauth-promotion',
|
||||
'bib-file-tpr-prompt',
|
||||
'ai-error-assistant-consent',
|
||||
]
|
||||
|
||||
async function completeTutorial(req, res, next) {
|
||||
|
|
|
@ -21,6 +21,7 @@ meta(name="ol-pdfjsVariant" content=pdfjsVariant)
|
|||
meta(name="ol-debugPdfDetach" data-type="boolean" content=debugPdfDetach)
|
||||
meta(name="ol-showSymbolPalette" data-type="boolean" content=showSymbolPalette)
|
||||
meta(name="ol-symbolPaletteAvailable" data-type="boolean" content=symbolPaletteAvailable)
|
||||
meta(name="ol-showAiErrorAssistant" data-type="boolean" content=showAiErrorAssistant)
|
||||
meta(name="ol-detachRole" data-type="string" content=detachRole)
|
||||
meta(name="ol-allowedImageNames" data-type="json" content=allowedImageNames)
|
||||
meta(name="ol-languages" data-type="json" content=languages)
|
||||
|
|
|
@ -876,6 +876,7 @@ module.exports = {
|
|||
sourceEditorExtensions: [],
|
||||
sourceEditorComponents: [],
|
||||
pdfLogEntryComponents: [],
|
||||
diagnosticActions: [],
|
||||
sourceEditorCompletionSources: [],
|
||||
sourceEditorSymbolPalette: [],
|
||||
sourceEditorToolbarComponents: [],
|
||||
|
|
|
@ -5,6 +5,7 @@ import PreviewLogEntryHeader from '../../preview/components/preview-log-entry-he
|
|||
import PdfLogEntryContent from './pdf-log-entry-content'
|
||||
import HumanReadableLogsHints from '../../../ide/human-readable-logs/HumanReadableLogsHints'
|
||||
import { sendMB } from '@/infrastructure/event-tracking'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
function PdfLogEntry({
|
||||
ruleId,
|
||||
|
@ -25,7 +26,10 @@ function PdfLogEntry({
|
|||
onClose,
|
||||
index,
|
||||
logEntry,
|
||||
id,
|
||||
}) {
|
||||
const showAiErrorAssistant = getMeta('ol-showAiErrorAssistant')
|
||||
|
||||
if (ruleId && HumanReadableLogsHints[ruleId]) {
|
||||
const hint = HumanReadableLogsHints[ruleId]
|
||||
formattedContent = hint.formattedContent(contentDetails)
|
||||
|
@ -44,11 +48,29 @@ function PdfLogEntry({
|
|||
[level, onSourceLocationClick, ruleId, sourceLocation]
|
||||
)
|
||||
|
||||
const logEntryRef = useCallback(
|
||||
element => {
|
||||
if (element) {
|
||||
window.addEventListener('editor:view-compile-log-entry', event => {
|
||||
if (event.detail.id === id) {
|
||||
element.scrollIntoView({ block: 'start', inline: 'nearest' })
|
||||
}
|
||||
|
||||
if (event.detail.suggestFix) {
|
||||
element.querySelector('button[data-action="suggest-fix"]')?.click()
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
[id]
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('log-entry', customClass)}
|
||||
aria-label={entryAriaLabel}
|
||||
data-ruleid={ruleId}
|
||||
ref={logEntryRef}
|
||||
>
|
||||
<PreviewLogEntryHeader
|
||||
level={level}
|
||||
|
@ -62,7 +84,7 @@ function PdfLogEntry({
|
|||
onClose={onClose}
|
||||
/>
|
||||
|
||||
{(rawContent || formattedContent || window.user.alphaProgram) && (
|
||||
{(rawContent || formattedContent || showAiErrorAssistant) && (
|
||||
<PdfLogEntryContent
|
||||
rawContent={rawContent}
|
||||
formattedContent={formattedContent}
|
||||
|
@ -101,6 +123,7 @@ PdfLogEntry.propTypes = {
|
|||
onClose: PropTypes.func,
|
||||
index: PropTypes.number,
|
||||
logEntry: PropTypes.any,
|
||||
id: PropTypes.string,
|
||||
}
|
||||
|
||||
export default memo(PdfLogEntry)
|
||||
|
|
|
@ -26,6 +26,7 @@ function PdfLogsEntries({ entries, hasErrors }) {
|
|||
<PdfLogEntry
|
||||
key={logEntry.key}
|
||||
index={index}
|
||||
id={logEntry.key}
|
||||
logEntry={logEntry}
|
||||
ruleId={logEntry.ruleId}
|
||||
headerTitle={logEntry.messageComponent ?? logEntry.message}
|
||||
|
|
|
@ -41,7 +41,7 @@ export function handleOutputFiles(outputFiles, projectId, data) {
|
|||
let nextEntryId = 1
|
||||
|
||||
function generateEntryKey() {
|
||||
return '' + nextEntryId++
|
||||
return 'compile-log-entry-' + nextEntryId++
|
||||
}
|
||||
|
||||
export const handleLogFiles = async (outputFiles, data, signal) => {
|
||||
|
@ -140,6 +140,7 @@ export function buildLogEntryAnnotations(entries, fileTreeData, rootDocId) {
|
|||
const rootDocDirname = dirname(fileTreeData, rootDocId)
|
||||
|
||||
const logEntryAnnotations = {}
|
||||
const seenLine = {}
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.file) {
|
||||
|
@ -153,12 +154,17 @@ export function buildLogEntryAnnotations(entries, fileTreeData, rootDocId) {
|
|||
}
|
||||
|
||||
logEntryAnnotations[entity._id].push({
|
||||
id: entry.key,
|
||||
entryIndex: logEntryAnnotations[entity._id].length, // used for maintaining the order of items on the same line
|
||||
row: entry.line - 1,
|
||||
type: entry.level === 'error' ? 'error' : 'warning',
|
||||
text: entry.message,
|
||||
source: 'compile', // NOTE: this is used in Ace for filtering the annotations
|
||||
ruleId: entry.ruleId,
|
||||
firstOnLine: !seenLine[entry.line],
|
||||
})
|
||||
|
||||
seenLine[entry.line] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,34 @@ import {
|
|||
import { Annotation } from '../../../../../types/annotation'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { sendMB } from '@/infrastructure/event-tracking'
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
|
||||
interface CompileLogDiagnostic extends Diagnostic {
|
||||
compile?: true
|
||||
ruleId?: string
|
||||
id?: string
|
||||
entryIndex: number
|
||||
firstOnLine?: boolean
|
||||
}
|
||||
|
||||
type RenderedDiagnostic = Pick<
|
||||
CompileLogDiagnostic,
|
||||
| 'message'
|
||||
| 'severity'
|
||||
| 'ruleId'
|
||||
| 'compile'
|
||||
| 'source'
|
||||
| 'id'
|
||||
| 'firstOnLine'
|
||||
>
|
||||
|
||||
export type DiagnosticAction = (
|
||||
diagnostic: RenderedDiagnostic
|
||||
) => HTMLButtonElement | null
|
||||
|
||||
const diagnosticActions = importOverleafModules('diagnosticActions') as {
|
||||
import: { default: DiagnosticAction }
|
||||
}[]
|
||||
|
||||
const compileLintSourceConf = new Compartment()
|
||||
|
||||
|
@ -56,7 +84,8 @@ export const lintSourceConfig = {
|
|||
*/
|
||||
const compileLogLintSource = (): Extension =>
|
||||
linter(view => {
|
||||
const items: Diagnostic[] = []
|
||||
const items: CompileLogDiagnostic[] = []
|
||||
// NOTE: iter() changes the order of diagnostics on the same line
|
||||
const cursor = view.state.field(compileDiagnosticsState).iter()
|
||||
while (cursor.value !== null) {
|
||||
const { diagnostic } = cursor.value
|
||||
|
@ -68,14 +97,11 @@ const compileLogLintSource = (): Extension =>
|
|||
})
|
||||
cursor.next()
|
||||
}
|
||||
// restore the original order of items
|
||||
items.sort((a, b) => a.from - b.from || a.entryIndex - b.entryIndex)
|
||||
return items
|
||||
}, lintSourceConfig)
|
||||
|
||||
interface CompileLogDiagnostic extends Diagnostic {
|
||||
compile?: true
|
||||
ruleId?: string
|
||||
}
|
||||
|
||||
class CompileLogDiagnosticRangeValue extends RangeValue {
|
||||
constructor(public diagnostic: CompileLogDiagnostic) {
|
||||
super()
|
||||
|
@ -117,7 +143,7 @@ export const compileDiagnosticsState = StateField.define<
|
|||
})
|
||||
|
||||
export const setAnnotations = (doc: Text, annotations: Annotation[]) => {
|
||||
const diagnostics: Diagnostic[] = []
|
||||
const diagnostics: CompileLogDiagnostic[] = []
|
||||
|
||||
for (const annotation of annotations) {
|
||||
// ignore "whole document" (row: -1) annotations
|
||||
|
@ -162,19 +188,31 @@ const convertAnnotationToDiagnostic = (
|
|||
message: annotation.text,
|
||||
ruleId: annotation.ruleId,
|
||||
compile: true,
|
||||
id: annotation.id,
|
||||
entryIndex: annotation.entryIndex,
|
||||
source: annotation.source,
|
||||
firstOnLine: annotation.firstOnLine,
|
||||
}
|
||||
}
|
||||
|
||||
export const renderMessage = (
|
||||
diagnostic: Pick<
|
||||
CompileLogDiagnostic,
|
||||
'message' | 'severity' | 'ruleId' | 'compile'
|
||||
>
|
||||
) => {
|
||||
export const renderMessage = (diagnostic: RenderedDiagnostic) => {
|
||||
const { message, severity, ruleId, compile = false } = diagnostic
|
||||
|
||||
const div = document.createElement('div')
|
||||
div.textContent = message
|
||||
div.classList.add('ol-cm-diagnostic-message')
|
||||
|
||||
div.append(message)
|
||||
|
||||
const activeDiagnosticActions = diagnosticActions
|
||||
.map(m => m.import.default(diagnostic))
|
||||
.filter(Boolean) as HTMLButtonElement[]
|
||||
|
||||
if (activeDiagnosticActions.length) {
|
||||
const actions = document.createElement('div')
|
||||
actions.classList.add('ol-cm-diagnostic-actions')
|
||||
actions.append(...activeDiagnosticActions)
|
||||
div.append(actions)
|
||||
}
|
||||
|
||||
window.setTimeout(() => {
|
||||
if (div.isConnected) {
|
||||
|
|
|
@ -155,6 +155,15 @@ const baseTheme = EditorView.baseTheme({
|
|||
boxShadow: '0 1px 1px rgba(255, 255, 255, 0.7)',
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.2)',
|
||||
},
|
||||
'.cm-diagnosticSource': {
|
||||
display: 'none',
|
||||
},
|
||||
'.ol-cm-diagnostic-actions': {
|
||||
marginTop: '4px',
|
||||
},
|
||||
'.cm-diagnostic:last-of-type .ol-cm-diagnostic-actions': {
|
||||
marginBottom: '4px',
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
|
@ -211,7 +211,7 @@ export default class LatexParser {
|
|||
// Check if we're entering or leaving a new file in this line
|
||||
|
||||
parseParensForFilenames() {
|
||||
const pos = this.currentLine.search(/\(|\)/)
|
||||
const pos = this.currentLine.search(/[()]/)
|
||||
if (pos !== -1) {
|
||||
const token = this.currentLine[pos]
|
||||
this.currentLine = this.currentLine.slice(pos + 1)
|
||||
|
@ -251,12 +251,14 @@ export default class LatexParser {
|
|||
|
||||
consumeFilePath() {
|
||||
// Our heuristic for detecting file names are rather crude
|
||||
// A file may not contain a ')' in it
|
||||
// To be a file path it must have at least one /
|
||||
if (!this.currentLine.match(/^\/?([^ )]+\/)+/)) {
|
||||
|
||||
// To contain a file path this line must have at least one / before any '(', ')' or '\'
|
||||
if (!this.currentLine.match(/^\/?([^ ()\\]+\/)+/)) {
|
||||
return false
|
||||
}
|
||||
let endOfFilePath = this.currentLine.search(/ |\)/)
|
||||
|
||||
// A file may not contain a '(', ')' or '\'
|
||||
let endOfFilePath = this.currentLine.search(/[ ()\\]/)
|
||||
|
||||
// handle the case where there is a space in a filename
|
||||
while (endOfFilePath !== -1 && this.currentLine[endOfFilePath] === ' ') {
|
||||
|
|
|
@ -596,6 +596,18 @@ export const LocalCompileProvider: FC = ({ children }) => {
|
|||
// used for that compile.
|
||||
const lastCompileOptions = useMemo(() => data?.options || {}, [data])
|
||||
|
||||
useEffect(() => {
|
||||
const listener = (event: Event) => {
|
||||
setShowLogs((event as CustomEvent<boolean>).detail as boolean)
|
||||
}
|
||||
|
||||
window.addEventListener('editor:show-logs', listener)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('editor:show-logs', listener)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
animateCompileDropdownArrow,
|
||||
|
|
|
@ -10,6 +10,7 @@ const ProjectContext = createContext<
|
|||
_id: string
|
||||
name: string
|
||||
rootDocId?: string
|
||||
compiler: string
|
||||
members: { _id: UserId; email: string; privileges: string }[]
|
||||
invites: { _id: UserId }[]
|
||||
features: {
|
||||
|
@ -66,6 +67,7 @@ export const ProjectProvider: FC = ({ children }) => {
|
|||
|
||||
const {
|
||||
_id,
|
||||
compiler,
|
||||
name,
|
||||
rootDoc_id: rootDocId,
|
||||
members,
|
||||
|
@ -87,6 +89,7 @@ export const ProjectProvider: FC = ({ children }) => {
|
|||
const value = useMemo(() => {
|
||||
return {
|
||||
_id,
|
||||
compiler,
|
||||
name,
|
||||
rootDocId,
|
||||
members,
|
||||
|
@ -99,6 +102,7 @@ export const ProjectProvider: FC = ({ children }) => {
|
|||
}
|
||||
}, [
|
||||
_id,
|
||||
compiler,
|
||||
name,
|
||||
rootDocId,
|
||||
members,
|
||||
|
|
|
@ -85,6 +85,10 @@
|
|||
);
|
||||
|
||||
background: var(--premium-gradient);
|
||||
transition: none;
|
||||
&:hover {
|
||||
background: var(--blue-70);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,9 @@
|
|||
.btn-premium {
|
||||
.premium-background;
|
||||
color: @white;
|
||||
&:hover {
|
||||
background: @blue-70;
|
||||
}
|
||||
}
|
||||
|
||||
.reset-btns {
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
"east": "^2.0.2",
|
||||
"ejs": "^3.1.10",
|
||||
"email-addresses": "^5.0.0",
|
||||
"eventsource-parser": "^1.1.2",
|
||||
"express": "^4.19.2",
|
||||
"express-bearer-token": "^2.4.0",
|
||||
"express-http-proxy": "^1.6.0",
|
||||
|
@ -140,7 +141,6 @@
|
|||
"nodemailer": "^6.7.0",
|
||||
"nodemailer-ses-transport": "^1.5.1",
|
||||
"on-headers": "^1.0.2",
|
||||
"openai": "^4.36.0",
|
||||
"otplib": "^12.0.1",
|
||||
"p-limit": "^2.3.0",
|
||||
"p-props": "4.0.0",
|
||||
|
@ -312,7 +312,6 @@
|
|||
"mathjax": "^3.2.2",
|
||||
"mensch": "^0.3.4",
|
||||
"micromark": "^4.0.0",
|
||||
"micromark-extension-gfm-table": "^2.0.0",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
"mocha": "^10.2.0",
|
||||
"mocha-each": "^2.0.1",
|
||||
|
|
2
services/web/test/frontend/bootstrap.js
vendored
2
services/web/test/frontend/bootstrap.js
vendored
|
@ -1,6 +1,6 @@
|
|||
// Run babel on tests to allow support for import/export statements in Node
|
||||
require('@babel/register')({
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs'],
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.svg'],
|
||||
plugins: [['module-resolver', { alias: { '^@/(.+)': './frontend/js/\\1' } }]],
|
||||
})
|
||||
|
||||
|
|
|
@ -4,4 +4,7 @@ export type Annotation = {
|
|||
text: string
|
||||
source?: string
|
||||
ruleId?: string
|
||||
id: string
|
||||
entryIndex: number
|
||||
firstOnLine: boolean
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue