Merge pull request #29 from Discours/chunks

Chunks
This commit is contained in:
Tony 2022-10-07 16:14:10 +03:00 committed by GitHub
commit 4a96197ee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 959 additions and 1295 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ pnpm-debug.log*
.eslint/.eslintcache
public/upload/*
src/graphql/introspec.gen.ts
stats.html

View File

@ -2,5 +2,5 @@
"*.{js,ts,tsx,json,scss,css,html}": "prettier --write",
"package.json": "sort-package-json",
"*.{scss,css}": "stylelint",
"*.{ts,tsx,js}": "eslint --fix",
"*.{ts,tsx,js}": "eslint --fix"
}

View File

@ -1,15 +1,10 @@
import { defineConfig, AstroUserConfig } from 'astro/config'
import vercel from '@astrojs/vercel/serverless'
// import node from '@astrojs/node'
import solidJs from '@astrojs/solid-js'
import mdx from '@astrojs/mdx'
// import partytown from '@astrojs/partytown'
import { markdownOptions as markdown } from './mdx.config'
// import sitemap from '@astrojs/sitemap'
import type { CSSOptions } from 'vite'
import defaultGenerateScopedName from 'postcss-modules/build/generateScopedName'
import { isDev } from './src/utils/config'
import { fileURLToPath, URL } from 'url'
import { visualizer } from 'rollup-plugin-visualizer'
const PATH_PREFIX = '/src/'
@ -37,35 +32,51 @@ const css: CSSOptions = {
const astroConfig: AstroUserConfig = {
site: 'https://new.discours.io',
// Enable Solid to support Solid JSX components.
// experimental: { integrations: true },
integrations: [solidJs(), mdx()],
// sitemap({
/* customPages: [
'',
'/feed',
'/search',
'topics',
'authors'
]
})],*/
//, partytown({})],
markdown,
integrations: [solidJs()],
output: 'server',
adapter: vercel(),
vite: {
build: {
chunkSizeWarningLimit: 777,
rollupOptions: {
plugins: [visualizer()],
output: {
// eslint-disable-next-line sonarjs/cognitive-complexity
manualChunks(id) {
if (id.includes('node_modules')) {
let chunkid = 'vendor'
if (id.includes('solid')) {
chunkid = 'solid'
}
if (id.includes('acorn')) {
chunkid = 'acorn'
}
if (id.includes('simple-peer')) {
chunkid = 'simple-peer'
}
if (id.includes('prosemirror')) {
chunkid = 'prosemirror'
}
if (id.includes('markdown') || id.includes('mdurl')) {
chunkid = 'markdown'
}
if (id.includes('swiper')) {
chunkid = 'swiper'
}
if (
id.includes('yjs') ||
id.includes('y-prosemirror') ||
id.includes('y-protocols') ||
id.includes('y-webrtc')
) {
chunkid = 'yjs'
}
return chunkid
}
}
},
external: ['@aws-sdk/clients/s3']
}
},
resolve: {
alias: {
'./runtimeConfig': './runtimeConfig.browser',
'@': fileURLToPath(new URL('src', import.meta.url))
}
},
css
}
}

View File

@ -1,34 +0,0 @@
import type { AstroUserConfig } from 'astro'
import type { RehypePlugin } from '@astrojs/markdown-remark'
import { selectAll } from 'hast-util-select'
import rehypeToc from '@jsdevtools/rehype-toc'
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
import rehypeSlug from 'rehype-slug'
import remarkCodeTitles from 'remark-code-titles'
const write =
(cl) =>
({ properties }) => {
properties.className = properties.className ? properties.className + ' ' + cl : cl
}
const adder = ([selector, className]) => {
const writer = write(className)
return (node) => selectAll(selector, node).forEach((el) => writer(el as any))
}
const addClasses = (additions) => {
const adders = Object.entries(additions).map((entry) => adder(entry))
return (node) => adders.forEach((a) => a(node))
}
export const markdownOptions: AstroUserConfig['markdown'] = {
remarkPlugins: [remarkCodeTitles],
rehypePlugins: [
rehypeSlug,
[rehypeToc as RehypePlugin<any>, { headings: ['h1', 'h2', 'h3'] }],
[rehypeAutolinkHeadings, { behavior: 'prepend' }],
[addClasses, { 'h1,h2,h3': 'title' }]
],
extendDefaultPlugins: true
}

View File

@ -29,7 +29,6 @@
},
"dependencies": {
"@aws-sdk/client-s3": "^3.178.0",
"@jsdevtools/rehype-toc": "^3.0.2",
"@nanostores/persistent": "^0.7.0",
"@nanostores/router": "^0.7.0",
"@nanostores/solid": "^0.3.0",
@ -37,19 +36,18 @@
"loglevel": "^1.8.0",
"loglevel-plugin-prefix": "^0.8.4",
"mailgun.js": "^8.0.1",
"markdown-it": "^13.0.1",
"markdown-it-container": "^3.0.0",
"markdown-it-implicit-figures": "^0.10.0",
"markdown-it-mark": "^3.0.1",
"markdown-it-replace-link": "^1.1.0",
"nanostores": "^0.7.0",
"postcss-modules": "^5.0.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1",
"remark-code-titles": "^0.1.2"
"postcss-modules": "^5.0.0"
},
"devDependencies": {
"@astrojs/markdown-remark": "1.1.2",
"@astrojs/mdx": "^0.11.1",
"@astrojs/node": "^1.0.1",
"@astrojs/partytown": "^1.0.0",
"@astrojs/language-server": "^0.27.0",
"@astrojs/solid-js": "^1.1.0",
"@astrojs/vercel": "^2.0.0",
"@astrojs/vercel": "^2.1.0",
"@babel/core": "^7.18.13",
"@graphql-codegen/cli": "^2.12.1",
"@graphql-codegen/typescript": "^2.7.3",
@ -114,7 +112,12 @@
"prosemirror-schema-list": "^1.2.2",
"prosemirror-state": "^1.4.1",
"prosemirror-view": "^1.28.1",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1",
"rehype-toc": "^3.0.2",
"remark-code-titles": "^0.1.2",
"rollup": "~2.79.1",
"rollup-plugin-visualizer": "^5.8.2",
"sass": "^1.55.0",
"solid-devtools": "^0.16.2",
"solid-js": "^1.5.6",
@ -122,7 +125,7 @@
"solid-jsx": "^0.9.1",
"solid-social": "^0.9.0",
"solid-utils": "^0.8.1",
"sort-package-json": "^1.57.0",
"sort-package-json": "^2.0.0",
"stylelint": "^14.12.1",
"stylelint-config-css-modules": "^4.1.0",
"stylelint-config-prettier-scss": "^0.0.1",

View File

@ -4,11 +4,10 @@ import { AuthorCard } from '../Author/Card'
import { Show } from 'solid-js/web'
import { clsx } from 'clsx'
import type { Author, Reaction as Point } from '../../graphql/types.gen'
import { createMemo, createSignal, onMount } from 'solid-js'
import { createMemo } from 'solid-js'
import { t } from '../../utils/intl'
// import { createReaction, updateReaction, deleteReaction } from '../../stores/zine/reactions'
import { renderMarkdown } from '@astrojs/markdown-remark'
import { markdownOptions } from '../../../mdx.config'
import MD from './MD'
import { deleteReaction } from '../../stores/zine/reactions'
export default (props: {
@ -18,17 +17,7 @@ export default (props: {
compact?: boolean
}) => {
const comment = createMemo(() => props.comment)
const [body, setBody] = createSignal('')
onMount(() => {
const b: string = props.comment?.body
if (b?.toString().startsWith('<')) {
setBody(b)
} else {
renderMarkdown(b, markdownOptions)
.then(({ code }) => setBody(code))
.catch(console.error)
}
})
const body = createMemo(() => comment().body.toString().trim())
const remove = () => {
if (comment()?.id) {
console.log('[comment] removing', comment().id)
@ -71,7 +60,7 @@ export default (props: {
</Show>
<div class="comment-body" contenteditable={props.canEdit} id={'comment-' + (comment().id || '')}>
<div innerHTML={body()} />
<MD body={body()} />
</div>
<Show when={!props.compact}>

View File

@ -3,14 +3,13 @@ import './Full.scss'
import { Icon } from '../Nav/Icon'
import ArticleComment from './Comment'
import { AuthorCard } from '../Author/Card'
import { createEffect, createMemo, createSignal, For, onMount, Show } from 'solid-js'
import { createMemo, For, onMount, Show } from 'solid-js'
import type { Author, Reaction, Shout } from '../../graphql/types.gen'
import { t } from '../../utils/intl'
import { showModal } from '../../stores/ui'
import { useAuthStore } from '../../stores/auth'
import { incrementView } from '../../stores/zine/articles'
import { renderMarkdown } from '@astrojs/markdown-remark'
import { markdownOptions } from '../../../mdx.config'
import MD from './MD'
const MAX_COMMENT_LEVEL = 6
@ -38,24 +37,9 @@ const formatDate = (date: Date) => {
}
export const FullArticle = (props: ArticleProps) => {
const [body, setBody] = createSignal(props.article.body?.startsWith('<') ? props.article.body : '')
const body = createMemo(() => props.article.body.toString().trim())
const { session } = useAuthStore()
createEffect(() => {
if (body() || !props.article.body) {
return
}
if (props.article.body.startsWith('<')) {
setBody(props.article.body)
} else {
renderMarkdown(props.article.body, markdownOptions)
.then(({ code }) => setBody(code))
.catch(console.error)
}
})
onMount(() => {
incrementView({ articleSlug: props.article.slug })
})
@ -110,7 +94,7 @@ export const FullArticle = (props: ArticleProps) => {
</div>
<div class="shout__body">
<div innerHTML={body()} />
<MD body={body()} />
</div>
</article>

View File

@ -0,0 +1,24 @@
import MD from 'markdown-it'
import mdfig from 'markdown-it-implicit-figures'
import mdmark from 'markdown-it-mark'
import mdcustom from 'markdown-it-container'
import mdlinks from 'markdown-it-replace-link'
import { createMemo } from 'solid-js'
const mit = MD({
html: true,
linkify: true,
typographer: true
})
mit.use(mdmark)
mit.use(mdcustom)
mit.use(mdfig, {
dataType: false, // <figure data-type="image">
figcaption: true // <figcaption>alternative text</figcaption>
})
mit.use(mdlinks)
export default (props: { body: string }) => {
const body = createMemo(() => (props.body.startsWith('<') ? props.body : mit.render(props.body)))
return <div innerHTML={body()} />
}

View File

@ -1,3 +1,6 @@
@import './Button';
@import './Sidebar';
.editor {
flex: 1;
padding-top: 1em;

View File

@ -1,6 +1,5 @@
import { Switch, Match } from 'solid-js'
import { useState } from './prosemirror/context'
import './Button.scss'
import { Switch, Match, createMemo } from 'solid-js'
import { ErrorObject, useState } from './store'
const InvalidState = (props: { title: string }) => {
const [store, ctrl] = useState()
@ -16,7 +15,7 @@ const InvalidState = (props: { title: string }) => {
you can copy important notes from below, clean the state and paste it again.
</p>
<pre>
<code>{JSON.stringify(store.error?.props)}</code>
<code>{JSON.stringify(store.error)}</code>
</pre>
<button class="primary" onClick={onClick}>
Clean
@ -29,12 +28,7 @@ const InvalidState = (props: { title: string }) => {
const Other = () => {
const [store, ctrl] = useState()
const onClick = () => ctrl.discard()
const getMessage = () => {
const err = (store.error?.props as any).error
return typeof err === 'string' ? err : err.message
}
const getMessage = createMemo<ErrorObject['message']>(() => store.error.message)
return (
<div class="error" data-tauri-drag-region="true">

View File

@ -4,7 +4,6 @@ import { unwrap } from 'solid-js/store'
import { File, useState /*, Config, PrettierConfig */ } from './store'
import { clsx } from 'clsx'
import type { Styled } from './Layout'
import './Sidebar.scss'
// import type { EditorState } from 'prosemirror-state'
// import { serialize } from './prosemirror/markdown'
// import { baseUrl } from '../../graphql/client'

View File

@ -1,8 +1,8 @@
import './Editor.scss'
import type { EditorView } from 'prosemirror-view'
import type { EditorState } from 'prosemirror-state'
import { useState } from './prosemirror/context'
import { useState } from './store'
import { ProseMirror } from './prosemirror'
import './Editor.scss'
export default () => {
const [store, ctrl] = useState()

View File

@ -1,118 +0,0 @@
import { createContext, useContext } from 'solid-js'
import type { Store } from 'solid-js/store'
import type { XmlFragment } from 'yjs'
import type { WebrtcProvider } from 'y-webrtc'
import type { ProseMirrorExtension, ProseMirrorState } from './state'
import type { Reaction } from '../../../graphql/types.gen'
export const isMac = true
export const mod = isMac ? 'Cmd' : 'Ctrl'
export const alt = isMac ? 'Cmd' : 'Alt'
export interface Args {
cwd?: string
file?: string
room?: string
text?: any
}
export interface PrettierConfig {
printWidth: number
tabWidth: number
useTabs: boolean
semi: boolean
singleQuote: boolean
}
export interface Config {
theme: string
// codeTheme: string;
font: string
fontSize: number
contentWidth: number
alwaysOnTop: boolean
// typewriterMode: boolean;
prettier: PrettierConfig
}
export interface ErrorObject {
id: string
props?: unknown
}
export interface YOptions {
type: XmlFragment
provider: WebrtcProvider
}
export interface Collab {
started?: boolean
error?: boolean
room?: string
y?: YOptions
}
export type LoadingType = 'loading' | 'initialized'
export interface File {
text?: { [key: string]: any }
lastModified?: string
path?: string
markdown?: boolean
}
export interface State {
text?: ProseMirrorState
editorView?: any
extensions?: ProseMirrorExtension[]
markdown?: boolean
lastModified?: Date
files: File[]
config: Config
error?: ErrorObject
loading: LoadingType
fullscreen: boolean
collab?: Collab
path?: string
args?: Args
}
export class ServiceError extends Error {
public errorObject: ErrorObject
constructor(id: string, props: unknown) {
super(id)
this.errorObject = { id, props }
}
}
const DEFAULT_CONFIG = {
theme: '',
// codeTheme: 'material-light',
font: 'muller',
fontSize: 24,
contentWidth: 800,
alwaysOnTop: isMac,
// typewriterMode: true,
prettier: {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true
}
}
export const StateContext = createContext<[Store<State>, any]>([{} as Store<State>, undefined])
export const useState = () => useContext(StateContext)
export const newState = (props: Partial<State> = {}): State => ({
extensions: [],
files: [],
loading: 'loading',
fullscreen: false,
markdown: false,
config: DEFAULT_CONFIG,
...props
})

View File

@ -1,6 +1,6 @@
import { ySyncPlugin, yCursorPlugin, yUndoPlugin } from 'y-prosemirror'
import type { ProseMirrorExtension } from '../state'
import type { YOptions } from '../context'
import type { YOptions } from '../../store'
export const cursorBuilder = (user: any): HTMLElement => {
const cursor = document.createElement('span')

View File

@ -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, YOptions } from './context'
import type { Config, YOptions } from '../store'
import selectionMenu from './extension/selection'
interface Opts {

View File

@ -3,7 +3,13 @@ import type { Store } from 'solid-js/store'
import type { XmlFragment } from 'yjs'
import type { WebrtcProvider } from 'y-webrtc'
import type { ProseMirrorExtension, ProseMirrorState } from '../prosemirror/state'
import { isMac } from '../prosemirror/context'
import type { Reaction } from '../../../graphql/types.gen'
import type { EditorView } from 'prosemirror-view'
export const isMac = true
export const mod = isMac ? 'Cmd' : 'Ctrl'
export const alt = isMac ? 'Cmd' : 'Alt'
export interface Args {
cwd?: string
@ -32,8 +38,9 @@ export interface Config {
}
export interface ErrorObject {
message: string
id: string
props?: unknown
props: unknown
}
export interface YOptions {
@ -59,7 +66,7 @@ export interface File {
export interface State {
text?: ProseMirrorState
editorView?: any
editorView?: EditorView
extensions?: ProseMirrorExtension[]
markdown?: boolean
lastModified?: Date
@ -77,7 +84,24 @@ export class ServiceError extends Error {
public errorObject: ErrorObject
constructor(id: string, props: unknown) {
super(id)
this.errorObject = { id, props }
this.errorObject = { id, props, message: '' }
}
}
const DEFAULT_CONFIG = {
theme: '',
// codeTheme: 'material-light',
font: 'muller',
fontSize: 24,
contentWidth: 800,
alwaysOnTop: isMac,
// typewriterMode: true,
prettier: {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true
}
}
@ -91,21 +115,6 @@ export const newState = (props: Partial<State> = {}): State => ({
loading: 'loading',
fullscreen: false,
markdown: false,
config: {
theme: 'light',
// codeTheme: 'material-light',
font: 'muller',
fontSize: 24,
contentWidth: 800,
alwaysOnTop: isMac,
// typewriterMode: true,
prettier: {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true
}
},
config: DEFAULT_CONFIG,
...props
})

View File

@ -46,6 +46,7 @@ import { CreatePage } from './Pages/CreatePage'
// const ProjectsPage = lazy(() => import('./Pages/about/ProjectsPage'))
// const TermsOfUsePage = lazy(() => import('./Pages/about/TermsOfUsePage'))
// const ThanksPage = lazy(() => import('./Pages/about/ThanksPage'))
// const CreatePage = lazy(() => import('./Pages/about/CreatePage'))
const log = getLogger('root')

View File

@ -1,12 +1,11 @@
import { Show, onCleanup, createEffect, onError, onMount, untrack } from 'solid-js'
import { createMutable, unwrap } from 'solid-js/store'
import { State, StateContext } from '../Editor/prosemirror/context'
import { State, StateContext, newState } from '../Editor/store'
import { createCtrl } from '../Editor/store/ctrl'
import { Layout } from '../Editor/Layout'
import Editor from '../Editor'
import { Sidebar } from '../Editor/Sidebar'
import ErrorView from '../Editor/Error'
import { newState } from '../Editor/store'
import { getLogger } from '../../utils/logger'
const log = getLogger('CreateView')
@ -15,7 +14,7 @@ export const CreateView = () => {
const [store, ctrl] = createCtrl(newState())
const mouseEnterCoords = createMutable({ x: 0, y: 0 })
const onMouseEnter = (e: any) => {
const onMouseEnter = (e: MouseEvent) => {
mouseEnterCoords.x = e.pageX
mouseEnterCoords.y = e.pageY
}

View File

@ -10,7 +10,7 @@ export const roomConnect = (
keyname = 'reactions'
): [Y.XmlFragment, WebrtcProvider] => {
const ydoc = new Y.Doc()
const yxmlfrag = ydoc.getXmlFragment(keyname) // TODO: encode/decode payload to Reactions[]
const yxmlfrag = ydoc.getXmlFragment(keyname) // TODO: use ydoc.getArray(keyname) as Reactions[]
const webrtcOptions = {
awareness: new Awareness(ydoc),
filterBcConns: true,

1859
yarn.lock

File diff suppressed because it is too large Load Diff