first commit

This commit is contained in:
2025-04-24 13:11:28 +08:00
commit ff9c54d5e4
5960 changed files with 834111 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
const ONE_MINUTE = 60 * 1000
const user = {
id: 'fake_user',
first_name: 'mortimer',
email: 'fake@example.com',
}
const user2 = {
id: 'another_fake_user',
first_name: 'leopold',
email: 'another_fake@example.com',
}
let nextMessageId = 1
export function generateMessages(count) {
const messages = []
let timestamp = new Date().getTime() // newest message goes first
for (let i = 0; i <= count; i++) {
const author = Math.random() > 0.5 ? user : user2
// modify the timestamp so the previous message has 70% chances to be within 5 minutes from
// the current one, for grouping purposes
timestamp -= (4.3 + Math.random()) * ONE_MINUTE
messages.push({
id: '' + nextMessageId++,
content: `message #${i}`,
user: author,
timestamp,
})
}
return messages
}

View File

@@ -0,0 +1,220 @@
import examplePdf from './storybook-example.pdf'
import { cloneDeep } from 'lodash'
export const dispatchDocChanged = () => {
window.dispatchEvent(
new CustomEvent('doc:changed', { detail: { doc_id: 'foo' } })
)
}
export const outputFiles = [
{
path: 'output.pdf',
build: '123',
url: '/build/output.pdf',
type: 'pdf',
},
{
path: 'output.bbl',
build: '123',
url: '/build/output.bbl',
type: 'bbl',
},
{
path: 'output.bib',
build: '123',
url: '/build/output.bib',
type: 'bib',
},
{
path: 'example.txt',
build: '123',
url: '/build/example.txt',
type: 'txt',
},
{
path: 'output.log',
build: '123',
url: '/build/output.log',
type: 'log',
},
{
path: 'output.blg',
build: '123',
url: '/build/output.blg',
type: 'blg',
},
]
export const mockCompile = (fetchMock, delay = 1000) =>
fetchMock.post(
'express:/project/:projectId/compile',
{
body: {
status: 'success',
clsiServerId: 'foo',
compileGroup: 'priority',
pdfDownloadDomain: '',
outputFiles: cloneDeep(outputFiles),
},
},
{ delay }
)
export const mockCompileError = (fetchMock, status = 'success', delay = 1000) =>
fetchMock.post(
'express:/project/:projectId/compile',
{
body: {
status,
clsiServerId: 'foo',
compileGroup: 'priority',
},
},
{ delay, overwriteRoutes: true }
)
export const mockCompileValidationIssues = (
fetchMock,
validationProblems,
delay = 1000
) =>
fetchMock.post(
'express:/project/:projectId/compile',
() => {
return {
body: {
status: 'validation-problems',
validationProblems,
clsiServerId: 'foo',
compileGroup: 'priority',
},
}
},
{ delay }
)
export const mockClearCache = fetchMock =>
fetchMock.delete('express:/project/:projectId/output', 204, {
delay: 1000,
})
export const mockBuildFile = fetchMock =>
fetchMock.get('express:/build/:file', (url, options, request) => {
const { pathname } = new URL(url, 'https://example.com')
switch (pathname) {
case '/build/output.blg':
return 'This is BibTeX, Version 4.0' // FIXME
case '/build/output.log':
return `
The LaTeX compiler output
* With a lot of details
Wrapped in an HTML <pre> element with
preformatted text which is to be presented exactly
as written in the HTML file
(whitespace included™)
The text is typically rendered using a non-proportional ("monospace") font.
LaTeX Font Info: External font \`cmex10' loaded for size
(Font) <7> on input line 18.
LaTeX Font Info: External font \`cmex10' loaded for size
(Font) <5> on input line 18.
! Undefined control sequence.
<recently read> \\Zlpha
main.tex, line 23
`
case '/build/output.pdf':
return new Promise(resolve => {
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', () => {
resolve({
status: 200,
headers: {
'Content-Length': xhr.getResponseHeader('Content-Length'),
'Content-Type': xhr.getResponseHeader('Content-Type'),
},
body: xhr.response,
})
})
xhr.open('GET', examplePdf)
xhr.responseType = 'arraybuffer'
xhr.send()
})
default:
console.log(pathname)
return 404
}
})
const mockHighlights = [
{
page: 1,
h: 85.03936,
v: 509.999878,
width: 441.921265,
height: 8.855677,
},
{
page: 1,
h: 85.03936,
v: 486.089539,
width: 441.921265,
height: 8.855677,
},
{
page: 1,
h: 85.03936,
v: 498.044708,
width: 441.921265,
height: 8.855677,
},
{
page: 1,
h: 85.03936,
v: 521.955078,
width: 441.921265,
height: 8.855677,
},
]
export const mockEventTracking = fetchMock =>
fetchMock.get('express:/event/:event', 204)
export const mockValidPdf = fetchMock =>
fetchMock.get('express:/build/output.pdf', (url, options, request) => {
return new Promise(resolve => {
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', () => {
resolve({
status: 200,
headers: {
'Content-Length': xhr.getResponseHeader('Content-Length'),
'Content-Type': xhr.getResponseHeader('Content-Type'),
'Accept-Ranges': 'bytes',
},
body: xhr.response,
})
})
xhr.open('GET', examplePdf)
xhr.responseType = 'arraybuffer'
xhr.send()
})
})
export const mockSynctex = fetchMock =>
fetchMock
.get('express:/project/:projectId/sync/code', () => {
return { pdf: cloneDeep(mockHighlights) }
})
.get('express:/project/:projectId/sync/pdf', () => {
return { code: [{ file: 'main.tex', line: 100 }] }
})

View File

@@ -0,0 +1,41 @@
export const contacts = [
// user with edited name
{
type: 'user',
email: 'test-user@example.com',
first_name: 'Test',
last_name: 'User',
name: 'Test User',
},
// user with default name (email prefix)
{
type: 'user',
email: 'test@example.com',
first_name: 'test',
},
// no last name
{
type: 'user',
first_name: 'Eratosthenes',
email: 'eratosthenes@example.com',
},
// more users
{
type: 'user',
first_name: 'Claudius',
last_name: 'Ptolemy',
email: 'ptolemy@example.com',
},
{
type: 'user',
first_name: 'Abd al-Rahman',
last_name: 'Al-Sufi',
email: 'al-sufi@example.com',
},
{
type: 'user',
first_name: 'Nicolaus',
last_name: 'Copernicus',
email: 'copernicus@example.com',
},
]

View File

@@ -0,0 +1,40 @@
export function mockDocument(text: string) {
return {
doc_id: 'story-doc',
getSnapshot: () => text,
hasBufferedOps: () => false,
}
}
export const document = {
tex: `\\documentclass{article}
% Language setting
% Replace \`english' with e.g. \`spanish' to change the document language
\\usepackage[english]{babel}
% Set page size and margins
% Replace \`letterpaper' with\`a4paper' for UK/EU standard size
\\usepackage[letterpaper,top=2cm,bottom=2cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}
% Useful packages
\\usepackage{amsmath}
\\usepackage{graphicx}
\\usepackage[colorlinks=true, allcolors=blue]{hyperref}
\\title{Your Paper}
\\author{You}
\\begin{document}
\\maketitle
\\begin{abstract}
Your abstract.
\\end{abstract}
\\section{Introduction}
Your introduction goes here! Simply start writing your document and use the Recompile button to view the updated PDF preview. Examples of commonly used commands and features are listed below, to help you get started.
Once you're familiar with the editor, you can find various project setting in the Overleaf menu, accessed via the button in the very top left of the editor. To view tutorials, user guides, and further documentation, please visit our \\href{https://www.overleaf.com/learn}{help library}, or head to our plans page to \\href{https://www.overleaf.com/user/subscription/plans}{choose your plan}.`,
}

View File

@@ -0,0 +1,44 @@
export const rootFolderBase = [
{
_id: '5e74f1a7ce17ae0041dfd054',
name: 'rootFolder',
folders: [
{
_id: '5f638e58b652df0026c5c8f5',
name: 'a folder',
folders: [
{
_id: '5f956f62700e19000177daa0',
name: 'sub folder',
folders: [],
fileRefs: [],
docs: [],
},
],
fileRefs: [
{ _id: '5cffb9d93da45d3995d05362', name: 'file-in-a-folder.pdf' },
],
docs: [
{ _id: '5f46786322d556004e72a555', name: 'doc-in-a-folder.tex' },
],
},
{
_id: '5f638e68b652df0026c5c8f6',
name: 'another folder',
folders: [],
fileRefs: [],
docs: [],
},
],
fileRefs: [{ _id: '5f11c78e0924770027412a67', name: 'univers.jpg' }],
docs: [
{ _id: '5e74f1a7ce17ae0041dfd056', name: 'main.tex' },
{ _id: '5f46789522d556004e72a556', name: 'perso.bib' },
{
_id: '5da532e29019e800015321c6',
name: 'zotero.bib',
linkedFileData: { provider: 'zotero' },
},
],
},
]

View File

@@ -0,0 +1,52 @@
const FILE_PER_FOLDER = 2
const DOC_PER_FOLDER = 3
const FOLDER_PER_FOLDER = 2
const MAX_DEPTH = 7
function fakeId() {
return Math.random().toString(16).replace(/0\./, 'random-test-id-')
}
function makeFileRefs(path) {
const fileRefs = []
for (let index = 0; index < FILE_PER_FOLDER; index++) {
fileRefs.push({ _id: fakeId(), name: `${path}-file-${index}.jpg` })
}
return fileRefs
}
function makeDocs(path) {
const docs = []
for (let index = 0; index < DOC_PER_FOLDER; index++) {
docs.push({ _id: fakeId(), name: `${path}-doc-${index}.tex` })
}
return docs
}
function makeFolders(path, depth = 0) {
const folders = []
for (let index = 0; index < FOLDER_PER_FOLDER; index++) {
const folderPath = `${path}-folder-${index}`
folders.push({
_id: fakeId(),
name: folderPath,
folders: depth < MAX_DEPTH ? makeFolders(folderPath, depth + 1) : [],
fileRefs: makeFileRefs(folderPath),
docs: makeDocs(folderPath),
})
}
return folders
}
export const rootFolderLimit = [
{
_id: fakeId(),
name: 'rootFolder',
folders: makeFolders('root'),
fileRefs: makeFileRefs('root'),
docs: makeDocs('root'),
},
]

View File

@@ -0,0 +1,48 @@
import { Project } from '../../../types/project'
export const project: Project = {
_id: '63e21c07946dd8c76505f85a',
name: 'A Project',
features: {
collaborators: -1, // unlimited
},
publicAccesLevel: 'private',
tokens: {
readOnly: 'ro-token',
readAndWrite: 'rw-token',
},
owner: {
_id: 'project-owner',
email: 'stories@overleaf.com',
},
members: [
{
_id: 'viewer-member',
type: 'user',
privileges: 'readOnly',
name: 'Viewer User',
email: 'viewer@example.com',
},
{
_id: 'author-member',
type: 'user',
privileges: 'readAndWrite',
name: 'Author User',
email: 'author@example.com',
},
],
invites: [
{
_id: 'test-invite-1',
privileges: 'readOnly',
name: 'Invited Viewer',
email: 'invited-viewer@example.com',
},
{
_id: 'test-invite-2',
privileges: 'readAndWrite',
name: 'Invited Author',
email: 'invited-author@example.com',
},
],
}