diff --git a/.eslintrc b/.eslintrc index b3edf6125..7fdd61584 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,6 +25,7 @@ ], "rules": { "eqeqeq": 2, + "curly": 2, "no-mixed-operators": "off", "no-useless-escape": "off", "@typescript-eslint/no-unused-vars": [ diff --git a/app/actions/definitions/collections.tsx b/app/actions/definitions/collections.tsx index ad17a3ba6..dae75f5a4 100644 --- a/app/actions/definitions/collections.tsx +++ b/app/actions/definitions/collections.tsx @@ -52,7 +52,9 @@ export const editCollection = createAction({ !!activeCollectionId && stores.policies.abilities(activeCollectionId).update, perform: ({ t, activeCollectionId }) => { - if (!activeCollectionId) return; + if (!activeCollectionId) { + return; + } stores.dialogs.openModal({ title: t("Edit collection"), diff --git a/app/actions/definitions/documents.tsx b/app/actions/definitions/documents.tsx index c69f26ebf..7dbb5a315 100644 --- a/app/actions/definitions/documents.tsx +++ b/app/actions/definitions/documents.tsx @@ -61,14 +61,18 @@ export const starDocument = createAction({ icon: , keywords: "favorite bookmark", visible: ({ activeDocumentId, stores }) => { - if (!activeDocumentId) return false; + if (!activeDocumentId) { + return false; + } const document = stores.documents.get(activeDocumentId); return ( !document?.isStarred && stores.policies.abilities(activeDocumentId).star ); }, perform: ({ activeDocumentId, stores }) => { - if (!activeDocumentId) return; + if (!activeDocumentId) { + return; + } const document = stores.documents.get(activeDocumentId); document?.star(); @@ -81,7 +85,9 @@ export const unstarDocument = createAction({ icon: , keywords: "unfavorite unbookmark", visible: ({ activeDocumentId, stores }) => { - if (!activeDocumentId) return false; + if (!activeDocumentId) { + return false; + } const document = stores.documents.get(activeDocumentId); return ( !!document?.isStarred && @@ -89,7 +95,9 @@ export const unstarDocument = createAction({ ); }, perform: ({ activeDocumentId, stores }) => { - if (!activeDocumentId) return; + if (!activeDocumentId) { + return; + } const document = stores.documents.get(activeDocumentId); document?.unstar(); @@ -105,7 +113,9 @@ export const downloadDocument = createAction({ visible: ({ activeDocumentId, stores }) => !!activeDocumentId && stores.policies.abilities(activeDocumentId).download, perform: ({ activeDocumentId, stores }) => { - if (!activeDocumentId) return; + if (!activeDocumentId) { + return; + } const document = stores.documents.get(activeDocumentId); document?.download(); @@ -121,7 +131,9 @@ export const duplicateDocument = createAction({ visible: ({ activeDocumentId, stores }) => !!activeDocumentId && stores.policies.abilities(activeDocumentId).update, perform: async ({ activeDocumentId, t, stores }) => { - if (!activeDocumentId) return; + if (!activeDocumentId) { + return; + } const document = stores.documents.get(activeDocumentId); invariant(document, "Document must exist"); @@ -189,7 +201,9 @@ export const pinDocumentToHome = createAction({ ); }, perform: async ({ activeDocumentId, location, t, stores }) => { - if (!activeDocumentId) return; + if (!activeDocumentId) { + return; + } const document = stores.documents.get(activeDocumentId); await document?.pin(); @@ -265,7 +279,9 @@ export const createTemplate = createAction({ icon: , keywords: "new create template", visible: ({ activeCollectionId, activeDocumentId, stores }) => { - if (!activeDocumentId) return false; + if (!activeDocumentId) { + return false; + } const document = stores.documents.get(activeDocumentId); return ( !!activeCollectionId && @@ -274,7 +290,9 @@ export const createTemplate = createAction({ ); }, perform: ({ activeDocumentId, stores, t, event }) => { - if (!activeDocumentId) return; + if (!activeDocumentId) { + return; + } event?.preventDefault(); event?.stopPropagation(); diff --git a/app/components/AuthenticatedLayout.tsx b/app/components/AuthenticatedLayout.tsx index 7330c5cf9..36219e605 100644 --- a/app/components/AuthenticatedLayout.tsx +++ b/app/components/AuthenticatedLayout.tsx @@ -55,9 +55,13 @@ class AuthenticatedLayout extends React.Component { goToNewDocument = () => { const { activeCollectionId } = this.props.ui; - if (!activeCollectionId) return; + if (!activeCollectionId) { + return; + } const can = this.props.policies.abilities(activeCollectionId); - if (!can.update) return; + if (!can.update) { + return; + } history.push(newDocumentPath(activeCollectionId)); }; @@ -65,7 +69,9 @@ class AuthenticatedLayout extends React.Component { const { auth } = this.props; const { user, team } = auth; const showSidebar = auth.authenticated && user && team; - if (auth.isSuspended) return ; + if (auth.isSuspended) { + return ; + } const sidebar = showSidebar ? ( diff --git a/app/components/ContextMenu/Template.tsx b/app/components/ContextMenu/Template.tsx index 9c10a490b..981b58690 100644 --- a/app/components/ContextMenu/Template.tsx +++ b/app/components/ContextMenu/Template.tsx @@ -72,13 +72,18 @@ export function filterTemplateItems(items: TMenuItem[]): TMenuItem[] { // this block literally just trims unnecessary separators filtered = filtered.reduce((acc, item, index) => { // trim separators from start / end - if (item.type === "separator" && index === 0) return acc; - if (item.type === "separator" && index === filtered.length - 1) return acc; + if (item.type === "separator" && index === 0) { + return acc; + } + if (item.type === "separator" && index === filtered.length - 1) { + return acc; + } // trim double separators looking ahead / behind const prev = filtered[index - 1]; - if (prev && prev.type === "separator" && item.type === "separator") + if (prev && prev.type === "separator" && item.type === "separator") { return acc; + } // otherwise, continue return [...acc, item]; diff --git a/app/components/HoverPreview.tsx b/app/components/HoverPreview.tsx index 51ffdb8fd..32fb8133d 100644 --- a/app/components/HoverPreview.tsx +++ b/app/components/HoverPreview.tsx @@ -28,7 +28,9 @@ function HoverPreviewInternal({ node, onClose }: Props) { const startCloseTimer = () => { stopOpenTimer(); timerClose.current = setTimeout(() => { - if (isVisible) setVisible(false); + if (isVisible) { + setVisible(false); + } onClose(); }, DELAY_CLOSE); }; diff --git a/app/components/HoverPreviewDocument.tsx b/app/components/HoverPreviewDocument.tsx index e87fc7e2e..453bb750f 100644 --- a/app/components/HoverPreviewDocument.tsx +++ b/app/components/HoverPreviewDocument.tsx @@ -21,7 +21,9 @@ function HoverPreviewDocument({ url, children }: Props) { } const document = slug ? documents.getByUrl(slug) : undefined; - if (!document) return null; + if (!document) { + return null; + } return ( <> diff --git a/app/components/InputSelect.tsx b/app/components/InputSelect.tsx index 0fc20adc9..a57bb3050 100644 --- a/app/components/InputSelect.tsx +++ b/app/components/InputSelect.tsx @@ -84,7 +84,9 @@ const InputSelect = (props: Props) => { ); React.useEffect(() => { - if (previousValue.current === select.selectedValue) return; + if (previousValue.current === select.selectedValue) { + return; + } previousValue.current = select.selectedValue; async function load() { diff --git a/app/components/PaginatedList.tsx b/app/components/PaginatedList.tsx index 73f00e1e0..040ca1b3d 100644 --- a/app/components/PaginatedList.tsx +++ b/app/components/PaginatedList.tsx @@ -70,7 +70,9 @@ class PaginatedList extends React.Component { }; fetchResults = async () => { - if (!this.props.fetch) return; + if (!this.props.fetch) { + return; + } this.isFetching = true; const limit = DEFAULT_PAGINATION_LIMIT; const results = await this.props.fetch({ @@ -94,7 +96,9 @@ class PaginatedList extends React.Component { @action loadMoreResults = async () => { // Don't paginate if there aren't more results or we’re currently fetching - if (!this.allowLoadMore || this.isFetching) return; + if (!this.allowLoadMore || this.isFetching) { + return; + } // If there are already cached results that we haven't yet rendered because // of lazy rendering then show another page. const leftToRender = this.props.items.length - this.renderCount; diff --git a/app/components/PathToDocument.tsx b/app/components/PathToDocument.tsx index 18cbf343b..915afc001 100644 --- a/app/components/PathToDocument.tsx +++ b/app/components/PathToDocument.tsx @@ -22,7 +22,9 @@ class PathToDocument extends React.Component { handleClick = async (ev: React.SyntheticEvent) => { ev.preventDefault(); const { document, result, onSuccess } = this.props; - if (!document) return; + if (!document) { + return; + } if (result.type === "document") { await document.move(result.collectionId, result.id); @@ -30,13 +32,17 @@ class PathToDocument extends React.Component { await document.move(result.collectionId); } - if (onSuccess) onSuccess(); + if (onSuccess) { + onSuccess(); + } }; render() { const { result, collection, document, ref, style } = this.props; const Component = document ? ResultWrapperLink : ResultWrapper; - if (!result) return
; + if (!result) { + return
; + } return ( // @ts-expect-error ts-migrate(2604) FIXME: JSX element type 'Component' does not have any con... Remove this comment to see the full error message diff --git a/app/components/ScrollToTop.ts b/app/components/ScrollToTop.ts index 9750a8f5e..d7638e9a2 100644 --- a/app/components/ScrollToTop.ts +++ b/app/components/ScrollToTop.ts @@ -12,13 +12,16 @@ export default function ScrollToTop({ children }: Props) { const previousLocationPathname = usePrevious(location.pathname); React.useEffect(() => { - if (location.pathname === previousLocationPathname) return; + if (location.pathname === previousLocationPathname) { + return; + } // exception for when entering or exiting document edit, scroll position should not reset if ( location.pathname.match(/\/edit\/?$/) || previousLocationPathname?.match(/\/edit\/?$/) - ) + ) { return; + } window.scrollTo(0, 0); }, [location.pathname, previousLocationPathname]); diff --git a/app/components/Scrollable.tsx b/app/components/Scrollable.tsx index 7ea9b136d..58ced4d09 100644 --- a/app/components/Scrollable.tsx +++ b/app/components/Scrollable.tsx @@ -21,7 +21,9 @@ function Scrollable( const { height } = useWindowSize(); const updateShadows = React.useCallback(() => { const c = (ref || fallbackRef).current; - if (!c) return; + if (!c) { + return; + } const scrollTop = c.scrollTop; const tsv = !!((shadow || topShadow) && scrollTop > 0); diff --git a/app/components/Sidebar/components/CollectionLink.tsx b/app/components/Sidebar/components/CollectionLink.tsx index ce8b8d27b..c942fc66c 100644 --- a/app/components/Sidebar/components/CollectionLink.tsx +++ b/app/components/Sidebar/components/CollectionLink.tsx @@ -79,8 +79,12 @@ function CollectionLink({ accept: "document", drop: (item: DragObject, monitor) => { const { id, collectionId } = item; - if (monitor.didDrop()) return; - if (!collection) return; + if (monitor.didDrop()) { + return; + } + if (!collection) { + return; + } const document = documents.get(id); if (collection.id === collectionId && !document?.parentDocumentId) { @@ -115,7 +119,9 @@ function CollectionLink({ const [{ isOverReorder }, dropToReorder] = useDrop({ accept: "document", drop: async (item: DragObject) => { - if (!collection) return; + if (!collection) { + return; + } documents.move(item.id, collection.id, undefined, 0); }, collect: (monitor) => ({ diff --git a/app/components/Sidebar/components/DocumentLink.tsx b/app/components/Sidebar/components/DocumentLink.tsx index 85015d7f0..63aa5677c 100644 --- a/app/components/Sidebar/components/DocumentLink.tsx +++ b/app/components/Sidebar/components/DocumentLink.tsx @@ -112,7 +112,9 @@ function DocumentLink( const handleTitleChange = React.useCallback( async (title: string) => { - if (!document) return; + if (!document) { + return; + } await documents.update( { id: document.id, @@ -167,8 +169,12 @@ function DocumentLink( const [{ isOverReparent, canDropToReparent }, dropToReparent] = useDrop({ accept: "document", drop: (item: DragObject, monitor) => { - if (monitor.didDrop()) return; - if (!collection) return; + if (monitor.didDrop()) { + return; + } + if (!collection) { + return; + } documents.move(item.id, collection.id, node.id); }, canDrop: (_item, monitor) => @@ -212,8 +218,12 @@ function DocumentLink( const [{ isOverReorder, isDraggingAnyDocument }, dropToReorder] = useDrop({ accept: "document", drop: (item: DragObject) => { - if (!collection) return; - if (item.id === node.id) return; + if (!collection) { + return; + } + if (item.id === node.id) { + return; + } if (expanded) { documents.move(item.id, collection.id, node.id, 0); diff --git a/app/components/Sidebar/components/StarredLink.tsx b/app/components/Sidebar/components/StarredLink.tsx index d4d8c8979..8ce6bb9bb 100644 --- a/app/components/Sidebar/components/StarredLink.tsx +++ b/app/components/Sidebar/components/StarredLink.tsx @@ -67,7 +67,9 @@ function StarredLink({ const handleTitleChange = React.useCallback( async (title: string) => { - if (!document) return; + if (!document) { + return; + } await documents.update( { id: document.id, diff --git a/app/components/SocketProvider.tsx b/app/components/SocketProvider.tsx index 7e5b43982..ae9d0fc99 100644 --- a/app/components/SocketProvider.tsx +++ b/app/components/SocketProvider.tsx @@ -79,7 +79,9 @@ class SocketProvider extends React.Component { views, fileOperations, } = this.props; - if (!auth.token) return; + if (!auth.token) { + return; + } this.socket.on("connect", () => { // immediately send current users token to the websocket backend where it @@ -329,8 +331,9 @@ class SocketProvider extends React.Component { this.socket.on("fileOperations.update", async (event: any) => { const user = auth.user; let collection = null; - if (event.collectionId) + if (event.collectionId) { collection = await collections.fetch(event.collectionId); + } if (user) { fileOperations.add({ ...event, user, collection }); diff --git a/app/components/Tabs.tsx b/app/components/Tabs.tsx index b050d8948..0805d12d6 100644 --- a/app/components/Tabs.tsx +++ b/app/components/Tabs.tsx @@ -63,7 +63,9 @@ const Tabs = ({ children }: { children: React.ReactNode }) => { const updateShadows = React.useCallback(() => { const c = ref.current; - if (!c) return; + if (!c) { + return; + } const scrollLeft = c.scrollLeft; const wrapperWidth = c.scrollWidth - c.clientWidth; const fade = !!(wrapperWidth - scrollLeft !== 0); diff --git a/app/editor/components/CommandMenu.tsx b/app/editor/components/CommandMenu.tsx index 62d387d9c..c32cbb691 100644 --- a/app/editor/components/CommandMenu.tsx +++ b/app/editor/components/CommandMenu.tsx @@ -106,7 +106,9 @@ class CommandMenu extends React.Component, State> { } handleKeyDown = (event: KeyboardEvent) => { - if (!this.props.isActive) return; + if (!this.props.isActive) { + return; + } if (event.key === "Enter") { event.preventDefault(); @@ -196,8 +198,12 @@ class CommandMenu extends React.Component, State> { }; handleLinkInputKeydown = (event: React.KeyboardEvent) => { - if (!this.props.isActive) return; - if (!this.state.insertItem) return; + if (!this.props.isActive) { + return; + } + if (!this.state.insertItem) { + return; + } if (event.key === "Enter") { event.preventDefault(); @@ -229,8 +235,12 @@ class CommandMenu extends React.Component, State> { }; handleLinkInputPaste = (event: React.ClipboardEvent) => { - if (!this.props.isActive) return; - if (!this.state.insertItem) return; + if (!this.props.isActive) { + return; + } + if (!this.state.insertItem) { + return; + } const href = event.clipboardData.getData("text/plain"); const matches = this.state.insertItem.matcher(href); @@ -423,7 +433,9 @@ class CommandMenu extends React.Component, State> { } const filtered = items.filter((item) => { - if (item.name === "separator") return true; + if (item.name === "separator") { + return true; + } // Some extensions may be disabled, remove corresponding menu items if ( @@ -435,10 +447,14 @@ class CommandMenu extends React.Component, State> { } // If no image upload callback has been passed, filter the image block out - if (!uploadImage && item.name === "image") return false; + if (!uploadImage && item.name === "image") { + return false; + } // some items (defaultHidden) are not visible until a search query exists - if (!search) return !item.defaultHidden; + if (!search) { + return !item.defaultHidden; + } const n = search.toLowerCase(); if (!filterable) { diff --git a/app/editor/components/LinkEditor.tsx b/app/editor/components/LinkEditor.tsx index 9f3f2fb3a..dee3b960b 100644 --- a/app/editor/components/LinkEditor.tsx +++ b/app/editor/components/LinkEditor.tsx @@ -105,7 +105,9 @@ class LinkEditor extends React.Component { save = (href: string, title?: string): void => { href = href.trim(); - if (href.length === 0) return; + if (href.length === 0) { + return; + } this.discardInputValue = true; const { from, to } = this.props; @@ -163,7 +165,9 @@ class LinkEditor extends React.Component { } case "ArrowUp": { - if (event.shiftKey) return; + if (event.shiftKey) { + return; + } event.preventDefault(); event.stopPropagation(); const prevIndex = this.state.selectedIndex - 1; @@ -176,7 +180,9 @@ class LinkEditor extends React.Component { case "ArrowDown": case "Tab": { - if (event.shiftKey) return; + if (event.shiftKey) { + return; + } event.preventDefault(); event.stopPropagation(); @@ -239,9 +245,13 @@ class LinkEditor extends React.Component { const { onCreateLink } = this.props; value = value.trim(); - if (value.length === 0) return; + if (value.length === 0) { + return; + } - if (onCreateLink) return onCreateLink(value); + if (onCreateLink) { + return onCreateLink(value); + } }; handleRemoveLink = (): void => { diff --git a/app/editor/components/SelectionToolbar.tsx b/app/editor/components/SelectionToolbar.tsx index 453f6b509..9e10334cc 100644 --- a/app/editor/components/SelectionToolbar.tsx +++ b/app/editor/components/SelectionToolbar.tsx @@ -44,8 +44,12 @@ function isVisible(props: Props) { const { view } = props; const { selection } = view.state; - if (!selection) return false; - if (selection.empty) return false; + if (!selection) { + return false; + } + if (selection.empty) { + return false; + } if (selection instanceof NodeSelection && selection.node.type.name === "hr") { return true; } @@ -209,8 +213,12 @@ export default class SelectionToolbar extends React.Component { // Some extensions may be disabled, remove corresponding items items = items.filter((item) => { - if (item.name === "separator") return true; - if (item.name && !this.props.commands[item.name]) return false; + if (item.name === "separator") { + return true; + } + if (item.name && !this.props.commands[item.name]) { + return false; + } return true; }); diff --git a/app/editor/index.tsx b/app/editor/index.tsx index 1bdcefe25..69122ea85 100644 --- a/app/editor/index.tsx +++ b/app/editor/index.tsx @@ -233,7 +233,9 @@ export class Editor extends React.PureComponent< this.calculateDir(); - if (this.props.readOnly) return; + if (this.props.readOnly) { + return; + } if (this.props.autoFocus) { this.focusAtEnd(); @@ -581,11 +583,15 @@ export class Editor extends React.PureComponent< } scrollToAnchor(hash: string) { - if (!hash) return; + if (!hash) { + return; + } try { const element = document.querySelector(hash); - if (element) element.scrollIntoView({ behavior: "smooth" }); + if (element) { + element.scrollIntoView({ behavior: "smooth" }); + } } catch (err) { // querySelector will throw an error if the hash begins with a number // or contains a period. This is protected against now by safeSlugify @@ -595,7 +601,9 @@ export class Editor extends React.PureComponent< } calculateDir = () => { - if (!this.element) return; + if (!this.element) { + return; + } const isRTL = this.props.dir === "rtl" || @@ -611,7 +619,9 @@ export class Editor extends React.PureComponent< }; handleChange = () => { - if (!this.props.onChange) return; + if (!this.props.onChange) { + return; + } this.props.onChange(() => { return this.value(); @@ -661,7 +671,9 @@ export class Editor extends React.PureComponent< }; handleCloseBlockMenu = () => { - if (!this.state.blockMenuOpen) return; + if (!this.state.blockMenuOpen) { + return; + } this.setState({ blockMenuOpen: false }); }; diff --git a/app/index.tsx b/app/index.tsx index bc2af86e5..3b7758ad4 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -87,7 +87,9 @@ if (element) { window.addEventListener("load", async () => { // installation does not use Google Analytics, or tracking is blocked on client // no point loading the rest of the analytics bundles - if (!env.GOOGLE_ANALYTICS_ID || !window.ga) return; + if (!env.GOOGLE_ANALYTICS_ID || !window.ga) { + return; + } // https://github.com/googleanalytics/autotrack/issues/137#issuecomment-305890099 await import( /* webpackChunkName: "autotrack" */ diff --git a/app/models/Document.ts b/app/models/Document.ts index 9e08fe95c..6f4d29071 100644 --- a/app/models/Document.ts +++ b/app/models/Document.ts @@ -298,7 +298,9 @@ export default class Document extends BaseModel { lastRevision?: number; } ) => { - if (this.isSaving) return this; + if (this.isSaving) { + return this; + } this.isSaving = true; try { @@ -325,7 +327,9 @@ export default class Document extends BaseModel { @action save = async (options?: SaveOptions | undefined) => { - if (this.isSaving) return this; + if (this.isSaving) { + return this; + } const isCreating = !this.id; this.isSaving = true; @@ -422,7 +426,9 @@ export default class Document extends BaseModel { const url = URL.createObjectURL(blob); const a = document.createElement("a"); // Firefox support requires the anchor tag be in the DOM to trigger the dl - if (document.body) document.body.appendChild(a); + if (document.body) { + document.body.appendChild(a); + } a.href = url; a.download = `${this.titleWithDefault}.md`; a.click(); diff --git a/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx b/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx index 2e0d4f0d7..b24ee66f7 100644 --- a/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx +++ b/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx @@ -80,7 +80,9 @@ class AddGroupsToCollection extends React.Component { render() { const { groups, policies, collection, auth, t } = this.props; const { user, team } = auth; - if (!user || !team) return null; + if (!user || !team) { + return null; + } const can = policies.abilities(team.id); diff --git a/app/scenes/CollectionPermissions/AddPeopleToCollection.tsx b/app/scenes/CollectionPermissions/AddPeopleToCollection.tsx index a197492aa..57359d45e 100644 --- a/app/scenes/CollectionPermissions/AddPeopleToCollection.tsx +++ b/app/scenes/CollectionPermissions/AddPeopleToCollection.tsx @@ -77,7 +77,9 @@ class AddPeopleToCollection extends React.Component { render() { const { users, collection, auth, t } = this.props; const { user, team } = auth; - if (!user || !team) return null; + if (!user || !team) { + return null; + } return ( diff --git a/app/scenes/Document/components/Document.tsx b/app/scenes/Document/components/Document.tsx index ecd031965..f8a832376 100644 --- a/app/scenes/Document/components/Document.tsx +++ b/app/scenes/Document/components/Document.tsx @@ -194,7 +194,9 @@ class DocumentScene extends React.Component { }; goToMove = (ev: KeyboardEvent) => { - if (!this.props.readOnly) return; + if (!this.props.readOnly) { + return; + } ev.preventDefault(); const { document, abilities } = this.props; @@ -204,7 +206,9 @@ class DocumentScene extends React.Component { }; goToEdit = (ev: KeyboardEvent) => { - if (!this.props.readOnly) return; + if (!this.props.readOnly) { + return; + } ev.preventDefault(); const { document, abilities } = this.props; @@ -214,8 +218,12 @@ class DocumentScene extends React.Component { }; goToHistory = (ev: KeyboardEvent) => { - if (!this.props.readOnly) return; - if (ev.ctrlKey) return; + if (!this.props.readOnly) { + return; + } + if (ev.ctrlKey) { + return; + } ev.preventDefault(); const { document, location } = this.props; @@ -229,7 +237,9 @@ class DocumentScene extends React.Component { onPublish = (ev: React.MouseEvent | KeyboardEvent) => { ev.preventDefault(); const { document } = this.props; - if (document.publishedAt) return; + if (document.publishedAt) { + return; + } this.onSave({ publish: true, done: true, @@ -237,7 +247,9 @@ class DocumentScene extends React.Component { }; onToggleTableOfContents = (ev: KeyboardEvent) => { - if (!this.props.readOnly) return; + if (!this.props.readOnly) { + return; + } ev.preventDefault(); const { ui } = this.props; @@ -257,13 +269,17 @@ class DocumentScene extends React.Component { ) => { const { document, auth } = this.props; // prevent saves when we are already saving - if (document.isSaving) return; + if (document.isSaving) { + return; + } // get the latest version of the editor text value const text = this.getEditorText ? this.getEditorText() : document.text; // prevent save before anything has been written (single hash is empty doc) - if (text.trim() === "" && document.title.trim() === "") return; + if (text.trim() === "" && document.title.trim() === "") { + return; + } document.text = text; document.tasks = getTasks(document.text); diff --git a/app/scenes/Document/components/PublicReferences.tsx b/app/scenes/Document/components/PublicReferences.tsx index f23ec7c1b..5fd01d630 100644 --- a/app/scenes/Document/components/PublicReferences.tsx +++ b/app/scenes/Document/components/PublicReferences.tsx @@ -22,7 +22,9 @@ function PublicReferences(props: Props) { let result: NavigationNode[]; function findChildren(node?: NavigationNode) { - if (!node) return; + if (!node) { + return; + } if (node.id === documentId) { result = node.children; diff --git a/app/scenes/Document/components/SocketPresence.ts b/app/scenes/Document/components/SocketPresence.ts index f3422fdaa..63d393d9a 100644 --- a/app/scenes/Document/components/SocketPresence.ts +++ b/app/scenes/Document/components/SocketPresence.ts @@ -58,7 +58,9 @@ export default class SocketPresence extends React.Component { }; emitJoin = () => { - if (!this.context) return; + if (!this.context) { + return; + } this.context.emit("join", { documentId: this.props.documentId, isEditing: this.props.isEditing, @@ -66,7 +68,9 @@ export default class SocketPresence extends React.Component { }; emitPresence = () => { - if (!this.context) return; + if (!this.context) { + return; + } this.context.emit("presence", { documentId: this.props.documentId, isEditing: this.props.isEditing, diff --git a/app/scenes/GroupMembers/AddPeopleToGroup.tsx b/app/scenes/GroupMembers/AddPeopleToGroup.tsx index e8bc935a2..f41122146 100644 --- a/app/scenes/GroupMembers/AddPeopleToGroup.tsx +++ b/app/scenes/GroupMembers/AddPeopleToGroup.tsx @@ -76,7 +76,9 @@ class AddPeopleToGroup extends React.Component { render() { const { users, group, auth, t } = this.props; const { user, team } = auth; - if (!user || !team) return null; + if (!user || !team) { + return null; + } return ( diff --git a/app/scenes/Search/Search.tsx b/app/scenes/Search/Search.tsx index e0f8445cb..a649fcec5 100644 --- a/app/scenes/Search/Search.tsx +++ b/app/scenes/Search/Search.tsx @@ -177,14 +177,18 @@ class Search extends React.Component { get title() { const query = this.query; const title = this.props.t("Search"); - if (query) return `${query} – ${title}`; + if (query) { + return `${query} – ${title}`; + } return title; } @action loadMoreResults = async () => { // Don't paginate if there aren't more results or we’re in the middle of fetching - if (!this.allowLoadMore || this.isLoading) return; + if (!this.allowLoadMore || this.isLoading) { + return; + } // Fetch more results await this.fetchResults(); @@ -330,7 +334,9 @@ class Search extends React.Component { > {results.map((result, index) => { const document = documents.data.get(result.document.id); - if (!document) return null; + if (!document) { + return null; + } return ( index === 0 && this.setFirstDocumentRef(ref)} diff --git a/app/scenes/UserProfile.tsx b/app/scenes/UserProfile.tsx index 7c6e2fa0f..00bc4c6f0 100644 --- a/app/scenes/UserProfile.tsx +++ b/app/scenes/UserProfile.tsx @@ -30,7 +30,9 @@ function UserProfile(props: Props) { const currentUser = useCurrentUser(); const history = useHistory(); const { user, ...rest } = props; - if (!user) return null; + if (!user) { + return null; + } const isCurrentUser = currentUser.id === user.id; return ( diff --git a/app/stores/AuthStore.ts b/app/stores/AuthStore.ts index b7c4be1dc..2fc696aa1 100644 --- a/app/stores/AuthStore.ts +++ b/app/stores/AuthStore.ts @@ -89,7 +89,9 @@ export default class AuthStore { event.newValue ); // data may be null if key is deleted in localStorage - if (!data) return; + if (!data) { + return; + } // If we're not signed in then hydrate from the received data, otherwise if // we are signed in and the received data contains no user then sign out diff --git a/app/stores/BaseStore.ts b/app/stores/BaseStore.ts index f37eaaf11..64019abd4 100644 --- a/app/stores/BaseStore.ts +++ b/app/stores/BaseStore.ts @@ -111,7 +111,9 @@ export default class BaseStore { } save(params: Partial): Promise { - if (params.id) return this.update(params); + if (params.id) { + return this.update(params); + } return this.create(params); } @@ -195,7 +197,9 @@ export default class BaseStore { } const item = this.data.get(id); - if (item && !options.force) return item; + if (item && !options.force) { + return item; + } this.isFetching = true; try { diff --git a/app/stores/CollectionsStore.ts b/app/stores/CollectionsStore.ts index d71bc2aba..dcc24c1ac 100644 --- a/app/stores/CollectionsStore.ts +++ b/app/stores/CollectionsStore.ts @@ -141,7 +141,9 @@ export default class CollectionsStore extends BaseStore { @action async fetch(id: string, options: Record = {}): Promise { const item = this.get(id) || this.getByUrl(id); - if (item && !options.force) return item; + if (item && !options.force) { + return item; + } this.isFetching = true; try { diff --git a/app/stores/DocumentsStore.ts b/app/stores/DocumentsStore.ts index 7d1de02e9..f01c13058 100644 --- a/app/stores/DocumentsStore.ts +++ b/app/stores/DocumentsStore.ts @@ -398,7 +398,9 @@ export default class DocumentsStore extends BaseStore { const results: SearchResult[] = compact( res.data.map((result: SearchResult) => { const document = this.data.get(result.document.id); - if (!document) return null; + if (!document) { + return null; + } return { ranking: result.ranking, context: result.context, @@ -450,7 +452,9 @@ export default class DocumentsStore extends BaseStore { document: Document; sharedTree?: NavigationNode; }> => { - if (!options.prefetch) this.isFetching = true; + if (!options.prefetch) { + this.isFetching = true; + } try { const doc: Document | null | undefined = @@ -540,7 +544,9 @@ export default class DocumentsStore extends BaseStore { }); invariant(res && res.data, "Data should be available"); const collection = this.getCollectionForDocument(document); - if (collection) collection.refresh(); + if (collection) { + collection.refresh(); + } this.addPolicies(res.policies); return this.add(res.data); }; @@ -635,7 +641,9 @@ export default class DocumentsStore extends BaseStore { // Because the collection object contains the url and title // we need to ensure they are updated there as well. const collection = this.getCollectionForDocument(document); - if (collection) collection.updateDocument(document); + if (collection) { + collection.updateDocument(document); + } return document; } @@ -656,7 +664,9 @@ export default class DocumentsStore extends BaseStore { } const collection = this.getCollectionForDocument(document); - if (collection) collection.refresh(); + if (collection) { + collection.refresh(); + } } @action @@ -670,7 +680,9 @@ export default class DocumentsStore extends BaseStore { this.addPolicies(res.policies); }); const collection = this.getCollectionForDocument(document); - if (collection) collection.refresh(); + if (collection) { + collection.refresh(); + } }; @action @@ -692,7 +704,9 @@ export default class DocumentsStore extends BaseStore { this.addPolicies(res.policies); }); const collection = this.getCollectionForDocument(document); - if (collection) collection.refresh(); + if (collection) { + collection.refresh(); + } }; @action @@ -706,7 +720,9 @@ export default class DocumentsStore extends BaseStore { this.addPolicies(res.policies); }); const collection = this.getCollectionForDocument(document); - if (collection) collection.refresh(); + if (collection) { + collection.refresh(); + } }; star = async (document: Document) => { diff --git a/app/stores/GroupsStore.ts b/app/stores/GroupsStore.ts index 472c85960..a28635ce0 100644 --- a/app/stores/GroupsStore.ts +++ b/app/stores/GroupsStore.ts @@ -48,7 +48,9 @@ export default class GroupsStore extends BaseStore { const groups = filter(this.orderedData, (group) => groupIds.includes(group.id) ); - if (!query) return groups; + if (!query) { + return groups; + } return queriedGroups(groups, query); }; @@ -62,7 +64,9 @@ export default class GroupsStore extends BaseStore { this.orderedData, (group) => !groupIds.includes(group.id) ); - if (!query) return groups; + if (!query) { + return groups; + } return queriedGroups(groups, query); }; } diff --git a/app/stores/SharesStore.ts b/app/stores/SharesStore.ts index c767af8ff..e6c72e428 100644 --- a/app/stores/SharesStore.ts +++ b/app/stores/SharesStore.ts @@ -39,7 +39,9 @@ export default class SharesStore extends BaseStore { @action async create(params: Record) { const item = this.getByDocumentId(params.documentId); - if (item) return item; + if (item) { + return item; + } return super.create(params); } @@ -49,7 +51,9 @@ export default class SharesStore extends BaseStore { options: Record = {} ): Promise { const item = this.getByDocumentId(documentId); - if (item && !options.force) return item; + if (item && !options.force) { + return item; + } this.isFetching = true; try { @@ -58,7 +62,9 @@ export default class SharesStore extends BaseStore { apiVersion: 2, }); - if (isUndefined(res)) return; + if (isUndefined(res)) { + return; + } invariant(res && res.data, "Data should be available"); this.addPolicies(res.policies); return res.data.shares.map(this.add); @@ -69,10 +75,14 @@ export default class SharesStore extends BaseStore { getByDocumentParents = (documentId: string): Share | null | undefined => { const document = this.rootStore.documents.get(documentId); - if (!document) return; + if (!document) { + return; + } const collection = this.rootStore.collections.get(document.collectionId); - if (!collection) return; + if (!collection) { + return; + } const parentIds = collection .pathToDocument(documentId) diff --git a/app/stores/ToastsStore.ts b/app/stores/ToastsStore.ts index 06db81687..77ec8db92 100644 --- a/app/stores/ToastsStore.ts +++ b/app/stores/ToastsStore.ts @@ -16,7 +16,9 @@ export default class ToastsStore { type: "info", } ) => { - if (!message) return; + if (!message) { + return; + } const lastToast = this.toasts.get(this.lastToastId); if (lastToast && lastToast.message === message) { diff --git a/app/stores/UsersStore.ts b/app/stores/UsersStore.ts index a414860d7..e7a785e46 100644 --- a/app/stores/UsersStore.ts +++ b/app/stores/UsersStore.ts @@ -211,7 +211,9 @@ export default class UsersStore extends BaseStore { this.activeOrInvited, (user) => !userIds.includes(user.id) ); - if (!query) return users; + if (!query) { + return users; + } return queriedUsers(users, query); }; @@ -224,7 +226,9 @@ export default class UsersStore extends BaseStore { const users = filter(this.activeOrInvited, (user) => userIds.includes(user.id) ); - if (!query) return users; + if (!query) { + return users; + } return queriedUsers(users, query); }; @@ -238,7 +242,9 @@ export default class UsersStore extends BaseStore { this.activeOrInvited, (user) => !userIds.includes(user.id) ); - if (!query) return users; + if (!query) { + return users; + } return queriedUsers(users, query); }; @@ -251,7 +257,9 @@ export default class UsersStore extends BaseStore { const users = filter(this.activeOrInvited, (user) => userIds.includes(user.id) ); - if (!query) return users; + if (!query) { + return users; + } return queriedUsers(users, query); }; diff --git a/app/stores/ViewsStore.ts b/app/stores/ViewsStore.ts index 74f430a40..05a2d2855 100644 --- a/app/stores/ViewsStore.ts +++ b/app/stores/ViewsStore.ts @@ -28,7 +28,9 @@ export default class ViewsStore extends BaseStore { this.orderedData, (view) => view.documentId === documentId && view.user.id === userId ); - if (!view) return; + if (!view) { + return; + } view.touch(); } } diff --git a/app/utils/routeHelpers.ts b/app/utils/routeHelpers.ts index c655d6aa9..3fc34c2d7 100644 --- a/app/utils/routeHelpers.ts +++ b/app/utils/routeHelpers.ts @@ -31,7 +31,9 @@ export function groupSettingsPath(): string { } export function collectionUrl(url: string, section?: string): string { - if (section) return `${url}/${section}`; + if (section) { + return `${url}/${section}`; + } return url; } @@ -60,7 +62,9 @@ export function documentMoveUrl(doc: Document): string { export function documentHistoryUrl(doc: Document, revisionId?: string): string { let base = `${doc.url}/history`; - if (revisionId) base += `/${revisionId}`; + if (revisionId) { + base += `/${revisionId}`; + } return base; } diff --git a/app/utils/urls.ts b/app/utils/urls.ts index 54541f568..70b3b9472 100644 --- a/app/utils/urls.ts +++ b/app/utils/urls.ts @@ -1,7 +1,9 @@ import { parseDomain } from "@shared/utils/domains"; export function isInternalUrl(href: string) { - if (href[0] === "/") return true; + if (href[0] === "/") { + return true; + } const outline = parseDomain(window.location.href); const parsed = parseDomain(href); @@ -19,7 +21,9 @@ export function isInternalUrl(href: string) { } export function isHash(href: string) { - if (href[0] === "#") return true; + if (href[0] === "#") { + return true; + } try { const outline = new URL(window.location.href); diff --git a/server/emails/index.ts b/server/emails/index.ts index 42d9114ef..b37ef1b74 100644 --- a/server/emails/index.ts +++ b/server/emails/index.ts @@ -27,7 +27,9 @@ router.get("/:type/:format", async (ctx) => { } } - if (!mailerOutput) return; + if (!mailerOutput) { + return; + } if (ctx.params.format === "text") { // @ts-expect-error ts-migrate(2339) FIXME: Property 'text' does not exist on type 'never'. diff --git a/server/models/Attachment.ts b/server/models/Attachment.ts index da311f80b..62e3946ac 100644 --- a/server/models/Attachment.ts +++ b/server/models/Attachment.ts @@ -92,8 +92,12 @@ class Attachment extends BaseModel { query: FindOptions ) => Promise ) { - if (!query.offset) query.offset = 0; - if (!query.limit) query.limit = 10; + if (!query.offset) { + query.offset = 0; + } + if (!query.limit) { + query.limit = 10; + } let results; do { diff --git a/server/models/Collection.ts b/server/models/Collection.ts index efe9fab78..5774fda1e 100644 --- a/server/models/Collection.ts +++ b/server/models/Collection.ts @@ -186,7 +186,9 @@ class Collection extends ParanoidModel { // getters get url(): string { - if (!this.name) return `/collection/untitled-${this.urlId}`; + if (!this.name) { + return `/collection/untitled-${this.urlId}`; + } return `/collection/${slugify(this.name)}-${this.urlId}`; } @@ -354,7 +356,9 @@ class Collection extends ParanoidModel { } getDocumentTree = (documentId: string): NavigationNode | null => { - if (!this.documentStructure) return null; + if (!this.documentStructure) { + return null; + } const sort: Sort = this.sort || { field: "title", direction: "asc", @@ -386,7 +390,9 @@ class Collection extends ParanoidModel { loopChildren(this.documentStructure); // if the document is a draft loopChildren will not find it in the structure - if (!result) return null; + if (!result) { + return null; + } return { ...result, @@ -548,7 +554,9 @@ class Collection extends ParanoidModel { * Update document's title and url in the documentStructure */ updateDocument = async function (updatedDocument: Document) { - if (!this.documentStructure) return; + if (!this.documentStructure) { + return; + } let transaction; try { diff --git a/server/models/Document.ts b/server/models/Document.ts index 6a551f0bd..c583ac15d 100644 --- a/server/models/Document.ts +++ b/server/models/Document.ts @@ -127,7 +127,9 @@ export const DOCUMENT_VERSION = 2; ], }, withViews: (userId: string) => { - if (!userId) return {}; + if (!userId) { + return {}; + } return { include: [ { @@ -215,7 +217,9 @@ class Document extends ParanoidModel { // getters get url() { - if (!this.title) return `/doc/untitled-${this.urlId}`; + if (!this.title) { + return `/doc/untitled-${this.urlId}`; + } const slugifiedTitle = slugify(this.title); return `/doc/${slugifiedTitle}-${this.urlId}`; } @@ -721,7 +725,9 @@ class Document extends ParanoidModel { }; publish = async (userId: string, options?: FindOptions) => { - if (this.publishedAt) return this.save(options); + if (this.publishedAt) { + return this.save(options); + } if (!this.template) { const collection = await Collection.findByPk(this.collectionId); @@ -735,7 +741,9 @@ class Document extends ParanoidModel { }; unpublish = async (userId: string, options?: FindOptions) => { - if (!this.publishedAt) return this; + if (!this.publishedAt) { + return this; + } const collection = await this.$get("collection"); await collection?.removeDocumentInStructure(this); @@ -777,7 +785,9 @@ class Document extends ParanoidModel { }, }, }); - if (!parent) this.parentDocumentId = null; + if (!parent) { + this.parentDocumentId = null; + } } if (!this.template && collection) { diff --git a/server/models/Group.ts b/server/models/Group.ts index 569073089..1ed0a791f 100644 --- a/server/models/Group.ts +++ b/server/models/Group.ts @@ -58,7 +58,9 @@ class Group extends ParanoidModel { @AfterDestroy static async deleteGroupUsers(model: Group) { - if (!model.deletedAt) return; + if (!model.deletedAt) { + return; + } await GroupUser.destroy({ where: { groupId: model.id, diff --git a/server/models/Team.ts b/server/models/Team.ts index c25f6a06d..ebb6c6885 100644 --- a/server/models/Team.ts +++ b/server/models/Team.ts @@ -125,7 +125,9 @@ class Team extends ParanoidModel { requestedSubdomain: string, options = {} ) { - if (this.subdomain) return this.subdomain; + if (this.subdomain) { + return this.subdomain; + } let subdomain = requestedSubdomain; let append = 0; @@ -234,7 +236,9 @@ class Team extends ParanoidModel { `avatars/${model.id}/${uuidv4()}`, "public-read" ); - if (newUrl) model.avatarUrl = newUrl; + if (newUrl) { + model.avatarUrl = newUrl; + } } catch (err) { Logger.error("Error uploading avatar to S3", err, { url: avatarUrl, diff --git a/server/models/User.ts b/server/models/User.ts index 70377f116..a68025ba0 100644 --- a/server/models/User.ts +++ b/server/models/User.ts @@ -360,7 +360,9 @@ class User extends ParanoidModel { `avatars/${model.id}/${uuidv4()}`, "public-read" ); - if (newUrl) model.avatarUrl = newUrl; + if (newUrl) { + model.avatarUrl = newUrl; + } } catch (err) { Logger.error("Couldn't upload user avatar image to S3", err, { url: avatarUrl, @@ -452,8 +454,12 @@ class User extends ParanoidModel { query: FindOptions, callback: (users: Array, query: FindOptions) => Promise ) { - if (!query.offset) query.offset = 0; - if (!query.limit) query.limit = 10; + if (!query.offset) { + query.offset = 0; + } + if (!query.limit) { + query.limit = 10; + } let results; do { diff --git a/server/policies/apiKey.ts b/server/policies/apiKey.ts index b5009b074..07e6145df 100644 --- a/server/policies/apiKey.ts +++ b/server/policies/apiKey.ts @@ -2,12 +2,18 @@ import { ApiKey, User, Team } from "@server/models"; import { allow } from "./cancan"; allow(User, "createApiKey", Team, (user, team) => { - if (!team || user.isViewer || user.teamId !== team.id) return false; + if (!team || user.isViewer || user.teamId !== team.id) { + return false; + } return true; }); allow(User, ["read", "update", "delete"], ApiKey, (user, apiKey) => { - if (!apiKey) return false; - if (user.isViewer) return false; + if (!apiKey) { + return false; + } + if (user.isViewer) { + return false; + } return user && user.id === apiKey.userId; }); diff --git a/server/policies/attachment.ts b/server/policies/attachment.ts index c79eb3b8e..0cf2f82d1 100644 --- a/server/policies/attachment.ts +++ b/server/policies/attachment.ts @@ -2,21 +2,37 @@ import { Attachment, User, Team } from "@server/models"; import { allow } from "./cancan"; allow(User, "createAttachment", Team, (user, team) => { - if (!team || user.isViewer || user.teamId !== team.id) return false; + if (!team || user.isViewer || user.teamId !== team.id) { + return false; + } return true; }); allow(User, "read", Attachment, (actor, attachment) => { - if (!attachment || attachment.teamId !== actor.teamId) return false; - if (actor.isAdmin) return true; - if (actor.id === attachment.userId) return true; + if (!attachment || attachment.teamId !== actor.teamId) { + return false; + } + if (actor.isAdmin) { + return true; + } + if (actor.id === attachment.userId) { + return true; + } return false; }); allow(User, "delete", Attachment, (actor, attachment) => { - if (actor.isViewer) return false; - if (!attachment || attachment.teamId !== actor.teamId) return false; - if (actor.isAdmin) return true; - if (actor.id === attachment.userId) return true; + if (actor.isViewer) { + return false; + } + if (!attachment || attachment.teamId !== actor.teamId) { + return false; + } + if (actor.isAdmin) { + return true; + } + if (actor.id === attachment.userId) { + return true; + } return false; }); diff --git a/server/policies/authenticationProvider.ts b/server/policies/authenticationProvider.ts index 25b773be4..2a08ad3ea 100644 --- a/server/policies/authenticationProvider.ts +++ b/server/policies/authenticationProvider.ts @@ -3,8 +3,12 @@ import { AdminRequiredError } from "../errors"; import { allow } from "./cancan"; allow(User, "createAuthenticationProvider", Team, (actor, team) => { - if (!team || actor.teamId !== team.id) return false; - if (actor.isAdmin) return true; + if (!team || actor.teamId !== team.id) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); @@ -24,8 +28,12 @@ allow( AuthenticationProvider, (actor, authenticationProvider) => { - if (actor.teamId !== authenticationProvider?.teamId) return false; - if (actor.isAdmin) return true; + if (actor.teamId !== authenticationProvider?.teamId) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); } diff --git a/server/policies/collection.ts b/server/policies/collection.ts index 5a916e763..fe3695ffd 100644 --- a/server/policies/collection.ts +++ b/server/policies/collection.ts @@ -5,27 +5,41 @@ import { AdminRequiredError } from "../errors"; import { allow } from "./cancan"; allow(User, "createCollection", Team, (user, team) => { - if (!team || user.isViewer || user.teamId !== team.id) return false; + if (!team || user.isViewer || user.teamId !== team.id) { + return false; + } return true; }); allow(User, "importCollection", Team, (actor, team) => { - if (!team || actor.teamId !== team.id) return false; - if (actor.isAdmin) return true; + if (!team || actor.teamId !== team.id) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); allow(User, "move", Collection, (user, collection) => { - if (!collection || user.teamId !== collection.teamId) return false; - if (collection.deletedAt) return false; - if (user.isAdmin) return true; + if (!collection || user.teamId !== collection.teamId) { + return false; + } + if (collection.deletedAt) { + return false; + } + if (user.isAdmin) { + return true; + } throw AdminRequiredError(); }); allow(User, "read", Collection, (user, collection) => { - if (!collection || user.teamId !== collection.teamId) return false; + if (!collection || user.teamId !== collection.teamId) { + return false; + } if (!collection.permission) { invariant( @@ -45,9 +59,15 @@ allow(User, "read", Collection, (user, collection) => { }); allow(User, "share", Collection, (user, collection) => { - if (user.isViewer) return false; - if (!collection || user.teamId !== collection.teamId) return false; - if (!collection.sharing) return false; + if (user.isViewer) { + return false; + } + if (!collection || user.teamId !== collection.teamId) { + return false; + } + if (!collection.sharing) { + return false; + } if (collection.permission !== "read_write") { invariant( @@ -67,8 +87,12 @@ allow(User, "share", Collection, (user, collection) => { }); allow(User, ["publish", "update"], Collection, (user, collection) => { - if (user.isViewer) return false; - if (!collection || user.teamId !== collection.teamId) return false; + if (user.isViewer) { + return false; + } + if (!collection || user.teamId !== collection.teamId) { + return false; + } if (collection.permission !== "read_write") { invariant( @@ -88,8 +112,12 @@ allow(User, ["publish", "update"], Collection, (user, collection) => { }); allow(User, "delete", Collection, (user, collection) => { - if (user.isViewer) return false; - if (!collection || user.teamId !== collection.teamId) return false; + if (user.isViewer) { + return false; + } + if (!collection || user.teamId !== collection.teamId) { + return false; + } if (collection.permission !== "read_write") { invariant( @@ -105,8 +133,12 @@ allow(User, "delete", Collection, (user, collection) => { ); } - if (user.isAdmin) return true; - if (user.id === collection.createdById) return true; + if (user.isAdmin) { + return true; + } + if (user.id === collection.createdById) { + return true; + } throw AdminRequiredError(); }); diff --git a/server/policies/document.ts b/server/policies/document.ts index 82f4fd9b2..395c76ba3 100644 --- a/server/policies/document.ts +++ b/server/policies/document.ts @@ -4,12 +4,16 @@ import { NavigationNode } from "~/types"; import { allow, _cannot as cannot } from "./cancan"; allow(User, "createDocument", Team, (user, team) => { - if (!team || user.isViewer || user.teamId !== team.id) return false; + if (!team || user.isViewer || user.teamId !== team.id) { + return false; + } return true; }); allow(User, ["read", "download"], Document, (user, document) => { - if (!document) return false; + if (!document) { + return false; + } // existence of collection option is not required here to account for share tokens if (document.collection && cannot(user, "read", document.collection)) { @@ -20,33 +24,55 @@ allow(User, ["read", "download"], Document, (user, document) => { }); allow(User, "star", Document, (user, document) => { - if (!document) return false; - if (document.archivedAt) return false; - if (document.deletedAt) return false; - if (document.template) return false; + if (!document) { + return false; + } + if (document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } + if (document.template) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" ); - if (cannot(user, "read", document.collection)) return false; + if (cannot(user, "read", document.collection)) { + return false; + } return user.teamId === document.teamId; }); allow(User, "unstar", Document, (user, document) => { - if (!document) return false; - if (document.template) return false; + if (!document) { + return false; + } + if (document.template) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" ); - if (cannot(user, "read", document.collection)) return false; + if (cannot(user, "read", document.collection)) { + return false; + } return user.teamId === document.teamId; }); allow(User, "share", Document, (user, document) => { - if (!document) return false; - if (document.archivedAt) return false; - if (document.deletedAt) return false; + if (!document) { + return false; + } + if (document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" @@ -60,9 +86,15 @@ allow(User, "share", Document, (user, document) => { }); allow(User, "update", Document, (user, document) => { - if (!document) return false; - if (document.archivedAt) return false; - if (document.deletedAt) return false; + if (!document) { + return false; + } + if (document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } if (cannot(user, "update", document.collection)) { return false; @@ -72,60 +104,110 @@ allow(User, "update", Document, (user, document) => { }); allow(User, "createChildDocument", Document, (user, document) => { - if (!document) return false; - if (document.archivedAt) return false; - if (document.deletedAt) return false; - if (document.template) return false; - if (!document.publishedAt) return false; + if (!document) { + return false; + } + if (document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } + if (document.template) { + return false; + } + if (!document.publishedAt) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" ); - if (cannot(user, "update", document.collection)) return false; + if (cannot(user, "update", document.collection)) { + return false; + } return user.teamId === document.teamId; }); allow(User, "move", Document, (user, document) => { - if (!document) return false; - if (document.archivedAt) return false; - if (document.deletedAt) return false; - if (!document.publishedAt) return false; + if (!document) { + return false; + } + if (document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } + if (!document.publishedAt) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" ); - if (cannot(user, "update", document.collection)) return false; + if (cannot(user, "update", document.collection)) { + return false; + } return user.teamId === document.teamId; }); allow(User, ["pin", "unpin"], Document, (user, document) => { - if (!document) return false; - if (document.archivedAt) return false; - if (document.deletedAt) return false; - if (document.template) return false; - if (!document.publishedAt) return false; + if (!document) { + return false; + } + if (document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } + if (document.template) { + return false; + } + if (!document.publishedAt) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" ); - if (cannot(user, "update", document.collection)) return false; + if (cannot(user, "update", document.collection)) { + return false; + } return user.teamId === document.teamId; }); allow(User, ["pinToHome"], Document, (user, document) => { - if (!document) return false; - if (document.archivedAt) return false; - if (document.deletedAt) return false; - if (document.template) return false; - if (!document.publishedAt) return false; + if (!document) { + return false; + } + if (document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } + if (document.template) { + return false; + } + if (!document.publishedAt) { + return false; + } return user.teamId === document.teamId && user.isAdmin; }); allow(User, "delete", Document, (user, document) => { - if (!document) return false; - if (document.deletedAt) return false; - if (user.isViewer) return false; + if (!document) { + return false; + } + if (document.deletedAt) { + return false; + } + if (user.isViewer) { + return false; + } // allow deleting document without a collection if (document.collection && cannot(user, "update", document.collection)) { @@ -145,9 +227,15 @@ allow(User, "delete", Document, (user, document) => { }); allow(User, "permanentDelete", Document, (user, document) => { - if (!document) return false; - if (!document.deletedAt) return false; - if (user.isViewer) return false; + if (!document) { + return false; + } + if (!document.deletedAt) { + return false; + } + if (user.isViewer) { + return false; + } // allow deleting document without a collection if (document.collection && cannot(user, "update", document.collection)) { @@ -158,9 +246,15 @@ allow(User, "permanentDelete", Document, (user, document) => { }); allow(User, "restore", Document, (user, document) => { - if (!document) return false; - if (!document.deletedAt) return false; - if (user.isViewer) return false; + if (!document) { + return false; + } + if (!document.deletedAt) { + return false; + } + if (user.isViewer) { + return false; + } if (document.collection && cannot(user, "update", document.collection)) { return false; @@ -170,27 +264,45 @@ allow(User, "restore", Document, (user, document) => { }); allow(User, "archive", Document, (user, document) => { - if (!document) return false; - if (!document.publishedAt) return false; - if (document.archivedAt) return false; - if (document.deletedAt) return false; + if (!document) { + return false; + } + if (!document.publishedAt) { + return false; + } + if (document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" ); - if (cannot(user, "update", document.collection)) return false; + if (cannot(user, "update", document.collection)) { + return false; + } return user.teamId === document.teamId; }); allow(User, "unarchive", Document, (user, document) => { - if (!document) return false; + if (!document) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" ); - if (cannot(user, "update", document.collection)) return false; - if (!document.archivedAt) return false; - if (document.deletedAt) return false; + if (cannot(user, "update", document.collection)) { + return false; + } + if (!document.archivedAt) { + return false; + } + if (document.deletedAt) { + return false; + } return user.teamId === document.teamId; }); @@ -202,19 +314,26 @@ allow( ); allow(User, "unpublish", Document, (user, document) => { - if (!document) return false; + if (!document) { + return false; + } invariant( document.collection, "collection is missing, did you forget to include in the query scope?" ); - if (!document.publishedAt || !!document.deletedAt || !!document.archivedAt) + if (!document.publishedAt || !!document.deletedAt || !!document.archivedAt) { return false; - if (cannot(user, "update", document.collection)) return false; + } + if (cannot(user, "update", document.collection)) { + return false; + } const documentID = document.id; const hasChild = (documents: NavigationNode[]): boolean => documents.some((doc) => { - if (doc.id === documentID) return doc.children.length > 0; + if (doc.id === documentID) { + return doc.children.length > 0; + } return hasChild(doc.children); }); diff --git a/server/policies/group.ts b/server/policies/group.ts index 0afa2ac95..3922cd6ca 100644 --- a/server/policies/group.ts +++ b/server/policies/group.ts @@ -3,8 +3,12 @@ import { AdminRequiredError } from "../errors"; import { allow } from "./cancan"; allow(User, "createGroup", Team, (actor, team) => { - if (!team || actor.isViewer || actor.teamId !== team.id) return false; - if (actor.isAdmin) return true; + if (!team || actor.isViewer || actor.teamId !== team.id) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); @@ -12,13 +16,19 @@ allow(User, "createGroup", Team, (actor, team) => { allow(User, "read", Group, (actor, group) => { // for the time being, we're going to let everyone on the team see every group // we may need to make this more granular in the future - if (!group || actor.teamId !== group.teamId) return false; + if (!group || actor.teamId !== group.teamId) { + return false; + } return true; }); allow(User, ["update", "delete"], Group, (actor, group) => { - if (!group || actor.isViewer || actor.teamId !== group.teamId) return false; - if (actor.isAdmin) return true; + if (!group || actor.isViewer || actor.teamId !== group.teamId) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); diff --git a/server/policies/integration.ts b/server/policies/integration.ts index bc9a5f91f..893af6afb 100644 --- a/server/policies/integration.ts +++ b/server/policies/integration.ts @@ -3,8 +3,12 @@ import { AdminRequiredError } from "../errors"; import { allow } from "./cancan"; allow(User, "createIntegration", Team, (actor, team) => { - if (!team || actor.isViewer || actor.teamId !== team.id) return false; - if (actor.isAdmin) return true; + if (!team || actor.isViewer || actor.teamId !== team.id) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); @@ -17,9 +21,15 @@ allow( ); allow(User, ["update", "delete"], Integration, (user, integration) => { - if (user.isViewer) return false; - if (!integration || user.teamId !== integration.teamId) return false; - if (user.isAdmin) return true; + if (user.isViewer) { + return false; + } + if (!integration || user.teamId !== integration.teamId) { + return false; + } + if (user.isAdmin) { + return true; + } throw AdminRequiredError(); }); diff --git a/server/policies/notificationSetting.ts b/server/policies/notificationSetting.ts index e0461d739..0eaa591d3 100644 --- a/server/policies/notificationSetting.ts +++ b/server/policies/notificationSetting.ts @@ -2,7 +2,9 @@ import { NotificationSetting, Team, User } from "@server/models"; import { allow } from "./cancan"; allow(User, "createNotificationSetting", Team, (user, team) => { - if (!team || user.teamId !== team.id) return false; + if (!team || user.teamId !== team.id) { + return false; + } return true; }); diff --git a/server/policies/share.ts b/server/policies/share.ts index 0b1da3e73..b0139ae9c 100644 --- a/server/policies/share.ts +++ b/server/policies/share.ts @@ -5,21 +5,37 @@ import { allow, _cannot as cannot } from "./cancan"; allow(User, "read", Share, (user, share) => user.teamId === share?.teamId); allow(User, "update", Share, (user, share) => { - if (!share) return false; - if (user.isViewer) return false; + if (!share) { + return false; + } + if (user.isViewer) { + return false; + } // only the user who can share the document publicly can update the share. - if (cannot(user, "share", share.document)) return false; + if (cannot(user, "share", share.document)) { + return false; + } return user.teamId === share.teamId; }); allow(User, "revoke", Share, (user, share) => { - if (!share) return false; - if (user.isViewer) return false; - if (user.teamId !== share.teamId) return false; - if (user.id === share.userId) return true; - if (user.isAdmin) return true; + if (!share) { + return false; + } + if (user.isViewer) { + return false; + } + if (user.teamId !== share.teamId) { + return false; + } + if (user.id === share.userId) { + return true; + } + if (user.isAdmin) { + return true; + } throw AdminRequiredError(); }); diff --git a/server/policies/team.ts b/server/policies/team.ts index a6ee519d7..63f5b72b6 100644 --- a/server/policies/team.ts +++ b/server/policies/team.ts @@ -4,11 +4,15 @@ import { allow } from "./cancan"; allow(User, "read", Team, (user, team) => user.teamId === team?.id); allow(User, "share", Team, (user, team) => { - if (!team || user.isViewer || user.teamId !== team.id) return false; + if (!team || user.isViewer || user.teamId !== team.id) { + return false; + } return team.sharing; }); allow(User, ["update", "export", "manage"], Team, (user, team) => { - if (!team || user.isViewer || user.teamId !== team.id) return false; + if (!team || user.isViewer || user.teamId !== team.id) { + return false; + } return user.isAdmin; }); diff --git a/server/policies/user.ts b/server/policies/user.ts index 4af423506..4d88df50f 100644 --- a/server/policies/user.ts +++ b/server/policies/user.ts @@ -10,52 +10,86 @@ allow( ); allow(User, "inviteUser", Team, (actor, team) => { - if (!team || actor.teamId !== team.id) return false; - if (actor.isAdmin) return true; + if (!team || actor.teamId !== team.id) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); allow(User, "update", User, (actor, user) => { - if (!user || user.teamId !== actor.teamId) return false; - if (user.id === actor.id) return true; + if (!user || user.teamId !== actor.teamId) { + return false; + } + if (user.id === actor.id) { + return true; + } throw AdminRequiredError(); }); allow(User, "delete", User, (actor, user) => { - if (!user || user.teamId !== actor.teamId) return false; - if (user.id === actor.id) return true; - if (actor.isAdmin && !user.lastActiveAt) return true; + if (!user || user.teamId !== actor.teamId) { + return false; + } + if (user.id === actor.id) { + return true; + } + if (actor.isAdmin && !user.lastActiveAt) { + return true; + } throw AdminRequiredError(); }); allow(User, ["activate", "suspend"], User, (actor, user) => { - if (!user || user.teamId !== actor.teamId) return false; - if (actor.isAdmin) return true; + if (!user || user.teamId !== actor.teamId) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); allow(User, "readDetails", User, (actor, user) => { - if (!user || user.teamId !== actor.teamId) return false; - if (user === actor) return true; + if (!user || user.teamId !== actor.teamId) { + return false; + } + if (user === actor) { + return true; + } return actor.isAdmin; }); allow(User, "promote", User, (actor, user) => { - if (!user || user.teamId !== actor.teamId) return false; - if (user.isAdmin || user.isSuspended) return false; - if (actor.isAdmin) return true; + if (!user || user.teamId !== actor.teamId) { + return false; + } + if (user.isAdmin || user.isSuspended) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); allow(User, "demote", User, (actor, user) => { - if (!user || user.teamId !== actor.teamId) return false; - if (user.isSuspended) return false; - if (actor.isAdmin) return true; + if (!user || user.teamId !== actor.teamId) { + return false; + } + if (user.isSuspended) { + return false; + } + if (actor.isAdmin) { + return true; + } throw AdminRequiredError(); }); diff --git a/server/queues/processors/backlinks.ts b/server/queues/processors/backlinks.ts index 3a0e6754e..8c34d48c8 100644 --- a/server/queues/processors/backlinks.ts +++ b/server/queues/processors/backlinks.ts @@ -9,7 +9,9 @@ export default class BacklinksProcessor { switch (event.name) { case "documents.publish": { const document = await Document.findByPk(event.documentId); - if (!document) return; + if (!document) { + return; + } const linkIds = parseDocumentIds(document.text); await Promise.all( linkIds.map(async (linkId) => { @@ -35,10 +37,14 @@ export default class BacklinksProcessor { case "documents.update": { const document = await Document.findByPk(event.documentId); - if (!document) return; + if (!document) { + return; + } // backlinks are only created for published documents - if (!document.publishedAt) return; + if (!document.publishedAt) { + return; + } const linkIds = parseDocumentIds(document.text); const linkedDocumentIds: string[] = []; @@ -80,10 +86,14 @@ export default class BacklinksProcessor { case "documents.title_change": { // might as well check const { title, previousTitle } = event.data; - if (!previousTitle || title === previousTitle) break; + if (!previousTitle || title === previousTitle) { + break; + } const document = await Document.findByPk(event.documentId); - if (!document) return; + if (!document) { + return; + } // TODO: Handle re-writing of titles into CRDT const team = await Team.findByPk(document.teamId); diff --git a/server/queues/processors/debouncer.ts b/server/queues/processors/debouncer.ts index ed4d85ec2..466614c8b 100644 --- a/server/queues/processors/debouncer.ts +++ b/server/queues/processors/debouncer.ts @@ -21,12 +21,16 @@ export default class DebounceProcessor { }); // If the document has been deleted then prevent further processing - if (!document) return; + if (!document) { + return; + } // If the document has been updated since we initially queued the delayed // event then abort, there must be another updated event in the queue – // this functions as a simple distributed debounce. - if (document.updatedAt > new Date(event.createdAt)) return; + if (document.updatedAt > new Date(event.createdAt)) { + return; + } globalEventQueue.add({ ...event, name: "documents.update.debounced" }); break; diff --git a/server/queues/processors/notifications.ts b/server/queues/processors/notifications.ts index 5687aec42..a5e9fbd12 100644 --- a/server/queues/processors/notifications.ts +++ b/server/queues/processors/notifications.ts @@ -33,12 +33,16 @@ export default class NotificationsProcessor { async documentUpdated(event: DocumentEvent | RevisionEvent) { // never send notifications when batch importing documents // @ts-expect-error ts-migrate(2339) FIXME: Property 'data' does not exist on type 'DocumentEv... Remove this comment to see the full error message - if (event.data?.source === "import") return; + if (event.data?.source === "import") { + return; + } const [document, team] = await Promise.all([ Document.findByPk(event.documentId), Team.findByPk(event.teamId), ]); - if (!document || !team || !document.collection) return; + if (!document || !team || !document.collection) { + return; + } const { collection } = document; const notificationSettings = await NotificationSetting.findAll({ where: { @@ -132,8 +136,12 @@ export default class NotificationsProcessor { }, ], }); - if (!collection) return; - if (!collection.permission) return; + if (!collection) { + return; + } + if (!collection.permission) { + return; + } const notificationSettings = await NotificationSetting.findAll({ where: { userId: { diff --git a/server/queues/processors/slack.ts b/server/queues/processors/slack.ts index b45a63496..f793ee277 100644 --- a/server/queues/processors/slack.ts +++ b/server/queues/processors/slack.ts @@ -38,10 +38,14 @@ export default class SlackProcessor { }, ], }); - if (!integration) return; + if (!integration) { + return; + } const collection = integration.collection; - if (!collection) return; + if (!collection) { + return; + } await fetch(integration.settings.url, { method: "POST", @@ -65,15 +69,21 @@ export default class SlackProcessor { async documentUpdated(event: DocumentEvent | RevisionEvent) { // never send notifications when batch importing documents // @ts-expect-error ts-migrate(2339) FIXME: Property 'data' does not exist on type 'DocumentEv... Remove this comment to see the full error message - if (event.data && event.data.source === "import") return; + if (event.data && event.data.source === "import") { + return; + } const [document, team] = await Promise.all([ Document.findByPk(event.documentId), Team.findByPk(event.teamId), ]); - if (!document || !team) return; + if (!document || !team) { + return; + } // never send notifications for draft documents - if (!document.publishedAt) return; + if (!document.publishedAt) { + return; + } const integration = await Integration.findOne({ where: { @@ -88,7 +98,9 @@ export default class SlackProcessor { }, }, }); - if (!integration) return; + if (!integration) { + return; + } let text = `${document.updatedBy.name} updated a document`; if (event.name === "documents.publish") { diff --git a/server/routes/api/collections.ts b/server/routes/api/collections.ts index 19a22a81f..66ef572c2 100644 --- a/server/routes/api/collections.ts +++ b/server/routes/api/collections.ts @@ -652,7 +652,9 @@ router.post("collections.delete", auth(), async (ctx) => { authorize(user, "delete", collection); const total = await Collection.count(); - if (total === 1) throw ValidationError("Cannot delete last collection"); + if (total === 1) { + throw ValidationError("Cannot delete last collection"); + } await collection.destroy(); await Event.create({ diff --git a/server/routes/api/documents.ts b/server/routes/api/documents.ts index 1a29414d2..103a892dc 100644 --- a/server/routes/api/documents.ts +++ b/server/routes/api/documents.ts @@ -50,7 +50,9 @@ router.post("documents.list", auth(), pagination(), async (ctx) => { const collectionId = ctx.body.collectionId || ctx.body.collection; const createdById = ctx.body.userId || ctx.body.user; let direction = ctx.body.direction; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } // always filter by the current team const { user } = ctx.state; let where: WhereOptions = { @@ -162,7 +164,9 @@ router.post("documents.archived", auth(), pagination(), async (ctx) => { assertSort(sort, Document); let direction = ctx.body.direction; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } const { user } = ctx.state; const collectionIds = await user.collectionIds(); const collectionScope: Readonly = { @@ -204,7 +208,9 @@ router.post("documents.deleted", auth(), pagination(), async (ctx) => { assertSort(sort, Document); let direction = ctx.body.direction; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } const { user } = ctx.state; const collectionIds = await user.collectionIds({ paranoid: false, @@ -257,7 +263,9 @@ router.post("documents.viewed", auth(), pagination(), async (ctx) => { const { sort = "updatedAt" } = ctx.body; assertSort(sort, Document); - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } const { user } = ctx.state; const collectionIds = await user.collectionIds(); const userId = user.id; @@ -318,7 +326,9 @@ router.post("documents.starred", auth(), pagination(), async (ctx) => { const { sort = "updatedAt" } = ctx.body; assertSort(sort, Document); - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } const { user } = ctx.state; const collectionIds = await user.collectionIds(); const stars = await Star.findAll({ @@ -371,7 +381,9 @@ router.post("documents.drafts", auth(), pagination(), async (ctx) => { const { collectionId, dateFilter, sort = "updatedAt" } = ctx.body; assertSort(sort, Document); - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } const { user } = ctx.state; if (collectionId) { @@ -997,7 +1009,9 @@ router.post("documents.update", auth(), async (ctx) => { const editorVersion = ctx.headers["x-editor-version"] as string | undefined; assertPresent(id, "id is required"); assertPresent(title || text, "title or text is required"); - if (append) assertPresent(text, "Text is required while appending"); + if (append) { + assertPresent(text, "Text is required while appending"); + } const { user } = ctx.state; const document = await Document.findByPk(id, { @@ -1012,10 +1026,18 @@ router.post("documents.update", auth(), async (ctx) => { const previousTitle = document.title; // Update document - if (title) document.title = title; - if (editorVersion) document.editorVersion = editorVersion; - if (templateId) document.templateId = templateId; - if (fullWidth !== undefined) document.fullWidth = fullWidth; + if (title) { + document.title = title; + } + if (editorVersion) { + document.editorVersion = editorVersion; + } + if (templateId) { + document.templateId = templateId; + } + if (fullWidth !== undefined) { + document.fullWidth = fullWidth; + } if (!user.team?.collaborativeEditing) { if (append) { @@ -1303,7 +1325,9 @@ router.post("documents.import", auth(), async (ctx) => { assertUuid(parentDocumentId, "parentDocumentId must be an uuid"); } - if (index) assertPositiveInteger(index, "index must be an integer (>=0)"); + if (index) { + assertPositiveInteger(index, "index must be an integer (>=0)"); + } const { user } = ctx.state; authorize(user, "createDocument", user.team); @@ -1372,7 +1396,9 @@ router.post("documents.create", auth(), async (ctx) => { assertUuid(parentDocumentId, "parentDocumentId must be an uuid"); } - if (index) assertPositiveInteger(index, "index must be an integer (>=0)"); + if (index) { + assertPositiveInteger(index, "index must be an integer (>=0)"); + } const { user } = ctx.state; authorize(user, "createDocument", user.team); diff --git a/server/routes/api/events.ts b/server/routes/api/events.ts index af82f0bc9..f9830cc6e 100644 --- a/server/routes/api/events.ts +++ b/server/routes/api/events.ts @@ -20,7 +20,9 @@ router.post("events.list", auth(), pagination(), async (ctx) => { name, auditLog = false, } = ctx.body; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } assertSort(sort, Event); let where: WhereOptions = { diff --git a/server/routes/api/fileOperations.ts b/server/routes/api/fileOperations.ts index 52398e8ad..b58c116ea 100644 --- a/server/routes/api/fileOperations.ts +++ b/server/routes/api/fileOperations.ts @@ -42,7 +42,9 @@ router.post("fileOperations.list", auth(), pagination(), async (ctx) => { "type must be one of 'import' or 'export'" ); - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } const { user } = ctx.state; const where: WhereOptions = { teamId: user.teamId, diff --git a/server/routes/api/groups.ts b/server/routes/api/groups.ts index a2fc1fe61..d6495b89e 100644 --- a/server/routes/api/groups.ts +++ b/server/routes/api/groups.ts @@ -19,7 +19,9 @@ const router = new Router(); router.post("groups.list", auth(), pagination(), async (ctx) => { let { direction } = ctx.body; const { sort = "updatedAt" } = ctx.body; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } assertSort(sort, Group); const { user } = ctx.state; diff --git a/server/routes/api/hooks.ts b/server/routes/api/hooks.ts index 2f03f60ad..22e70cd0d 100644 --- a/server/routes/api/hooks.ts +++ b/server/routes/api/hooks.ts @@ -21,7 +21,9 @@ const router = new Router(); // triggered by a user posting a getoutline.com link in Slack router.post("hooks.unfurl", async (ctx) => { const { challenge, token, event } = ctx.body; - if (challenge) return (ctx.body = ctx.body.challenge); + if (challenge) { + return (ctx.body = ctx.body.challenge); + } if (token !== process.env.SLACK_VERIFICATION_TOKEN) { throw AuthenticationError("Invalid token"); @@ -39,21 +41,27 @@ router.post("hooks.unfurl", async (ctx) => { }, ], }); - if (!user) return; + if (!user) { + return; + } const auth = await IntegrationAuthentication.findOne({ where: { service: "slack", teamId: user.teamId, }, }); - if (!auth) return; + if (!auth) { + return; + } // get content for unfurled links const unfurls = {}; for (const link of event.links) { const id = link.url.substr(link.url.lastIndexOf("/") + 1); const doc = await Document.findByPk(id); - if (!doc || doc.teamId !== user.teamId) continue; + if (!doc || doc.teamId !== user.teamId) { + continue; + } unfurls[link.url] = { title: doc.title, text: doc.getSummary(), diff --git a/server/routes/api/integrations.ts b/server/routes/api/integrations.ts index c1b55494c..a02a09b3d 100644 --- a/server/routes/api/integrations.ts +++ b/server/routes/api/integrations.ts @@ -12,7 +12,9 @@ const router = new Router(); router.post("integrations.list", auth(), pagination(), async (ctx) => { let { direction } = ctx.body; const { sort = "updatedAt" } = ctx.body; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } assertSort(sort, Integration); const { user } = ctx.state; diff --git a/server/routes/api/revisions.ts b/server/routes/api/revisions.ts index 0b72110ae..f8a94d634 100644 --- a/server/routes/api/revisions.ts +++ b/server/routes/api/revisions.ts @@ -33,7 +33,9 @@ router.post("revisions.info", auth(), async (ctx) => { router.post("revisions.list", auth(), pagination(), async (ctx) => { let { direction } = ctx.body; const { documentId, sort = "updatedAt" } = ctx.body; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } assertSort(sort, Revision); assertPresent(documentId, "documentId is required"); diff --git a/server/routes/api/shares.ts b/server/routes/api/shares.ts index fe31e8037..967252ba7 100644 --- a/server/routes/api/shares.ts +++ b/server/routes/api/shares.ts @@ -100,7 +100,9 @@ router.post("shares.info", auth(), async (ctx) => { router.post("shares.list", auth(), pagination(), async (ctx) => { let { direction } = ctx.body; const { sort = "updatedAt" } = ctx.body; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } assertSort(sort, Share); const { user } = ctx.state; diff --git a/server/routes/api/team.ts b/server/routes/api/team.ts index 11f197ef9..e931a3d36 100644 --- a/server/routes/api/team.ts +++ b/server/routes/api/team.ts @@ -25,11 +25,21 @@ router.post("team.update", auth(), async (ctx) => { team.subdomain = subdomain === "" ? null : subdomain; } - if (name) team.name = name; - if (sharing !== undefined) team.sharing = sharing; - if (documentEmbeds !== undefined) team.documentEmbeds = documentEmbeds; - if (guestSignin !== undefined) team.guestSignin = guestSignin; - if (avatarUrl !== undefined) team.avatarUrl = avatarUrl; + if (name) { + team.name = name; + } + if (sharing !== undefined) { + team.sharing = sharing; + } + if (documentEmbeds !== undefined) { + team.documentEmbeds = documentEmbeds; + } + if (guestSignin !== undefined) { + team.guestSignin = guestSignin; + } + if (avatarUrl !== undefined) { + team.avatarUrl = avatarUrl; + } if (collaborativeEditing !== undefined) { team.collaborativeEditing = collaborativeEditing; diff --git a/server/routes/api/users.ts b/server/routes/api/users.ts index a290b64ab..c5ebbba5c 100644 --- a/server/routes/api/users.ts +++ b/server/routes/api/users.ts @@ -20,7 +20,9 @@ const router = new Router(); router.post("users.list", auth(), pagination(), async (ctx) => { let { direction } = ctx.body; const { sort = "createdAt", query, filter } = ctx.body; - if (direction !== "ASC") direction = "DESC"; + if (direction !== "ASC") { + direction = "DESC"; + } assertSort(sort, User); if (filter) { @@ -138,9 +140,15 @@ router.post("users.info", auth(), async (ctx) => { router.post("users.update", auth(), async (ctx) => { const { user } = ctx.state; const { name, avatarUrl, language } = ctx.body; - if (name) user.name = name; - if (avatarUrl) user.avatarUrl = avatarUrl; - if (language) user.language = language; + if (name) { + user.name = name; + } + if (avatarUrl) { + user.avatarUrl = avatarUrl; + } + if (language) { + user.language = language; + } await user.save(); await Event.create({ name: "users.update", diff --git a/server/utils/prefetchTags.tsx b/server/utils/prefetchTags.tsx index f6a14a402..1c69c03da 100644 --- a/server/utils/prefetchTags.tsx +++ b/server/utils/prefetchTags.tsx @@ -30,8 +30,12 @@ try { let index = 0; Object.values(manifestData).forEach((filename) => { - if (typeof filename !== "string") return; - if (!env.CDN_URL) return; + if (typeof filename !== "string") { + return; + } + if (!env.CDN_URL) { + return; + } if (filename.endsWith(".js")) { // Preload resources you have high-confidence will be used in the current diff --git a/server/utils/zip.ts b/server/utils/zip.ts index 0250d4a68..473d495cc 100644 --- a/server/utils/zip.ts +++ b/server/utils/zip.ts @@ -71,7 +71,9 @@ async function archiveToPath(zip: JSZip) { postfix: ".zip", }, (err, path) => { - if (err) return reject(err); + if (err) { + return reject(err); + } zip .generateNodeStream({ type: "nodebuffer", diff --git a/shared/editor/commands/backspaceToParagraph.ts b/shared/editor/commands/backspaceToParagraph.ts index ae06ba43f..b6c35fe28 100644 --- a/shared/editor/commands/backspaceToParagraph.ts +++ b/shared/editor/commands/backspaceToParagraph.ts @@ -6,14 +6,20 @@ export default function backspaceToParagraph(type: NodeType) { const { $from, from, to, empty } = state.selection; // if the selection has anything in it then use standard delete behavior - if (!empty) return null; + if (!empty) { + return null; + } // check we're in a matching node - if ($from.parent.type !== type) return null; + if ($from.parent.type !== type) { + return null; + } // check if we're at the beginning of the heading const $pos = state.doc.resolve(from - 1); - if ($pos.parent === $from.parent) return null; + if ($pos.parent === $from.parent) { + return null; + } // okay, replace it with a paragraph dispatch( diff --git a/shared/editor/commands/createAndInsertLink.ts b/shared/editor/commands/createAndInsertLink.ts index 7c267eab9..d2e9f10f1 100644 --- a/shared/editor/commands/createAndInsertLink.ts +++ b/shared/editor/commands/createAndInsertLink.ts @@ -48,7 +48,9 @@ const createAndInsertLink = async function ( const url = await onCreateLink(title); const result = findPlaceholderLink(view.state.doc, href); - if (!result) return; + if (!result) { + return; + } dispatch( view.state.tr @@ -65,7 +67,9 @@ const createAndInsertLink = async function ( ); } catch (err) { const result = findPlaceholderLink(view.state.doc, href); - if (!result) return; + if (!result) { + return; + } dispatch( view.state.tr.removeMark( diff --git a/shared/editor/commands/insertFiles.ts b/shared/editor/commands/insertFiles.ts index 986502c20..ca320836d 100644 --- a/shared/editor/commands/insertFiles.ts +++ b/shared/editor/commands/insertFiles.ts @@ -25,7 +25,9 @@ const insertFiles = function ( ): void { // filter to only include image files const images = files.filter((file) => /image/i.test(file.type)); - if (images.length === 0) return; + if (images.length === 0) { + return; + } const { dictionary, @@ -47,7 +49,9 @@ const insertFiles = function ( event.preventDefault(); // let the user know we're starting to process the images - if (onImageUploadStart) onImageUploadStart(); + if (onImageUploadStart) { + onImageUploadStart(); + } const { schema } = view.state; diff --git a/shared/editor/commands/splitHeading.ts b/shared/editor/commands/splitHeading.ts index e5b7e6298..59f52bff6 100644 --- a/shared/editor/commands/splitHeading.ts +++ b/shared/editor/commands/splitHeading.ts @@ -8,15 +8,21 @@ export default function splitHeading(type: NodeType) { const { $from, from, $to, to } = state.selection; // check we're in a matching heading node - if ($from.parent.type !== type) return false; + if ($from.parent.type !== type) { + return false; + } // check that the caret is at the end of the content, if it isn't then // standard node splitting behaviour applies const endPos = $to.after() - 1; - if (endPos !== to) return false; + if (endPos !== to) { + return false; + } // If the node isn't collapsed standard behavior applies - if (!$from.parent.attrs.collapsed) return false; + if (!$from.parent.attrs.collapsed) { + return false; + } // Find the next visible block after this one. It takes into account nested // collapsed headings and reaching the end of the document diff --git a/shared/editor/embeds/components/Frame.tsx b/shared/editor/embeds/components/Frame.tsx index ea4e6c5db..b721447e0 100644 --- a/shared/editor/embeds/components/Frame.tsx +++ b/shared/editor/embeds/components/Frame.tsx @@ -37,7 +37,9 @@ class Frame extends React.Component { } loadIframe = () => { - if (!this.mounted) return; + if (!this.mounted) { + return; + } this.isLoaded = true; }; diff --git a/shared/editor/lib/ExtensionManager.ts b/shared/editor/lib/ExtensionManager.ts index b2b3a306f..af14e4f96 100644 --- a/shared/editor/lib/ExtensionManager.ts +++ b/shared/editor/lib/ExtensionManager.ts @@ -73,7 +73,9 @@ export default class ExtensionManager { ) .reduce((nodes, extension: Node | Mark) => { const md = extension.parseMarkdown(); - if (!md) return nodes; + if (!md) { + return nodes; + } return { ...nodes, diff --git a/shared/editor/lib/filterExcessSeparators.ts b/shared/editor/lib/filterExcessSeparators.ts index a57ad680e..48f6bcf58 100644 --- a/shared/editor/lib/filterExcessSeparators.ts +++ b/shared/editor/lib/filterExcessSeparators.ts @@ -5,17 +5,23 @@ export default function filterExcessSeparators( ): (MenuItem | EmbedDescriptor)[] { return items.reduce((acc, item, index) => { // trim separators from start / end - if (item.name === "separator" && index === 0) return acc; - if (item.name === "separator" && index === items.length - 1) return acc; + if (item.name === "separator" && index === 0) { + return acc; + } + if (item.name === "separator" && index === items.length - 1) { + return acc; + } // trim double separators looking ahead / behind const prev = items[index - 1]; - if (prev && prev.name === "separator" && item.name === "separator") + if (prev && prev.name === "separator" && item.name === "separator") { return acc; + } const next = items[index + 1]; - if (next && next.name === "separator" && item.name === "separator") + if (next && next.name === "separator" && item.name === "separator") { return acc; + } // otherwise, continue return [...acc, item]; diff --git a/shared/editor/lib/headingToSlug.ts b/shared/editor/lib/headingToSlug.ts index d467f7814..71fd3b75b 100644 --- a/shared/editor/lib/headingToSlug.ts +++ b/shared/editor/lib/headingToSlug.ts @@ -18,7 +18,9 @@ function safeSlugify(text: string) { // in the document that is as stable as possible export default function headingToSlug(node: Node, index = 0) { const slugified = safeSlugify(node.textContent); - if (index === 0) return slugified; + if (index === 0) { + return slugified; + } return `${slugified}-${index}`; } diff --git a/shared/editor/lib/isMarkdown.ts b/shared/editor/lib/isMarkdown.ts index 994ebe33f..1b660ae51 100644 --- a/shared/editor/lib/isMarkdown.ts +++ b/shared/editor/lib/isMarkdown.ts @@ -1,18 +1,28 @@ export default function isMarkdown(text: string): boolean { // code-ish const fences = text.match(/^```/gm); - if (fences && fences.length > 1) return true; + if (fences && fences.length > 1) { + return true; + } // link-ish - if (text.match(/\[[^]+\]\(https?:\/\/\S+\)/gm)) return true; - if (text.match(/\[[^]+\]\(\/\S+\)/gm)) return true; + if (text.match(/\[[^]+\]\(https?:\/\/\S+\)/gm)) { + return true; + } + if (text.match(/\[[^]+\]\(\/\S+\)/gm)) { + return true; + } // heading-ish - if (text.match(/^#{1,6}\s+\S+/gm)) return true; + if (text.match(/^#{1,6}\s+\S+/gm)) { + return true; + } // list-ish const listItems = text.match(/^[\d-*].?\s\S+/gm); - if (listItems && listItems.length > 1) return true; + if (listItems && listItems.length > 1) { + return true; + } return false; } diff --git a/shared/editor/lib/markdown/serializer.ts b/shared/editor/lib/markdown/serializer.ts index cd8732717..5c83c78ff 100644 --- a/shared/editor/lib/markdown/serializer.ts +++ b/shared/editor/lib/markdown/serializer.ts @@ -80,20 +80,28 @@ export class MarkdownSerializerState { // on a node level by specifying a tight attribute on the node. // Defaults to false. this.options = options || {}; - if (typeof this.options.tightLists === "undefined") + if (typeof this.options.tightLists === "undefined") { this.options.tightLists = true; + } } flushClose(size) { if (this.closed) { - if (!this.atBlank()) this.out += "\n"; - if (size === null || size === undefined) size = 2; + if (!this.atBlank()) { + this.out += "\n"; + } + if (size === null || size === undefined) { + size = 2; + } if (size > 1) { let delimMin = this.delim; const trim = /\s+$/.exec(delimMin); - if (trim) + if (trim) { delimMin = delimMin.slice(0, delimMin.length - trim[0].length); - for (let i = 1; i < size; i++) this.out += delimMin + "\n"; + } + for (let i = 1; i < size; i++) { + this.out += delimMin + "\n"; + } } this.closed = false; } @@ -120,7 +128,9 @@ export class MarkdownSerializerState { // :: () // Ensure the current content ends with a newline. ensureNewLine() { - if (!this.atBlank()) this.out += "\n"; + if (!this.atBlank()) { + this.out += "\n"; + } } // :: (?string) @@ -129,8 +139,12 @@ export class MarkdownSerializerState { // (unescaped) to the output. write(content) { this.flushClose(); - if (this.delim && this.atBlank()) this.out += this.delim; - if (content) this.out += content; + if (this.delim && this.atBlank()) { + this.out += this.delim; + } + if (content) { + this.out += content; + } } // :: (Node) @@ -148,14 +162,18 @@ export class MarkdownSerializerState { const startOfLine = this.atBlank() || this.closed; this.write(); this.out += escape !== false ? this.esc(lines[i], startOfLine) : lines[i]; - if (i !== lines.length - 1) this.out += "\n"; + if (i !== lines.length - 1) { + this.out += "\n"; + } } } // :: (Node) // Render the given node as a block. render(node, parent, index) { - if (typeof parent === "number") throw new Error("!"); + if (typeof parent === "number") { + throw new Error("!"); + } this.nodes[node.type.name](this, node, parent, index); } @@ -178,14 +196,17 @@ export class MarkdownSerializerState { // before closing marks. // (FIXME it'd be nice if we had a schema-agnostic way to // identify nodes that serialize as hard breaks) - if (node && node.type.name === "hard_break") + if (node && node.type.name === "hard_break") { marks = marks.filter((m) => { - if (index + 1 === parent.childCount) return false; + if (index + 1 === parent.childCount) { + return false; + } const next = parent.child(index + 1); return ( m.isInSet(next.marks) && (!next.isText || /\S/.test(next.text)) ); }); + } let leading = trailing; trailing = ""; @@ -205,7 +226,9 @@ export class MarkdownSerializerState { trailing = trail; if (lead || trail) { node = inner ? node.withText(inner) : null; - if (!node) marks = active; + if (!node) { + marks = active; + } } } @@ -219,23 +242,28 @@ export class MarkdownSerializerState { // active. outer: for (let i = 0; i < len; i++) { const mark = marks[i]; - if (!this.marks[mark.type.name]().mixable) break; + if (!this.marks[mark.type.name]().mixable) { + break; + } for (let j = 0; j < active.length; j++) { const other = active[j]; - if (!this.marks[other.type.name]().mixable) break; + if (!this.marks[other.type.name]().mixable) { + break; + } if (mark.eq(other)) { - if (i > j) + if (i > j) { marks = marks .slice(0, j) .concat(mark) .concat(marks.slice(j, i)) .concat(marks.slice(i + 1, len)); - else if (j > i) + } else if (j > i) { marks = marks .slice(0, i) .concat(marks.slice(i + 1, j)) .concat(mark) .concat(marks.slice(j, len)); + } continue outer; } } @@ -246,15 +274,19 @@ export class MarkdownSerializerState { while ( keep < Math.min(active.length, len) && marks[keep].eq(active[keep]) - ) + ) { ++keep; + } // Close the marks that need to be closed - while (keep < active.length) + while (keep < active.length) { this.text(this.markString(active.pop(), false, parent, index), false); + } // Output any previously expelled trailing whitespace outside the marks - if (leading) this.text(leading); + if (leading) { + this.text(leading); + } // Open the marks that need to be opened if (node) { @@ -266,14 +298,16 @@ export class MarkdownSerializerState { // Render the node. Special case code marks, since their content // may not be escaped. - if (noEsc && node.isText) + if (noEsc && node.isText) { this.text( this.markString(inner, true, parent, index) + node.text + this.markString(inner, false, parent, index + 1), false ); - else this.render(node, parent, index); + } else { + this.render(node, parent, index); + } } }; parent.forEach(progress); @@ -286,8 +320,11 @@ export class MarkdownSerializerState { // `firstDelim` is a function going from an item index to a // delimiter for the first line of the item. renderList(node, delim, firstDelim) { - if (this.closed && this.closed.type === node.type) this.flushClose(3); - else if (this.inTightList) this.flushClose(1); + if (this.closed && this.closed.type === node.type) { + this.flushClose(3); + } else if (this.inTightList) { + this.flushClose(1); + } const isTight = typeof node.attrs.tight !== "undefined" @@ -298,7 +335,9 @@ export class MarkdownSerializerState { this.inList = true; this.inTightList = isTight; node.forEach((child, _, i) => { - if (i && isTight) this.flushClose(1); + if (i && isTight) { + this.flushClose(1); + } this.wrapBlock(delim, firstDelim(i), node, () => this.render(child, node, i) ); @@ -387,7 +426,9 @@ export class MarkdownSerializerState { // Repeat the given string `n` times. repeat(str, n) { let out = ""; - for (let i = 0; i < n; i++) out += str; + for (let i = 0; i < n; i++) { + out += str; + } return out; } diff --git a/shared/editor/marks/Placeholder.ts b/shared/editor/marks/Placeholder.ts index 14092601c..84591b229 100644 --- a/shared/editor/marks/Placeholder.ts +++ b/shared/editor/marks/Placeholder.ts @@ -46,7 +46,9 @@ export default class Placeholder extends Mark { const $from = state.doc.resolve(from); const range = getMarkRange($from, state.schema.marks.placeholder); - if (!range) return false; + if (!range) { + return false; + } const selectionStart = Math.min(from, range.from); const selectionEnd = Math.max(to, range.to); @@ -88,7 +90,9 @@ export default class Placeholder extends Mark { state.doc.resolve(Math.max(0, state.selection.from - 1)), state.schema.marks.placeholder ); - if (!range) return false; + if (!range) { + return false; + } dispatch( state.tr @@ -107,7 +111,9 @@ export default class Placeholder extends Mark { state.doc.resolve(Math.max(0, state.selection.from - 1)), state.schema.marks.placeholder ); - if (!range) return false; + if (!range) { + return false; + } const startOfMark = state.doc.resolve(range.from); dispatch(state.tr.setSelection(TextSelection.near(startOfMark))); @@ -119,7 +125,9 @@ export default class Placeholder extends Mark { state.selection.$from, state.schema.marks.placeholder ); - if (!range) return false; + if (!range) { + return false; + } const endOfMark = state.doc.resolve(range.to); dispatch(state.tr.setSelection(TextSelection.near(endOfMark))); @@ -145,7 +153,9 @@ export default class Placeholder extends Mark { state.selection.$from, state.schema.marks.placeholder ); - if (!range) return false; + if (!range) { + return false; + } event.stopPropagation(); event.preventDefault(); diff --git a/shared/editor/nodes/CodeFence.ts b/shared/editor/nodes/CodeFence.ts index 3b8b6e0fb..754bb1565 100644 --- a/shared/editor/nodes/CodeFence.ts +++ b/shared/editor/nodes/CodeFence.ts @@ -150,7 +150,9 @@ export default class CodeFence extends Node { state: EditorState, dispatch: (tr: Transaction) => void ) => { - if (!isInCode(state)) return false; + if (!isInCode(state)) { + return false; + } const { tr, selection, @@ -171,7 +173,9 @@ export default class CodeFence extends Node { return true; }, Tab: (state: EditorState, dispatch: (tr: Transaction) => void) => { - if (!isInCode(state)) return false; + if (!isInCode(state)) { + return false; + } const { tr, selection } = state; dispatch(tr.insertText(" ", selection.from, selection.to)); diff --git a/shared/editor/nodes/HardBreak.ts b/shared/editor/nodes/HardBreak.ts index 9389e2327..4a25f3b76 100644 --- a/shared/editor/nodes/HardBreak.ts +++ b/shared/editor/nodes/HardBreak.ts @@ -39,7 +39,9 @@ export default class HardBreak extends Node { state: EditorState, dispatch: (tr: Transaction) => void ) => { - if (!isInTable(state)) return false; + if (!isInTable(state)) { + return false; + } dispatch(state.tr.replaceSelectionWith(type.create()).scrollIntoView()); return true; }, diff --git a/shared/editor/nodes/Heading.ts b/shared/editor/nodes/Heading.ts index 983590c24..3104cdfb0 100644 --- a/shared/editor/nodes/Heading.ts +++ b/shared/editor/nodes/Heading.ts @@ -216,7 +216,9 @@ export default class Heading extends Node { const previouslySeen = {}; doc.descendants((node, pos) => { - if (node.type.name !== this.name) return; + if (node.type.name !== this.name) { + return; + } // calculate the optimal id const slug = headingToSlug(node); diff --git a/shared/editor/nodes/Image.tsx b/shared/editor/nodes/Image.tsx index 91fc79359..e2b06031c 100644 --- a/shared/editor/nodes/Image.tsx +++ b/shared/editor/nodes/Image.tsx @@ -41,7 +41,9 @@ const uploadPlugin = (options: Options) => return false; } - if (!event.clipboardData) return false; + if (!event.clipboardData) { + return false; + } // check if we actually pasted any files const files = Array.prototype.slice @@ -49,7 +51,9 @@ const uploadPlugin = (options: Options) => .map((dt: any) => dt.getAsFile()) .filter((file: File) => file); - if (files.length === 0) return false; + if (files.length === 0) { + return false; + } const { tr } = view.state; if (!tr.selection.empty) { @@ -96,7 +100,9 @@ const uploadPlugin = (options: Options) => const IMAGE_CLASSES = ["right-50", "left-50"]; const getLayoutAndTitle = (tokenTitle: string | null) => { - if (!tokenTitle) return {}; + if (!tokenTitle) { + return {}; + } if (IMAGE_CLASSES.includes(tokenTitle)) { return { layoutClass: tokenTitle, @@ -242,7 +248,9 @@ export default class Image extends Node { const alt = event.currentTarget.innerText; const { src, title, layoutClass } = node.attrs; - if (alt === node.attrs.alt) return; + if (alt === node.attrs.alt) { + return; + } const { view } = this.editor; const { tr } = view.state; diff --git a/shared/editor/nodes/ListItem.ts b/shared/editor/nodes/ListItem.ts index f9fb090fa..9070657a9 100644 --- a/shared/editor/nodes/ListItem.ts +++ b/shared/editor/nodes/ListItem.ts @@ -203,8 +203,12 @@ export default class ListItem extends Node { state: EditorState, dispatch: (tr: Transaction) => void ) => { - if (!isInList(state)) return false; - if (!state.selection.empty) return false; + if (!isInList(state)) { + return false; + } + if (!state.selection.empty) { + return false; + } const { tr, selection } = state; dispatch(tr.split(selection.to)); @@ -214,9 +218,13 @@ export default class ListItem extends Node { state: EditorState, dispatch: (tr: Transaction) => void ) => { - if (!state.selection.empty) return false; + if (!state.selection.empty) { + return false; + } const result = getParentListItem(state); - if (!result) return false; + if (!result) { + return false; + } const [li, pos] = result; const $pos = state.doc.resolve(pos); @@ -244,9 +252,13 @@ export default class ListItem extends Node { state: EditorState, dispatch: (tr: Transaction) => void ) => { - if (!state.selection.empty) return false; + if (!state.selection.empty) { + return false; + } const result = getParentListItem(state); - if (!result) return false; + if (!result) { + return false; + } const [li, pos] = result; const $pos = state.doc.resolve(pos + li.nodeSize); diff --git a/shared/editor/nodes/Table.ts b/shared/editor/nodes/Table.ts index 90de2225f..d2be72656 100644 --- a/shared/editor/nodes/Table.ts +++ b/shared/editor/nodes/Table.ts @@ -124,7 +124,9 @@ export default class Table extends Node { Tab: goToNextCell(1), "Shift-Tab": goToNextCell(-1), Enter: (state: EditorState, dispatch: (tr: Transaction) => void) => { - if (!isInTable(state)) return false; + if (!isInTable(state)) { + return false; + } // TODO: Adding row at the end for now, can we find the current cell // row index and add the row below that? @@ -156,11 +158,15 @@ export default class Table extends Node { let index = 0; doc.descendants((node, pos) => { - if (node.type.name !== this.name) return; + if (node.type.name !== this.name) { + return; + } const elements = document.getElementsByClassName("rme-table"); const table = elements[index]; - if (!table) return; + if (!table) { + return; + } const element = table.parentElement; const shadowRight = !!( diff --git a/shared/editor/plugins/BlockMenuTrigger.tsx b/shared/editor/plugins/BlockMenuTrigger.tsx index 2b77c8a10..63d7342c0 100644 --- a/shared/editor/plugins/BlockMenuTrigger.tsx +++ b/shared/editor/plugins/BlockMenuTrigger.tsx @@ -44,7 +44,9 @@ export function run( const match = regex.exec(textBefore); const tr = handler(state, match, match ? from - match[0].length : from, to); - if (!tr) return false; + if (!tr) { + return false; + } return true; } diff --git a/shared/editor/plugins/Folding.tsx b/shared/editor/plugins/Folding.tsx index 14d60d780..ef287bfc1 100644 --- a/shared/editor/plugins/Folding.tsx +++ b/shared/editor/plugins/Folding.tsx @@ -21,7 +21,9 @@ export default class Folding extends Extension { return {}; }, appendTransaction: (transactions, oldState, newState) => { - if (loaded) return; + if (loaded) { + return; + } if ( !transactions.some((transaction) => transaction.getMeta("folding")) ) { diff --git a/shared/editor/plugins/PasteHandler.ts b/shared/editor/plugins/PasteHandler.ts index dfcc54433..5d8f1d6e2 100644 --- a/shared/editor/plugins/PasteHandler.ts +++ b/shared/editor/plugins/PasteHandler.ts @@ -53,7 +53,9 @@ export default class PasteHandler extends Extension { if (view.props.editable && !view.props.editable(view.state)) { return false; } - if (!event.clipboardData) return false; + if (!event.clipboardData) { + return false; + } const text = event.clipboardData.getData("text/plain"); const html = event.clipboardData.getData("text/html"); diff --git a/shared/editor/queries/getColumnIndex.ts b/shared/editor/queries/getColumnIndex.ts index 8b5ffceab..e82956528 100644 --- a/shared/editor/queries/getColumnIndex.ts +++ b/shared/editor/queries/getColumnIndex.ts @@ -2,7 +2,9 @@ import { CellSelection } from "prosemirror-tables"; export default function getColumnIndex(selection: CellSelection) { const isColSelection = selection.isColSelection && selection.isColSelection(); - if (!isColSelection) return undefined; + if (!isColSelection) { + return undefined; + } const path = (selection.$from as any).path; return path[path.length - 5]; diff --git a/shared/editor/queries/getRowIndex.ts b/shared/editor/queries/getRowIndex.ts index 7cab1f3cd..39cbb8f3f 100644 --- a/shared/editor/queries/getRowIndex.ts +++ b/shared/editor/queries/getRowIndex.ts @@ -2,7 +2,9 @@ import { CellSelection } from "prosemirror-tables"; export default function getRowIndex(selection: CellSelection) { const isRowSelection = selection.isRowSelection && selection.isRowSelection(); - if (!isRowSelection) return undefined; + if (!isRowSelection) { + return undefined; + } const path = (selection.$from as any).path; return path[path.length - 8]; diff --git a/shared/editor/rules/breaks.ts b/shared/editor/rules/breaks.ts index 56a406e27..fd2863f70 100644 --- a/shared/editor/rules/breaks.ts +++ b/shared/editor/rules/breaks.ts @@ -26,7 +26,9 @@ export default function markdownBreakToParagraphs(md: MarkdownIt) { const children = tokenChildren.filter((child) => !isHardbreak(child)); let count = matches.length; - if (children.length) count++; + if (children.length) { + count++; + } for (let i = 0; i < count; i++) { const isLast = i === count - 1; diff --git a/shared/editor/rules/embeds.ts b/shared/editor/rules/embeds.ts index 923d70653..1089ce8f5 100644 --- a/shared/editor/rules/embeds.ts +++ b/shared/editor/rules/embeds.ts @@ -23,8 +23,12 @@ export default function (embeds: EmbedDescriptor[]) { const href = link.attrs ? link.attrs[0][1] : ""; const simpleLink = href === token.content; - if (!simpleLink) return false; - if (!embeds) return false; + if (!simpleLink) { + return false; + } + if (!embeds) { + return false; + } for (const embed of embeds) { const matches = embed.matcher(href); @@ -51,7 +55,9 @@ export default function (embeds: EmbedDescriptor[]) { for (let j = 0; j < tokenChildren.length - 1; j++) { const current = tokenChildren[j]; - if (!current) continue; + if (!current) { + continue; + } if (isLinkOpen(current)) { insideLink = current; diff --git a/shared/utils/domains.ts b/shared/utils/domains.ts index 3b1024773..9daafff62 100644 --- a/shared/utils/domains.ts +++ b/shared/utils/domains.ts @@ -10,8 +10,12 @@ type Domain = { // a large list of possible TLD's which increase the size of the bundle // unnecessarily for our usecase of trusted input. export function parseDomain(url?: string): Domain | null | undefined { - if (typeof url !== "string") return null; - if (url === "") return null; + if (typeof url !== "string") { + return null; + } + if (url === "") { + return null; + } // strip extermeties and whitespace from input const normalizedDomain = trim(url.replace(/(https?:)?\/\//, "")); @@ -54,8 +58,12 @@ export function parseDomain(url?: string): Domain | null | undefined { export function stripSubdomain(hostname: string) { const parsed = parseDomain(hostname); - if (!parsed) return hostname; - if (parsed.tld) return `${parsed.domain}.${parsed.tld}`; + if (!parsed) { + return hostname; + } + if (parsed.tld) { + return `${parsed.domain}.${parsed.tld}`; + } return parsed.domain; } diff --git a/shared/utils/naturalSort.ts b/shared/utils/naturalSort.ts index 6f104814a..8cb7ad11b 100644 --- a/shared/utils/naturalSort.ts +++ b/shared/utils/naturalSort.ts @@ -30,7 +30,9 @@ function naturalSortBy( key: string | ((item: T) => string), sortOptions?: NaturalSortOptions ): T[] { - if (!items) return []; + if (!items) { + return []; + } const sort = sortOptions ? naturalSort({ caseSensitive: sortOptions.caseSensitive,