mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Remove CM5 Rich Text module (#11776)
GitOrigin-RevId: 812d3b5f1df7e769c8be732ccb31653e8e9a8aa3
This commit is contained in:
parent
379ead7431
commit
c8f0885316
37 changed files with 129 additions and 587 deletions
12
package-lock.json
generated
12
package-lock.json
generated
|
@ -20065,11 +20065,6 @@
|
||||||
"node": ">=0.12.0"
|
"node": ">=0.12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/codemirror": {
|
|
||||||
"version": "5.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.33.0.tgz",
|
|
||||||
"integrity": "sha512-HT6PKVqkwpzwB3jl5hXFoQteEWXbSWMzG3Z8RVYlx8hZwCOLCy4NU7vkSB3dYX3e6ORwRfGw4uFOXaw4rn/a9Q=="
|
|
||||||
},
|
|
||||||
"node_modules/coffee-script": {
|
"node_modules/coffee-script": {
|
||||||
"version": "1.12.7",
|
"version": "1.12.7",
|
||||||
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz",
|
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz",
|
||||||
|
@ -45222,7 +45217,6 @@
|
||||||
"chartjs-adapter-moment": "^1.0.1",
|
"chartjs-adapter-moment": "^1.0.1",
|
||||||
"chartjs-plugin-datalabels": "^2.2.0",
|
"chartjs-plugin-datalabels": "^2.2.0",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"codemirror": "~5.33.0",
|
|
||||||
"connect-redis": "^6.1.3",
|
"connect-redis": "^6.1.3",
|
||||||
"content-disposition": "^0.5.0",
|
"content-disposition": "^0.5.0",
|
||||||
"contentful": "^6.1.1",
|
"contentful": "^6.1.1",
|
||||||
|
@ -54014,7 +54008,6 @@
|
||||||
"chartjs-plugin-datalabels": "^2.2.0",
|
"chartjs-plugin-datalabels": "^2.2.0",
|
||||||
"cheerio": "^1.0.0-rc.3",
|
"cheerio": "^1.0.0-rc.3",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"codemirror": "~5.33.0",
|
|
||||||
"connect-redis": "^6.1.3",
|
"connect-redis": "^6.1.3",
|
||||||
"content-disposition": "^0.5.0",
|
"content-disposition": "^0.5.0",
|
||||||
"contentful": "^6.1.1",
|
"contentful": "^6.1.1",
|
||||||
|
@ -63599,11 +63592,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/co-use/-/co-use-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/co-use/-/co-use-1.1.0.tgz",
|
||||||
"integrity": "sha1-xrs83xDLc17Kqdru2kbXJclKTmI="
|
"integrity": "sha1-xrs83xDLc17Kqdru2kbXJclKTmI="
|
||||||
},
|
},
|
||||||
"codemirror": {
|
|
||||||
"version": "5.33.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.33.0.tgz",
|
|
||||||
"integrity": "sha512-HT6PKVqkwpzwB3jl5hXFoQteEWXbSWMzG3Z8RVYlx8hZwCOLCy4NU7vkSB3dYX3e6ORwRfGw4uFOXaw4rn/a9Q=="
|
|
||||||
},
|
|
||||||
"coffee-script": {
|
"coffee-script": {
|
||||||
"version": "1.12.7",
|
"version": "1.12.7",
|
||||||
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz",
|
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz",
|
||||||
|
|
|
@ -662,6 +662,7 @@ const ProjectController = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
// this is only needed until the survey link is removed from the toolbar
|
||||||
richTextAssignment(cb) {
|
richTextAssignment(cb) {
|
||||||
SplitTestHandler.getAssignment(
|
SplitTestHandler.getAssignment(
|
||||||
req,
|
req,
|
||||||
|
@ -755,7 +756,6 @@ const ProjectController = {
|
||||||
brandVariation,
|
brandVariation,
|
||||||
pdfjsAssignment,
|
pdfjsAssignment,
|
||||||
editorLeftMenuAssignment,
|
editorLeftMenuAssignment,
|
||||||
richTextAssignment,
|
|
||||||
sourceEditorToolbarAssigment,
|
sourceEditorToolbarAssigment,
|
||||||
historyViewAssignment,
|
historyViewAssignment,
|
||||||
reviewPanelAssignment,
|
reviewPanelAssignment,
|
||||||
|
@ -880,13 +880,6 @@ const ProjectController = {
|
||||||
? 'project/editor_detached'
|
? 'project/editor_detached'
|
||||||
: 'project/editor'
|
: 'project/editor'
|
||||||
|
|
||||||
let richTextVariant
|
|
||||||
if (!Features.hasFeature('saas')) {
|
|
||||||
richTextVariant = 'cm6'
|
|
||||||
} else {
|
|
||||||
richTextVariant = richTextAssignment.variant
|
|
||||||
}
|
|
||||||
|
|
||||||
res.render(template, {
|
res.render(template, {
|
||||||
title: project.name,
|
title: project.name,
|
||||||
priority_title: true,
|
priority_title: true,
|
||||||
|
@ -961,7 +954,6 @@ const ProjectController = {
|
||||||
fixedSizeDocument: true,
|
fixedSizeDocument: true,
|
||||||
useOpenTelemetry: Settings.useOpenTelemetryClient,
|
useOpenTelemetry: Settings.useOpenTelemetryClient,
|
||||||
showCM6SwitchAwaySurvey: Settings.showCM6SwitchAwaySurvey,
|
showCM6SwitchAwaySurvey: Settings.showCM6SwitchAwaySurvey,
|
||||||
richTextVariant,
|
|
||||||
historyViewReact: historyViewAssignment.variant === 'react',
|
historyViewReact: historyViewAssignment.variant === 'react',
|
||||||
isReviewPanelReact: reviewPanelAssignment.variant === 'react',
|
isReviewPanelReact: reviewPanelAssignment.variant === 'react',
|
||||||
showPersonalAccessToken,
|
showPersonalAccessToken,
|
||||||
|
|
|
@ -124,7 +124,5 @@ block foot-scripts
|
||||||
each file in (useOpenTelemetry ? entrypointScripts("tracing") : [])
|
each file in (useOpenTelemetry ? entrypointScripts("tracing") : [])
|
||||||
script(type="text/javascript", nonce=scriptNonce, src=file)
|
script(type="text/javascript", nonce=scriptNonce, src=file)
|
||||||
script(type="text/javascript", nonce=scriptNonce, src=(wsUrl || '/socket.io') + '/socket.io.js')
|
script(type="text/javascript", nonce=scriptNonce, src=(wsUrl || '/socket.io') + '/socket.io.js')
|
||||||
if (richTextVariant !== 'cm6')
|
|
||||||
script(type="text/javascript", nonce=scriptNonce, src=mathJaxPath)
|
|
||||||
each file in entrypointScripts("ide")
|
each file in entrypointScripts("ide")
|
||||||
script(type="text/javascript", nonce=scriptNonce, src=file)
|
script(type="text/javascript", nonce=scriptNonce, src=file)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
.ui-layout-center(
|
.ui-layout-center(
|
||||||
ng-controller="ReviewPanelController",
|
ng-controller="ReviewPanelController",
|
||||||
ng-class="{\
|
ng-class="{\
|
||||||
'rp-unsupported': editor.showRichText,\
|
|
||||||
'rp-state-current-file': (reviewPanel.subView === SubViews.CUR_FILE),\
|
'rp-state-current-file': (reviewPanel.subView === SubViews.CUR_FILE),\
|
||||||
'rp-state-current-file-expanded': (reviewPanel.subView === SubViews.CUR_FILE && ui.reviewPanelOpen),\
|
'rp-state-current-file-expanded': (reviewPanel.subView === SubViews.CUR_FILE && ui.reviewPanelOpen),\
|
||||||
'rp-state-current-file-mini': (reviewPanel.subView === SubViews.CUR_FILE && !ui.reviewPanelOpen),\
|
'rp-state-current-file-mini': (reviewPanel.subView === SubViews.CUR_FILE && !ui.reviewPanelOpen),\
|
||||||
|
@ -36,7 +35,6 @@
|
||||||
|
|
||||||
.loading-panel(
|
.loading-panel(
|
||||||
ng-show="(!editor.sharejs_doc || editor.opening) && !editor.error_state",
|
ng-show="(!editor.sharejs_doc || editor.opening) && !editor.error_state",
|
||||||
style=showRichText ? "top: 32px" : "",
|
|
||||||
)
|
)
|
||||||
span(ng-show="editor.open_doc_id")
|
span(ng-show="editor.open_doc_id")
|
||||||
i.fa.fa-spin.fa-refresh
|
i.fa.fa-spin.fa-refresh
|
||||||
|
@ -45,10 +43,9 @@
|
||||||
i.fa.fa-arrow-left
|
i.fa.fa-arrow-left
|
||||||
| #{translate("open_a_file_on_the_left")}
|
| #{translate("open_a_file_on_the_left")}
|
||||||
|
|
||||||
if moduleIncludesAvailable('editor:main')
|
div(ng-controller="EditorLoaderController")
|
||||||
!= moduleIncludes('editor:main', locals)
|
if (!showSourceToolbar)
|
||||||
else
|
include ./toolbar
|
||||||
.toolbar.toolbar-editor
|
|
||||||
|
|
||||||
div(ng-if="editor.newSourceEditor")
|
div(ng-if="editor.newSourceEditor")
|
||||||
include ../../source-editor/source-editor
|
include ../../source-editor/source-editor
|
||||||
|
|
|
@ -38,11 +38,9 @@ meta(name="ol-useOpenTelemetry" data-type="boolean" content=useOpenTelemetry)
|
||||||
meta(name="ol-showSupport", data-type="boolean" content=showSupport)
|
meta(name="ol-showSupport", data-type="boolean" content=showSupport)
|
||||||
meta(name="ol-showTemplatesServerPro", data-type="boolean" content=showTemplatesServerPro)
|
meta(name="ol-showTemplatesServerPro", data-type="boolean" content=showTemplatesServerPro)
|
||||||
meta(name="ol-showCM6SwitchAwaySurvey", data-type="boolean" content=showCM6SwitchAwaySurvey)
|
meta(name="ol-showCM6SwitchAwaySurvey", data-type="boolean" content=showCM6SwitchAwaySurvey)
|
||||||
meta(name="ol-richTextVariant" content=richTextVariant)
|
|
||||||
meta(name="ol-showPersonalAccessToken", data-type="boolean" content=showPersonalAccessToken)
|
meta(name="ol-showPersonalAccessToken", data-type="boolean" content=showPersonalAccessToken)
|
||||||
meta(name="ol-isReviewPanelReact", data-type="boolean" content=isReviewPanelReact)
|
meta(name="ol-isReviewPanelReact", data-type="boolean" content=isReviewPanelReact)
|
||||||
meta(name="ol-hasTrackChangesFeature", data-type="boolean" content=hasTrackChangesFeature)
|
meta(name="ol-hasTrackChangesFeature", data-type="boolean" content=hasTrackChangesFeature)
|
||||||
if (richTextVariant === 'cm6')
|
|
||||||
meta(name="ol-mathJax3Path" content=mathJax3Path)
|
meta(name="ol-mathJax3Path" content=mathJax3Path)
|
||||||
|
|
||||||
- var fileActionI18n = ['edited', 'renamed', 'created', 'deleted'].reduce((acc, i) => {acc[i] = translate('file_action_' + i); return acc}, {})
|
- var fileActionI18n = ['edited', 'renamed', 'created', 'deleted'].reduce((acc, i) => {acc[i] = translate('file_action_' + i); return acc}, {})
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#editor(
|
#editor(
|
||||||
ace-editor="editor",
|
ace-editor="editor",
|
||||||
ng-if="!editor.showRichText",
|
|
||||||
ng-show="!!editor.sharejs_doc && !editor.opening && multiSelectedCount === 0 && !editor.error_state",
|
ng-show="!!editor.sharejs_doc && !editor.opening && multiSelectedCount === 0 && !editor.error_state",
|
||||||
theme="settings.editorTheme",
|
theme="settings.editorTheme",
|
||||||
keybindings="settings.mode",
|
keybindings="settings.mode",
|
||||||
|
|
46
services/web/app/views/project/editor/toolbar.pug
Normal file
46
services/web/app/views/project/editor/toolbar.pug
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
.toolbar.toolbar-editor(ng-controller="EditorToolbarController")
|
||||||
|
.toggle-wrapper
|
||||||
|
editor-switch
|
||||||
|
|
||||||
|
div(
|
||||||
|
formatting-buttons
|
||||||
|
ng-cloak
|
||||||
|
ng-if="!editor.showVisual"
|
||||||
|
buttons="editorButtons"
|
||||||
|
opening="editor.opening"
|
||||||
|
resize-on="layout:main:resize,layout:pdf:resize,layout:review:resize,review-panel:toggle"
|
||||||
|
is-fullscreen-editor="ui.view == 'editor' && ui.pdfLayout == 'flat'"
|
||||||
|
class="formatting-buttons"
|
||||||
|
)
|
||||||
|
div(
|
||||||
|
formatting-buttons
|
||||||
|
ng-cloak
|
||||||
|
ng-if="editor.showVisual"
|
||||||
|
buttons="[]"
|
||||||
|
opening="editor.opening"
|
||||||
|
resize-on="layout:main:resize,layout:pdf:resize,layout:review:resize,review-panel:toggle"
|
||||||
|
is-fullscreen-editor="ui.view == 'editor' && ui.pdfLayout == 'flat'"
|
||||||
|
class="formatting-buttons"
|
||||||
|
)
|
||||||
|
|
||||||
|
.toolbar-pdf-right
|
||||||
|
switch-to-pdf-button()
|
||||||
|
detacher-synctex-control()
|
||||||
|
editor-compile-button()
|
||||||
|
|
||||||
|
script(type="text/ng-template", id="formattingButtonsTpl")
|
||||||
|
.formatting-buttons-wrapper
|
||||||
|
|
|
||||||
|
button.btn.formatting-btn.formatting-btn--icon(
|
||||||
|
ng-repeat="button in shownButtons"
|
||||||
|
ng-click="button.handleClick()"
|
||||||
|
ng-class="{ active: button.active }",
|
||||||
|
aria-label="{{button.title}}"
|
||||||
|
tooltip="{{button.title}}"
|
||||||
|
tooltip-placement="bottom"
|
||||||
|
tooltip-append-to-body="true"
|
||||||
|
)
|
||||||
|
i(class="{{button.iconClass}}") {{button.iconText}}
|
||||||
|
|
||||||
|
if moduleIncludesAvailable('editor:galileo')
|
||||||
|
galileo-toolbar-button
|
|
@ -1,5 +1,4 @@
|
||||||
source-editor#editor(
|
source-editor#editor(
|
||||||
ng-class="{ 'review-panel-react': reviewPanel.isReact }"
|
ng-class="{ 'review-panel-react': reviewPanel.isReact }"
|
||||||
ng-if="!editor.showRichText"
|
|
||||||
ng-show="!!editor.sharejs_doc && !editor.opening && multiSelectedCount === 0 && !editor.error_state"
|
ng-show="!!editor.sharejs_doc && !editor.opening && multiSelectedCount === 0 && !editor.error_state"
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,9 +9,6 @@ App.controller('OutlineController', function ($scope, ide, eventTracking) {
|
||||||
$scope.eventTracking = eventTracking
|
$scope.eventTracking = eventTracking
|
||||||
|
|
||||||
function shouldShowOutline() {
|
function shouldShowOutline() {
|
||||||
if ($scope.editor.showRichText) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return !$scope.editor.newSourceEditor
|
return !$scope.editor.newSourceEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,10 +18,6 @@ App.controller('OutlineController', function ($scope, ide, eventTracking) {
|
||||||
$scope.show = shouldShowOutline()
|
$scope.show = shouldShowOutline()
|
||||||
})
|
})
|
||||||
|
|
||||||
$scope.$watch('editor.showRichText', function () {
|
|
||||||
$scope.show = shouldShowOutline()
|
|
||||||
})
|
|
||||||
|
|
||||||
$scope.$on('outline-manager:outline-changed', onOutlineChange)
|
$scope.$on('outline-manager:outline-changed', onOutlineChange)
|
||||||
|
|
||||||
function onOutlineChange(e, outlineInfo) {
|
function onOutlineChange(e, outlineInfo) {
|
||||||
|
|
|
@ -68,21 +68,9 @@ class OutlineManager {
|
||||||
|
|
||||||
this.updateHighlightedLine(middleVisibleRow + 1)
|
this.updateHighlightedLine(middleVisibleRow + 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
scope.$watch('editor.showRichText', () => {
|
|
||||||
this.ignoreNextScroll = true
|
|
||||||
this.ignoreNextCursorUpdate = true
|
|
||||||
if (this.shouldShowOutline()) {
|
|
||||||
this.updateOutline()
|
|
||||||
this.broadcastChangeEvent()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldShowOutline() {
|
shouldShowOutline() {
|
||||||
if (this.scope.editor.showRichText) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return !this.scope.editor.newSourceEditor
|
return !this.scope.editor.newSourceEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { Button } from 'react-bootstrap'
|
import { Button } from 'react-bootstrap'
|
||||||
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
||||||
import {
|
import {
|
||||||
|
@ -12,33 +12,18 @@ type CM6SwitchAwaySurveyState = 'disabled' | 'enabled' | 'shown'
|
||||||
export default function CM6SwitchAwaySurvey() {
|
export default function CM6SwitchAwaySurvey() {
|
||||||
const [state, setState] = useState<CM6SwitchAwaySurveyState>('disabled')
|
const [state, setState] = useState<CM6SwitchAwaySurveyState>('disabled')
|
||||||
const [newSourceEditor] = useScopeValue('editor.newSourceEditor')
|
const [newSourceEditor] = useScopeValue('editor.newSourceEditor')
|
||||||
const [richText] = useScopeValue('editor.showRichText')
|
|
||||||
const initialRichTextPreference = useRef<boolean>(richText)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// If the user has previously seen any switch-away survey, then don't show
|
// If the user has previously seen any switch-away survey, then don't show
|
||||||
// the current one
|
// the current one
|
||||||
if (hasSeenCM6SwitchAwaySurvey()) return
|
if (hasSeenCM6SwitchAwaySurvey()) return
|
||||||
|
|
||||||
if (initialRichTextPreference.current) {
|
if (!newSourceEditor) {
|
||||||
if (!richText && newSourceEditor) {
|
|
||||||
// If user change from rich text to cm6, we remove the rich text
|
|
||||||
// preference so if user use rich text -> cm6 -> ace, we will show the
|
|
||||||
// current survey
|
|
||||||
initialRichTextPreference.current = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user loaded rich text initially, then don't show the survey
|
|
||||||
// (we are assuming that they will not have used CM6 as much)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newSourceEditor && !richText) {
|
|
||||||
setState('enabled')
|
setState('enabled')
|
||||||
} else {
|
} else {
|
||||||
setState('disabled')
|
setState('disabled')
|
||||||
}
|
}
|
||||||
}, [newSourceEditor, richText])
|
}, [newSourceEditor])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = () => {
|
const handleKeyDown = () => {
|
||||||
|
|
|
@ -48,12 +48,12 @@ function EditorSwitch() {
|
||||||
const [newSourceEditor, setNewSourceEditor] = useScopeValue(
|
const [newSourceEditor, setNewSourceEditor] = useScopeValue(
|
||||||
'editor.newSourceEditor'
|
'editor.newSourceEditor'
|
||||||
)
|
)
|
||||||
const [richText, setRichText] = useScopeValue('editor.showRichText')
|
|
||||||
const [visual, setVisual] = useScopeValue('editor.showVisual')
|
const [visual, setVisual] = useScopeValue('editor.showVisual')
|
||||||
|
|
||||||
const [docName] = useScopeValue('editor.open_doc_name')
|
const [docName] = useScopeValue('editor.open_doc_name')
|
||||||
const richTextAvailable = isValidTeXFile(docName)
|
const richTextAvailable = isValidTeXFile(docName)
|
||||||
const richTextOrVisual = richText || (richTextAvailable && visual)
|
// TODO: rename this after legacy & toolbar split tests are complete
|
||||||
|
const richTextOrVisual = richTextAvailable && visual
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
event => {
|
event => {
|
||||||
|
@ -61,33 +61,25 @@ function EditorSwitch() {
|
||||||
|
|
||||||
switch (editorType) {
|
switch (editorType) {
|
||||||
case 'ace':
|
case 'ace':
|
||||||
setRichText(false)
|
|
||||||
setVisual(false)
|
setVisual(false)
|
||||||
setNewSourceEditor(false)
|
setNewSourceEditor(false)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'cm6':
|
case 'cm6':
|
||||||
setRichText(false)
|
|
||||||
setVisual(false)
|
setVisual(false)
|
||||||
setNewSourceEditor(true)
|
setNewSourceEditor(true)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'rich-text':
|
case 'rich-text':
|
||||||
if (getMeta('ol-richTextVariant') === 'cm6') {
|
|
||||||
setRichText(false)
|
|
||||||
setVisual(true)
|
setVisual(true)
|
||||||
setNewSourceEditor(true)
|
setNewSourceEditor(true)
|
||||||
} else {
|
|
||||||
setRichText(true)
|
|
||||||
setVisual(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMB('editor-switch-change', { editorType })
|
sendMB('editor-switch-change', { editorType })
|
||||||
},
|
},
|
||||||
[setRichText, setVisual, setNewSourceEditor]
|
[setVisual, setNewSourceEditor]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { ChangeEvent, FC, memo, useCallback } from 'react'
|
||||||
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
||||||
import Tooltip from '../../../shared/components/tooltip'
|
import Tooltip from '../../../shared/components/tooltip'
|
||||||
import { sendMB } from '../../../infrastructure/event-tracking'
|
import { sendMB } from '../../../infrastructure/event-tracking'
|
||||||
import getMeta from '../../../utils/meta'
|
|
||||||
import isValidTeXFile from '../../../main/is-valid-tex-file'
|
import isValidTeXFile from '../../../main/is-valid-tex-file'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import SplitTestBadge from '../../../shared/components/split-test-badge'
|
import SplitTestBadge from '../../../shared/components/split-test-badge'
|
||||||
|
@ -12,12 +11,12 @@ function EditorSwitch() {
|
||||||
const [newSourceEditor, setNewSourceEditor] = useScopeValue(
|
const [newSourceEditor, setNewSourceEditor] = useScopeValue(
|
||||||
'editor.newSourceEditor'
|
'editor.newSourceEditor'
|
||||||
)
|
)
|
||||||
const [richText, setRichText] = useScopeValue('editor.showRichText')
|
|
||||||
const [visual, setVisual] = useScopeValue('editor.showVisual')
|
const [visual, setVisual] = useScopeValue('editor.showVisual')
|
||||||
|
|
||||||
const [docName] = useScopeValue('editor.open_doc_name')
|
const [docName] = useScopeValue('editor.open_doc_name')
|
||||||
const richTextAvailable = isValidTeXFile(docName)
|
const richTextAvailable = isValidTeXFile(docName)
|
||||||
const richTextOrVisual = richText || (richTextAvailable && visual)
|
// TODO: rename this after legacy & toolbar split tests are complete
|
||||||
|
const richTextOrVisual = richTextAvailable && visual
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
event => {
|
event => {
|
||||||
|
@ -25,33 +24,24 @@ function EditorSwitch() {
|
||||||
|
|
||||||
switch (editorType) {
|
switch (editorType) {
|
||||||
case 'ace':
|
case 'ace':
|
||||||
setRichText(false)
|
|
||||||
setVisual(false)
|
setVisual(false)
|
||||||
setNewSourceEditor(false)
|
setNewSourceEditor(false)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'cm6':
|
case 'cm6':
|
||||||
setRichText(false)
|
|
||||||
setVisual(false)
|
setVisual(false)
|
||||||
setNewSourceEditor(true)
|
setNewSourceEditor(true)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'rich-text':
|
case 'rich-text':
|
||||||
if (getMeta('ol-richTextVariant') === 'cm6') {
|
|
||||||
setRichText(false)
|
|
||||||
setVisual(true)
|
setVisual(true)
|
||||||
setNewSourceEditor(true)
|
setNewSourceEditor(true)
|
||||||
} else {
|
|
||||||
setRichText(true)
|
|
||||||
setVisual(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMB('editor-switch-change', { editorType })
|
sendMB('editor-switch-change', { editorType })
|
||||||
},
|
},
|
||||||
[setRichText, setVisual, setNewSourceEditor]
|
[setVisual, setNewSourceEditor]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -12,7 +12,6 @@ type GrammarlyWarningProps = {
|
||||||
export default function GrammarlyWarning({ delay }: GrammarlyWarningProps) {
|
export default function GrammarlyWarning({ delay }: GrammarlyWarningProps) {
|
||||||
const [show, setShow] = useState(false)
|
const [show, setShow] = useState(false)
|
||||||
const [newSourceEditor] = useScopeValue('editor.newSourceEditor')
|
const [newSourceEditor] = useScopeValue('editor.newSourceEditor')
|
||||||
const [showRichText] = useScopeValue('editor.showRichText')
|
|
||||||
const grammarly = grammarlyExtensionPresent()
|
const grammarly = grammarlyExtensionPresent()
|
||||||
const hasDismissedGrammarlyWarning = customLocalStorage.getItem(
|
const hasDismissedGrammarlyWarning = customLocalStorage.getItem(
|
||||||
'editor.has_dismissed_grammarly_warning'
|
'editor.has_dismissed_grammarly_warning'
|
||||||
|
@ -20,10 +19,7 @@ export default function GrammarlyWarning({ delay }: GrammarlyWarningProps) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const showGrammarlyWarning =
|
const showGrammarlyWarning =
|
||||||
!hasDismissedGrammarlyWarning &&
|
!hasDismissedGrammarlyWarning && grammarly && newSourceEditor
|
||||||
grammarly &&
|
|
||||||
newSourceEditor &&
|
|
||||||
!showRichText
|
|
||||||
|
|
||||||
let timeoutID: Nullable<number>
|
let timeoutID: Nullable<number>
|
||||||
|
|
||||||
|
@ -41,13 +37,7 @@ export default function GrammarlyWarning({ delay }: GrammarlyWarningProps) {
|
||||||
clearTimeout(timeoutID)
|
clearTimeout(timeoutID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [
|
}, [grammarly, hasDismissedGrammarlyWarning, newSourceEditor, delay])
|
||||||
grammarly,
|
|
||||||
hasDismissedGrammarlyWarning,
|
|
||||||
newSourceEditor,
|
|
||||||
showRichText,
|
|
||||||
delay,
|
|
||||||
])
|
|
||||||
|
|
||||||
const handleClose = useCallback(() => {
|
const handleClose = useCallback(() => {
|
||||||
setShow(false)
|
setShow(false)
|
||||||
|
|
|
@ -106,7 +106,7 @@ export class EditorFacade extends EventEmitter {
|
||||||
// as new transactions.
|
// as new transactions.
|
||||||
// This is a broad immitation of helper functions supplied in
|
// This is a broad immitation of helper functions supplied in
|
||||||
// the sharejs library. (See vendor/libs/sharejs, in particular
|
// the sharejs library. (See vendor/libs/sharejs, in particular
|
||||||
// the 'attach_cm' and 'attach_ace' helpers)
|
// the 'attach_ace' helper)
|
||||||
attachShareJs(shareDoc: ShareDoc, maxDocLength?: number) {
|
attachShareJs(shareDoc: ShareDoc, maxDocLength?: number) {
|
||||||
this.shareDoc = shareDoc
|
this.shareDoc = shareDoc
|
||||||
this.maxDocLength = maxDocLength
|
this.maxDocLength = maxDocLength
|
||||||
|
|
|
@ -37,6 +37,7 @@ import './ide/clone/index'
|
||||||
import './ide/file-view/index'
|
import './ide/file-view/index'
|
||||||
import './ide/hotkeys/index'
|
import './ide/hotkeys/index'
|
||||||
import './ide/wordcount/index'
|
import './ide/wordcount/index'
|
||||||
|
import './ide/toolbar/index'
|
||||||
import './ide/directives/layout'
|
import './ide/directives/layout'
|
||||||
import './ide/directives/validFile'
|
import './ide/directives/validFile'
|
||||||
import './ide/directives/verticalResizablePanes'
|
import './ide/directives/verticalResizablePanes'
|
||||||
|
|
|
@ -85,7 +85,6 @@ export default Document = (function () {
|
||||||
this.joined = false
|
this.joined = false
|
||||||
this.wantToBeJoined = false
|
this.wantToBeJoined = false
|
||||||
this._checkAceConsistency = () => this._checkConsistency(this.ace)
|
this._checkAceConsistency = () => this._checkConsistency(this.ace)
|
||||||
this._checkCMConsistency = () => this._checkConsistency(this.cm)
|
|
||||||
this._checkCM6Consistency = () => this._checkConsistency(this.cm6)
|
this._checkCM6Consistency = () => this._checkConsistency(this.cm6)
|
||||||
this._bindToEditorEvents()
|
this._bindToEditorEvents()
|
||||||
this._bindToSocketEvents()
|
this._bindToSocketEvents()
|
||||||
|
@ -96,8 +95,6 @@ export default Document = (function () {
|
||||||
return 'ace'
|
return 'ace'
|
||||||
} else if (this.cm6) {
|
} else if (this.cm6) {
|
||||||
return 'cm6'
|
return 'cm6'
|
||||||
} else if (this.cm) {
|
|
||||||
return 'cm-rich-text'
|
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -127,29 +124,6 @@ export default Document = (function () {
|
||||||
return this.ide.$scope.$emit('document:closed', this.doc)
|
return this.ide.$scope.$emit('document:closed', this.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
attachToCM(cm) {
|
|
||||||
this.cm = cm
|
|
||||||
if (this.doc != null) {
|
|
||||||
this.doc.attachToCM(this.cm)
|
|
||||||
}
|
|
||||||
if (this.cm != null) {
|
|
||||||
this.cm.on('change', this._checkCMConsistency)
|
|
||||||
}
|
|
||||||
return this.ide.$scope.$emit('document:opened', this.doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
detachFromCM() {
|
|
||||||
if (this.doc != null) {
|
|
||||||
this.doc.detachFromCM()
|
|
||||||
}
|
|
||||||
if (this.cm != null) {
|
|
||||||
this.cm.off('change', this._checkCMConsistency)
|
|
||||||
}
|
|
||||||
delete this.cm
|
|
||||||
this.clearChaosMonkey()
|
|
||||||
return this.ide.$scope.$emit('document:closed', this.doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
attachToCM6(cm6) {
|
attachToCM6(cm6) {
|
||||||
this.cm6 = cm6
|
this.cm6 = cm6
|
||||||
if (this.doc != null) {
|
if (this.doc != null) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import _ from 'lodash'
|
||||||
import Document from './Document'
|
import Document from './Document'
|
||||||
import './components/spellMenu'
|
import './components/spellMenu'
|
||||||
import './directives/aceEditor'
|
import './directives/aceEditor'
|
||||||
|
import './directives/formattingButtons'
|
||||||
import './directives/toggleSwitch'
|
import './directives/toggleSwitch'
|
||||||
import './controllers/SavingNotificationController'
|
import './controllers/SavingNotificationController'
|
||||||
import './controllers/CompileButton'
|
import './controllers/CompileButton'
|
||||||
|
@ -45,7 +46,6 @@ export default EditorManager = (function () {
|
||||||
trackChanges: false,
|
trackChanges: false,
|
||||||
wantTrackChanges: false,
|
wantTrackChanges: false,
|
||||||
docTooLongErrorShown: false,
|
docTooLongErrorShown: false,
|
||||||
showRichText: this.showRichText(),
|
|
||||||
showVisual: this.showVisual(),
|
showVisual: this.showVisual(),
|
||||||
newSourceEditor: this.newSourceEditor(),
|
newSourceEditor: this.newSourceEditor(),
|
||||||
showSymbolPalette: false,
|
showSymbolPalette: false,
|
||||||
|
@ -184,22 +184,7 @@ export default EditorManager = (function () {
|
||||||
return editorType
|
return editorType
|
||||||
}
|
}
|
||||||
|
|
||||||
showRichText() {
|
|
||||||
if (getMeta('ol-richTextVariant') === 'cm6') {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
this.localStorage(`editor.mode.${this.$scope.project_id}`) ===
|
|
||||||
'rich-text'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
showVisual() {
|
showVisual() {
|
||||||
if (getMeta('ol-richTextVariant') !== 'cm6') {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
this.localStorage(`editor.mode.${this.$scope.project_id}`) ===
|
this.localStorage(`editor.mode.${this.$scope.project_id}`) ===
|
||||||
'rich-text'
|
'rich-text'
|
||||||
|
|
|
@ -366,19 +366,6 @@ export default ShareJsDoc = (function () {
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
attachToCM(cm) {
|
|
||||||
this._attachToEditor('CM', cm, () => {
|
|
||||||
this._doc.attach_cm(cm, window.maxDocLength)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
detachFromCM() {
|
|
||||||
this._maybeDetachEditorWatchdogManager()
|
|
||||||
return typeof this._doc.detach_cm === 'function'
|
|
||||||
? this._doc.detach_cm()
|
|
||||||
: undefined
|
|
||||||
} // If we're waiting for the project to join, try again in 0.5 seconds
|
|
||||||
|
|
||||||
attachToCM6(cm6) {
|
attachToCM6(cm6) {
|
||||||
this._attachToEditor('CM6', cm6, () => {
|
this._attachToEditor('CM6', cm6, () => {
|
||||||
cm6.attachShareJs(this._doc, window.maxDocLength)
|
cm6.attachShareJs(this._doc, window.maxDocLength)
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import App from '../../../base'
|
||||||
|
|
||||||
|
export default App.directive('formattingButtons', () => ({
|
||||||
|
scope: {
|
||||||
|
buttons: '=',
|
||||||
|
opening: '=',
|
||||||
|
isFullscreenEditor: '=',
|
||||||
|
},
|
||||||
|
|
||||||
|
link(scope, element, attrs) {
|
||||||
|
scope.showMore = false
|
||||||
|
scope.shownButtons = scope.buttons
|
||||||
|
scope.overflowedButtons = []
|
||||||
|
},
|
||||||
|
|
||||||
|
templateUrl: 'formattingButtonsTpl',
|
||||||
|
}))
|
|
@ -285,8 +285,7 @@ export default App.controller(
|
||||||
function updateScrollbar() {
|
function updateScrollbar() {
|
||||||
if (
|
if (
|
||||||
scrollbar.isVisible &&
|
scrollbar.isVisible &&
|
||||||
ide.$scope.reviewPanel.subView === $scope.SubViews.CUR_FILE &&
|
ide.$scope.reviewPanel.subView === $scope.SubViews.CUR_FILE
|
||||||
!$scope.editor.showRichText
|
|
||||||
) {
|
) {
|
||||||
return $reviewPanelEl.css('right', `${scrollbar.scrollbarWidth}px`)
|
return $reviewPanelEl.css('right', `${scrollbar.scrollbarWidth}px`)
|
||||||
} else {
|
} else {
|
||||||
|
@ -554,13 +553,10 @@ export default App.controller(
|
||||||
const doc_id = $scope.editor.open_doc_id
|
const doc_id = $scope.editor.open_doc_id
|
||||||
const entries = updateEntries(doc_id)
|
const entries = updateEntries(doc_id)
|
||||||
|
|
||||||
// For now, not worrying about entry panels for rich text
|
|
||||||
if (!$scope.editor.showRichText) {
|
|
||||||
$scope.$broadcast('review-panel:recalculate-screen-positions')
|
$scope.$broadcast('review-panel:recalculate-screen-positions')
|
||||||
dispatchReviewPanelEvent('recalculate-screen-positions', entries)
|
dispatchReviewPanelEvent('recalculate-screen-positions', entries)
|
||||||
|
|
||||||
return ide.$scope.$broadcast('review-panel:layout')
|
return ide.$scope.$broadcast('review-panel:layout')
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
$scope.$on('editor:track-changes:visibility_changed', () =>
|
$scope.$on('editor:track-changes:visibility_changed', () =>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import App from '../../base'
|
||||||
|
|
||||||
|
App.controller('EditorLoaderController', function ($scope, localStorage) {
|
||||||
|
$scope.$watch('editor.showVisual', function (val) {
|
||||||
|
localStorage(
|
||||||
|
`editor.mode.${$scope.project_id}`,
|
||||||
|
val === true ? 'rich-text' : 'source'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
$scope.$watch('editor.newSourceEditor', function (val) {
|
||||||
|
localStorage(
|
||||||
|
`editor.source_editor.${$scope.project_id}`,
|
||||||
|
val === true ? 'cm6' : 'ace'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,19 @@
|
||||||
|
import App from '../../base'
|
||||||
|
import importOverleafModules from '../../../macros/import-overleaf-module.macro'
|
||||||
|
|
||||||
|
const eModules = importOverleafModules('editorToolbarButtons')
|
||||||
|
const editorToolbarButtons = eModules.map(item => item.import.default)
|
||||||
|
|
||||||
|
export default App.controller('EditorToolbarController', ($scope, ide) => {
|
||||||
|
const editorButtons = []
|
||||||
|
|
||||||
|
for (const editorToolbarButton of editorToolbarButtons) {
|
||||||
|
const button = editorToolbarButton.button($scope, ide)
|
||||||
|
|
||||||
|
if (editorToolbarButton.source) {
|
||||||
|
editorButtons.push(button)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.editorButtons = editorButtons
|
||||||
|
})
|
2
services/web/frontend/js/ide/toolbar/index.js
Normal file
2
services/web/frontend/js/ide/toolbar/index.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import './EditorLoaderController'
|
||||||
|
import './EditorToolbarController'
|
114
services/web/frontend/js/vendor/libs/sharejs.js
vendored
114
services/web/frontend/js/vendor/libs/sharejs.js
vendored
|
@ -1584,119 +1584,5 @@ define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// This is some utility code to connect a CodeMirror editor
|
|
||||||
// to a sharejs document.
|
|
||||||
// It is heavily inspired from the Ace editor hook.
|
|
||||||
|
|
||||||
// Convert a CodeMirror delta into an op understood by share.js
|
|
||||||
var applyCMToShareJS = function applyCMToShareJS(editorDoc, delta, doc, fromUndo) {
|
|
||||||
// CodeMirror deltas give a text replacement.
|
|
||||||
// I tuned this operation a little bit, for speed.
|
|
||||||
var startPos = 0; // Get character position from # of chars in each line.
|
|
||||||
var i = 0; // i goes through all lines.
|
|
||||||
// Compute the position from the shareJS snapshot because we are in the CodeMirror
|
|
||||||
// change event, where the change has already been applied to the editorDoc
|
|
||||||
var docLines = doc.snapshot.split('\n', delta.from.line) // only split the document as far as we need to
|
|
||||||
while (i < delta.from.line) {
|
|
||||||
startPos += docLines[i].length + 1; // Add 1 for '\n'
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
startPos += delta.from.ch;
|
|
||||||
|
|
||||||
// NOTE: Keep in sync with EditorWatchdogManager.
|
|
||||||
if (delta.removed) {
|
|
||||||
doc.del(startPos, delta.removed.join('\n').length, fromUndo);
|
|
||||||
}
|
|
||||||
if (delta.text) {
|
|
||||||
return doc.insert(startPos, delta.text.join('\n'), fromUndo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Attach a CodeMirror editor to the document. The editor's contents are replaced
|
|
||||||
// with the document's contents.
|
|
||||||
// NOTE: When upgrading CM, make sure to check for new special cases of
|
|
||||||
// origin prefixes as documented for `doc.setSelection`. We are using
|
|
||||||
// a custom `origin: 'remote'` which may conflict.
|
|
||||||
// Perma link of the docs at the time of writing this note:
|
|
||||||
// https://web.archive.org/web/20201029163528/https://codemirror.net/doc/manual.html#selection_origin
|
|
||||||
window.sharejs.extendDoc('attach_cm', function (editor, maxDocLength) {
|
|
||||||
if (!this.provides.text) {
|
|
||||||
throw new Error('Only text documents can be attached to CodeMirror2');
|
|
||||||
}
|
|
||||||
|
|
||||||
var sharedoc = this;
|
|
||||||
var editorDoc = editor.getDoc();
|
|
||||||
|
|
||||||
function check() {
|
|
||||||
return window.setTimeout(function () {
|
|
||||||
var editorText = editor.getValue();
|
|
||||||
var otText = sharedoc.getText();
|
|
||||||
|
|
||||||
if (editorText !== otText) {
|
|
||||||
sharedoc.emit('error','Text does not match in CodeMirror')
|
|
||||||
console.error('Text does not match!');
|
|
||||||
console.error('editor: ' + editorText);
|
|
||||||
return console.error('ot: ' + otText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Removed editor.setValue here as it would cause recursive loops if
|
|
||||||
// consistency check failed - because setting the value would trigger
|
|
||||||
// the change event
|
|
||||||
, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
onDelete(0, editor.getValue());
|
|
||||||
onInsert(0, sharedoc.getText());
|
|
||||||
|
|
||||||
check();
|
|
||||||
|
|
||||||
// Listen for edits in CodeMirror.
|
|
||||||
function editorListener(ed, change) {
|
|
||||||
if (change.origin === 'remote') {
|
|
||||||
// this change has been injected via sharejs
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (maxDocLength != null && editorDoc.getValue().length >= maxDocLength) {
|
|
||||||
sharedoc.emit('error', new Error('document length is greater than maxDocLength'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var fromUndo = (change.origin === 'undo')
|
|
||||||
applyCMToShareJS(editorDoc, change, sharedoc, fromUndo);
|
|
||||||
return check();
|
|
||||||
};
|
|
||||||
|
|
||||||
editorDoc.on('change', editorListener);
|
|
||||||
|
|
||||||
function onInsert(pos, text) {
|
|
||||||
// All the primitives we need are already in CM's API.
|
|
||||||
// call signature: editor.replaceRange(text, from, to, origin)
|
|
||||||
editor.replaceRange(text, editor.posFromIndex(pos), undefined, 'remote');
|
|
||||||
// Clear CM's undo/redo history on remote edit. This prevents issues where
|
|
||||||
// a user can accidentally remove another user's edits
|
|
||||||
editor.clearHistory();
|
|
||||||
return check();
|
|
||||||
};
|
|
||||||
|
|
||||||
function onDelete(pos, text) {
|
|
||||||
var from = editor.posFromIndex(pos);
|
|
||||||
var to = editor.posFromIndex(pos + text.length);
|
|
||||||
editor.replaceRange('', from, to, 'remote');
|
|
||||||
// Clear CM's undo/redo history on remote edit. This prevents issues where
|
|
||||||
// a user can accidentally remove another user's edits
|
|
||||||
editor.clearHistory()
|
|
||||||
return check();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.on('insert', onInsert);
|
|
||||||
this.on('delete', onDelete);
|
|
||||||
|
|
||||||
this.detach_cm = function () {
|
|
||||||
this.removeListener('insert', onInsert);
|
|
||||||
this.removeListener('delete', onDelete);
|
|
||||||
editorDoc.off('change', editorListener);
|
|
||||||
return delete this.detach_cm;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return window.sharejs;
|
return window.sharejs;
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { ScopeDecorator } from './decorators/scope'
|
||||||
import { useLocalCompileContext } from '../js/shared/context/local-compile-context'
|
import { useLocalCompileContext } from '../js/shared/context/local-compile-context'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { PdfPreviewMessages } from '../js/features/pdf-preview/components/pdf-preview-messages'
|
import { PdfPreviewMessages } from '../js/features/pdf-preview/components/pdf-preview-messages'
|
||||||
import { useScope } from './hooks/use-scope'
|
|
||||||
import CompileTimeWarning from '../js/features/pdf-preview/components/compile-time-warning'
|
import CompileTimeWarning from '../js/features/pdf-preview/components/compile-time-warning'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -18,12 +17,6 @@ export const Dismissible = () => {
|
||||||
setShowCompileTimeWarning(true)
|
setShowCompileTimeWarning(true)
|
||||||
}, [setShowCompileTimeWarning])
|
}, [setShowCompileTimeWarning])
|
||||||
|
|
||||||
useScope({
|
|
||||||
editor: {
|
|
||||||
showRichText: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: 800, position: 'relative' }}>
|
<div style={{ width: 800, position: 'relative' }}>
|
||||||
<PdfPreviewMessages>
|
<PdfPreviewMessages>
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
@import './editor/online-users.less';
|
@import './editor/online-users.less';
|
||||||
@import './editor/hotkeys.less';
|
@import './editor/hotkeys.less';
|
||||||
@import './editor/review-panel.less';
|
@import './editor/review-panel.less';
|
||||||
@import './editor/rich-text.less';
|
|
||||||
@import './editor/publish-modal.less';
|
@import './editor/publish-modal.less';
|
||||||
@import './editor/outline.less';
|
@import './editor/outline.less';
|
||||||
@import './editor/logs.less';
|
@import './editor/logs.less';
|
||||||
|
@ -93,8 +92,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#editor,
|
#editor {
|
||||||
#editor-rich-text {
|
|
||||||
.full-size;
|
.full-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -858,12 +858,6 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#editor-rich-text {
|
|
||||||
.rp-size-expanded & {
|
|
||||||
right: @review-panel-width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rp-unsupported-msg-wrapper {
|
.rp-unsupported-msg-wrapper {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
|
|
|
@ -1,254 +0,0 @@
|
||||||
@rt-font-family-serif: 'Palatino Linotype', 'Book Antiqua', Palatino, serif;
|
|
||||||
@rt-line-padding: 8%;
|
|
||||||
|
|
||||||
.rich-text .CodeMirror {
|
|
||||||
font-family: @rt-font-family-serif;
|
|
||||||
font-size: 1.15em;
|
|
||||||
|
|
||||||
pre {
|
|
||||||
font-family: @rt-font-family-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-line {
|
|
||||||
// Add horizontal padding, to emulate a manuscript more closely
|
|
||||||
padding: 0 @rt-line-padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-linenumber {
|
|
||||||
font-size: 0.8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Change prefix away from wl- ?
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
.preamble h1 {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 2em;
|
|
||||||
color: @text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preamble ul.authors {
|
|
||||||
margin-left: 0;
|
|
||||||
padding-left: 0;
|
|
||||||
list-style: none;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preamble ul.authors li {
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
// wl-indent-X is used to add extra left padding to nested itemize/enumerate
|
|
||||||
// environments, so that the inner list appears more indented than the outer
|
|
||||||
.wl-indent-0 {
|
|
||||||
padding-left: calc(~'2.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-indent-1 {
|
|
||||||
padding-left: calc(~'3.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-indent-2 {
|
|
||||||
padding-left: calc(~'4.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-indent-3 {
|
|
||||||
padding-left: calc(~'5.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-indent-4 {
|
|
||||||
padding-left: calc(~'6.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wl-indent-env-X is used to add extra left padding to empty nested itemize/
|
|
||||||
// enumerate environments
|
|
||||||
.wl-indent-env-0 {
|
|
||||||
padding-left: calc(~'4px + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-indent-env-1 {
|
|
||||||
padding-left: calc(~'1.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-indent-env-2 {
|
|
||||||
padding-left: calc(~'2.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-indent-env-3 {
|
|
||||||
padding-left: calc(~'3.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-indent-env-4 {
|
|
||||||
padding-left: calc(~'4.5em + @{rt-line-padding}') !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-enumerate-item-open {
|
|
||||||
text-align: right;
|
|
||||||
width: 1.5em;
|
|
||||||
display: inline-block;
|
|
||||||
padding-right: 0.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-item-open {
|
|
||||||
text-align: right;
|
|
||||||
width: 1.5em;
|
|
||||||
display: inline-block;
|
|
||||||
padding-right: 0.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-input {
|
|
||||||
font-style: oblique;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
.wl-abstract-open,
|
|
||||||
.wl-abstract-close {
|
|
||||||
border-top: 1px solid #999;
|
|
||||||
font-size: large;
|
|
||||||
font-weight: bold;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-figure {
|
|
||||||
max-height: 120px;
|
|
||||||
width: auto;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-figure-wrap {
|
|
||||||
padding: 10px 0;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
box-shadow: 1.3px 2px 2px #dfdfdf;
|
|
||||||
width: 96%;
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-figure-caption {
|
|
||||||
padding: 3px 0 4px;
|
|
||||||
font-size: small;
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
.wl-chapter,
|
|
||||||
.wl-chapter-open,
|
|
||||||
.wl-chapter-close {
|
|
||||||
font-size: 2.2em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-chapter-open,
|
|
||||||
.wl-chapter-close {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
.wl-section,
|
|
||||||
.wl-section-open,
|
|
||||||
.wl-section-close {
|
|
||||||
font-size: 1.8em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-section-open,
|
|
||||||
.wl-section-close {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
.wl-subsection,
|
|
||||||
.wl-subsection-open,
|
|
||||||
.wl-subsection-close {
|
|
||||||
font-size: 1.5em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-subsection-open,
|
|
||||||
.wl-subsection-close {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
.wl-subsubsection,
|
|
||||||
.wl-subsubsection-open,
|
|
||||||
.wl-subsubsection-close {
|
|
||||||
font-size: 1.1em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-subsubsection-open,
|
|
||||||
.wl-subsubsection-close {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
.wl-textbf {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-textbf-open {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-textbf-close {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-label-bracket {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-label-open,
|
|
||||||
.wl-input-link {
|
|
||||||
.wl-icon {
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 2px;
|
|
||||||
vertical-align: middle;
|
|
||||||
// @include wl-icon-size(inherit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-img-default {
|
|
||||||
width: 0.9em;
|
|
||||||
padding: 0 1px 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-label-close {
|
|
||||||
background-color: #f7f7f9;
|
|
||||||
border: 1px solid #e1e1e8;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: small;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
.wl-textit {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-textit-open {
|
|
||||||
font-style: italic;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wl-textit-close {
|
|
||||||
font-style: italic;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spelling-error {
|
|
||||||
background-image: url(../../../../public/img/spellcheck-underline.png);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
background-position: bottom;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@
|
||||||
@import 'core/ol-ieee-variables.less';
|
@import 'core/ol-ieee-variables.less';
|
||||||
|
|
||||||
@is-overleaf-light: false;
|
@is-overleaf-light: false;
|
||||||
@show-rich-text: true;
|
|
||||||
|
|
||||||
@ieee-wedge: 30px;
|
@ieee-wedge: 30px;
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,3 @@
|
||||||
@import 'core/ol-light-variables.less';
|
@import 'core/ol-light-variables.less';
|
||||||
|
|
||||||
@is-overleaf-light: true;
|
@is-overleaf-light: true;
|
||||||
@show-rich-text: true;
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
@import 'variables/themes/ieee.less';
|
@import 'variables/themes/ieee.less';
|
||||||
|
|
||||||
@is-overleaf-light: false;
|
@is-overleaf-light: false;
|
||||||
@show-rich-text: true;
|
|
||||||
|
|
||||||
@ieee-wedge: 30px;
|
@ieee-wedge: 30px;
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,3 @@
|
||||||
@import 'variables/themes/light.less';
|
@import 'variables/themes/light.less';
|
||||||
|
|
||||||
@is-overleaf-light: true;
|
@is-overleaf-light: true;
|
||||||
@show-rich-text: true;
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
@import (less) '../fonts/material-symbols.css';
|
@import (less) '../fonts/material-symbols.css';
|
||||||
|
|
||||||
@is-overleaf-light: false;
|
@is-overleaf-light: false;
|
||||||
@show-rich-text: true;
|
|
||||||
@is-new-css: true;
|
@is-new-css: true;
|
||||||
|
|
||||||
// Core variables and mixins
|
// Core variables and mixins
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
@import (less) '../fonts/material-symbols.css';
|
@import (less) '../fonts/material-symbols.css';
|
||||||
|
|
||||||
@is-overleaf-light: false;
|
@is-overleaf-light: false;
|
||||||
@show-rich-text: true;
|
|
||||||
@is-new-css: false;
|
@is-new-css: false;
|
||||||
|
|
||||||
// Core variables and mixins
|
// Core variables and mixins
|
||||||
|
|
|
@ -146,7 +146,6 @@
|
||||||
"chartjs-adapter-moment": "^1.0.1",
|
"chartjs-adapter-moment": "^1.0.1",
|
||||||
"chartjs-plugin-datalabels": "^2.2.0",
|
"chartjs-plugin-datalabels": "^2.2.0",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"codemirror": "~5.33.0",
|
|
||||||
"connect-redis": "^6.1.3",
|
"connect-redis": "^6.1.3",
|
||||||
"content-disposition": "^0.5.0",
|
"content-disposition": "^0.5.0",
|
||||||
"contentful": "^6.1.1",
|
"contentful": "^6.1.1",
|
||||||
|
|
|
@ -104,27 +104,6 @@ describe('<GrammarlyWarning />', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('does not show warning when user have rich text as their preference', async function () {
|
|
||||||
grammarlyStub.returns(true)
|
|
||||||
|
|
||||||
renderWithEditorContext(<GrammarlyWarning delay={100} />, {
|
|
||||||
scope: {
|
|
||||||
editor: {
|
|
||||||
newSourceEditor: true,
|
|
||||||
showRichText: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(
|
|
||||||
screen.queryByText(
|
|
||||||
'A browser extension, for example Grammarly, may be slowing down Overleaf.'
|
|
||||||
)
|
|
||||||
).to.not.exist
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('hides warning if close button is pressed', async function () {
|
it('hides warning if close button is pressed', async function () {
|
||||||
grammarlyStub.returns(true)
|
grammarlyStub.returns(true)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue