mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-17 01:37:43 +00:00
Add types (#8154)
GitOrigin-RevId: 41ee6b6873a01fbfedc41a884b9e3ebee47fc08f
This commit is contained in:
parent
c138e43b64
commit
910e07ca1c
19 changed files with 188 additions and 41 deletions
87
package-lock.json
generated
87
package-lock.json
generated
|
@ -5,6 +5,7 @@
|
|||
"packages": {
|
||||
"": {
|
||||
"name": "overleaf",
|
||||
"hasInstallScript": true,
|
||||
"workspaces": [
|
||||
"libraries/*",
|
||||
"services/analytics",
|
||||
|
@ -5923,6 +5924,12 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz",
|
||||
"integrity": "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg=="
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz",
|
||||
|
@ -35046,7 +35053,7 @@
|
|||
"jsonwebtoken": "^8.5.1",
|
||||
"ldapjs": "^0.7.1",
|
||||
"lodash": "^4.17.19",
|
||||
"lru-cache": "^6.0.0",
|
||||
"lru-cache": "^7.10.1",
|
||||
"mailchimp-api-v3": "^1.12.0",
|
||||
"marked": "^0.3.5",
|
||||
"match-sorter": "^6.2.0",
|
||||
|
@ -35133,6 +35140,7 @@
|
|||
"@types/react-bootstrap": "^0.32.29",
|
||||
"@types/react-dom": "^17.0.13",
|
||||
"@types/sinon-chai": "^3.2.8",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.1",
|
||||
"@typescript-eslint/parser": "^5.3.1",
|
||||
"acorn": "^7.1.1",
|
||||
|
@ -35571,6 +35579,18 @@
|
|||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"services/web/node_modules/css-loader/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"services/web/node_modules/css-loader/node_modules/semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
|
@ -36088,14 +36108,11 @@
|
|||
"dev": true
|
||||
},
|
||||
"services/web/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"version": "7.10.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz",
|
||||
"integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"services/web/node_modules/marked": {
|
||||
|
@ -36522,6 +36539,18 @@
|
|||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"services/web/node_modules/postcss-loader/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"services/web/node_modules/postcss-loader/node_modules/semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
|
@ -37237,7 +37266,8 @@
|
|||
"services/web/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -42714,6 +42744,7 @@
|
|||
"@types/react-bootstrap": "^0.32.29",
|
||||
"@types/react-dom": "^17.0.13",
|
||||
"@types/sinon-chai": "^3.2.8",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.1",
|
||||
"@typescript-eslint/parser": "^5.3.1",
|
||||
"@uppy/core": "^1.15.0",
|
||||
|
@ -42818,7 +42849,7 @@
|
|||
"less-loader": "^10.2.0",
|
||||
"less-plugin-autoprefix": "^2.0.0",
|
||||
"lodash": "^4.17.19",
|
||||
"lru-cache": "^6.0.0",
|
||||
"lru-cache": "^7.10.1",
|
||||
"mailchimp-api-v3": "^1.12.0",
|
||||
"marked": "^0.3.5",
|
||||
"match-sorter": "^6.2.0",
|
||||
|
@ -43194,6 +43225,15 @@
|
|||
"semver": "^7.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
|
@ -43567,12 +43607,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
"version": "7.10.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz",
|
||||
"integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A=="
|
||||
},
|
||||
"marked": {
|
||||
"version": "0.3.19",
|
||||
|
@ -43855,6 +43892,15 @@
|
|||
"semver": "^7.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
|
@ -44345,7 +44391,8 @@
|
|||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -45528,6 +45575,12 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz",
|
||||
"integrity": "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg=="
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz",
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-this-alias": "off"
|
||||
"@typescript-eslint/no-this-alias": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off"
|
||||
},
|
||||
"overrides": [
|
||||
// NOTE: changing paths may require updating them in the Makefile too.
|
||||
|
|
|
@ -2,7 +2,7 @@ import getMeta from '../../utils/meta'
|
|||
import { IGNORED_MISSPELLINGS } from '../../ide/editor/directives/aceEditor/spell-check/IgnoredMisspellings'
|
||||
|
||||
export class IgnoredWords {
|
||||
public learnedWords: Set<string>
|
||||
public learnedWords!: Set<string>
|
||||
private ignoredMisspellings: Set<string>
|
||||
|
||||
constructor() {
|
||||
|
@ -16,21 +16,21 @@ export class IgnoredWords {
|
|||
window.dispatchEvent(new CustomEvent('learnedWords:reset'))
|
||||
}
|
||||
|
||||
add(wordText) {
|
||||
add(wordText: string) {
|
||||
this.learnedWords.add(wordText)
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('learnedWords:add', { detail: wordText })
|
||||
)
|
||||
}
|
||||
|
||||
remove(wordText) {
|
||||
remove(wordText: string) {
|
||||
this.learnedWords.delete(wordText)
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('learnedWords:remove', { detail: wordText })
|
||||
)
|
||||
}
|
||||
|
||||
has(wordText) {
|
||||
has(wordText: string) {
|
||||
return (
|
||||
this.ignoredMisspellings.has(wordText) || this.learnedWords.has(wordText)
|
||||
)
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
import _ from 'lodash'
|
||||
import localStorage from '../../infrastructure/local-storage'
|
||||
|
||||
function usePersistedState<T>(
|
||||
function usePersistedState<T = any>(
|
||||
key: string,
|
||||
defaultValue?: T,
|
||||
listen = false
|
||||
|
|
|
@ -18,13 +18,13 @@ import _ from 'lodash'
|
|||
export default function useScopeValueSetterOnly<T = any>(
|
||||
path: string, // dot '.' path of a property in the Angular scope.
|
||||
defaultValue?: T
|
||||
): [T, Dispatch<SetStateAction<T>>] {
|
||||
): [T | undefined, Dispatch<SetStateAction<T | undefined>>] {
|
||||
const { $scope } = useIdeContext()
|
||||
|
||||
const [value, setValue] = useState<T>(defaultValue)
|
||||
const [value, setValue] = useState<T | undefined>(defaultValue)
|
||||
|
||||
const scopeSetter = useCallback(
|
||||
(newValue: SetStateAction<T>) => {
|
||||
(newValue: SetStateAction<T | undefined>) => {
|
||||
setValue(val => {
|
||||
const actualNewValue = _.isFunction(newValue) ? newValue(val) : newValue
|
||||
$scope.$applyAsync(() => _.set($scope, path, actualNewValue))
|
||||
|
|
|
@ -24,7 +24,7 @@ export default function useScopeValue<T = any>(
|
|||
useEffect(() => {
|
||||
return $scope.$watch(
|
||||
path,
|
||||
newValue => {
|
||||
(newValue: T) => {
|
||||
setValue(() => {
|
||||
// NOTE: this is deliberately wrapped in a function,
|
||||
// to avoid calling setValue directly with a value that's a function
|
||||
|
|
|
@ -5,7 +5,9 @@ fetchMock.config.fallbackToNetwork = true
|
|||
/**
|
||||
* Run callback to mock fetch routes, call restore() when unmounted
|
||||
*/
|
||||
export default function useFetchMock(callback) {
|
||||
export default function useFetchMock(
|
||||
callback: (value: typeof fetchMock) => void
|
||||
) {
|
||||
useLayoutEffect(() => {
|
||||
callback(fetchMock)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useLayoutEffect, useRef } from 'react'
|
|||
* Merge properties with the scope object, for use in Storybook stories
|
||||
*/
|
||||
export const useScope = (scope: Record<string, unknown>) => {
|
||||
const scopeRef = useRef(null)
|
||||
const scopeRef = useRef<Record<string, unknown> | null>(null)
|
||||
if (scopeRef.current === null) {
|
||||
scopeRef.current = scope
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
"jsonwebtoken": "^8.5.1",
|
||||
"ldapjs": "^0.7.1",
|
||||
"lodash": "^4.17.19",
|
||||
"lru-cache": "^6.0.0",
|
||||
"lru-cache": "^7.10.1",
|
||||
"mailchimp-api-v3": "^1.12.0",
|
||||
"marked": "^0.3.5",
|
||||
"match-sorter": "^6.2.0",
|
||||
|
@ -218,6 +218,7 @@
|
|||
"@types/react-bootstrap": "^0.32.29",
|
||||
"@types/react-dom": "^17.0.13",
|
||||
"@types/sinon-chai": "^3.2.8",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.1",
|
||||
"@typescript-eslint/parser": "^5.3.1",
|
||||
"acorn": "^7.1.1",
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('<PdfLogsEntries/>', function () {
|
|||
},
|
||||
]
|
||||
|
||||
let props
|
||||
let props: Record<string, any>
|
||||
|
||||
beforeEach(function () {
|
||||
props = {
|
||||
|
|
|
@ -4,7 +4,7 @@ import PdfPreview from '../../../../frontend/js/features/pdf-preview/components/
|
|||
import { EditorProviders } from '../../helpers/editor-providers'
|
||||
import { mockScope } from './scope'
|
||||
|
||||
const storeAndFireEvent = (win, key, value) => {
|
||||
const storeAndFireEvent = (win: typeof window, key: string, value: unknown) => {
|
||||
localStorage.setItem(key, value)
|
||||
win.dispatchEvent(new StorageEvent('storage', { key }))
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ describe('<PdfPreview/>', function () {
|
|||
})
|
||||
|
||||
it('does not compile while compiling', function () {
|
||||
let compileResolve
|
||||
let compileResolve: (value?: unknown) => void
|
||||
let counter = 0
|
||||
|
||||
const promise = new Promise(resolve => {
|
||||
|
|
|
@ -25,15 +25,25 @@ const mockHighlights = [
|
|||
},
|
||||
]
|
||||
|
||||
const mockPosition = {
|
||||
type Position = {
|
||||
page: number
|
||||
offset: { top: number; left: number }
|
||||
pageSize: { height: number; width: number }
|
||||
}
|
||||
|
||||
const mockPosition: Position = {
|
||||
page: 1,
|
||||
offset: { top: 10, left: 10 },
|
||||
pageSize: { height: 500, width: 500 },
|
||||
}
|
||||
|
||||
const mockSelectedEntities = [{ type: 'doc' }]
|
||||
type Entity = {
|
||||
type: string
|
||||
}
|
||||
|
||||
const WithPosition = ({ mockPosition }) => {
|
||||
const mockSelectedEntities: Entity[] = [{ type: 'doc' }]
|
||||
|
||||
const WithPosition = ({ mockPosition }: { mockPosition: Position }) => {
|
||||
const { setPosition } = useCompileContext()
|
||||
|
||||
// mock PDF scroll position update
|
||||
|
@ -44,7 +54,11 @@ const WithPosition = ({ mockPosition }) => {
|
|||
return null
|
||||
}
|
||||
|
||||
const WithSelectedEntities = ({ mockSelectedEntities = [] }) => {
|
||||
const WithSelectedEntities = ({
|
||||
mockSelectedEntities = [],
|
||||
}: {
|
||||
mockSelectedEntities: Entity[]
|
||||
}) => {
|
||||
const { setSelectedEntities } = useFileTreeData()
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -210,10 +224,10 @@ describe('<PdfSynctexControls/>', function () {
|
|||
cy.wait('@sync-code').should(() => {
|
||||
const messages = sysendTestHelper
|
||||
.getAllBroacastMessages()
|
||||
.map(item => item.args[1])
|
||||
.map((item: any) => item.args[1])
|
||||
|
||||
const message = messages.find(
|
||||
message => message.event === 'action-setHighlights'
|
||||
(message: any) => message.event === 'action-setHighlights'
|
||||
)
|
||||
|
||||
// synctex is called locally and the result are broadcast for the detached tab
|
||||
|
|
|
@ -119,7 +119,7 @@ describe('usePersistedState', function () {
|
|||
expect(window.Storage.prototype.setItem).to.have.callCount(1)
|
||||
|
||||
const Test = () => {
|
||||
const [value, setValue] = usePersistedState(key)
|
||||
const [value, setValue] = usePersistedState<string>(key)
|
||||
|
||||
useEffect(() => {
|
||||
setValue(value => value + 'bar')
|
||||
|
|
5
services/web/types/annotation.ts
Normal file
5
services/web/types/annotation.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export type Annotation = {
|
||||
row: number
|
||||
type: 'info' | 'warning' | 'error'
|
||||
text: string
|
||||
}
|
33
services/web/types/change.ts
Normal file
33
services/web/types/change.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
export interface Operation {
|
||||
p: number
|
||||
}
|
||||
|
||||
export interface InsertOperation extends Operation {
|
||||
i: string
|
||||
t: string
|
||||
}
|
||||
|
||||
export interface ChangeOperation extends Operation {
|
||||
c: string
|
||||
t: string
|
||||
}
|
||||
|
||||
export interface DeleteOperation extends Operation {
|
||||
d: string
|
||||
}
|
||||
|
||||
export interface CommentOperation extends Operation {
|
||||
c: string
|
||||
}
|
||||
|
||||
export type AnyOperation =
|
||||
| InsertOperation
|
||||
| ChangeOperation
|
||||
| DeleteOperation
|
||||
| CommentOperation
|
||||
|
||||
export type Change<T extends AnyOperation = AnyOperation> = {
|
||||
id: string
|
||||
metadata?: string
|
||||
op: T
|
||||
}
|
32
services/web/types/current-doc.ts
Normal file
32
services/web/types/current-doc.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { EditorFacade } from '../modules/source-editor/frontend/js/extensions/realtime'
|
||||
import {
|
||||
AnyOperation,
|
||||
Change,
|
||||
ChangeOperation,
|
||||
CommentOperation,
|
||||
DeleteOperation,
|
||||
InsertOperation,
|
||||
} from './change'
|
||||
|
||||
export type CurrentDoc = {
|
||||
doc_id: string
|
||||
docName: string
|
||||
track_changes_as: string | null
|
||||
ranges: {
|
||||
changes: Change<InsertOperation | ChangeOperation | DeleteOperation>[]
|
||||
comments: Change<CommentOperation>[]
|
||||
resolvedThreadIds: Record<string, any>
|
||||
removeCommentId: (id: string) => void
|
||||
removeChangeIds: (ids: string[]) => void
|
||||
getChanges: (
|
||||
ids: string[]
|
||||
) => Change<InsertOperation | ChangeOperation | DeleteOperation>[]
|
||||
validate: (text: string) => void
|
||||
}
|
||||
attachToCM6: (editor: EditorFacade) => void
|
||||
detachFromCM6: () => void
|
||||
on: (eventName: string, listener: EventListener) => void
|
||||
off: (eventName: string) => void
|
||||
submitOp: (op: AnyOperation) => void
|
||||
getSnapshot: () => string
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { Doc } from './doc'
|
||||
import { FileRef } from './fileref'
|
||||
import { FileRef } from './file-ref'
|
||||
|
||||
export type Folder = {
|
||||
_id: string
|
||||
|
|
5
services/web/types/highlight.ts
Normal file
5
services/web/types/highlight.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export type Highlight = {
|
||||
cursor: { row: number; column: number }
|
||||
hue: string
|
||||
label: string
|
||||
}
|
Loading…
Add table
Reference in a new issue