Skip to content

Commit

Permalink
style: add & run eslint, prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
TeemuKoivisto committed Jul 28, 2022
1 parent 6656bb8 commit 6f7b58e
Show file tree
Hide file tree
Showing 377 changed files with 4,953 additions and 5,857 deletions.
32 changes: 32 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "eslint-plugin-import", "eslint-plugin-prettier"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
"env": {
"es6": true,
"node": true
},
"rules": {
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/explicit-member-accessibility": 0,
"@typescript-eslint/indent": 0,
"@typescript-eslint/member-delimiter-style": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-use-before-define": 0,
"@typescript-eslint/no-unused-vars": [
2,
{
"argsIgnorePattern": "^_"
}
],
"no-console": [
2,
{
"allow": ["warn", "error"]
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pnpm-lock.yaml
node_modules
build
.next
package.json
dist
tmp
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": false,
"tabWidth": 2,
"printWidth": 100,
"singleQuote": true,
"jsxBracketSameLine": true
}
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ Also during this time I have dabbled with SSR and Next.js so I added examples wh

In my SSR examples I load the editor in both client and server but without actually rendering the editor doc HTML and hydrating the page from it. I just use `useEffect` to set the state before painting which should look perfectly the same as server-side rendering the page. You could probably hack something together that would do just that but I don't really have time for it.

Also compared to the basic `example-app` server-side rendering the pages show an empty white frame before the actual app renders. Which to me is a bit weird (and also the `example-ssr-app` really messes up the loading of styles, haven't bothered to fix that). This is remedied with `example-nextjs-app` if you build the app with `yarn static` and then serve it: `yarn serve` (with however the atlassian editor still jumping around a little bit). Just something to keep in mind if you decide to use SSR.
Also compared to the basic `example-app` server-side rendering the pages show an empty white frame before the actual app renders. Which to me is a bit weird (and also the `example-ssr-app` really messes up the loading of styles, haven't bothered to fix that). This is remedied with `example-nextjs-app` if you build the app with `yarn static` and then serve it: `yarn serve` (with however the atlassian editor still jumping around a little bit). Just something to keep in mind if you decide to use SSR.

## Architecture

I think the majority of the code is pretty self-explanatory in the `minimal` and `full` examples. For the `atlassian` editor you kinda have to delve deep yourself into the original editor to figure out why things are what they are.

But the basic gist of it is, you need a custom interface (EditorPlugin) to add extra logic to the basic PM plugins (`./full/src/editor-plugins`). These are loaded alongside the EditorState and EditorView and include for example all the basic PM plugin logic (pluginKey, normal pmPlugins, nodeviews, typings) as well as possible API providers, extensions, portalProvider, toolbar components and so forth. However, since Atlassian editor uses a separate repository to store the editor schema I use also a separate folder for schema. This keeps things simpler but definitely not entirely modular.
But the basic gist of it is, you need a custom interface (EditorPlugin) to add extra logic to the basic PM plugins (`./full/src/editor-plugins`). These are loaded alongside the EditorState and EditorView and include for example all the basic PM plugin logic (pluginKey, normal pmPlugins, nodeviews, typings) as well as possible API providers, extensions, portalProvider, toolbar components and so forth. However, since Atlassian editor uses a separate repository to store the editor schema I use also a separate folder for schema. This keeps things simpler but definitely not entirely modular.

React components can hook up to the editor state by using EditorContext for watching either plugin changes or executing commands with editorViewProvider. Incase you want to use nodeViews as React components they use portalProvider to render themselves as portals which are updated inside each `dispatchTransaction` call to flush the changes only once (instead of updating them in each `update` call in each ReactNodeView separately).

Expand All @@ -47,17 +47,17 @@ When compiling the editors you should not include React or styled-components as

## Similar projects & resources

* https://github.com/dminkovsky/use-prosemirror
* https://github.com/hubgit/react-prosemirror
* https://gist.github.com/manigandham/65543a0bc2bf7006a487
- https://github.com/dminkovsky/use-prosemirror
- https://github.com/hubgit/react-prosemirror
- https://gist.github.com/manigandham/65543a0bc2bf7006a487

* https://github.com/bangle-io/bangle.dev
* https://github.com/remirror/remirror
* https://github.com/ueberdosis/tiptap
* https://github.com/nib-edit/Nib
- https://github.com/bangle-io/bangle.dev
- https://github.com/remirror/remirror
- https://github.com/ueberdosis/tiptap
- https://github.com/nib-edit/Nib

* https://bitbucket.org/atlassian/atlassian-frontend-mirror/src/master/editor/editor-core/
* https://gitlab.com/mpapp-public/manuscripts-manuscript-editor
* https://github.com/fiduswriter/fiduswriter
* https://gitlab.coko.foundation/wax/wax-prosemirror
* https://github.com/MO-Movia/licit
- https://bitbucket.org/atlassian/atlassian-frontend-mirror/src/master/editor/editor-core/
- https://gitlab.com/mpapp-public/manuscripts-manuscript-editor
- https://github.com/fiduswriter/fiduswriter
- https://gitlab.coko.foundation/wax/wax-prosemirror
- https://github.com/MO-Movia/licit
16 changes: 14 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
},
"homepage": "https://github.com/TeemuKoivisto/prosemirror-react-typescript-example#readme",
"scripts": {
"format": "prettier --write \"*.+(js|json|yml|yaml|ts|md|graphql|mdx)\" .",
"lint:fix": "eslint --ignore-path .gitignore --fix --ext .js,.cjs,.ts,.tsx .",
"build": "pnpm -r build",
"dev:editors": "concurrently 'pnpm --filter atlassian watch' 'pnpm --filter full watch' 'pnpm --filter full-v2 watch' 'pnpm --filter minimal watch'",
"dev:client": "pnpm --filter client-cra start",
Expand All @@ -24,6 +26,16 @@
"pnpm": "^7.0.0"
},
"devDependencies": {
"concurrently": "^7.2.2"
"concurrently": "^7.3.0",
"eslint": "8.20.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.7.1"
}
}
}
34 changes: 0 additions & 34 deletions packages/api-collab/.eslintrc.json

This file was deleted.

6 changes: 3 additions & 3 deletions packages/api-collab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ This project uses Yarn workspaces so you don't really have to install anything.

## Commands

* `yarn dev` starts a Nodemon process to restart the Node.js server on source file changes
* `yarn watch` starts the Rollup compiler and watches changes to the source files
* `yarn build` compiles the code as both CommonJS and ES module.
- `yarn dev` starts a Nodemon process to restart the Node.js server on source file changes
- `yarn watch` starts the Rollup compiler and watches changes to the source files
- `yarn build` compiles the code as both CommonJS and ES module.
8 changes: 2 additions & 6 deletions packages/api-collab/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ export default {
format: 'es',
},
],
external: [
...Object.keys(pkg.dependencies || {}),
],
plugins: [
typescript(),
],
external: [...Object.keys(pkg.dependencies || {})],
plugins: [typescript()],
}
6 changes: 4 additions & 2 deletions packages/api-collab/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const corsOptions: cors.CorsOptions = {
origin(origin, callback) {
callback(null, true)
},
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
}

app.use(cors(corsOptions))
Expand All @@ -21,7 +21,9 @@ app.use(express.json())

// By adding this route before morgan prevents it being logged which in production setting
// is annoying and pollutes the logs with gazillion "GET /health" lines
app.get('/health', (req: any, res: any) => { res.sendStatus(200) })
app.get('/health', (req: any, res: any) => {
res.sendStatus(200)
})

app.use(morgan('short', { stream: logStream }))

Expand Down
4 changes: 2 additions & 2 deletions packages/api-collab/src/common/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ if (process.env.NODE_ENV === undefined || process.env.NODE_ENV === 'local') {
require('dotenv').config()
}

function parseNodeEnv(NODE_ENV) : 'production' | 'local' {
function parseNodeEnv(NODE_ENV): 'production' | 'local' {
if (NODE_ENV === 'production') return 'production'
return 'local'
}
Expand All @@ -13,5 +13,5 @@ export const config = {
CORS_SAME_ORIGIN: process.env.CORS_SAME_ORIGIN || false,
LOG: {
LEVEL: process.env.LOG_LEVEL || 'info',
}
},
}
4 changes: 0 additions & 4 deletions packages/api-collab/src/common/error.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@

export interface IError extends Error {
statusCode?: number
}

export class CustomError extends Error implements IError {

statusCode: number

constructor(message: string, errorCode = 500) {
Expand All @@ -16,7 +14,6 @@ export class CustomError extends Error implements IError {
}

export class ValidationError extends Error implements IError {

readonly statusCode: number = 400

constructor(message: string) {
Expand All @@ -27,7 +24,6 @@ export class ValidationError extends Error implements IError {
}

export class DBError extends Error implements IError {

readonly statusCode: number = 500

constructor(message: string) {
Expand Down
2 changes: 1 addition & 1 deletion packages/api-collab/src/common/errorHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function errorHandler(err: IError, req: Request, res: Response, next: Nex
if (err) {
const statusCode = err.statusCode ? err.statusCode : 500
const message = statusCode === 500 ? 'Internal server error.' : 'Something went wrong.'
const body: { message: string, stack?: string } = { message }
const body: { message: string; stack?: string } = { message }
if (statusCode === 500) {
log.error('Handled internal server error:')
log.error(err)
Expand Down
15 changes: 6 additions & 9 deletions packages/api-collab/src/common/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@ import { config } from './config'
let logFormat
// Add colors in local environment
if (config.ENV === 'production') {
logFormat = winston.format.combine(
winston.format.json()
)
logFormat = winston.format.combine(winston.format.json())
} else {
logFormat = winston.format.combine(
winston.format.colorize(),
winston.format.simple(),
)
logFormat = winston.format.combine(winston.format.colorize(), winston.format.simple())
}

export const log: winston.Logger = winston.createLogger({
Expand All @@ -22,9 +17,11 @@ export const log: winston.Logger = winston.createLogger({
level: config.LOG.LEVEL,
}),
],
exitOnError: false
exitOnError: false,
})

export const logStream = {
write: (message: string) => { log.info(message) }
write: (message: string) => {
log.info(message)
},
}
12 changes: 7 additions & 5 deletions packages/api-collab/src/db/collab.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ type EditedDoc = {
}

class CollabDB {

editedDocs = new Map<string, EditedDoc>()
FILE = './collab.db.json'

Expand Down Expand Up @@ -58,14 +57,14 @@ class CollabDB {
if (!documentId) {
Array.from(this.editedDocs.entries()).forEach(([docId, doc]) => {
if (doc.users.includes(userId)) {
this.editedDocs.set(docId, { ...doc, users: doc.users.filter(id => id !== userId) })
this.editedDocs.set(docId, { ...doc, users: doc.users.filter((id) => id !== userId) })
}
})
this.write()
}
const doc = documentId && this.editedDocs.get(documentId)
if (doc) {
this.editedDocs.set(documentId, { ...doc, users: doc.users.filter(id => id !== userId) })
this.editedDocs.set(documentId, { ...doc, users: doc.users.filter((id) => id !== userId) })
this.write()
}
}
Expand All @@ -83,7 +82,10 @@ class CollabDB {
}

async read() {
const exists = await fs.access(this.FILE).then(() => true).catch(() => false)
const exists = await fs
.access(this.FILE)
.then(() => true)
.catch(() => false)
const data = exists ? await fs.readFile(this.FILE, 'utf-8') : undefined
let parsed: StoredData
try {
Expand All @@ -92,7 +94,7 @@ class CollabDB {
console.error(err)
exists && fs.unlink(this.FILE)
}
parsed?.editedDocs?.forEach(mapValue => {
parsed?.editedDocs?.forEach((mapValue) => {
this.editedDocs.set(mapValue[0], mapValue[1])
})
}
Expand Down
10 changes: 6 additions & 4 deletions packages/api-collab/src/db/doc.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ interface StoredData {
}

class DocDB {

docsMap: Map<string, IDBDocument> = new Map()
FILE = './doc.db.json'

Expand Down Expand Up @@ -43,7 +42,10 @@ class DocDB {
}

async read() {
const exists = await fs.access(this.FILE).then(() => true).catch(() => false)
const exists = await fs
.access(this.FILE)
.then(() => true)
.catch(() => false)
const data = exists ? await fs.readFile(this.FILE, 'utf-8') : undefined
let parsed: StoredData
try {
Expand All @@ -52,7 +54,7 @@ class DocDB {
console.error(err)
exists && fs.unlink(this.FILE)
}
parsed?.docsMap?.forEach(mapValue => {
parsed?.docsMap?.forEach((mapValue) => {
this.docsMap.set(mapValue[0], {
id: mapValue[0],
title: mapValue[1].title,
Expand All @@ -65,7 +67,7 @@ class DocDB {

write() {
const data: StoredData = {
docsMap: Array.from(this.docsMap.entries())
docsMap: Array.from(this.docsMap.entries()),
}
fs.writeFile(this.FILE, JSON.stringify(data))
}
Expand Down
Loading

0 comments on commit 6f7b58e

Please sign in to comment.