commit 44e0d1183268728a62bff1e40c68cd08d13328bf Author: tonyrewin Date: Fri Sep 9 14:53:35 2022 +0300 init diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..7a7eca5f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true +max_line_length = 108 + +[*.md] +max_line_length=off + +[*.mdx] +max_line_length=off diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..b896d136 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +node_modules +public +*.cjs +src/graphql/*.gen.ts +src/legacy_* diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..d535701b --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,85 @@ +module.exports = { + plugins: ['@typescript-eslint', 'import', 'sonarjs', 'unicorn', 'promise', 'solid', 'jest'], + extends: [ + 'eslint:recommended', + 'plugin:import/recommended', + 'plugin:import/typescript', + 'prettier', + 'plugin:sonarjs/recommended', + 'plugin:unicorn/recommended', + 'plugin:promise/recommended', + 'plugin:solid/recommended', + 'plugin:jest/recommended' + ], + overrides: [ + { + files: ['**/*.ts', '**/*.tsx'], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2021, + ecmaFeatures: { jsx: true }, + sourceType: 'module', + project: './tsconfig.json' + }, + extends: [ + 'plugin:@typescript-eslint/recommended' + // Maybe one day... + // 'plugin:@typescript-eslint/recommended-requiring-type-checking' + ], + rules: { + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], + // TODO: Remove any usage and enable + '@typescript-eslint/no-explicit-any': 'off', + // TODO: Fix errors and enable this rule + '@typescript-eslint/no-non-null-assertion': 'off', + + // solid-js fix + 'import/no-unresolved': [2, { ignore: ['solid-js/'] }] + } + } + ], + env: { + browser: true, + node: true, + mocha: true + }, + globals: {}, + rules: { + // FIXME: turn on + 'import/no-default-export': 'off', + + // FIXME + 'unicorn/prefer-dom-node-append': 'off', + + // TEMP + // FIXME + 'solid/reactivity': 'off', + + // TODO: Should be enabled + 'promise/catch-or-return': 'off', + + 'solid/no-innerhtml': 'off', + + /** Unicorn **/ + 'unicorn/no-null': 'off', + 'unicorn/filename-case': 'off', + 'unicorn/no-array-for-each': 'off', + 'unicorn/no-array-reduce': 'off', + 'unicorn/prefer-string-replace-all': 'warn', + 'unicorn/prevent-abbreviations': 'off', + 'unicorn/prefer-module': 'off', + 'unicorn/import-style': 'off', + 'unicorn/numeric-separators-style': 'off', + 'unicorn/prefer-node-protocol': 'off', + + eqeqeq: 'error', + 'no-param-reassign': 'error', + 'no-nested-ternary': 'error' + }, + settings: { + 'import/resolver': { + typescript: true, + node: true + } + } +} diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml new file mode 100644 index 00000000..1134e136 --- /dev/null +++ b/.github/workflows/node-ci.yml @@ -0,0 +1,21 @@ +name: CI + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '16' + + - name: Install deps + run: yarn install + + - name: Lint + run: npm run lint + + - name: Type check + run: npm run typecheck diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..605d6be6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +dist/ +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +.vscode +.env +.env.production +.DS_Store +.vercel +.idea/ +.eslint/.eslintcache +public/upload/* +src/graphql/introspec.gen.ts diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..d4a43dd1 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npm run pre-commit diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 00000000..b4c0b12d --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npm run pre-push diff --git a/.lintstagedrc b/.lintstagedrc new file mode 100644 index 00000000..e8df73eb --- /dev/null +++ b/.lintstagedrc @@ -0,0 +1,6 @@ +{ + "*.{js,ts,tsx,json,scss,css,html,astro}": "prettier --write", + "package.json": "sort-package-json", + "*.{scss,css}": "stylelint", + "*.{ts,tsx,js}": "eslint --fix", +} diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..ef83021a --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +# Expose Astro dependencies for `pnpm` users +shamefully-hoist=true diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..0126822f --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,17 @@ +{ + "htmlWhitespaceSensitivity": "ignore", + "semi": false, + "singleQuote": true, + "proseWrap": "always", + "printWidth": 108, + "trailingComma": "none", + "plugins": [], + "overrides": [ + { + "files": "*.ts", + "options": { + "parser": "typescript" + } + } + ] +} diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 00000000..940d502b --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,22 @@ +{ + "extends": [ + "stylelint-config-standard-scss", + "stylelint-config-prettier-scss", + "stylelint-config-css-modules" + ], + "plugins": [ + "stylelint-order", + "stylelint-scss" + ], + "rules": { + "selector-class-pattern": null, + "no-descending-specificity": null, + "scss/function-no-unknown": null, + "function-url-quotes": null, + "font-family-no-missing-generic-family-keyword": null, + "order/order": [ + "custom-properties", + "declarations" + ] + } +} diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 00000000..df9c7049 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,141 @@ +[0.5.1] +[+] nanostores-based custom spa routing +[-] Root.tsx components +[+] astro/solid basic hydration + +[0.5.0] +[-] removed solid-primitives/i18n +[+] added custom dummy utils/intl +[-] solid-app-router +[+] astro build and routing +[-] solid-top-loading-bar +[+] lint, prettier +[-] context providers, _cache +[+] ssr PoW + +[0.4.1] +[-] markdown-it +[+] remark, rehype, gfm +[+] api fixes + +[0.4.0] +[+] upload, feedback, newsletter serverless +[-] ratings +[-] comments +[-] proposals +[+] universal reaction entity +[+] staged preload + +[0.3.1] +[+] promisisified stores +[+] prerender based on mdx +[+] hybryd zine state manager + +[0.3.0] +[+] markup is simpler +[+] really use mdx +[+] really use i18n +[+] refactored queries +[+] final routing + +[0.2.1] +[+] custom store +[+] playwright +[+] mdx + +[0.2.0] +[-] sveltekit +[-] graphql-request +[+] migrated to solid +[+] urql +[+] graphql caching results + +[0.1.0] +[+] husky, lint-staged +[+] components refactoring +[+] 'static' pages fixes +[+] ShoutFeed's reusable components +[+] render order revised + +[0.0.9] +[+] lots of visual changes for demo +[+] cookie-based subscriptions +[+] prerender fix +[+] refactor queries +[+] caching topics with localStorage +[+] added some 'static' routes + +[0.0.8] +[+] isolated editor codebase +[+] sveo +[+] SSG first +[+] svelte-kit caching fixes +[+] isolated MD component +[-] code cleanup +[-] /auth route +[-] top nav changes + +[0.0.7] +[+] nav refactoring /[what] /@[who] +[+] /reset/[code], /reset/password +[+] modal auth dialog +[+] Topic.pic field +[+] internal svelte prerender +[+] GET_SHOUTS, TOP_SHOUTS_BY_RATING, GET_TOPICS, GET_COMMUNITIES via caching json trick +[~] User.username -> User.name + +[0.0.6] +[-] organization, org_id +[+] community entity +[+] mainpage markup +[+] topics filter navigation +[+] monor schema fixes +[-] gitea.js api +[-] postcss with plugins +[-] bootstrap +[+] windicss +[+] async sveltekit-styled queries +[+] login basic markup + +[0.0.5] +[+] migrate to sveltekit +[-] removed apollo due bug +[-] removed custom prerender code +[+] stylelint enabled +[+] precompiler windows support +[+] precompiler separated + +[0.0.4] + +[+] precompiler generated static indexes +[-] puppeteer switched off +[+] topic entity added +[-] i18n switched off +[+] own signaling server connected +[-] store-based routing removed +[+] reset password page +[+] login/register form +[+] social auth fb, ggl, vk + +[0.0.3] + +[~] prerender with puppeteer +[+] precompiled data.json +[~] international content support +[+] auth graphql client +[-] removed ws yjs-server +[-] pathfinder replaced +[+] mdsvex support + +[0.0.2] + +[+] apollo client with codegen +[+] ci basics +[+] code organized + + +[0.0.1] + +[+] 3rd party deps: tiptap, apollo, +[+] boiilerplate with esbuild +[+] simple structure diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..c5359825 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-2022 Discours + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..c11373be --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Astro + Solid.js + +Created with + +``` +npm init astro -- --template framework-solid +``` + +Astro working with [Solid](https://www.solidjs.com/). + +Write your Solid components as `.jsx` or `.tsx` files in your project. diff --git a/astro.config.ts b/astro.config.ts new file mode 100644 index 00000000..4b91f8b2 --- /dev/null +++ b/astro.config.ts @@ -0,0 +1,53 @@ +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' + +// const dev = process.env.NODE_ENV != 'production' + +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, + output: 'server', + adapter: vercel(), + vite: { + build: { + chunkSizeWarningLimit: 777, + rollupOptions: { + external: ['@aws-sdk/clients/s3'] + } + }, + resolve: { + alias: { + '@': './src' + } + }, + css: { + preprocessorOptions: { + scss: { + additionalData: '@import "src/styles/imports";\n' + } + } + } as CSSOptions + } +} + +// https://astro.build/config +export default defineConfig(astroConfig) diff --git a/clean-git.sh b/clean-git.sh new file mode 100755 index 00000000..5ec6d1c7 --- /dev/null +++ b/clean-git.sh @@ -0,0 +1,9 @@ +git filter-branch --tag-name-filter 'cat' -f --tree-filter ' + find . -type d -name binarydir | while read dir + do + find $dir -type f -name "*.ear" -o -name "*.war" -o -name "*.jar" -o -name "*.zip" -o -name "*.exe" | while read file + do + git rm -r -f --ignore-unmatch $file + done + done +' -- --all diff --git a/codegen.yml b/codegen.yml new file mode 100644 index 00000000..1e8c8a47 --- /dev/null +++ b/codegen.yml @@ -0,0 +1,20 @@ +overwrite: true +schema: 'https://newapi.discours.io/graphql' +generates: + src/graphql/introspec.gen.ts: + plugins: + - urql-introspection + config: + useTypeImports: true + includeScalars: true + includeEnums: true + src/graphql/types.gen.ts: + plugins: + - 'typescript' + - 'typescript-operations' + - 'typescript-urql' + config: + skipTypename: true +hooks: + afterAllFileWrite: + - prettier --ignore-path .gitignore --write --plugin-search-dir=. src/graphql/types.gen.ts diff --git a/docs/article.puml b/docs/article.puml new file mode 100644 index 00000000..c74dce1c --- /dev/null +++ b/docs/article.puml @@ -0,0 +1,66 @@ +@startuml +actor User +participant Browser +participant Vercel +participant Astro +participant Solid +participant Store + +User -> Browser: discours.io +activate Browser +Browser -> Vercel: GET +activate Vercel +Vercel -> Astro: render +activate Astro +Astro -> apiClient: getArticle({ slug }) +activate apiClient +apiClient -> DB: query: articleBySlug +activate DB +DB --> apiClient: response +deactivate DB +apiClient --> Astro: article data +deactivate apiClient +Astro -> Solid: render +activate Solid +Solid -> Store: useCurrentArticleStore(article) +activate Store +Store -> Store: create store with initial data (server) +Store --> Solid: currentArticle +deactivate Store +Solid -> Solid: render component +Solid --> Astro: rendered component +deactivate Solid +Astro --> Vercel: rendered page +Vercel -> Vercel: save rendered page to CDN +deactivate Astro +Vercel --> Browser: rendered page +deactivate Vercel +Browser --> User: rendered page +deactivate Browser +Browser -> Browser: load client scripts +Browser -> Solid: render +Solid -> Store: useCurrentArticleStore(article) +activate Store +Store -> Store: create store with initial data (client) +Store --> Solid: currentArticle +deactivate Store +Solid -> Solid: render component (no changes) +Solid -> Solid: onMount +Solid -> Store: loadArticleComments +activate Store +Store -> apiClient: getArticleComments +activate apiClient +apiClient -> DB: query: articleReactions +activate DB +DB --> apiClient: response +deactivate DB +apiClient --> Store: comments data +deactivate apiClient +Store -> Store: update store +Store --> Solid: store updated +deactivate Store +Solid -> Solid: render comments +Solid --> Browser: rendered comments +Browser --> User: comments +@enduml + diff --git a/mdx.config.ts b/mdx.config.ts new file mode 100644 index 00000000..27bf8079 --- /dev/null +++ b/mdx.config.ts @@ -0,0 +1,26 @@ +import type { AstroUserConfig } from 'astro' +import { selectAll } from 'hast-util-select' + +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: ['remark-code-titles'], + rehypePlugins: [ + // 'rehype-slug', + // ['rehype-autolink-headings', { behavior: 'prepend' }], + // ['rehype-toc', { headings: ['h2', 'h3'] }], + [addClasses, { 'h1,h2,h3': 'title' }] + ] +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..52304d6d --- /dev/null +++ b/package.json @@ -0,0 +1,153 @@ +{ + "name": "discoursio-astro", + "version": "0.5.1", + "private": true, + "license": "MIT", + "scripts": { + "build": "astro build", + "check": "npm run lint && npm run typecheck", + "codegen": "graphql-codegen", + "deploy": "graphql-codegen && npm run typecheck && astro build && vercel", + "dev": "astro dev", + "ffix": "npm run lint:code:fix && npm run lint:styles:fix && npm run format", + "fix": "npm run lint:code:fix && npm run lint:styles:fix", + "format": "npx prettier \"{,!(node_modules)/**/}*.{js,ts,tsx,json,scss,css}\" --write --ignore-path .gitignore", + "lint": "npm run lint:code && npm run lint:styles", + "lint:code": "eslint .", + "lint:code:fix": "eslint . --fix", + "lint:styles": "stylelint **/*.{scss,css}", + "lint:styles:fix": "stylelint **/*.{scss,css} --fix", + "pre-commit": "lint-staged", + "pre-push": "npm run typecheck", + "prepare": "husky install", + "preview": "astro preview", + "server": "node server/server.mjs", + "start": "astro dev", + "typecheck": "astro check && tsc --noEmit", + "typecheck:watch": "tsc --noEmit --watch", + "vercel-build": "astro build" + }, + "dependencies": { + "@aws-sdk/client-s3": "^3.159.0", + "@nanostores/i18n": "^0.6.0", + "@nanostores/persistent": "^0.6.2", + "@nanostores/router": "^0.6.0", + "@nanostores/solid": "^0.2.0", + "axios": "^0.27.2", + "google-translate-api-x": "^10.3.5", + "loglevel": "^1.8.0", + "loglevel-plugin-prefix": "^0.8.4", + "mailgun.js": "^8.0.0", + "nanostores": "^0.6.0", + "rehype-autolink-headings": "^6.1.1", + "rehype-slug": "^5.0.1", + "rehype-toc": "^3.0.2", + "remark-code-titles": "^0.1.2" + }, + "devDependencies": { + "@astrojs/markdown-remark": "^1.0.0", + "@astrojs/mdx": "^0.11.1", + "@astrojs/node": "^1.0.1", + "@astrojs/partytown": "^1.0.0", + "@astrojs/sitemap": "^1.0.0", + "@astrojs/solid-js": "^1.0.0", + "@astrojs/vercel": "^1.0.1", + "@babel/core": "^7.18.13", + "@graphql-codegen/cli": "^2.6.1", + "@graphql-codegen/typescript": "^2.5.1", + "@graphql-codegen/typescript-operations": "^2.4.2", + "@graphql-codegen/typescript-urql": "^3.5.12", + "@graphql-codegen/urql-introspection": "^2.2.1", + "@graphql-typed-document-node/core": "^3.1.1", + "@popperjs/core": "^2.11.5", + "@solid-primitives/clipboard": "^1.3.0", + "@solid-primitives/event-listener": "^2.2.0", + "@solid-primitives/intersection-observer": "^2.0.0", + "@solid-primitives/scheduled": "^1.0.1", + "@solid-primitives/script-loader": "^1.1.0", + "@solid-primitives/scroll": "^2.0.2", + "@solid-primitives/storage": "^1.3.1", + "@solidjs/meta": "^0.28.0", + "@types/express": "^4.17.13", + "@types/node": "^18.0.0", + "@types/uuid": "^8.3.4", + "@typescript-eslint/eslint-plugin": "^5.29.0", + "@typescript-eslint/parser": "^5.35.1", + "@urql/core": "^3.0.1", + "@urql/devtools": "^2.0.3", + "@urql/exchange-auth": "^1.0.0", + "@urql/exchange-graphcache": "^5.0.0", + "astro": "^1.1.1", + "astro-eslint-parser": "^0.6.1", + "bcryptjs": "^2.4.3", + "bootstrap": "5.1.3", + "clsx": "^1.2.1", + "cookie": "^0.5.0", + "cookie-signature": "^1.2.0", + "eslint": "8.22.0", + "eslint-config-stylelint": "^16.0.0", + "eslint-import-resolver-typescript": "^3.5.0", + "eslint-mdx": "^2.0.2", + "eslint-plugin-astro": "^0.19.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsx-a11y": "^6.6.1", + "eslint-plugin-mdx": "^2.0.2", + "eslint-plugin-promise": "^6.0.1", + "eslint-plugin-solid": "^0.7.1", + "eslint-plugin-sonarjs": "^0.15.0", + "eslint-plugin-unicorn": "^43.0.2", + "graphql": "^16.5.0", + "graphql-tag": "^2.12.6", + "graphql-ws": "^5.10.0", + "hast-util-select": "^5.0.1", + "husky": "^8.0.0", + "idb": "^7.0.1", + "jest": "^29.0.1", + "jsdom": "^20.0.0", + "lint-staged": "^13.0.3", + "postcss": "^8.4.16", + "prettier": "^2.7.0", + "prettier-eslint": "^15.0.0", + "prosemirror-commands": "^1.3.0", + "prosemirror-dropcursor": "^1.5.0", + "prosemirror-example-setup": "^1.2.1", + "prosemirror-gapcursor": "^1.3.1", + "prosemirror-history": "^1.3.0", + "prosemirror-inputrules": "^1.2.0", + "prosemirror-keymap": "^1.2.0", + "prosemirror-markdown": "^1.9.1", + "prosemirror-menu": "^1.2.1", + "prosemirror-model": "1.16.1", + "prosemirror-schema-basic": "^1.2.0", + "prosemirror-schema-list": "^1.1.6", + "prosemirror-state": "1.3.4", + "prosemirror-view": "^1.26.2", + "rollup": "~2.5.0", + "sass": "^1.54.0", + "solid-js": "^1.5.3", + "solid-js-form": "^0.1.5", + "solid-jsx": "^0.9.0", + "solid-social": "^0.9.0", + "solid-transition-group": "^0.0.11", + "solid-utils": "^0.8.1", + "sort-package-json": "^1.57.0", + "stylelint": "^14.11.0", + "stylelint-config-css-modules": "^4.1.0", + "stylelint-config-prettier-scss": "^0.0.1", + "stylelint-config-standard-scss": "^5.0.0", + "stylelint-order": "^5.0.0", + "stylelint-scss": "^4.3.0", + "swiper": "^8.3.2", + "ts-debounce": "^4.0.0", + "ts-node": "^10.9.1", + "typescript": "4.7.4", + "undici": "^5.10.0", + "unique-names-generator": "^4.7.1", + "uuid": "^9.0.0", + "vite": "^3.0.9", + "y-prosemirror": "^1.1.3", + "y-protocols": "^1.0.5", + "y-webrtc": "^10.2.2", + "yjs": "^13.5.38" + } +} diff --git a/public/auth-page.jpg b/public/auth-page.jpg new file mode 100644 index 00000000..ab788a9f Binary files /dev/null and b/public/auth-page.jpg differ diff --git a/public/bonfire.png b/public/bonfire.png new file mode 100644 index 00000000..11ee31fa Binary files /dev/null and b/public/bonfire.png differ diff --git a/public/confirm/index.html b/public/confirm/index.html new file mode 100644 index 00000000..9bd2a61a --- /dev/null +++ b/public/confirm/index.html @@ -0,0 +1,29 @@ + +discours.io + + +
+ Авторизация завершена, это окно закрывается по куче причин. +
+ + + \ No newline at end of file diff --git a/public/discours-banner.jpg b/public/discours-banner.jpg new file mode 100644 index 00000000..77299720 Binary files /dev/null and b/public/discours-banner.jpg differ diff --git a/public/error.svg b/public/error.svg new file mode 100644 index 00000000..a520a262 --- /dev/null +++ b/public/error.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 00000000..ba2c31b0 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/favicon.png b/public/favicon.png new file mode 100755 index 00000000..06dbd0ab Binary files /dev/null and b/public/favicon.png differ diff --git a/public/fonts/JetBrainsMono-Regular.woff2 b/public/fonts/JetBrainsMono-Regular.woff2 new file mode 100644 index 00000000..fdf95dde Binary files /dev/null and b/public/fonts/JetBrainsMono-Regular.woff2 differ diff --git a/public/fonts/Muller-Bold.woff b/public/fonts/Muller-Bold.woff new file mode 100644 index 00000000..b238fbaa Binary files /dev/null and b/public/fonts/Muller-Bold.woff differ diff --git a/public/fonts/Muller-Bold.woff2 b/public/fonts/Muller-Bold.woff2 new file mode 100644 index 00000000..8bf3e9d6 Binary files /dev/null and b/public/fonts/Muller-Bold.woff2 differ diff --git a/public/fonts/Muller-ExtraBold.eot b/public/fonts/Muller-ExtraBold.eot new file mode 100644 index 00000000..fe188a9c Binary files /dev/null and b/public/fonts/Muller-ExtraBold.eot differ diff --git a/public/fonts/Muller-ExtraBold.woff b/public/fonts/Muller-ExtraBold.woff new file mode 100644 index 00000000..5ac9b1f4 Binary files /dev/null and b/public/fonts/Muller-ExtraBold.woff differ diff --git a/public/fonts/Muller-ExtraBold.woff2 b/public/fonts/Muller-ExtraBold.woff2 new file mode 100644 index 00000000..47e28bc3 Binary files /dev/null and b/public/fonts/Muller-ExtraBold.woff2 differ diff --git a/public/fonts/Muller-Medium.woff b/public/fonts/Muller-Medium.woff new file mode 100644 index 00000000..b494ad73 Binary files /dev/null and b/public/fonts/Muller-Medium.woff differ diff --git a/public/fonts/Muller-Medium.woff2 b/public/fonts/Muller-Medium.woff2 new file mode 100644 index 00000000..fa53ed21 Binary files /dev/null and b/public/fonts/Muller-Medium.woff2 differ diff --git a/public/fonts/Muller-MediumItalic.eot b/public/fonts/Muller-MediumItalic.eot new file mode 100644 index 00000000..986fecb2 Binary files /dev/null and b/public/fonts/Muller-MediumItalic.eot differ diff --git a/public/fonts/Muller-MediumItalic.woff b/public/fonts/Muller-MediumItalic.woff new file mode 100644 index 00000000..c41adca7 Binary files /dev/null and b/public/fonts/Muller-MediumItalic.woff differ diff --git a/public/fonts/Muller-MediumItalic.woff2 b/public/fonts/Muller-MediumItalic.woff2 new file mode 100644 index 00000000..cbba7705 Binary files /dev/null and b/public/fonts/Muller-MediumItalic.woff2 differ diff --git a/public/fonts/Muller-Regular.woff b/public/fonts/Muller-Regular.woff new file mode 100644 index 00000000..f523c788 Binary files /dev/null and b/public/fonts/Muller-Regular.woff differ diff --git a/public/fonts/Muller-Regular.woff2 b/public/fonts/Muller-Regular.woff2 new file mode 100644 index 00000000..39772008 Binary files /dev/null and b/public/fonts/Muller-Regular.woff2 differ diff --git a/public/fonts/Muller-RegularItalic.woff b/public/fonts/Muller-RegularItalic.woff new file mode 100644 index 00000000..36e201a6 Binary files /dev/null and b/public/fonts/Muller-RegularItalic.woff differ diff --git a/public/fonts/Muller-RegularItalic.woff2 b/public/fonts/Muller-RegularItalic.woff2 new file mode 100644 index 00000000..81e50470 Binary files /dev/null and b/public/fonts/Muller-RegularItalic.woff2 differ diff --git a/public/icons/arrow-right-black.svg b/public/icons/arrow-right-black.svg new file mode 100644 index 00000000..6c559bc9 --- /dev/null +++ b/public/icons/arrow-right-black.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/arrow-right-white.svg b/public/icons/arrow-right-white.svg new file mode 100644 index 00000000..bc989b9d --- /dev/null +++ b/public/icons/arrow-right-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/arrow-right.svg b/public/icons/arrow-right.svg new file mode 100644 index 00000000..eed27f33 --- /dev/null +++ b/public/icons/arrow-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/art.svg b/public/icons/art.svg new file mode 100644 index 00000000..be04ae10 --- /dev/null +++ b/public/icons/art.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/icons/article.svg b/public/icons/article.svg new file mode 100644 index 00000000..08b1031a --- /dev/null +++ b/public/icons/article.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/author-subscribe.svg b/public/icons/author-subscribe.svg new file mode 100644 index 00000000..4118c185 --- /dev/null +++ b/public/icons/author-subscribe.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/icons/author-unsubscribe.svg b/public/icons/author-unsubscribe.svg new file mode 100644 index 00000000..a5eaab85 --- /dev/null +++ b/public/icons/author-unsubscribe.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/bell-white.svg b/public/icons/bell-white.svg new file mode 100644 index 00000000..31e57cd7 --- /dev/null +++ b/public/icons/bell-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/bell.svg b/public/icons/bell.svg new file mode 100644 index 00000000..f32faefd --- /dev/null +++ b/public/icons/bell.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/bookmark-x.svg b/public/icons/bookmark-x.svg new file mode 100644 index 00000000..611542d8 --- /dev/null +++ b/public/icons/bookmark-x.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/bookmark.svg b/public/icons/bookmark.svg new file mode 100644 index 00000000..9930c548 --- /dev/null +++ b/public/icons/bookmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/checkbox-big.svg b/public/icons/checkbox-big.svg new file mode 100644 index 00000000..6b5e7358 --- /dev/null +++ b/public/icons/checkbox-big.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/checkbox-checked-big.svg b/public/icons/checkbox-checked-big.svg new file mode 100644 index 00000000..2b19c637 --- /dev/null +++ b/public/icons/checkbox-checked-big.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/checkbox-checked.svg b/public/icons/checkbox-checked.svg new file mode 100644 index 00000000..c462c1f6 --- /dev/null +++ b/public/icons/checkbox-checked.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/checkbox-notifications-checked.svg b/public/icons/checkbox-notifications-checked.svg new file mode 100644 index 00000000..ccff6a65 --- /dev/null +++ b/public/icons/checkbox-notifications-checked.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/checkbox-notifications.svg b/public/icons/checkbox-notifications.svg new file mode 100644 index 00000000..1c59e6cc --- /dev/null +++ b/public/icons/checkbox-notifications.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/icons/checkbox.svg b/public/icons/checkbox.svg new file mode 100644 index 00000000..61dd1216 --- /dev/null +++ b/public/icons/checkbox.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/close.svg b/public/icons/close.svg new file mode 100644 index 00000000..b779a490 --- /dev/null +++ b/public/icons/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/comment.svg b/public/icons/comment.svg new file mode 100644 index 00000000..7fca6067 --- /dev/null +++ b/public/icons/comment.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/delete.svg b/public/icons/delete.svg new file mode 100644 index 00000000..931cbe95 --- /dev/null +++ b/public/icons/delete.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/dislike.svg b/public/icons/dislike.svg new file mode 100644 index 00000000..ca18143f --- /dev/null +++ b/public/icons/dislike.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/disproof.svg b/public/icons/disproof.svg new file mode 100644 index 00000000..4b1ae8ea --- /dev/null +++ b/public/icons/disproof.svg @@ -0,0 +1,11 @@ + + + diff --git a/public/icons/ediitor-bold.svg b/public/icons/ediitor-bold.svg new file mode 100644 index 00000000..ee703b68 --- /dev/null +++ b/public/icons/ediitor-bold.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/icons/edit.svg b/public/icons/edit.svg new file mode 100644 index 00000000..abc01f82 --- /dev/null +++ b/public/icons/edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/editor-h1.svg b/public/icons/editor-h1.svg new file mode 100644 index 00000000..70097798 --- /dev/null +++ b/public/icons/editor-h1.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/editor-h2.svg b/public/icons/editor-h2.svg new file mode 100644 index 00000000..5ac6c205 --- /dev/null +++ b/public/icons/editor-h2.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/editor-italic.svg b/public/icons/editor-italic.svg new file mode 100644 index 00000000..98664487 --- /dev/null +++ b/public/icons/editor-italic.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/editor-link.svg b/public/icons/editor-link.svg new file mode 100644 index 00000000..c4943bd3 --- /dev/null +++ b/public/icons/editor-link.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/editor-quote.svg b/public/icons/editor-quote.svg new file mode 100644 index 00000000..66e55599 --- /dev/null +++ b/public/icons/editor-quote.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/ellipsis.svg b/public/icons/ellipsis.svg new file mode 100644 index 00000000..c45ab2f3 --- /dev/null +++ b/public/icons/ellipsis.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/eye.svg b/public/icons/eye.svg new file mode 100644 index 00000000..54e28bdc --- /dev/null +++ b/public/icons/eye.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/facebook-white.svg b/public/icons/facebook-white.svg new file mode 100644 index 00000000..7ba7b919 --- /dev/null +++ b/public/icons/facebook-white.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/icons/facebook.svg b/public/icons/facebook.svg new file mode 100644 index 00000000..58bc0cb0 --- /dev/null +++ b/public/icons/facebook.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/icons/github.svg b/public/icons/github.svg new file mode 100644 index 00000000..8780f5b0 --- /dev/null +++ b/public/icons/github.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/glasses.svg b/public/icons/glasses.svg new file mode 100644 index 00000000..730a1c1c --- /dev/null +++ b/public/icons/glasses.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/google.svg b/public/icons/google.svg new file mode 100644 index 00000000..ba7feefe --- /dev/null +++ b/public/icons/google.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/icons/image.svg b/public/icons/image.svg new file mode 100644 index 00000000..be04ae10 --- /dev/null +++ b/public/icons/image.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/icons/inbox-white.svg b/public/icons/inbox-white.svg new file mode 100644 index 00000000..da9ae69e --- /dev/null +++ b/public/icons/inbox-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/like.svg b/public/icons/like.svg new file mode 100644 index 00000000..3d8deeb8 --- /dev/null +++ b/public/icons/like.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/music.svg b/public/icons/music.svg new file mode 100644 index 00000000..87621cb9 --- /dev/null +++ b/public/icons/music.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/icons/nopic.png b/public/icons/nopic.png new file mode 100644 index 00000000..b6410d65 Binary files /dev/null and b/public/icons/nopic.png differ diff --git a/public/icons/pencil.svg b/public/icons/pencil.svg new file mode 100644 index 00000000..f4efb296 --- /dev/null +++ b/public/icons/pencil.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/proof.svg b/public/icons/proof.svg new file mode 100644 index 00000000..8c303c73 --- /dev/null +++ b/public/icons/proof.svg @@ -0,0 +1,11 @@ + + + diff --git a/public/icons/prose.svg b/public/icons/prose.svg new file mode 100644 index 00000000..8888804f --- /dev/null +++ b/public/icons/prose.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/reply-arrow.svg b/public/icons/reply-arrow.svg new file mode 100644 index 00000000..d6deee5e --- /dev/null +++ b/public/icons/reply-arrow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/reply.svg b/public/icons/reply.svg new file mode 100644 index 00000000..8dc91097 --- /dev/null +++ b/public/icons/reply.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/search-white.svg b/public/icons/search-white.svg new file mode 100644 index 00000000..ee426d9f --- /dev/null +++ b/public/icons/search-white.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/search.svg b/public/icons/search.svg new file mode 100644 index 00000000..3b4f989f --- /dev/null +++ b/public/icons/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/send-message.svg b/public/icons/send-message.svg new file mode 100644 index 00000000..00357843 --- /dev/null +++ b/public/icons/send-message.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/settings.svg b/public/icons/settings.svg new file mode 100644 index 00000000..da3e6951 --- /dev/null +++ b/public/icons/settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/share-x.svg b/public/icons/share-x.svg new file mode 100644 index 00000000..1da70f37 --- /dev/null +++ b/public/icons/share-x.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/share.svg b/public/icons/share.svg new file mode 100644 index 00000000..ee51dec3 --- /dev/null +++ b/public/icons/share.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/slider-arrow.svg b/public/icons/slider-arrow.svg new file mode 100644 index 00000000..b8e18ff1 --- /dev/null +++ b/public/icons/slider-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/telegram-white.svg b/public/icons/telegram-white.svg new file mode 100644 index 00000000..c8620205 --- /dev/null +++ b/public/icons/telegram-white.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/icons/tumblr-white.svg b/public/icons/tumblr-white.svg new file mode 100644 index 00000000..327dfb3b --- /dev/null +++ b/public/icons/tumblr-white.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/icons/tumblr.svg b/public/icons/tumblr.svg new file mode 100644 index 00000000..ef79bb33 --- /dev/null +++ b/public/icons/tumblr.svg @@ -0,0 +1 @@ +Tumblr icon \ No newline at end of file diff --git a/public/icons/twitter-white.svg b/public/icons/twitter-white.svg new file mode 100644 index 00000000..3d2db249 --- /dev/null +++ b/public/icons/twitter-white.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/icons/user-anonymous.svg b/public/icons/user-anonymous.svg new file mode 100644 index 00000000..c7b62b2e --- /dev/null +++ b/public/icons/user-anonymous.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/video.svg b/public/icons/video.svg new file mode 100644 index 00000000..57633e93 --- /dev/null +++ b/public/icons/video.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/view.svg b/public/icons/view.svg new file mode 100644 index 00000000..54e28bdc --- /dev/null +++ b/public/icons/view.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/visa_mastercard.svg b/public/icons/visa_mastercard.svg new file mode 100644 index 00000000..e69de29b diff --git a/public/icons/vk-white.svg b/public/icons/vk-white.svg new file mode 100644 index 00000000..16df28fa --- /dev/null +++ b/public/icons/vk-white.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/icons/vk.svg b/public/icons/vk.svg new file mode 100644 index 00000000..0e027d75 --- /dev/null +++ b/public/icons/vk.svg @@ -0,0 +1,4 @@ + + + diff --git a/public/icons/yandex.svg b/public/icons/yandex.svg new file mode 100644 index 00000000..e69de29b diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 00000000..c1056245 Binary files /dev/null and b/public/logo.png differ diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 00000000..bf7f6de3 --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 00000000..3e28032d --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,18 @@ +{ + "theme_color": "#111111", + "background_color": "#ffffff", + "display": "standalone", + "scope": "/", + "start_url": "/", + "name": "discours.io", + "short_name": "discours.io", + "description": "Дискурс - коллаборативная журналистика", + "icons": [ + { + "src": "/favicon.png", + "sizes": "200x200", + "type": "image/png", + "purpose": "any maskable" + } + ] +} diff --git a/src/components/Article/Comment.scss b/src/components/Article/Comment.scss new file mode 100644 index 00000000..b9bda801 --- /dev/null +++ b/src/components/Article/Comment.scss @@ -0,0 +1,119 @@ +.comment { + background-color: #fff; + margin: 0 -2.4rem 1.5em; + padding: 0.8rem 2.4rem; + transition: background-color 0.3s; + + &:hover { + background-color: #f6f6f6; + + .comment-control--share, + .comment-control--delete, + .comment-control--edit, + .comment-control--complain { + opacity: 1; + } + } + + .shout-body { + @include font-size(1.5rem); + + margin-bottom: 1em; + + *:last-child { + margin-bottom: 0; + } + } + + .circlewrap { + position: absolute; + } + + .author { + align-items: center; + margin-bottom: 1.4rem; + } + + .author__name { + font-weight: bold; + @include font-size(1.2rem); + + margin-bottom: 0; + } + + .author__details { + margin-left: 4rem; + } + + .shout-date { + @include font-size(1.2rem); + + flex: 1; + color: rgb(0 0 0 / 30%); + } +} + +.comment--level-1 { + margin-left: 2.4rem; +} + +.comment--level-2 { + margin-left: 4.8rem; +} + +.comment--level-3 { + margin-left: 7.2rem; +} + +.comment--level-4 { + margin-left: 9.6rem; +} + +.comment--level-5 { + margin-left: 12rem; +} + +.shout-controls { + align-items: baseline; + display: flex; + justify-content: space-between; + padding-top: 0.8rem; +} + +.comment-controls { + margin-bottom: 0.5em; +} + +.comment-control--share, +.comment-control--delete, +.comment-control--edit, +.comment-control--complain { + opacity: 0; + transition: opacity 0.3s; +} + +.comment-control { + background: rgb(0 0 0 / 5%); + border: none; + cursor: pointer; + display: inline-flex; + line-height: 1.2; + margin-right: 0.8rem; + padding: 0.2em 0.3em; + vertical-align: top; + + .icon { + margin-right: 0.3em; + + img { + margin-bottom: -0.1em; + } + } +} + +.comment-control--reply { + .icon { + height: 1.2em; + width: 1.2em; + } +} diff --git a/src/components/Article/Comment.tsx b/src/components/Article/Comment.tsx new file mode 100644 index 00000000..a5e83d5c --- /dev/null +++ b/src/components/Article/Comment.tsx @@ -0,0 +1,115 @@ +import './Comment.scss' +import Icon from '../Nav/Icon' +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 { t } from '../../utils/intl' +// import { createReaction, updateReaction, deleteReaction } from '../../stores/zine/reactions' +import { renderMarkdown } from '@astrojs/markdown-remark' +import { markdownOptions } from '../../../mdx.config' + +export default (props: { + level?: number + comment: Partial + canEdit?: boolean + 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)) + } + }) + const remove = () => { + if (comment()?.id) { + console.log('[comment] removing', comment().id) + // FIXME + // deleteReaction(comment().id) + } + } + + return ( +
+ + + } + > +
+
+ +
+ +
{comment()?.createdAt}
+
{comment().stat.rating}
+
+
+ +
+
+
+ + +
+ + + + {/*FIXME*/} + {/* showModal('editComment')}*/} + {/*>*/} + {/* */} + {/* {t('Edit')}*/} + {/**/} + + + + {/*FIXME*/} + {/*
+
+
+ +
+ ) +} diff --git a/src/components/Article/Full.scss b/src/components/Article/Full.scss new file mode 100644 index 00000000..eb3fc2d2 --- /dev/null +++ b/src/components/Article/Full.scss @@ -0,0 +1,163 @@ +h1 { + @include font-size(4rem); + + line-height: 1.1; + margin-top: 0.5em; +} + +h2 { + line-height: 1.1; +} + +img { + max-width: 100%; +} + +.article { + padding-top: 2em; +} + +.article__header { + margin-bottom: 2em; + + @include media-breakpoint-up(md) { + margin: 0 -16.6666% 2em; + } +} + +.article__cover { + background-size: cover; + height: 0; + padding-bottom: 56.2%; +} + +.article__body { + font-size: 1.7rem; + line-height: 1.6; + + img { + display: block; + margin-bottom: 0.5em; + } + + blockquote { + border-left: 4px solid; + font-size: 2rem; + font-weight: 500; + font-style: italic; + line-height: 1.4; + margin: 1.5em 0 1.5em -16.6666%; + padding: 0 0 0 1em; + } + + mark { + background: none; + font-size: 2rem; + font-weight: bold; + line-height: 1.4; + } +} + +.article__author { + margin-bottom: 2em; +} + +.article__authors-list { + margin-top: 2em; + + h4 { + color: #696969; + font-size: 1.5rem; + font-weight: normal; + } +} + +.write-comment { + border: 2px solid #f6f6f6; + @include font-size(1.7rem); + + outline: none; + padding: 0.2em 0.4em; + width: 100%; + + &::placeholder { + color: #858585; + } +} + +.comment-warning { + background: #f6f6f6; + @include font-size(2.2rem); + + margin-bottom: 1em; + padding: 2.4rem 1.8rem; +} + +.article-stats { + border-bottom: 1px solid #e8e8e8; + border-top: 4px solid #000; + padding: 3.2rem 0; +} + +.article-stats__item { + @include font-size(1.7rem); + + font-weight: 500; + display: inline-block; + margin-right: $grid-gutter-width; + vertical-align: baseline; + + .icon { + display: inline-block; + margin-right: 0.2em; + transition: filter 0.2s; + vertical-align: middle; + } + + img { + display: block; + } + + a { + border: none; + + &:hover { + .icon { + filter: invert(1); + } + } + } +} + +.article-stats__item--likes { + .icon { + vertical-align: baseline; + } + + .icon:last-of-type { + // transform: rotate(180deg); + transform-origin: center; + margin-left: 0.3em; + vertical-align: middle; + } +} + +.topics-list { + margin: 2.4rem 0; + + .article__topic { + display: inline-block; + margin: 0 0.8rem 0.8rem 0; + + a { + background: #f6f6f6; + color: #000; + padding: 0.4rem 0.8rem; + transition: background-color 0.2s; + + &:hover { + background-color: rgb(0 0 0 / 20%); + } + } + } +} diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx new file mode 100644 index 00000000..5f3a3233 --- /dev/null +++ b/src/components/Article/FullArticle.tsx @@ -0,0 +1,198 @@ +import { capitalize } from '../../utils' +import './Full.scss' +import Icon from '../Nav/Icon' +import ArticleComment from './Comment' +import { AuthorCard } from '../Author/Card' +import { createMemo, createSignal, 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 { renderMarkdown } from '@astrojs/markdown-remark' +import { markdownOptions } from '../../../mdx.config' +const MAX_COMMENT_LEVEL = 6 + +const getCommentLevel = (comment: Reaction, level = 0) => { + if (comment && comment.replyTo && level < MAX_COMMENT_LEVEL) { + return 0 // FIXME: getCommentLevel(commentsById[c.replyTo], level + 1) + } + return level +} + +interface ArticleProps { + article: Shout + reactions: Reaction[] + isCommentsLoading: boolean +} + +const formatDate = (date: Date) => { + return date + .toLocaleDateString('ru', { + month: 'long', + day: 'numeric', + year: 'numeric' + }) + .replace(' г.', '') +} + +export const FullArticle = (props: ArticleProps) => { + const [body, setBody] = createSignal('') + onMount(() => { + const b: string = props.article?.body + if (b?.toString().startsWith('<')) setBody(b) + else { + renderMarkdown(b, markdownOptions).then(({ code }) => setBody(code)) + } + }) + + const formattedDate = createMemo(() => formatDate(new Date(props.article.createdAt))) + + const mainTopic = () => + (props.article.topics?.find((topic) => topic?.slug === props.article.mainTopic)?.title || '').replace( + ' ', + ' ' + ) + + onMount(() => { + const windowHash = window.location.hash + + if (windowHash?.length > 0) { + const comments = document.querySelector(windowHash) + + if (comments) { + window.scrollTo({ + top: comments.getBoundingClientRect().top, + behavior: 'smooth' + }) + } + } + }) + + return ( +
+ + +
+
+ + +
+ + {props.article.stat?.commented || ''} +
+
+ + {props.article.stat?.viewed} +
+ {/*FIXME*/} + {/**/} + + {/*FIXME*/} + {/**/} + {/* */} + {/**/} +
{formattedDate}
+
+ + {/*FIXME*/} + {/*
*/} + {/* */} + {/* {(topic) => (*/} + {/* */} + {/* )}*/} + {/* */} + {/*
*/} + +
+ 1}> +

{t('Authors')}

+
+ + {(a: Author) => } + +
+ + +

+ {t('Comments')} {props.reactions?.length.toString() || ''} +

+ + r.body)}> + {(reaction) => ( + + )} + +
+ + {/*FIXME*/} + {/**/} + {/*
*/} + {/* {t('To leave a comment you please')}*/} + {/* {*/} + {/* evt.preventDefault()*/} + {/* showModal('auth')*/} + {/* }}*/} + {/* >*/} + {/* {t('sign up or sign in')}*/} + {/* */} + {/*
*/} + {/*
*/} + {/**/} + {/*