From 43fbe729f924d618f3dbdbc2cdefee05481b0dfc Mon Sep 17 00:00:00 2001 From: tonyrewin Date: Sat, 8 Oct 2022 19:40:58 +0300 Subject: [PATCH] editor refactoring --- package.json | 2 - src/components/Discours/Donate.tsx | 6 +- .../Editor/{ => components}/ArticlesList.tsx | 2 +- .../Editor/{ => components}/Error.tsx | 2 +- .../Editor/{ => components}/Layout.tsx | 11 +- .../Editor/{ => components}/Sidebar.tsx | 48 +++--- src/components/Editor/index.tsx | 4 +- .../Editor/prosemirror/extension/base.ts | 2 +- .../Editor/prosemirror/extension/code.ts | 2 +- .../Editor/prosemirror/extension/collab.ts | 4 +- .../prosemirror/extension/drag-handle.ts | 2 +- .../Editor/prosemirror/extension/image.ts | 9 +- .../Editor/prosemirror/extension/link.ts | 47 +----- .../prosemirror/extension/mark-input-rule.ts | 16 +- .../Editor/prosemirror/extension/markdown.ts | 2 +- .../Editor/prosemirror/extension/menu.ts | 2 +- .../prosemirror/extension/paste-markdown.ts | 2 +- .../prosemirror/extension/placeholder.ts | 2 +- .../Editor/prosemirror/extension/prompt.ts | 58 +++----- .../Editor/prosemirror/extension/scroll.ts | 2 +- .../Editor/prosemirror/extension/selection.ts | 21 +-- .../prosemirror/extension/strikethrough.ts | 2 +- .../Editor/prosemirror/extension/table.ts | 2 +- .../Editor/prosemirror/extension/todo-list.ts | 2 +- src/components/Editor/prosemirror/index.tsx | 15 +- src/components/Editor/prosemirror/setup.ts | 4 +- .../Editor/{prosemirror => store}/context.ts | 0 .../Editor/{prosemirror => store}/ctrl.ts | 139 +++++++++--------- .../Editor/{prosemirror => store}/state.ts | 4 +- .../Editor/{ => styles}/ArticlesList.scss | 0 .../Editor/{ => styles}/Button.scss | 0 .../Editor/{ => styles}/Editor.scss | 0 src/components/Editor/{ => styles}/Error.scss | 0 .../Editor/{ => styles}/Layout.scss | 0 .../Editor/{ => styles}/Sidebar.scss | 0 src/components/Feed/Card.tsx | 3 - src/components/Feed/Row5.tsx | 3 - src/components/Nav/Header.tsx | 3 - src/components/Nav/Modal.tsx | 5 +- src/components/Root.tsx | 3 - src/components/Topic/Card.tsx | 3 - src/components/Views/AllAuthors.tsx | 3 - src/components/Views/AllTopics.tsx | 3 - src/components/Views/Create.tsx | 13 +- src/components/Views/Home.tsx | 3 - src/stores/auth.ts | 11 +- src/stores/zine/articles.ts | 4 - src/stores/zine/authors.ts | 5 +- src/stores/zine/topics.ts | 17 +-- src/utils/apiClient.ts | 20 +-- src/utils/logger.ts | 9 -- yarn.lock | 15 +- 52 files changed, 200 insertions(+), 337 deletions(-) rename src/components/Editor/{ => components}/ArticlesList.tsx (96%) rename src/components/Editor/{ => components}/Error.tsx (96%) rename src/components/Editor/{ => components}/Layout.tsx (58%) rename src/components/Editor/{ => components}/Sidebar.tsx (87%) rename src/components/Editor/{prosemirror => store}/context.ts (100%) rename src/components/Editor/{prosemirror => store}/ctrl.ts (74%) rename src/components/Editor/{prosemirror => store}/state.ts (83%) rename src/components/Editor/{ => styles}/ArticlesList.scss (100%) rename src/components/Editor/{ => styles}/Button.scss (100%) rename src/components/Editor/{ => styles}/Editor.scss (100%) rename src/components/Editor/{ => styles}/Error.scss (100%) rename src/components/Editor/{ => styles}/Layout.scss (100%) rename src/components/Editor/{ => styles}/Sidebar.scss (100%) delete mode 100644 src/utils/logger.ts diff --git a/package.json b/package.json index f392ff43..74501095 100644 --- a/package.json +++ b/package.json @@ -83,8 +83,6 @@ "idb": "^7.0.1", "jest": "^29.0.1", "lint-staged": "^13.0.3", - "loglevel": "^1.8.0", - "loglevel-plugin-prefix": "^0.8.4", "markdown-it": "^13.0.1", "markdown-it-container": "^3.0.0", "markdown-it-implicit-figures": "^0.10.0", diff --git a/src/components/Discours/Donate.tsx b/src/components/Discours/Donate.tsx index d509d119..2fd74ce0 100644 --- a/src/components/Discours/Donate.tsx +++ b/src/components/Discours/Donate.tsx @@ -21,6 +21,7 @@ export const Donate = () => { const [amount, setAmount] = createSignal(0) onMount(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any const { cp: { CloudPayments } } = window as any // Checkout(cpOptions) @@ -60,6 +61,7 @@ export const Donate = () => { amountSwitchElement?.querySelector('input[type=radio]:checked') setAmount(Number.parseInt(customAmountElement?.value || choice?.value || '0')) console.log('[donate] input amount ' + amount) + // eslint-disable-next-line @typescript-eslint/no-explicit-any ;(widget() as any).charge( { // options @@ -81,13 +83,13 @@ export const Donate = () => { } } }, - (opts: any) => { + (opts) => { // success // действие при успешной оплате console.debug('[donate] options', opts) showModal('thank') }, - function (reason: string, options: any) { + function (reason: string, options) { // fail // действие при неуспешной оплате console.debug('[donate] options', options) diff --git a/src/components/Editor/ArticlesList.tsx b/src/components/Editor/components/ArticlesList.tsx similarity index 96% rename from src/components/Editor/ArticlesList.tsx rename to src/components/Editor/components/ArticlesList.tsx index b1e203c7..8bdd6e18 100644 --- a/src/components/Editor/ArticlesList.tsx +++ b/src/components/Editor/components/ArticlesList.tsx @@ -1,4 +1,4 @@ -import './ArticlesList.scss' +import '../styles/ArticlesList.scss' export default () => { return ( diff --git a/src/components/Editor/Error.tsx b/src/components/Editor/components/Error.tsx similarity index 96% rename from src/components/Editor/Error.tsx rename to src/components/Editor/components/Error.tsx index 20a0b43f..dc04cb26 100644 --- a/src/components/Editor/Error.tsx +++ b/src/components/Editor/components/Error.tsx @@ -1,5 +1,5 @@ import { Switch, Match, createMemo } from 'solid-js' -import { ErrorObject, useState } from './prosemirror/context' +import { ErrorObject, useState } from '../store/context' const InvalidState = (props: { title: string }) => { const [store, ctrl] = useState() diff --git a/src/components/Editor/Layout.tsx b/src/components/Editor/components/Layout.tsx similarity index 58% rename from src/components/Editor/Layout.tsx rename to src/components/Editor/components/Layout.tsx index e0e0e3d1..0a71ee85 100644 --- a/src/components/Editor/Layout.tsx +++ b/src/components/Editor/components/Layout.tsx @@ -1,12 +1,13 @@ -import type { Config } from './prosemirror/context' -import './Layout.scss' +import type { JSX } from 'solid-js/jsx-runtime' +import type { Config } from '../store/context' +import '../styles/Layout.scss' export type Styled = { - children: any + children: JSX.Element config?: Config 'data-testid'?: string - onClick?: () => void - onMouseEnter?: (e: any) => void + onClick?: (e: MouseEvent) => void + onMouseEnter?: (e: MouseEvent) => void } export const Layout = (props: Styled) => { diff --git a/src/components/Editor/Sidebar.tsx b/src/components/Editor/components/Sidebar.tsx similarity index 87% rename from src/components/Editor/Sidebar.tsx rename to src/components/Editor/components/Sidebar.tsx index 129c4923..e2a73f5f 100644 --- a/src/components/Editor/Sidebar.tsx +++ b/src/components/Editor/components/Sidebar.tsx @@ -1,10 +1,10 @@ -import { Show, createEffect, createSignal, onCleanup } from 'solid-js' +import { Show, createEffect, createSignal, onCleanup, For } from 'solid-js' import { unwrap } from 'solid-js/store' -// import { undo, redo } from 'prosemirror-history' -import { Draft, useState } from './prosemirror/context' +import { undo, redo } from 'prosemirror-history' +import { Draft, useState } from '../store/context' import { clsx } from 'clsx' import type { Styled } from './Layout' -import { t } from '../../utils/intl' +import { t } from '../../../utils/intl' // import type { EditorState } from 'prosemirror-state' // import { serialize } from './prosemirror/markdown' @@ -15,7 +15,7 @@ import { t } from '../../utils/intl' // const copyAllAsMarkdown = async (state: EditorState): Promise => // navigator.clipboard.writeText(serialize(state)) && !isServer -const Off = (props: any) => +const Off = (props) => const Label = (props: Styled) => const Link = ( props: Styled & { withMargin?: boolean; disabled?: boolean; title?: string; className?: string } @@ -85,13 +85,19 @@ export const Sidebar = () => { ctrl.updateConfig({ theme: document.body.className }) } - // const collabText = () => (store.collab?.started ? 'Stop' : store.collab?.error ? 'Restart 🚨' : 'Start') + const collabText = () => { + if (store.collab?.started) { + return 'Stop' + } else { + return store.collab?.error ? 'Restart 🚨' : 'Start' + } + } const editorView = () => unwrap(store.editorView) - // const onToggleMarkdown = () => ctrl.toggleMarkdown() + const onToggleMarkdown = () => ctrl.toggleMarkdown() const onOpenDraft = (draft: Draft) => ctrl.openDraft(unwrap(draft)) - // const collabUsers = () => store.collab?.y?.provider.awareness.meta.size ?? 0 - // const onUndo = () => undo(editorView().state, editorView().dispatch) - // const onRedo = () => redo(editorView().state, editorView().dispatch) + const collabUsers = () => store.collab?.y?.provider.awareness.meta.size ?? 0 + const onUndo = () => undo(editorView().state, editorView().dispatch) + const onRedo = () => redo(editorView().state, editorView().dispatch) // const onCopyAllAsMd = () => copyAllAsMarkdown(editorView().state).then(() => setLastAction('copy-md')) // const onToggleAlwaysOnTop = () => ctrl.updateConfig({ alwaysOnTop: !store.config.alwaysOnTop }) // const onNew = () => ctrl.newDraft() @@ -110,11 +116,11 @@ export const Sidebar = () => { // if (path) ctrl.updatePath(path) // } // - // const onCollab = () => { - // const state = unwrap(store) - // - // store.collab?.started ? ctrl.stopCollab(state) : console.log(state) - // } + const onCollab = () => { + const state = unwrap(store) + + store.collab?.started ? ctrl.stopCollab(state) : console.log(state) + } // // const onOpenInApp = () => { // // if (isTauri) return @@ -142,11 +148,11 @@ export const Sidebar = () => { // }) // } - // const Keys = (props: { keys: string[] }) => ( - // - // {(k: string) => {k}} - // - // ) + const Keys = (props: { keys: string[] }) => ( + + {(k: string) => {k}} + + ) createEffect(() => { setLastAction() @@ -165,7 +171,7 @@ export const Sidebar = () => { return (
- Советы и предложения + Советы и предложения editorView().focus()} data-tauri-drag-region="true"> diff --git a/src/components/Editor/index.tsx b/src/components/Editor/index.tsx index ea3614bb..0e38cc79 100644 --- a/src/components/Editor/index.tsx +++ b/src/components/Editor/index.tsx @@ -1,7 +1,7 @@ -import './Editor.scss' +import './styles/Editor.scss' import type { EditorView } from 'prosemirror-view' import type { EditorState } from 'prosemirror-state' -import { useState } from './prosemirror/context' +import { useState } from './store/context' import { ProseMirror } from './prosemirror' export default () => { diff --git a/src/components/Editor/prosemirror/extension/base.ts b/src/components/Editor/prosemirror/extension/base.ts index 14fd4bfa..e46d1810 100644 --- a/src/components/Editor/prosemirror/extension/base.ts +++ b/src/components/Editor/prosemirror/extension/base.ts @@ -6,7 +6,7 @@ import { history } from 'prosemirror-history' import { dropCursor } from 'prosemirror-dropcursor' import { buildKeymap } from 'prosemirror-example-setup' import { keymap } from 'prosemirror-keymap' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const plainSchema = new Schema({ nodes: { diff --git a/src/components/Editor/prosemirror/extension/code.ts b/src/components/Editor/prosemirror/extension/code.ts index 1f2fb0e4..ec0b38d7 100644 --- a/src/components/Editor/prosemirror/extension/code.ts +++ b/src/components/Editor/prosemirror/extension/code.ts @@ -4,7 +4,7 @@ import type { EditorState, Transaction } from 'prosemirror-state' import type { EditorView } from 'prosemirror-view' import { keymap } from 'prosemirror-keymap' import { markInputRule } from './mark-input-rule' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const blank = '\u00A0' diff --git a/src/components/Editor/prosemirror/extension/collab.ts b/src/components/Editor/prosemirror/extension/collab.ts index 56750de7..8806acdd 100644 --- a/src/components/Editor/prosemirror/extension/collab.ts +++ b/src/components/Editor/prosemirror/extension/collab.ts @@ -1,6 +1,6 @@ import { ySyncPlugin, yCursorPlugin, yUndoPlugin } from 'y-prosemirror' -import type { ProseMirrorExtension } from '../state' -import type { PeerData } from '../context' +import type { ProseMirrorExtension } from '../../store/state' +import type { PeerData } from '../../store/context' export const cursorBuilder = (user: { name: string diff --git a/src/components/Editor/prosemirror/extension/drag-handle.ts b/src/components/Editor/prosemirror/extension/drag-handle.ts index 8aa51b1d..5647e68d 100644 --- a/src/components/Editor/prosemirror/extension/drag-handle.ts +++ b/src/components/Editor/prosemirror/extension/drag-handle.ts @@ -1,6 +1,6 @@ import { Plugin, NodeSelection } from 'prosemirror-state' import { DecorationSet, Decoration } from 'prosemirror-view' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const handleIcon = ` diff --git a/src/components/Editor/prosemirror/extension/image.ts b/src/components/Editor/prosemirror/extension/image.ts index 7eb94705..c56331ce 100644 --- a/src/components/Editor/prosemirror/extension/image.ts +++ b/src/components/Editor/prosemirror/extension/image.ts @@ -1,10 +1,7 @@ import { Plugin } from 'prosemirror-state' import type { Node, Schema } from 'prosemirror-model' import type { EditorView } from 'prosemirror-view' -// import { convertFileSrc } from '@tauri-apps/api/tauri' -// import { resolvePath, dirname } from '../../remote' -// import { isTauri } from '../../env' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const REGEX = /^!\[([^[\]]*)]\((.+?)\)\s+/ const MAX_MATCH = 500 @@ -139,8 +136,8 @@ class ImageView { contentDOM: Element container: HTMLElement handle: HTMLElement - onResizeFn: any - onResizeEndFn: any + onResizeFn: (e: Event) => void + onResizeEndFn: (e: Event) => void width: number updating: number diff --git a/src/components/Editor/prosemirror/extension/link.ts b/src/components/Editor/prosemirror/extension/link.ts index 2b5e5b3a..e89fd853 100644 --- a/src/components/Editor/prosemirror/extension/link.ts +++ b/src/components/Editor/prosemirror/extension/link.ts @@ -1,33 +1,24 @@ import { Plugin, PluginKey, TextSelection, Transaction } from 'prosemirror-state' import type { EditorView } from 'prosemirror-view' import type { Mark, Node, ResolvedPos, Schema } from 'prosemirror-model' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const REGEX = /(^|\s)\[(.+)]\(([^ ]+)(?: "(.+)")?\)/ const findMarkPosition = (mark: Mark, doc: Node, from: number, to: number) => { let markPos = { from: -1, to: -1 } - doc.nodesBetween(from, to, (node, pos) => { if (markPos.from > -1) return false - if (markPos.from === -1 && mark.isInSet(node.marks)) { markPos = { from: pos, to: pos + Math.max(node.textContent.length, 1) } } }) - return markPos } const pluginKey = new PluginKey('markdown-links') -const resolvePos = (view: EditorView, pos: number) => { - try { - return view.state.doc.resolve(pos) - } catch { - // ignore - } -} +const resolvePos = (view: EditorView, pos: number) => view.state?.doc?.resolve(pos) // FIXME // eslint-disable-next-line sonarjs/cognitive-complexity @@ -38,50 +29,35 @@ const toLink = (view: EditorView, tr: Transaction) => { if (lastPos !== undefined) { const $from = resolvePos(view, lastPos) - if (!$from || $from.depth === 0 || $from.parent.type.spec.code) { return false } - const lineFrom = $from.before() const lineTo = $from.after() - const line = view.state.doc.textBetween(lineFrom, lineTo, '\0', '\0') const match = REGEX.exec(line) - if (match) { const [full, , text, href] = match const spaceLeft = full.indexOf(text) - 1 const spaceRight = full.length - text.length - href.length - spaceLeft - 4 const start = match.index + $from.start() + spaceLeft const end = start + full.length - spaceLeft - spaceRight - if (sel.$from.pos >= start && sel.$from.pos <= end) { return false } - // Do not convert md links if content has marks const $startPos = resolvePos(view, start) - if (($startPos as ResolvedPos).marks().length > 0) { return false } - const textStart = start + 1 const textEnd = textStart + text.length - if (textEnd < end) tr.delete(textEnd, end) - if (textStart > start) tr.delete(start, textStart) - const to = start + text.length - tr.addMark(start, to, state.schema.marks.link.create({ href })) - const sub = end - textEnd + textStart - start - tr.setMeta(pluginKey, { pos: sel.$head.pos - sub }) - return true } } @@ -92,11 +68,7 @@ const toLink = (view: EditorView, tr: Transaction) => { const toMarkdown = (view: EditorView, tr: Transaction) => { const { schema } = pluginKey.getState(view.state) const sel = view.state.selection - - if (sel.$head.depth === 0 || sel.$head.parent.type.spec.code) { - return false - } - + if (sel.$head.depth === 0 || sel.$head.parent.type.spec.code) return false const mark = schema.marks.link.isInSet(sel.$head.marks()) const textFrom = sel.$head.pos - sel.$head.textOffset const textTo = sel.$head.after() @@ -105,11 +77,9 @@ const toMarkdown = (view: EditorView, tr: Transaction) => { const { href } = mark.attrs const range = findMarkPosition(mark, view.state.doc, textFrom, textTo) const text = view.state.doc.textBetween(range.from, range.to, '\0', '\0') - tr.replaceRangeWith(range.from, range.to, view.state.schema.text(`[${text}](${href})`)) tr.setSelection(new TextSelection(tr.doc.resolve(sel.$head.pos + 1))) tr.setMeta(pluginKey, { pos: sel.$head.pos }) - return true } @@ -118,27 +88,19 @@ const toMarkdown = (view: EditorView, tr: Transaction) => { const handleMove = (view: EditorView) => { const sel = view.state.selection - if (!sel.empty || !sel.$head) return false - const pos = sel.$head.pos const tr = view.state.tr - if (toLink(view, tr)) { view.dispatch(tr) - return true } - if (toMarkdown(view, tr)) { view.dispatch(tr) - return true } - tr.setMeta(pluginKey, { pos }) view.dispatch(tr) - return false } @@ -151,14 +113,12 @@ const markdownLinks = (schema: Schema) => }, apply(tr, state) { const action = tr.getMeta(this) - if (action?.pos) { // FIXME // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore state.pos = action.pos } - return state } }, @@ -171,7 +131,6 @@ const markdownLinks = (schema: Schema) => if (handleMove(view)) { e.preventDefault() } - return true } } diff --git a/src/components/Editor/prosemirror/extension/mark-input-rule.ts b/src/components/Editor/prosemirror/extension/mark-input-rule.ts index 3e009338..4cb267c2 100644 --- a/src/components/Editor/prosemirror/extension/mark-input-rule.ts +++ b/src/components/Editor/prosemirror/extension/mark-input-rule.ts @@ -8,31 +8,19 @@ export const markInputRule = (regexp: RegExp, nodeType: MarkType, getAttrs?) => const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs const tr = state.tr let end = endArg - if (match[1]) { const textStart = start + match[0].indexOf(match[1]) const textEnd = textStart + match[1].length let hasMarks = false - state.doc.nodesBetween(textStart, textEnd, (node) => { - if (node.marks.length > 0) { - hasMarks = true - } + hasMarks = node.marks.length > 0 }) - - if (hasMarks) { - return - } - + if (hasMarks) return if (textEnd < end) tr.delete(textEnd, end) - if (textStart > start) tr.delete(start, textStart) - end = start + match[1].length } - tr.addMark(start, end, nodeType.create(attrs)) tr.removeStoredMark(nodeType) - return tr }) diff --git a/src/components/Editor/prosemirror/extension/markdown.ts b/src/components/Editor/prosemirror/extension/markdown.ts index b4707038..4fd147a8 100644 --- a/src/components/Editor/prosemirror/extension/markdown.ts +++ b/src/components/Editor/prosemirror/extension/markdown.ts @@ -7,7 +7,7 @@ import { ellipsis } from 'prosemirror-inputrules' import type { NodeType, Schema } from 'prosemirror-model' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const blockQuoteRule = (nodeType: NodeType) => wrappingInputRule(/^\s*>\s$/, nodeType) diff --git a/src/components/Editor/prosemirror/extension/menu.ts b/src/components/Editor/prosemirror/extension/menu.ts index 2cf583af..2baf591f 100644 --- a/src/components/Editor/prosemirror/extension/menu.ts +++ b/src/components/Editor/prosemirror/extension/menu.ts @@ -19,7 +19,7 @@ import { wrapInList } from 'prosemirror-schema-list' import { NodeSelection } from 'prosemirror-state' import { TextField, openPrompt } from './prompt' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' import type { Schema } from 'prosemirror-model' // Helpers to create specific types of items diff --git a/src/components/Editor/prosemirror/extension/paste-markdown.ts b/src/components/Editor/prosemirror/extension/paste-markdown.ts index c150c951..c864ebb9 100644 --- a/src/components/Editor/prosemirror/extension/paste-markdown.ts +++ b/src/components/Editor/prosemirror/extension/paste-markdown.ts @@ -1,7 +1,7 @@ import { Plugin } from 'prosemirror-state' // import { Fragment, Node, Schema } from 'prosemirror-model' import type { Schema } from 'prosemirror-model' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' // import { createMarkdownParser } from '../markdown' // const URL_REGEX = /(ftp|http|https):\/\/(\w+(?::\w*)?@)?(\S+)(:\d+)?(\/|\/([\w!#%&+./:=?@-]))?/g diff --git a/src/components/Editor/prosemirror/extension/placeholder.ts b/src/components/Editor/prosemirror/extension/placeholder.ts index 72d2a3dd..356fc391 100644 --- a/src/components/Editor/prosemirror/extension/placeholder.ts +++ b/src/components/Editor/prosemirror/extension/placeholder.ts @@ -1,6 +1,6 @@ import { Plugin } from 'prosemirror-state' import { DecorationSet, Decoration } from 'prosemirror-view' -import { ProseMirrorExtension, isEmpty } from '../state' +import { ProseMirrorExtension, isEmpty } from '../../store/state' const placeholder = (text: string) => new Plugin({ diff --git a/src/components/Editor/prosemirror/extension/prompt.ts b/src/components/Editor/prosemirror/extension/prompt.ts index e53e974f..31aebda6 100644 --- a/src/components/Editor/prosemirror/extension/prompt.ts +++ b/src/components/Editor/prosemirror/extension/prompt.ts @@ -2,51 +2,42 @@ const prefix = 'ProseMirror-prompt' // FIXME !!! // eslint-disable-next-line sonarjs/cognitive-complexity -export function openPrompt(options: any) { +export function openPrompt(options) { + const domFields = [] + const submitButton = document.createElement('button') + const cancelButton = document.createElement('button') const wrapper = document.body.appendChild(document.createElement('div')) + const form = wrapper.appendChild(document.createElement('form')) + const buttons = form.appendChild(document.createElement('div')) + const box = wrapper.getBoundingClientRect() wrapper.className = prefix - - const mouseOutside = (e: any) => { - if (!wrapper.contains(e.target)) close() + const mouseOutside = (e: MouseEvent) => { + if (!wrapper.contains(e.target as Node)) close() } - setTimeout(() => window.addEventListener('mousedown', mouseOutside), 50) + setTimeout(() => window.addEventListener('mousedown', mouseOutside), 50) // FIXME const close = () => { window.removeEventListener('mousedown', mouseOutside) if (wrapper.parentNode) wrapper.remove() } - - const domFields: any = [] - options.fields.forEach((name) => { - domFields.push(options.fields[name].render()) - }) - - const submitButton = document.createElement('button') + options.fields.forEach((name) => domFields.push(options.fields[name].render())) submitButton.type = 'submit' submitButton.className = prefix + '-submit' submitButton.textContent = 'OK' - const cancelButton = document.createElement('button') cancelButton.type = 'button' cancelButton.className = prefix + '-cancel' cancelButton.textContent = 'Cancel' cancelButton.addEventListener('click', close) - - const form = wrapper.appendChild(document.createElement('form')) if (options.title) { - form.appendChild(document.createElement('h5')).textContent = options.title + const headel = form.appendChild(document.createElement('h5')) + headel.textContent = options.title } - domFields.forEach((field: any) => { - form.appendChild(document.createElement('div')).append(field) - }) - const buttons = form.appendChild(document.createElement('div')) + domFields.forEach((fld) => form.appendChild(document.createElement('div')).append(fld)) buttons.className = prefix + '-buttons' buttons.append(submitButton) buttons.append(document.createTextNode(' ')) buttons.append(cancelButton) - - const box = wrapper.getBoundingClientRect() wrapper.style.top = (window.innerHeight - box.height) / 2 + 'px' wrapper.style.left = (window.innerWidth - box.width) / 2 + 'px' - const submit = () => { const params = getValues(options.fields, domFields) if (params) { @@ -54,12 +45,10 @@ export function openPrompt(options: any) { options.callback(params) } } - form.addEventListener('submit', (e) => { e.preventDefault() submit() }) - form.addEventListener('keydown', (e) => { if (e.key === 'Escape') { e.preventDefault() @@ -73,12 +62,11 @@ export function openPrompt(options: any) { }, 500) } }) - - const input: any = form.elements[0] + const input = form.elements[0] as HTMLInputElement if (input) input.focus() } -function getValues(fields: any, domFields: any) { +function getValues(fields, domFields) { const result = Object.create(null) let i = 0 fields.forEarch((name) => { @@ -95,7 +83,7 @@ function getValues(fields: any, domFields: any) { return result } -function reportInvalid(dom: any, message: any) { +function reportInvalid(dom, message) { const parent = dom.parentNode const msg = parent.appendChild(document.createElement('div')) msg.style.left = dom.offsetLeft + dom.offsetWidth + 2 + 'px' @@ -106,12 +94,12 @@ function reportInvalid(dom: any, message: any) { } export class Field { - options: any - constructor(options: any) { + options: { required: boolean; validate; clean; label: string; value: string } + constructor(options) { this.options = options } - read(dom: any) { + read(dom) { return dom.value } // :: (any) → ?string @@ -120,13 +108,12 @@ export class Field { return typeof _value === typeof '' } - validate(value: any) { + validate(value) { if (!value && this.options.required) return 'Required field' - return this.validateType(value) || (this.options.validate && this.options.validate(value)) } - clean(value: any) { + clean(value) { return this.options.clean ? this.options.clean(value) : value } } @@ -134,7 +121,6 @@ export class Field { export class TextField extends Field { render() { const input: HTMLInputElement = document.createElement('input') - input.type = 'text' input.placeholder = this.options.label input.value = this.options.value || '' diff --git a/src/components/Editor/prosemirror/extension/scroll.ts b/src/components/Editor/prosemirror/extension/scroll.ts index d284ce7c..5fc8e59d 100644 --- a/src/components/Editor/prosemirror/extension/scroll.ts +++ b/src/components/Editor/prosemirror/extension/scroll.ts @@ -1,6 +1,6 @@ import { Plugin } from 'prosemirror-state' import type { EditorView } from 'prosemirror-view' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const scroll = (view: EditorView) => { if (!view.state.selection.empty) return false diff --git a/src/components/Editor/prosemirror/extension/selection.ts b/src/components/Editor/prosemirror/extension/selection.ts index edf7b0ee..bb3eb81c 100644 --- a/src/components/Editor/prosemirror/extension/selection.ts +++ b/src/components/Editor/prosemirror/extension/selection.ts @@ -1,20 +1,21 @@ -import { /*MenuItem,*/ renderGrouped } from 'prosemirror-menu' +import { /*MenuItem,*/ MenuItem, renderGrouped } from 'prosemirror-menu' import type { Schema } from 'prosemirror-model' -import { Plugin } from 'prosemirror-state' +import { EditorState, Plugin } from 'prosemirror-state' +import type { EditorView } from 'prosemirror-view' // import { EditorView } from 'prosemirror-view' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' import { buildMenuItems } from './menu' -const cut = (arr: any[] | any) => arr.filter((a: any) => !!a) +const cut = (arr) => arr.filter((a) => !!a) export class SelectionTooltip { - tooltip: any + tooltip: HTMLElement - constructor(view: any, schema: Schema) { + constructor(view: EditorView, schema: Schema) { this.tooltip = document.createElement('div') this.tooltip.className = 'tooltip' view.dom.parentNode.append(this.tooltip) - const content = cut((buildMenuItems(schema) as { [key: string]: any })?.fullMenu) + const content = cut((buildMenuItems(schema) as { [key: string]: MenuItem })?.fullMenu) console.debug(content) const { dom } = renderGrouped(view, content) @@ -23,7 +24,7 @@ export class SelectionTooltip { this.update(view, null) } - update(view: any, lastState: any) { + update(view: EditorView, lastState: EditorState) { const state = view.state if (lastState && lastState.doc.eq(state.doc) && lastState.selection.eq(state.selection)) { @@ -52,9 +53,9 @@ export class SelectionTooltip { } } -export function toolTip(schema: any) { +export function toolTip(schema: Schema) { return new Plugin({ - view(editorView: any) { + view(editorView: EditorView) { return new SelectionTooltip(editorView, schema) } }) diff --git a/src/components/Editor/prosemirror/extension/strikethrough.ts b/src/components/Editor/prosemirror/extension/strikethrough.ts index 298f86b8..c0cadb4a 100644 --- a/src/components/Editor/prosemirror/extension/strikethrough.ts +++ b/src/components/Editor/prosemirror/extension/strikethrough.ts @@ -1,7 +1,7 @@ import { inputRules } from 'prosemirror-inputrules' import type { MarkType } from 'prosemirror-model' import { markInputRule } from './mark-input-rule' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const strikethroughRule = (nodeType: MarkType) => markInputRule(/~{2}(.+)~{2}$/, nodeType) diff --git a/src/components/Editor/prosemirror/extension/table.ts b/src/components/Editor/prosemirror/extension/table.ts index c482cf8e..86e082e1 100644 --- a/src/components/Editor/prosemirror/extension/table.ts +++ b/src/components/Editor/prosemirror/extension/table.ts @@ -2,7 +2,7 @@ import { EditorState, Selection } from 'prosemirror-state' import type { Node, Schema, ResolvedPos } from 'prosemirror-model' import { InputRule, inputRules } from 'prosemirror-inputrules' import { keymap } from 'prosemirror-keymap' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' export const tableInputRule = (schema: Schema) => new InputRule( diff --git a/src/components/Editor/prosemirror/extension/todo-list.ts b/src/components/Editor/prosemirror/extension/todo-list.ts index 14df3112..029a7ca0 100644 --- a/src/components/Editor/prosemirror/extension/todo-list.ts +++ b/src/components/Editor/prosemirror/extension/todo-list.ts @@ -3,7 +3,7 @@ import type { EditorView } from 'prosemirror-view' import { wrappingInputRule, inputRules } from 'prosemirror-inputrules' import { splitListItem } from 'prosemirror-schema-list' import { keymap } from 'prosemirror-keymap' -import type { ProseMirrorExtension } from '../state' +import type { ProseMirrorExtension } from '../../store/state' const todoListRule = (nodeType: NodeType) => wrappingInputRule(new RegExp('^\\[( |x)]\\s$'), nodeType, (match) => ({ diff --git a/src/components/Editor/prosemirror/index.tsx b/src/components/Editor/prosemirror/index.tsx index 25258f39..9126b495 100644 --- a/src/components/Editor/prosemirror/index.tsx +++ b/src/components/Editor/prosemirror/index.tsx @@ -3,7 +3,7 @@ import { Store, unwrap } from 'solid-js/store' import { EditorState, Plugin, Transaction } from 'prosemirror-state' import { EditorView } from 'prosemirror-view' import { Schema } from 'prosemirror-model' -import type { NodeViewFn, ProseMirrorExtension, ProseMirrorState } from './state' +import type { NodeViewFn, ProseMirrorExtension, ProseMirrorState } from '../store/state' interface ProseMirrorProps { style?: string @@ -38,7 +38,7 @@ const createEditorState = ( nodeViews = { ...nodeViews, ...extension.nodeViews } } } - + console.debug('[editor] create state with extensions', extensions) const schema = reconfigure ? prevText.schema : new Schema(schemaSpec) for (const extension of extensions) { @@ -66,15 +66,13 @@ export const ProseMirror = (props: ProseMirrorProps) => { props.onChange(newState) } - // eslint-disable-next-line solid/reactivity createEffect( (state: [EditorState, ProseMirrorExtension[]]) => { + console.debug('[prosemirror] init editor with extensions', state) const [prevText, prevExtensions] = state const text = unwrap(props.text) as EditorState const extensions: ProseMirrorExtension[] = unwrap(props.extensions) - if (!text || !extensions?.length) return [text, extensions] - if (!props.editorView) { const { editorState, nodeViews } = createEditorState(text, extensions) const view = new EditorView(editorRef, { @@ -82,26 +80,19 @@ export const ProseMirror = (props: ProseMirrorProps) => { nodeViews, dispatchTransaction }) - view.focus() props.onInit(editorState, view) - return [editorState, extensions] } - if (extensions !== prevExtensions || (!(text instanceof EditorState) && text !== prevText)) { const { editorState, nodeViews } = createEditorState(text, extensions, prevText) - if (!editorState) return - editorView().updateState(editorState) editorView().setProps({ nodeViews, dispatchTransaction }) props.onReconfigure(editorState) editorView().focus() - return [editorState, extensions] } - return [text, extensions] }, [props.text, props.extensions] diff --git a/src/components/Editor/prosemirror/setup.ts b/src/components/Editor/prosemirror/setup.ts index 3502a512..0e06f39c 100644 --- a/src/components/Editor/prosemirror/setup.ts +++ b/src/components/Editor/prosemirror/setup.ts @@ -1,5 +1,5 @@ import { keymap } from 'prosemirror-keymap' -import type { ProseMirrorExtension } from './state' +import type { ProseMirrorExtension } from '../store/state' import { Schema } from 'prosemirror-model' import base from './extension/base' import markdown from './extension/markdown' @@ -15,7 +15,7 @@ import dragHandle from './extension/drag-handle' import pasteMarkdown from './extension/paste-markdown' import table from './extension/table' import collab from './extension/collab' -import type { Config, PeerData } from './context' +import type { Config, PeerData } from '../store/context' import selectionMenu from './extension/selection' import type { Command } from 'prosemirror-state' diff --git a/src/components/Editor/prosemirror/context.ts b/src/components/Editor/store/context.ts similarity index 100% rename from src/components/Editor/prosemirror/context.ts rename to src/components/Editor/store/context.ts diff --git a/src/components/Editor/prosemirror/ctrl.ts b/src/components/Editor/store/ctrl.ts similarity index 74% rename from src/components/Editor/prosemirror/ctrl.ts rename to src/components/Editor/store/ctrl.ts index 70836e64..94df1728 100644 --- a/src/components/Editor/prosemirror/ctrl.ts +++ b/src/components/Editor/store/ctrl.ts @@ -6,14 +6,12 @@ import { selectAll, deleteSelection } from 'prosemirror-commands' import { undo as yUndo, redo as yRedo } from 'y-prosemirror' import debounce from 'lodash/debounce' import { createSchema, createExtensions, createEmptyText, InitOpts } from '../prosemirror/setup' -import { State, Config, ServiceError, newState, PeerData } from '../prosemirror/context' +import { State, Config, ServiceError, newState, PeerData } from './context' import { serialize, createMarkdownParser } from '../prosemirror/markdown' -import { isEmpty, isInitialized, ProseMirrorExtension } from '../prosemirror/state' +import { isEmpty, isInitialized, ProseMirrorExtension } from './state' import { isServer } from 'solid-js/web' import { roomConnect } from '../prosemirror/p2p' -const mod = 'Ctrl' - // eslint-disable-next-line @typescript-eslint/no-explicit-any export const createCtrl = (initial: State): [Store, { [key: string]: any }] => { const [store, setState] = createStore(initial) @@ -54,7 +52,7 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any } const onUndo = () => { - if (!isInitialized(store.text)) return false + if (!isInitialized(store.text as EditorState)) return false const text = store.text as EditorState if (store.collab?.started) yUndo(text) else undo(text, store.editorView.dispatch) @@ -62,7 +60,7 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any } const onRedo = () => { - if (!isInitialized(store.text)) return false + if (!isInitialized(store.text as EditorState)) return false const text = store.text as EditorState if (store.collab?.started) yRedo(text) else redo(text, store.editorView.dispatch) @@ -113,6 +111,7 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any }) } + const mod = 'Ctrl' const keymap = { [`${mod}-w`]: onDiscard, [`${mod}-z`]: onUndo, @@ -123,31 +122,27 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any const fetchData = async (): Promise => { if (isServer) return - const state: State = unwrap(store) - const room = undefined // window.location.pathname?.slice(1) + uuidv4() - // console.debug('[editor-ctrl] got unique room', room) - const args = { room } + console.debug('[editor] init state', state) const { default: db } = await import('../db') const data: string = await db.get('state') - console.debug('[editor-ctrl] got stored state from idb') - let parsed - let text = state.text - if (data !== undefined) { + console.debug('[editor] state stored before', data) try { - parsed = JSON.parse(data) + const parsed = JSON.parse(data) + let text = state.text + const room = undefined // window.location.pathname?.slice(1) + uuidv4() + const args = { room } if (!parsed) return { ...state, args } - - console.debug('[editor-ctrl] json state parsed successfully', parsed) if (parsed?.text) { if (!parsed.text || !parsed.text.doc || !parsed.text.selection) { throw new ServiceError('invalid_state', parsed.text) } else { text = parsed.text - console.debug('[editor-ctrl] got text from stored json', parsed) + console.debug('[editor] got text parsed') } } + console.debug('[editor] json state parsed successfully', parsed) return { ...parsed, text, @@ -166,71 +161,77 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any } } - const getTheme = (state: State) => ({ theme: state.config.theme }) + const getTheme = (state: State) => ({ theme: state.config?.theme || '' }) const clean = () => { - setState({ + const s: State = { ...newState(), loading: 'initialized', lastModified: new Date(), error: undefined, - text: undefined - }) + text: undefined, + args: {} + } + setState(s) + console.debug('[editor] clean state', s) } const init = async () => { let state = await fetchData() - console.debug('[editor-ctrl] state initiated', state) - try { - if (state.args?.room) { - state = doStartCollab(state) - } else if (!state.text) { - const text = createEmptyText() - const extensions = createExtensions({ - config: state.config, - markdown: state.markdown, - keymap - }) - - state = { ...state, text, extensions } + if (state) { + console.debug('[editor] state initiated', state) + try { + if (state.args?.room) { + state = { ...doStartCollab(state) } + } else if (!state.text) { + const text = createEmptyText() + const extensions = createExtensions({ + config: state?.config || ({} as Config), + markdown: state.markdown, + keymap + }) + state = { ...state, text, extensions } + } + } catch (error) { + state = { ...state, error } } - } catch (error) { - state = { ...state, error } + setState({ + ...state, + config: { + ...state.config, + ...getTheme(state) + }, + loading: 'initialized' + }) } - setState({ - ...state, - config: { ...state.config, ...getTheme(state) }, - loading: 'initialized' - }) } - const saveState = debounce(async (state: State) => { - const data = { - lastModified: state.lastModified, - config: state.config, - path: state.path, - markdown: state.markdown, - collab: { - room: state.collab?.room - }, - text: '' - } - - if (isInitialized(state.text)) { - data.text = store.editorView.state.toJSON() - } else if (state.text) { - data.text = state.text as string - } - if (!isServer) { - const { default: db } = await import('../db') - db.set('state', JSON.stringify(data)) - } - }, 200) + const saveState = () => + debounce(async (state: State) => { + const data = { + lastModified: state.lastModified, + config: state.config, + path: state.path, + markdown: state.markdown, + collab: { + room: state.collab?.room + }, + text: '' + } + if (isInitialized(state.text as EditorState)) { + data.text = store.editorView.state.toJSON() + } else if (state.text) { + data.text = state.text as string + } + if (!isServer) { + const { default: db } = await import('../db') + db.set('state', JSON.stringify(data)) + } + }, 200) const startCollab = () => { const state: State = unwrap(store) const update = doStartCollab(state) - setState(update) } @@ -239,7 +240,6 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any const room = state.args?.room ?? uuidv4() const username = '' // FIXME: use authenticated user name const [payload, provider] = roomConnect(room, username) - const extensions: ProseMirrorExtension[] = createExtensions({ config: state.config, markdown: state.markdown, @@ -247,10 +247,8 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any keymap, y: { payload, provider } as PeerData } as InitOpts) - let nState = state - - if ((backup && !isEmpty(state.text)) || state.path) { + if ((backup && !isEmpty(state.text as EditorState)) || state.path) { nState = { ...state, lastModified: undefined, @@ -258,7 +256,6 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any error: undefined } } - return { ...nState, extensions, @@ -274,7 +271,6 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any path: state.path, keymap }) - setState({ collab: undefined, extensions }) window.history.replaceState(null, '', '/') } @@ -302,7 +298,6 @@ export const createCtrl = (initial: State): [Store, { [key: string]: any const updateTheme = () => { const { theme } = getTheme(unwrap(store)) - setState('config', { theme }) } diff --git a/src/components/Editor/prosemirror/state.ts b/src/components/Editor/store/state.ts similarity index 83% rename from src/components/Editor/prosemirror/state.ts rename to src/components/Editor/store/state.ts index c04dd5b4..e7f0b2d6 100644 --- a/src/components/Editor/prosemirror/state.ts +++ b/src/components/Editor/store/state.ts @@ -17,9 +17,9 @@ export interface ProseMirrorExtension { export type ProseMirrorState = EditorState | unknown -export const isInitialized = (state: any) => state !== undefined && state instanceof EditorState +export const isInitialized = (state: EditorState) => state !== undefined && state instanceof EditorState -export const isEmpty = (state: any) => +export const isEmpty = (state: EditorState) => !isInitialized(state) || (state.doc.childCount === 1 && !state.doc.firstChild.type.spec.code && diff --git a/src/components/Editor/ArticlesList.scss b/src/components/Editor/styles/ArticlesList.scss similarity index 100% rename from src/components/Editor/ArticlesList.scss rename to src/components/Editor/styles/ArticlesList.scss diff --git a/src/components/Editor/Button.scss b/src/components/Editor/styles/Button.scss similarity index 100% rename from src/components/Editor/Button.scss rename to src/components/Editor/styles/Button.scss diff --git a/src/components/Editor/Editor.scss b/src/components/Editor/styles/Editor.scss similarity index 100% rename from src/components/Editor/Editor.scss rename to src/components/Editor/styles/Editor.scss diff --git a/src/components/Editor/Error.scss b/src/components/Editor/styles/Error.scss similarity index 100% rename from src/components/Editor/Error.scss rename to src/components/Editor/styles/Error.scss diff --git a/src/components/Editor/Layout.scss b/src/components/Editor/styles/Layout.scss similarity index 100% rename from src/components/Editor/Layout.scss rename to src/components/Editor/styles/Layout.scss diff --git a/src/components/Editor/Sidebar.scss b/src/components/Editor/styles/Sidebar.scss similarity index 100% rename from src/components/Editor/Sidebar.scss rename to src/components/Editor/styles/Sidebar.scss diff --git a/src/components/Feed/Card.tsx b/src/components/Feed/Card.tsx index da9e33a6..01a79125 100644 --- a/src/components/Feed/Card.tsx +++ b/src/components/Feed/Card.tsx @@ -8,9 +8,6 @@ import { Icon } from '../Nav/Icon' import './Card.scss' import { locale } from '../../stores/ui' import { handleClientRouteLinkClick } from '../../stores/router' -import { getLogger } from '../../utils/logger' - -const log = getLogger('card component') interface ArticleCardProps { settings?: { diff --git a/src/components/Feed/Row5.tsx b/src/components/Feed/Row5.tsx index 232176ad..e4d5e086 100644 --- a/src/components/Feed/Row5.tsx +++ b/src/components/Feed/Row5.tsx @@ -1,8 +1,5 @@ import type { Shout } from '../../graphql/types.gen' import { ArticleCard } from './Card' -import { getLogger } from '../../utils/logger' - -const log = getLogger('Row5') export const Row5 = (props: { articles: Shout[] }) => { return ( diff --git a/src/components/Nav/Header.tsx b/src/components/Nav/Header.tsx index 0d0a08f2..f767aa73 100644 --- a/src/components/Nav/Header.tsx +++ b/src/components/Nav/Header.tsx @@ -11,11 +11,8 @@ import { handleClientRouteLinkClick, router, Routes, useRouter } from '../../sto import styles from './Header.module.scss' import privateStyles from './Private.module.scss' import { getPagePath } from '@nanostores/router' -import { getLogger } from '../../utils/logger' import { clsx } from 'clsx' -const log = getLogger('header') - const resources: { name: string; route: keyof Routes }[] = [ { name: t('zine'), route: 'home' }, { name: t('feed'), route: 'feed' }, diff --git a/src/components/Nav/Modal.tsx b/src/components/Nav/Modal.tsx index ead90156..7423e4d3 100644 --- a/src/components/Nav/Modal.tsx +++ b/src/components/Nav/Modal.tsx @@ -1,10 +1,7 @@ import { createEffect, createSignal, JSX, onMount, Show } from 'solid-js' -import { getLogger } from '../../utils/logger' import './Modal.scss' import { hideModal, useModalStore } from '../../stores/ui' -const log = getLogger('modal') - interface ModalProps { name: string children: JSX.Element @@ -26,7 +23,7 @@ export const Modal = (props: ModalProps) => { const [visible, setVisible] = createSignal(false) createEffect(() => { setVisible(getModal() === props.name) - log.debug(`${props.name} is ${getModal() === props.name ? 'visible' : 'hidden'}`) + console.debug(`[modal] ${props.name} is ${getModal() === props.name ? 'visible' : 'hidden'}`) }) return ( diff --git a/src/components/Root.tsx b/src/components/Root.tsx index a770d97a..cb251179 100644 --- a/src/components/Root.tsx +++ b/src/components/Root.tsx @@ -5,7 +5,6 @@ import { setLocale } from '../stores/ui' import { Component, createEffect, createMemo } from 'solid-js' import { Routes, useRouter } from '../stores/router' import { Dynamic, isServer } from 'solid-js/web' -import { getLogger } from '../utils/logger' import type { PageProps } from './types' @@ -48,8 +47,6 @@ import { CreatePage } from './Pages/CreatePage' // const ThanksPage = lazy(() => import('./Pages/about/ThanksPage')) // const CreatePage = lazy(() => import('./Pages/about/CreatePage')) -const log = getLogger('root') - const pagesMap: Record> = { create: CreatePage, home: HomePage, diff --git a/src/components/Topic/Card.tsx b/src/components/Topic/Card.tsx index 257dad2e..3aa44ddd 100644 --- a/src/components/Topic/Card.tsx +++ b/src/components/Topic/Card.tsx @@ -8,9 +8,6 @@ import { t } from '../../utils/intl' import { locale } from '../../stores/ui' import { useAuthStore } from '../../stores/auth' import { follow, unfollow } from '../../stores/zine/common' -import { getLogger } from '../../utils/logger' - -const log = getLogger('TopicCard') interface TopicProps { topic: Topic diff --git a/src/components/Views/AllAuthors.tsx b/src/components/Views/AllAuthors.tsx index f27cc18e..bd632016 100644 --- a/src/components/Views/AllAuthors.tsx +++ b/src/components/Views/AllAuthors.tsx @@ -6,11 +6,8 @@ import { t } from '../../utils/intl' import { useAuthorsStore, setSortAllBy as setSortAllAuthorsBy } from '../../stores/zine/authors' import { handleClientRouteLinkClick, useRouter } from '../../stores/router' import { useAuthStore } from '../../stores/auth' -import { getLogger } from '../../utils/logger' import '../../styles/AllTopics.scss' -const log = getLogger('AllAuthorsView') - type AllAuthorsPageSearchParams = { by: '' | 'name' | 'shouts' | 'rating' } diff --git a/src/components/Views/AllTopics.tsx b/src/components/Views/AllTopics.tsx index 15b40959..6238d6d9 100644 --- a/src/components/Views/AllTopics.tsx +++ b/src/components/Views/AllTopics.tsx @@ -7,9 +7,6 @@ import { handleClientRouteLinkClick, useRouter } from '../../stores/router' import { TopicCard } from '../Topic/Card' import { useAuthStore } from '../../stores/auth' import '../../styles/AllTopics.scss' -import { getLogger } from '../../utils/logger' - -const log = getLogger('AllTopicsView') type AllTopicsPageSearchParams = { by: 'shouts' | 'authors' | 'title' | '' diff --git a/src/components/Views/Create.tsx b/src/components/Views/Create.tsx index a2a8f0d6..603ba88c 100644 --- a/src/components/Views/Create.tsx +++ b/src/components/Views/Create.tsx @@ -1,14 +1,11 @@ import { Show, onCleanup, createEffect, onError, onMount, untrack } from 'solid-js' import { createMutable, unwrap } from 'solid-js/store' -import { State, StateContext, newState } from '../Editor/prosemirror/context' -import { createCtrl } from '../Editor/prosemirror/ctrl' -import { Layout } from '../Editor/Layout' +import { State, StateContext, newState } from '../Editor/store/context' +import { createCtrl } from '../Editor/store/ctrl' +import { Layout } from '../Editor/components/Layout' import Editor from '../Editor' -import { Sidebar } from '../Editor/Sidebar' -import ErrorView from '../Editor/Error' -import { getLogger } from '../../utils/logger' - -const log = getLogger('CreateView') +import { Sidebar } from '../Editor/components/Sidebar' +import ErrorView from '../Editor/components/Error' export const CreateView = () => { const [store, ctrl] = createCtrl(newState()) diff --git a/src/components/Views/Home.tsx b/src/components/Views/Home.tsx index 418edf52..967bc531 100644 --- a/src/components/Views/Home.tsx +++ b/src/components/Views/Home.tsx @@ -10,7 +10,6 @@ import Beside from '../Feed/Beside' import RowShort from '../Feed/RowShort' import Slider from '../Feed/Slider' import Group from '../Feed/Group' -import { getLogger } from '../../utils/logger' import type { Shout, Topic } from '../../graphql/types.gen' import { Icon } from '../Nav/Icon' import { t } from '../../utils/intl' @@ -25,8 +24,6 @@ import { useTopAuthorsStore } from '../../stores/zine/topAuthors' import { locale } from '../../stores/ui' import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll' -const log = getLogger('home view') - type HomeProps = { randomTopics: Topic[] recentPublishedArticles: Shout[] diff --git a/src/stores/auth.ts b/src/stores/auth.ts index 5cc13fad..14b159d5 100644 --- a/src/stores/auth.ts +++ b/src/stores/auth.ts @@ -1,32 +1,29 @@ import { atom } from 'nanostores' import type { AuthResult } from '../graphql/types.gen' -import { getLogger } from '../utils/logger' import { resetToken, setToken } from '../graphql/privateGraphQLClient' import { apiClient } from '../utils/apiClient' import { createSignal } from 'solid-js' -const log = getLogger('auth-store') - const [session, setSession] = createSignal(null) export const signIn = async (params) => { const authResult = await apiClient.authLogin(params) setSession(authResult) setToken(authResult.token) - log.debug('signed in') + console.debug('signed in') } export const signUp = async (params) => { const authResult = await apiClient.authRegister(params) setSession(authResult) setToken(authResult.token) - log.debug('signed up') + console.debug('signed up') } export const signOut = () => { setSession(null) resetToken() - log.debug('signed out') + console.debug('signed out') } export const emailChecks = atom<{ [email: string]: boolean }>({}) @@ -44,7 +41,7 @@ export const register = async ({ email, password }: { email: string; password: s }) if (authResult && !authResult.error) { - log.debug('register session update', authResult) + console.debug('register session update', authResult) setSession(authResult) } } diff --git a/src/stores/zine/articles.ts b/src/stores/zine/articles.ts index fa2ca139..6f9af20d 100644 --- a/src/stores/zine/articles.ts +++ b/src/stores/zine/articles.ts @@ -3,13 +3,9 @@ import { apiClient } from '../../utils/apiClient' import { addAuthorsByTopic } from './authors' import { addTopicsByAuthor } from './topics' import { byStat } from '../../utils/sortby' - -import { getLogger } from '../../utils/logger' import { createSignal } from 'solid-js' import { createLazyMemo } from '@solid-primitives/memo' -const log = getLogger('articles store') - const [sortedArticles, setSortedArticles] = createSignal([]) const [articleEntities, setArticleEntities] = createSignal<{ [articleSlug: string]: Shout }>({}) diff --git a/src/stores/zine/authors.ts b/src/stores/zine/authors.ts index 537c6979..874cb9d0 100644 --- a/src/stores/zine/authors.ts +++ b/src/stores/zine/authors.ts @@ -1,11 +1,8 @@ import { apiClient } from '../../utils/apiClient' import type { Author } from '../../graphql/types.gen' -import { getLogger } from '../../utils/logger' import { createSignal } from 'solid-js' import { createLazyMemo } from '@solid-primitives/memo' -const log = getLogger('authors store') - export type AuthorsSortBy = 'shouts' | 'name' | 'rating' const [sortAllBy, setSortAllBy] = createSignal('shouts') @@ -32,7 +29,7 @@ const sortedAuthors = createLazyMemo(() => { break } case 'name': { - log.debug('sorted by name') + console.debug('sorted by name') authors.sort((a, b) => a.name.localeCompare(b.name)) break } diff --git a/src/stores/zine/topics.ts b/src/stores/zine/topics.ts index 3b2d706a..9e295e98 100644 --- a/src/stores/zine/topics.ts +++ b/src/stores/zine/topics.ts @@ -1,13 +1,10 @@ import { createMemo, createSignal } from 'solid-js' import { apiClient } from '../../utils/apiClient' import type { Topic } from '../../graphql/types.gen' -import { byCreated, byTopicStatDesc } from '../../utils/sortby' -import { getLogger } from '../../utils/logger' +import { byTopicStatDesc } from '../../utils/sortby' import { createLazyMemo } from '@solid-primitives/memo' -const log = getLogger('topics store') - -export type TopicsSortBy = 'created' | 'title' | 'authors' | 'shouts' +export type TopicsSortBy = 'followers' | 'title' | 'authors' | 'shouts' const [sortAllBy, setSortAllBy] = createSignal('shouts') @@ -21,9 +18,9 @@ const sortedTopics = createLazyMemo(() => { const topics = Object.values(topicEntities()) switch (sortAllBy()) { - case 'created': { - // log.debug('sorted by created') - topics.sort(byCreated) + case 'followers': { + // console.debug('[store.topics] sorted by followers') + topics.sort(byTopicStatDesc('followers')) break } case 'shouts': { @@ -37,12 +34,12 @@ const sortedTopics = createLazyMemo(() => { break } case 'title': { - // log.debug('sorted by title') + // console.debug('[store.topics] sorted by title') topics.sort((a, b) => a.title.localeCompare(b.title)) break } default: { - log.error(`Unknown sort: ${sortAllBy()}`) + console.error(`Unknown sort: ${sortAllBy()}`) } } diff --git a/src/utils/apiClient.ts b/src/utils/apiClient.ts index be9e29b5..cfd359fc 100644 --- a/src/utils/apiClient.ts +++ b/src/utils/apiClient.ts @@ -1,6 +1,4 @@ import type { Reaction, Shout, FollowingEntity, AuthResult } from '../graphql/types.gen' - -import { getLogger } from './logger' import { publicGraphQLClient } from '../graphql/publicGraphQLClient' import { privateGraphQLClient } from '../graphql/privateGraphQLClient' import articleBySlug from '../graphql/query/article-by-slug' @@ -32,8 +30,6 @@ import authorsBySlugs from '../graphql/query/authors-by-slugs' import incrementView from '../graphql/mutation/increment-view' import myChats from '../graphql/query/my-chats' -const log = getLogger('api-client') - const FEED_SIZE = 50 const REACTIONS_PAGE_SIZE = 100 @@ -51,7 +47,7 @@ export class ApiError extends Error { export const apiClient = { authLogin: async ({ email, password }): Promise => { const response = await publicGraphQLClient.query(authLoginQuery, { email, password }).toPromise() - // log.debug('authLogin', { response }) + // console.debug('[api-client] authLogin', { response }) if (response.error) { if (response.error.message === '[GraphQL] User not found') { throw new ApiError('user_not_found') @@ -119,7 +115,7 @@ export const apiClient = { const response = await publicGraphQLClient.query(topicsRandomQuery, { amount }).toPromise() if (!response.data) { - log.error('getRandomTopics', response.error) + console.error('[api-client] getRandomTopics', response.error) } return response.data.topicsRandom @@ -177,7 +173,7 @@ export const apiClient = { .toPromise() if (response.error) { - log.error('getArticlesForTopics', response.error) + console.error('[api-client] getArticlesForTopics', response.error) } return response.data.shoutsByTopics @@ -200,7 +196,7 @@ export const apiClient = { .toPromise() if (response.error) { - log.error('getArticlesForAuthors', response.error) + console.error('[api-client] getArticlesForAuthors', response.error) } return response.data.shoutsByAuthors @@ -226,7 +222,7 @@ export const apiClient = { const response = await publicGraphQLClient.query(articlesRecentPublished, { limit, offset }).toPromise() if (response.error) { - log.error('getPublishedArticles', response.error) + console.error('[api-client] getPublishedArticles', response.error) } return response.data.recentPublished @@ -234,14 +230,14 @@ export const apiClient = { getAllTopics: async () => { const response = await publicGraphQLClient.query(topicsAll, {}).toPromise() if (response.error) { - log.debug('getAllTopics', response.error) + console.debug('[api-client] getAllTopics', response.error) } return response.data.topicsAll }, getAllAuthors: async () => { const response = await publicGraphQLClient.query(authorsAll, {}).toPromise() if (response.error) { - log.debug('getAllAuthors', response.error) + console.debug('[api-client] getAllAuthors', response.error) } return response.data.authorsAll }, @@ -300,7 +296,7 @@ export const apiClient = { }, createReaction: async ({ reaction }) => { const response = await privateGraphQLClient.mutation(reactionCreate, { reaction }).toPromise() - log.debug('[api] create reaction mutation called') + console.debug('[api-client] [api] create reaction mutation called') return response.data.createReaction }, updateReaction: async ({ reaction }) => { diff --git a/src/utils/logger.ts b/src/utils/logger.ts deleted file mode 100644 index 14ce2b34..00000000 --- a/src/utils/logger.ts +++ /dev/null @@ -1,9 +0,0 @@ -import loglevel from 'loglevel' -import prefix from 'loglevel-plugin-prefix' -import { isDev } from './config' - -prefix.reg(loglevel) -prefix.apply(loglevel, { template: '[%n]' }) -loglevel.setLevel(isDev ? loglevel.levels.TRACE : loglevel.levels.ERROR) - -export const getLogger = (name: string) => loglevel.getLogger(name) diff --git a/yarn.lock b/yarn.lock index a8adb5b3..a7239546 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3448,10 +3448,10 @@ astro-eslint-parser@^0.7.0: eslint-visitor-keys "^3.0.0" espree "^9.0.0" -astro@^1.1.1: - version "1.4.5" - resolved "https://registry.yarnpkg.com/astro/-/astro-1.4.5.tgz#6515d8d6edd0d73be80707408c345dfe8c8c7b9a" - integrity sha512-7uflNdFMsAONkEdtNRqP1XgtgdUhiiFfYd3DjtaoaskYhcnfKKYy8Lht0stIQaMtAqITIy0LLTDvDM/j8SfuUw== +astro@^1.4.6: + version "1.4.6" + resolved "https://registry.yarnpkg.com/astro/-/astro-1.4.6.tgz#8442efca97605caf6d44f036b25f155df2cafdbd" + integrity sha512-zGi3uCl+VwBYwbmccyo9M4xI68gx+M7jJdP7kFSR3UCdmDbCoCY6u85ixAAjbkMUSNsuxsrBrhH9HW/X5SGTzQ== dependencies: "@astrojs/compiler" "^0.26.0" "@astrojs/language-server" "^0.26.2" @@ -7417,12 +7417,7 @@ loglevel-colored-level-prefix@^1.0.0: chalk "^1.1.3" loglevel "^1.4.1" -loglevel-plugin-prefix@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz#2fe0e05f1a820317d98d8c123e634c1bd84ff644" - integrity sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g== - -loglevel@^1.4.1, loglevel@^1.8.0: +loglevel@^1.4.1: version "1.8.0" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.0.tgz#e7ec73a57e1e7b419cb6c6ac06bf050b67356114" integrity sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==