linted-update
This commit is contained in:
parent
7d895aa343
commit
ba55780246
14
biome.json
14
biome.json
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://biomejs.dev/schemas/1.8.2/schema.json",
|
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
|
||||||
"files": {
|
"files": {
|
||||||
"include": ["*.tsx", "*.ts", "*.js", "*.json"],
|
"include": ["*.tsx", "*.ts", "*.js", "*.json"],
|
||||||
"ignore": ["./dist", "./node_modules", ".husky", "docs", "gen", "*.gen.ts", "*.d.ts"]
|
"ignore": ["./dist", "./node_modules", ".husky", "docs", "gen", "*.gen.ts", "*.d.ts"]
|
||||||
|
@ -42,7 +42,9 @@
|
||||||
"noExcessiveCognitiveComplexity": "off"
|
"noExcessiveCognitiveComplexity": "off"
|
||||||
},
|
},
|
||||||
"correctness": {
|
"correctness": {
|
||||||
"useHookAtTopLevel": "off"
|
"useHookAtTopLevel": "off",
|
||||||
|
"useImportExtensions": "off",
|
||||||
|
"noUndeclaredDependencies": "off"
|
||||||
},
|
},
|
||||||
"a11y": {
|
"a11y": {
|
||||||
"useHeadingContent": "off",
|
"useHeadingContent": "off",
|
||||||
|
@ -54,7 +56,8 @@
|
||||||
"useAltText": "off",
|
"useAltText": "off",
|
||||||
"useButtonType": "off",
|
"useButtonType": "off",
|
||||||
"noRedundantAlt": "off",
|
"noRedundantAlt": "off",
|
||||||
"noSvgWithoutTitle": "off"
|
"noSvgWithoutTitle": "off",
|
||||||
|
"noLabelWithoutControl": "off"
|
||||||
},
|
},
|
||||||
"nursery": {
|
"nursery": {
|
||||||
"useImportRestrictions": "off"
|
"useImportRestrictions": "off"
|
||||||
|
@ -63,15 +66,18 @@
|
||||||
"noBarrelFile": "off"
|
"noBarrelFile": "off"
|
||||||
},
|
},
|
||||||
"style": {
|
"style": {
|
||||||
|
"noNonNullAssertion": "off",
|
||||||
"noNamespaceImport": "warn",
|
"noNamespaceImport": "warn",
|
||||||
"useBlockStatements": "off",
|
"useBlockStatements": "off",
|
||||||
"noImplicitBoolean": "off",
|
"noImplicitBoolean": "off",
|
||||||
"useNamingConvention": "off",
|
"useNamingConvention": "off",
|
||||||
"useImportType": "off",
|
"useImportType": "off",
|
||||||
"noDefaultExport": "off",
|
"noDefaultExport": "off",
|
||||||
"useFilenamingConvention": "off"
|
"useFilenamingConvention": "off",
|
||||||
|
"useExplicitLengthCheck": "off"
|
||||||
},
|
},
|
||||||
"suspicious": {
|
"suspicious": {
|
||||||
|
"noConsole": "off",
|
||||||
"noConsoleLog": "off",
|
"noConsoleLog": "off",
|
||||||
"noAssignInExpressions": "off"
|
"noAssignInExpressions": "off"
|
||||||
}
|
}
|
||||||
|
|
48
package.json
48
package.json
|
@ -22,13 +22,13 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@authorizerdev/authorizer-js": "^2.0.3",
|
"@authorizerdev/authorizer-js": "^2.0.3",
|
||||||
"@biomejs/biome": "^1.8.3",
|
"@biomejs/biome": "^1.9.1",
|
||||||
"@graphql-codegen/cli": "^5.0.2",
|
"@graphql-codegen/cli": "^5.0.2",
|
||||||
"@graphql-codegen/typescript": "^4.0.9",
|
"@graphql-codegen/typescript": "^4.0.9",
|
||||||
"@graphql-codegen/typescript-operations": "^4.2.3",
|
"@graphql-codegen/typescript-operations": "^4.2.3",
|
||||||
"@graphql-codegen/typescript-urql": "^4.0.0",
|
"@graphql-codegen/typescript-urql": "^4.0.0",
|
||||||
"@hocuspocus/provider": "^2.13.5",
|
"@hocuspocus/provider": "^2.13.5",
|
||||||
"@playwright/test": "^1.46.1",
|
"@playwright/test": "^1.47.1",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@solid-primitives/media": "^2.2.9",
|
"@solid-primitives/media": "^2.2.9",
|
||||||
"@solid-primitives/memo": "^1.3.9",
|
"@solid-primitives/memo": "^1.3.9",
|
||||||
|
@ -38,22 +38,22 @@
|
||||||
"@solid-primitives/storage": "^3.8.0",
|
"@solid-primitives/storage": "^3.8.0",
|
||||||
"@solid-primitives/upload": "^0.0.117",
|
"@solid-primitives/upload": "^0.0.117",
|
||||||
"@solidjs/meta": "^0.29.4",
|
"@solidjs/meta": "^0.29.4",
|
||||||
"@solidjs/router": "^0.14.3",
|
"@solidjs/router": "^0.14.5",
|
||||||
"@solidjs/start": "^1.0.6",
|
"@solidjs/start": "^1.0.6",
|
||||||
"@storybook/addon-a11y": "^8.2.9",
|
"@storybook/addon-a11y": "^8.3.0",
|
||||||
"@storybook/addon-actions": "^8.2.9",
|
"@storybook/addon-actions": "^8.3.0",
|
||||||
"@storybook/addon-controls": "^8.2.9",
|
"@storybook/addon-controls": "^8.3.0",
|
||||||
"@storybook/addon-essentials": "^8.2.9",
|
"@storybook/addon-essentials": "^8.3.0",
|
||||||
"@storybook/addon-interactions": "^8.2.9",
|
"@storybook/addon-interactions": "^8.3.0",
|
||||||
"@storybook/addon-links": "^8.2.9",
|
"@storybook/addon-links": "^8.3.0",
|
||||||
"@storybook/addon-styling": "1.3.7",
|
"@storybook/addon-styling": "1.3.7",
|
||||||
"@storybook/addon-themes": "^8.2.9",
|
"@storybook/addon-themes": "^8.3.0",
|
||||||
"@storybook/addon-viewport": "^8.2.9",
|
"@storybook/addon-viewport": "^8.3.0",
|
||||||
"@storybook/blocks": "^8.2.9",
|
"@storybook/blocks": "^8.3.0",
|
||||||
"@storybook/builder-vite": "8.2.9",
|
"@storybook/builder-vite": "8.2.9",
|
||||||
"@storybook/docs-tools": "8.2.9",
|
"@storybook/docs-tools": "8.2.9",
|
||||||
"@storybook/html": "^8.2.9",
|
"@storybook/html": "^8.3.0",
|
||||||
"@storybook/react": "^8.2.9",
|
"@storybook/react": "^8.3.0",
|
||||||
"@storybook/test-runner": "^0.19.1",
|
"@storybook/test-runner": "^0.19.1",
|
||||||
"@storybook/testing-library": "^0.2.2",
|
"@storybook/testing-library": "^0.2.2",
|
||||||
"@tiptap/core": "^2.6.6",
|
"@tiptap/core": "^2.6.6",
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
"@tiptap/extension-youtube": "^2.6.6",
|
"@tiptap/extension-youtube": "^2.6.6",
|
||||||
"@types/cookie": "^0.6.0",
|
"@types/cookie": "^0.6.0",
|
||||||
"@types/cookie-signature": "^1.1.2",
|
"@types/cookie-signature": "^1.1.2",
|
||||||
"@types/node": "^22.5.2",
|
"@types/node": "^22.5.5",
|
||||||
"@types/throttle-debounce": "^5.0.2",
|
"@types/throttle-debounce": "^5.0.2",
|
||||||
"@urql/core": "^5.0.6",
|
"@urql/core": "^5.0.6",
|
||||||
"axe-playwright": "^2.0.2",
|
"axe-playwright": "^2.0.2",
|
||||||
|
@ -96,10 +96,10 @@
|
||||||
"cookie": "^0.6.0",
|
"cookie": "^0.6.0",
|
||||||
"cookie-signature": "^1.2.1",
|
"cookie-signature": "^1.2.1",
|
||||||
"cropperjs": "^1.6.2",
|
"cropperjs": "^1.6.2",
|
||||||
"extended-eventsource": "^1.4.9",
|
"extended-eventsource": "^1.6.4",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"graphql": "^16.9.0",
|
"graphql": "^16.9.0",
|
||||||
"i18next": "^23.14.0",
|
"i18next": "^23.15.1",
|
||||||
"i18next-http-backend": "^2.6.1",
|
"i18next-http-backend": "^2.6.1",
|
||||||
"i18next-icu": "^2.3.0",
|
"i18next-icu": "^2.3.0",
|
||||||
"intl-messageformat": "^10.5.14",
|
"intl-messageformat": "^10.5.14",
|
||||||
|
@ -107,31 +107,31 @@
|
||||||
"patch-package": "^8.0.0",
|
"patch-package": "^8.0.0",
|
||||||
"prosemirror-history": "^1.4.1",
|
"prosemirror-history": "^1.4.1",
|
||||||
"prosemirror-trailing-node": "^2.0.9",
|
"prosemirror-trailing-node": "^2.0.9",
|
||||||
"prosemirror-view": "^1.34.1",
|
"prosemirror-view": "^1.34.2",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"sass": "1.76.0",
|
"sass": "1.76.0",
|
||||||
"solid-js": "^1.8.22",
|
"solid-js": "^1.8.22",
|
||||||
"solid-popper": "^0.3.0",
|
"solid-popper": "^0.3.0",
|
||||||
"solid-tiptap": "0.7.0",
|
"solid-tiptap": "0.7.0",
|
||||||
"solid-transition-group": "^0.2.3",
|
"solid-transition-group": "^0.2.3",
|
||||||
"storybook": "^8.2.9",
|
"storybook": "^8.3.0",
|
||||||
"storybook-solidjs": "^1.0.0-beta.2",
|
"storybook-solidjs": "^1.0.0-beta.2",
|
||||||
"storybook-solidjs-vite": "^1.0.0-beta.2",
|
"storybook-solidjs-vite": "^1.0.0-beta.2",
|
||||||
"stylelint": "^16.9.0",
|
"stylelint": "^16.9.0",
|
||||||
"stylelint-config-recommended": "^14.0.1",
|
"stylelint-config-recommended": "^14.0.1",
|
||||||
"stylelint-config-standard-scss": "^13.1.0",
|
"stylelint-config-standard-scss": "^13.1.0",
|
||||||
"stylelint-order": "^6.0.4",
|
"stylelint-order": "^6.0.4",
|
||||||
"stylelint-scss": "^6.5.1",
|
"stylelint-scss": "^6.6.0",
|
||||||
"swiper": "^11.1.12",
|
"swiper": "^11.1.14",
|
||||||
"throttle-debounce": "^5.0.2",
|
"throttle-debounce": "^5.0.2",
|
||||||
"tslib": "^2.7.0",
|
"tslib": "^2.7.0",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.6.2",
|
||||||
"typograf": "^7.4.1",
|
"typograf": "^7.4.1",
|
||||||
"uniqolor": "^1.1.1",
|
"uniqolor": "^1.1.1",
|
||||||
"vinxi": "^0.4.2",
|
"vinxi": "^0.4.3",
|
||||||
"vite-plugin-mkcert": "^1.17.6",
|
"vite-plugin-mkcert": "^1.17.6",
|
||||||
"vite-plugin-node-polyfills": "^0.22.0",
|
"vite-plugin-node-polyfills": "^0.22.0",
|
||||||
"vite-plugin-sass-dts": "^1.3.25",
|
"vite-plugin-sass-dts": "^1.3.29",
|
||||||
"y-prosemirror": "1.2.12",
|
"y-prosemirror": "1.2.12",
|
||||||
"yjs": "13.6.18"
|
"yjs": "13.6.18"
|
||||||
},
|
},
|
||||||
|
|
|
@ -74,7 +74,7 @@ export const PlayerHeader = (props: Props) => {
|
||||||
onChange={({ target }) => props.onVolumeChange(Number(target.value))}
|
onChange={({ target }) => props.onVolumeChange(Number(target.value))}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
<button onClick={toggleVolumeBar} class={styles.volumeButton} role="button" aria-label="Volume">
|
<button onClick={toggleVolumeBar} class={styles.volumeButton} aria-label="Volume">
|
||||||
<Icon name="volume" />
|
<Icon name="volume" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -84,7 +84,6 @@ export const CommentRatingControl = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<div class={styles.commentRating}>
|
<div class={styles.commentRating}>
|
||||||
<button
|
<button
|
||||||
role="button"
|
|
||||||
disabled={!(canVote() && uid())}
|
disabled={!(canVote() && uid())}
|
||||||
onClick={() => handleRatingChange(true)}
|
onClick={() => handleRatingChange(true)}
|
||||||
class={clsx(styles.commentRatingControl, styles.commentRatingControlUp, {
|
class={clsx(styles.commentRatingControl, styles.commentRatingControlUp, {
|
||||||
|
@ -110,7 +109,6 @@ export const CommentRatingControl = (props: Props) => {
|
||||||
/>
|
/>
|
||||||
</Popup>
|
</Popup>
|
||||||
<button
|
<button
|
||||||
role="button"
|
|
||||||
disabled={!(canVote() && uid())}
|
disabled={!(canVote() && uid())}
|
||||||
onClick={() => handleRatingChange(false)}
|
onClick={() => handleRatingChange(false)}
|
||||||
class={clsx(styles.commentRatingControl, styles.commentRatingControlDown, {
|
class={clsx(styles.commentRatingControl, styles.commentRatingControlDown, {
|
||||||
|
|
|
@ -112,7 +112,7 @@ export const FullArticle = (props: Props) => {
|
||||||
const mainTopicSlug = (props.article.topics?.length || 0) > 0 ? props.article.main_topic : null
|
const mainTopicSlug = (props.article.topics?.length || 0) > 0 ? props.article.main_topic : null
|
||||||
const mt = props.article.topics?.find((tpc: Maybe<Topic>) => tpc?.slug === mainTopicSlug)
|
const mt = props.article.topics?.find((tpc: Maybe<Topic>) => tpc?.slug === mainTopicSlug)
|
||||||
if (mt) {
|
if (mt) {
|
||||||
mt.title = lang() === 'en' ? capitalize(mt.slug.replace(/-/, ' ')) : mt.title
|
mt.title = lang() === 'en' ? capitalize(mt.slug.replaceAll('-', ' ')) : mt.title
|
||||||
return mt
|
return mt
|
||||||
}
|
}
|
||||||
return props.article.topics?.[0]
|
return props.article.topics?.[0]
|
||||||
|
@ -326,7 +326,7 @@ export const FullArticle = (props: Props) => {
|
||||||
|
|
||||||
const shareUrl = createMemo(() => getShareUrl({ pathname: `/${props.article.slug || ''}` }))
|
const shareUrl = createMemo(() => getShareUrl({ pathname: `/${props.article.slug || ''}` }))
|
||||||
const getAuthorName = (a: Author) =>
|
const getAuthorName = (a: Author) =>
|
||||||
lang() === 'en' && isCyrillic(a.name || '') ? capitalize(a.slug.replace(/-/, ' ')) : a.name
|
lang() === 'en' && isCyrillic(a.name || '') ? capitalize(a.slug.replaceAll('-', ' ')) : a.name
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<For each={imageUrls()}>{(imageUrl) => <Link rel="preload" as="image" href={imageUrl} />}</For>
|
<For each={imageUrls()}>{(imageUrl) => <Link rel="preload" as="image" href={imageUrl} />}</For>
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const Userpic = (props: Props) => {
|
||||||
const letters = () => {
|
const letters = () => {
|
||||||
if (!props.name) return
|
if (!props.name) return
|
||||||
const names = props.name ? props.name.split(' ') : []
|
const names = props.name ? props.name.split(' ') : []
|
||||||
return `${names[0][0 ?? names[0][0]]}.${names.length > 1 ? `${names[1][0]}.` : ''}`
|
return `${names[0][0] ? names[0][0] : ''}.${names.length > 1 ? `${names[1][0]}.` : ''}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const avatarSize = createMemo(() => {
|
const avatarSize = createMemo(() => {
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const BlockquoteBubbleMenu = (props: Props) => {
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.editor.chain().focus().setBlockQuoteFloat('left').run()
|
props.editor?.chain().focus().setBlockQuoteFloat('left').run()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-align-left" />
|
<Icon name="editor-image-align-left" />
|
||||||
|
@ -35,7 +35,7 @@ export const BlockquoteBubbleMenu = (props: Props) => {
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setBlockQuoteFloat(null).run()}
|
onClick={() => props.editor?.chain().focus().setBlockQuoteFloat(null).run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-align-center" />
|
<Icon name="editor-image-align-center" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -47,7 +47,7 @@ export const BlockquoteBubbleMenu = (props: Props) => {
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setBlockQuoteFloat('right').run()}
|
onClick={() => props.editor?.chain().focus().setBlockQuoteFloat('right').run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-align-right" />
|
<Icon name="editor-image-align-right" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -33,7 +33,7 @@ export const FigureBubbleMenu = (props: Props) => {
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setFigureFloat('left').run()}
|
onClick={() => props.editor?.chain().focus().setFigureFloat('left').run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-align-left" />
|
<Icon name="editor-image-align-left" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -45,7 +45,7 @@ export const FigureBubbleMenu = (props: Props) => {
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setFigureFloat(null).run()}
|
onClick={() => props.editor?.chain().focus().setFigureFloat(null).run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-align-center" />
|
<Icon name="editor-image-align-center" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -57,7 +57,7 @@ export const FigureBubbleMenu = (props: Props) => {
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setFigureFloat('right').run()}
|
onClick={() => props.editor?.chain().focus().setFigureFloat('right').run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-align-right" />
|
<Icon name="editor-image-align-right" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -67,7 +67,7 @@ export const FigureBubbleMenu = (props: Props) => {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setFigcaptionFocus(true).run()}
|
onClick={() => props.editor?.chain().focus().setFigcaptionFocus(true).run()}
|
||||||
>
|
>
|
||||||
<span style={{ color: 'white' }}>{t('Add signature')}</span>
|
<span style={{ color: 'white' }}>{t('Add signature')}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const IncutBubbleMenu = (props: Props) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const [substratBubbleOpen, setSubstratBubbleOpen] = createSignal(false)
|
const [substratBubbleOpen, setSubstratBubbleOpen] = createSignal(false)
|
||||||
const handleChangeBg = (bg: string | null) => {
|
const handleChangeBg = (bg: string | null) => {
|
||||||
props.editor.chain().focus().setArticleBg(bg).run()
|
props.editor?.chain().focus().setArticleBg(bg).run()
|
||||||
setSubstratBubbleOpen(false)
|
setSubstratBubbleOpen(false)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -27,14 +27,14 @@ export const IncutBubbleMenu = (props: Props) => {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setArticleFloat('half-left').run()}
|
onClick={() => props.editor?.chain().focus().setArticleFloat('half-left').run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-half-align-left" />
|
<Icon name="editor-image-half-align-left" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setArticleFloat(null).run()}
|
onClick={() => props.editor?.chain().focus().setArticleFloat(null).run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-align-center" />
|
<Icon name="editor-image-align-center" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -42,7 +42,7 @@ export const IncutBubbleMenu = (props: Props) => {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class={styles.bubbleMenuButton}
|
class={styles.bubbleMenuButton}
|
||||||
onClick={() => props.editor.chain().focus().setArticleFloat('half-right').run()}
|
onClick={() => props.editor?.chain().focus().setArticleFloat('half-right').run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-image-half-align-right" />
|
<Icon name="editor-image-half-align-right" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -77,17 +77,15 @@ export const EditorFloatingMenu = (props: FloatingMenuProps) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
switch (selectedMenuItem()) {
|
if (selectedMenuItem() === 'image') {
|
||||||
case 'image': {
|
|
||||||
showModal('uploadImage')
|
showModal('uploadImage')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case 'horizontal-rule': {
|
if (selectedMenuItem() === 'horizontal-rule') {
|
||||||
props.editor?.chain().focus().setHorizontalRule().run()
|
props.editor?.chain().focus().setHorizontalRule().run()
|
||||||
setSelectedMenuItem()
|
setSelectedMenuItem()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const closeUploadModalHandler = () => {
|
const closeUploadModalHandler = () => {
|
||||||
|
|
|
@ -91,9 +91,9 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
|
|
||||||
const handleAddFootnote = (footnote: string) => {
|
const handleAddFootnote = (footnote: string) => {
|
||||||
if (footNote()) {
|
if (footNote()) {
|
||||||
props.editor.chain().focus().updateFootnote({ value: footnote }).run()
|
props.editor?.chain().focus().updateFootnote({ value: footnote }).run()
|
||||||
} else {
|
} else {
|
||||||
props.editor.chain().focus().setFootnote({ value: footnote }).run()
|
props.editor?.chain().focus().setFootnote({ value: footnote }).run()
|
||||||
}
|
}
|
||||||
setFootNote()
|
setFootNote()
|
||||||
setLinkEditorOpen(false)
|
setLinkEditorOpen(false)
|
||||||
|
@ -108,16 +108,16 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
|
|
||||||
const handleSetPunchline = () => {
|
const handleSetPunchline = () => {
|
||||||
if (isPunchLine()) {
|
if (isPunchLine()) {
|
||||||
props.editor.chain().focus().toggleBlockquote('punchline').run()
|
props.editor?.chain().focus().toggleBlockquote('punchline').run()
|
||||||
}
|
}
|
||||||
props.editor.chain().focus().toggleBlockquote('quote').run()
|
props.editor?.chain().focus().toggleBlockquote('quote').run()
|
||||||
toggleTextSizePopup()
|
toggleTextSizePopup()
|
||||||
}
|
}
|
||||||
const handleSetQuote = () => {
|
const handleSetQuote = () => {
|
||||||
if (isQuote()) {
|
if (isQuote()) {
|
||||||
props.editor.chain().focus().toggleBlockquote('quote').run()
|
props.editor?.chain().focus().toggleBlockquote('quote').run()
|
||||||
}
|
}
|
||||||
props.editor.chain().focus().toggleBlockquote('punchline').run()
|
props.editor?.chain().focus().toggleBlockquote('punchline').run()
|
||||||
toggleTextSizePopup()
|
toggleTextSizePopup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,13 +130,13 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleOpenLinkForm = () => {
|
const handleOpenLinkForm = () => {
|
||||||
props.editor.chain().focus().addTextWrap({ class: 'highlight-fake-selection' }).run()
|
props.editor?.chain().focus().addTextWrap({ class: 'highlight-fake-selection' }).run()
|
||||||
setLinkEditorOpen(true)
|
setLinkEditorOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCloseLinkForm = () => {
|
const handleCloseLinkForm = () => {
|
||||||
setLinkEditorOpen(false)
|
setLinkEditorOpen(false)
|
||||||
props.editor.chain().focus().removeTextWrap({ class: 'highlight-fake-selection' }).run()
|
props.editor?.chain().focus().removeTextWrap({ class: 'highlight-fake-selection' }).run()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -188,7 +188,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
[styles.bubbleMenuButtonActive]: isH1()
|
[styles.bubbleMenuButtonActive]: isH1()
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.editor.chain().focus().toggleHeading({ level: 2 }).run()
|
props.editor?.chain().focus().toggleHeading({ level: 2 }).run()
|
||||||
toggleTextSizePopup()
|
toggleTextSizePopup()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -205,7 +205,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
[styles.bubbleMenuButtonActive]: isH2()
|
[styles.bubbleMenuButtonActive]: isH2()
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.editor.chain().focus().toggleHeading({ level: 3 }).run()
|
props.editor?.chain().focus().toggleHeading({ level: 3 }).run()
|
||||||
toggleTextSizePopup()
|
toggleTextSizePopup()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -222,7 +222,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
[styles.bubbleMenuButtonActive]: isH3()
|
[styles.bubbleMenuButtonActive]: isH3()
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.editor.chain().focus().toggleHeading({ level: 4 }).run()
|
props.editor?.chain().focus().toggleHeading({ level: 4 }).run()
|
||||||
toggleTextSizePopup()
|
toggleTextSizePopup()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -273,7 +273,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
[styles.bubbleMenuButtonActive]: isIncut()
|
[styles.bubbleMenuButtonActive]: isIncut()
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.editor.chain().focus().toggleArticle().run()
|
props.editor?.chain().focus().toggleArticle().run()
|
||||||
toggleTextSizePopup()
|
toggleTextSizePopup()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -296,7 +296,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
class={clsx(styles.bubbleMenuButton, {
|
class={clsx(styles.bubbleMenuButton, {
|
||||||
[styles.bubbleMenuButtonActive]: isBold()
|
[styles.bubbleMenuButtonActive]: isBold()
|
||||||
})}
|
})}
|
||||||
onClick={() => props.editor.chain().focus().toggleBold().run()}
|
onClick={() => props.editor?.chain().focus().toggleBold().run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-bold" />
|
<Icon name="editor-bold" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -310,7 +310,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
class={clsx(styles.bubbleMenuButton, {
|
class={clsx(styles.bubbleMenuButton, {
|
||||||
[styles.bubbleMenuButtonActive]: isItalic()
|
[styles.bubbleMenuButtonActive]: isItalic()
|
||||||
})}
|
})}
|
||||||
onClick={() => props.editor.chain().focus().toggleItalic().run()}
|
onClick={() => props.editor?.chain().focus().toggleItalic().run()}
|
||||||
>
|
>
|
||||||
<Icon name="editor-italic" />
|
<Icon name="editor-italic" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -326,7 +326,9 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
class={clsx(styles.bubbleMenuButton, {
|
class={clsx(styles.bubbleMenuButton, {
|
||||||
[styles.bubbleMenuButtonActive]: isHighlight()
|
[styles.bubbleMenuButtonActive]: isHighlight()
|
||||||
})}
|
})}
|
||||||
onClick={() => props.editor.chain().focus().toggleHighlight({ color: '#f6e3a1' }).run()}
|
onClick={() =>
|
||||||
|
props.editor?.chain().focus().toggleHighlight({ color: '#f6e3a1' }).run()
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div class={styles.toggleHighlight} />
|
<div class={styles.toggleHighlight} />
|
||||||
</button>
|
</button>
|
||||||
|
@ -389,7 +391,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
[styles.bubbleMenuButtonActive]: isBulletList()
|
[styles.bubbleMenuButtonActive]: isBulletList()
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.editor.chain().focus().toggleBulletList().run()
|
props.editor?.chain().focus().toggleBulletList().run()
|
||||||
toggleListPopup()
|
toggleListPopup()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -406,7 +408,7 @@ export const TextBubbleMenu = (props: BubbleMenuProps) => {
|
||||||
[styles.bubbleMenuButtonActive]: isOrderedList()
|
[styles.bubbleMenuButtonActive]: isOrderedList()
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.editor.chain().focus().toggleOrderedList().run()
|
props.editor?.chain().focus().toggleOrderedList().run()
|
||||||
toggleListPopup()
|
toggleListPopup()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -38,7 +38,7 @@ export const Figure = Node.create({
|
||||||
}
|
}
|
||||||
const img = node.querySelector('img')
|
const img = node.querySelector('img')
|
||||||
const iframe = node.querySelector('iframe')
|
const iframe = node.querySelector('iframe')
|
||||||
let dataType = null
|
let dataType: string | undefined
|
||||||
if (img) {
|
if (img) {
|
||||||
dataType = 'image'
|
dataType = 'image'
|
||||||
} else if (iframe) {
|
} else if (iframe) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Popover } from '~/components/_shared/Popover'
|
||||||
import { useLocalize } from '~/context/localize'
|
import { useLocalize } from '~/context/localize'
|
||||||
import { useSession } from '~/context/session'
|
import { useSession } from '~/context/session'
|
||||||
import type { Author, Maybe, Shout, Topic } from '~/graphql/schema/core.gen'
|
import type { Author, Maybe, Shout, Topic } from '~/graphql/schema/core.gen'
|
||||||
|
import { sentenceSeparator } from '~/intl/chars'
|
||||||
import { capitalize } from '~/utils/capitalize'
|
import { capitalize } from '~/utils/capitalize'
|
||||||
import { descFromBody } from '~/utils/meta'
|
import { descFromBody } from '~/utils/meta'
|
||||||
import { CoverImage } from '../../Article/CoverImage'
|
import { CoverImage } from '../../Article/CoverImage'
|
||||||
|
@ -69,7 +70,7 @@ const getTitleAndSubtitle = (
|
||||||
let titleParts = article.title?.split('. ') || []
|
let titleParts = article.title?.split('. ') || []
|
||||||
|
|
||||||
if (titleParts?.length === 1) {
|
if (titleParts?.length === 1) {
|
||||||
titleParts = article.title?.split(/{!|\?|:|;}\s/) || []
|
titleParts = article.title?.split(sentenceSeparator) || []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (titleParts && titleParts.length > 1) {
|
if (titleParts && titleParts.length > 1) {
|
||||||
|
@ -88,7 +89,7 @@ const getMainTopicTitle = (article: Shout, lng: string) => {
|
||||||
const mainTopicSlug = article.main_topic || ''
|
const mainTopicSlug = article.main_topic || ''
|
||||||
const mainTopic = (article.topics || []).find((tpc: Maybe<Topic>) => tpc?.slug === mainTopicSlug)
|
const mainTopic = (article.topics || []).find((tpc: Maybe<Topic>) => tpc?.slug === mainTopicSlug)
|
||||||
const mainTopicTitle =
|
const mainTopicTitle =
|
||||||
mainTopicSlug && lng === 'en' ? mainTopicSlug.replace(/-/, ' ') : mainTopic?.title || ''
|
mainTopicSlug && lng === 'en' ? mainTopicSlug.replaceAll('-', ' ') : mainTopic?.title || ''
|
||||||
|
|
||||||
return [mainTopicTitle, mainTopicSlug]
|
return [mainTopicTitle, mainTopicSlug]
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ export const FeedArticlePopup = (props: Props) => {
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
class={styles.action}
|
class={styles.action}
|
||||||
role="button"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.onShareClick()
|
props.onShareClick()
|
||||||
setHidePopup(true)
|
setHidePopup(true)
|
||||||
|
@ -47,7 +46,6 @@ export const FeedArticlePopup = (props: Props) => {
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
class={styles.action}
|
class={styles.action}
|
||||||
role="button"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
alert('Help to edit')
|
alert('Help to edit')
|
||||||
setHidePopup(true)
|
setHidePopup(true)
|
||||||
|
@ -61,7 +59,6 @@ export const FeedArticlePopup = (props: Props) => {
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
class={styles.action}
|
class={styles.action}
|
||||||
role="button"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.onInviteClick()
|
props.onInviteClick()
|
||||||
setHidePopup(false)
|
setHidePopup(false)
|
||||||
|
@ -73,7 +70,7 @@ export const FeedArticlePopup = (props: Props) => {
|
||||||
</li>
|
</li>
|
||||||
<Show when={!props.canEdit}>
|
<Show when={!props.canEdit}>
|
||||||
<li>
|
<li>
|
||||||
<button class={clsx(styles.action, styles.soon)} role="button">
|
<button class={clsx(styles.action, styles.soon)}>
|
||||||
<Icon name="bell-white" class={styles.icon} />
|
<Icon name="bell-white" class={styles.icon} />
|
||||||
<div class={styles.title}>{t('Subscribe to comments')}</div>
|
<div class={styles.title}>{t('Subscribe to comments')}</div>
|
||||||
<SoonChip />
|
<SoonChip />
|
||||||
|
@ -81,7 +78,7 @@ export const FeedArticlePopup = (props: Props) => {
|
||||||
</li>
|
</li>
|
||||||
</Show>
|
</Show>
|
||||||
<li>
|
<li>
|
||||||
<button class={clsx(styles.action, styles.soon)} role="button">
|
<button class={clsx(styles.action, styles.soon)}>
|
||||||
<Icon name="bookmark" class={styles.icon} />
|
<Icon name="bookmark" class={styles.icon} />
|
||||||
<div class={styles.title}>{t('Add to bookmarks')}</div>
|
<div class={styles.title}>{t('Add to bookmarks')}</div>
|
||||||
<SoonChip />
|
<SoonChip />
|
||||||
|
@ -91,7 +88,7 @@ export const FeedArticlePopup = (props: Props) => {
|
||||||
{/* <li>*/}
|
{/* <li>*/}
|
||||||
{/* <button*/}
|
{/* <button*/}
|
||||||
{/* class={styles.action}*/}
|
{/* class={styles.action}*/}
|
||||||
{/* role="button"*/}
|
{/* */}
|
||||||
{/* onClick={() => {*/}
|
{/* onClick={() => {*/}
|
||||||
{/* alert('Complain')*/}
|
{/* alert('Complain')*/}
|
||||||
{/* }}*/}
|
{/* }}*/}
|
||||||
|
@ -103,7 +100,7 @@ export const FeedArticlePopup = (props: Props) => {
|
||||||
{/*<li>*/}
|
{/*<li>*/}
|
||||||
{/* <button*/}
|
{/* <button*/}
|
||||||
{/* class={styles.action}*/}
|
{/* class={styles.action}*/}
|
||||||
{/* role="button"*/}
|
{/* */}
|
||||||
{/* onClick={() => {*/}
|
{/* onClick={() => {*/}
|
||||||
{/* alert('Get notifications')*/}
|
{/* alert('Get notifications')*/}
|
||||||
{/* }}*/}
|
{/* }}*/}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
@mixin search-filter-control {
|
@mixin search-filter-control {
|
||||||
@include font-size(1.4rem);
|
|
||||||
|
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
padding: 0 2rem;
|
padding: 0 2rem;
|
||||||
background: rgb(64 64 64 / 50%);
|
background: rgb(64 64 64 / 50%);
|
||||||
|
@ -9,6 +7,8 @@
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
|
@include font-size(1.4rem);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #404040;
|
background: #404040;
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchInput {
|
.searchInput {
|
||||||
@include font-size(4.8rem);
|
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 0 0.5rem;
|
padding: 0 0 0.5rem;
|
||||||
background: none;
|
background: none;
|
||||||
|
@ -34,6 +32,8 @@
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
|
@include font-size(4.8rem);
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: rgb(255 255 255 / 32%);
|
color: rgb(255 255 255 / 32%);
|
||||||
}
|
}
|
||||||
|
@ -60,10 +60,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.searchDescription {
|
.searchDescription {
|
||||||
@include font-size(1.6rem);
|
|
||||||
|
|
||||||
margin-bottom: 44px;
|
margin-bottom: 44px;
|
||||||
color: rgb(255 255 255 / 64%);
|
color: rgb(255 255 255 / 64%);
|
||||||
|
|
||||||
|
@include font-size(1.6rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.topicsList {
|
.topicsList {
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const FullTopic = (props: Props) => {
|
||||||
/* FIXME: use title translation*/
|
/* FIXME: use title translation*/
|
||||||
setTitle((_) => tpc?.title || '')
|
setTitle((_) => tpc?.title || '')
|
||||||
return `#${capitalize(
|
return `#${capitalize(
|
||||||
lang() === 'en' ? tpc.slug.replace(/-/, ' ') : tpc.title || tpc.slug.replace(/-/, ' '),
|
lang() === 'en' ? tpc.slug.replaceAll('-', ' ') : tpc.title || tpc.slug.replaceAll('-', ' '),
|
||||||
true
|
true
|
||||||
)}`
|
)}`
|
||||||
},
|
},
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
|
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
margin: 0.8rem 0;
|
margin: 0.8rem 0;
|
||||||
-webkit-line-clamp: 2;
|
line-clamp: 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { Icon } from '~/components/_shared/Icon'
|
||||||
import { useLocalize } from '~/context/localize'
|
import { useLocalize } from '~/context/localize'
|
||||||
import { useTopics } from '~/context/topics'
|
import { useTopics } from '~/context/topics'
|
||||||
import type { Topic } from '~/graphql/schema/core.gen'
|
import type { Topic } from '~/graphql/schema/core.gen'
|
||||||
|
import { ruChars } from '~/intl/chars'
|
||||||
import { getRandomItemsFromArray } from '~/utils/random'
|
import { getRandomItemsFromArray } from '~/utils/random'
|
||||||
import styles from './TopicsNav.module.scss'
|
import styles from './TopicsNav.module.scss'
|
||||||
|
|
||||||
|
@ -12,7 +13,7 @@ export const RandomTopics = () => {
|
||||||
const { sortedTopics } = useTopics()
|
const { sortedTopics } = useTopics()
|
||||||
const { lang, t } = useLocalize()
|
const { lang, t } = useLocalize()
|
||||||
const tag = (topic: Topic) =>
|
const tag = (topic: Topic) =>
|
||||||
/[ЁА-яё]/.test(topic.title || '') && lang() !== 'ru' ? topic.slug : topic.title
|
ruChars.test(topic.title || '') && lang() !== 'ru' ? topic.slug : topic.title
|
||||||
const [randomTopics, setRandomTopics] = createSignal<Topic[]>([])
|
const [randomTopics, setRandomTopics] = createSignal<Topic[]>([])
|
||||||
createEffect(
|
createEffect(
|
||||||
on(sortedTopics, (ttt: Topic[]) => {
|
on(sortedTopics, (ttt: Topic[]) => {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { SearchField } from '~/components/_shared/SearchField'
|
||||||
import { useLocalize } from '~/context/localize'
|
import { useLocalize } from '~/context/localize'
|
||||||
import { useTopics } from '~/context/topics'
|
import { useTopics } from '~/context/topics'
|
||||||
import type { Topic } from '~/graphql/schema/core.gen'
|
import type { Topic } from '~/graphql/schema/core.gen'
|
||||||
|
import { enChars, ruChars } from '~/intl/chars'
|
||||||
import { dummyFilter } from '~/intl/dummyFilter'
|
import { dummyFilter } from '~/intl/dummyFilter'
|
||||||
import { scrollHandler } from '~/utils/scroll'
|
import { scrollHandler } from '~/utils/scroll'
|
||||||
import { TopicBadge } from '../../Topic/TopicBadge'
|
import { TopicBadge } from '../../Topic/TopicBadge'
|
||||||
|
@ -35,8 +36,8 @@ export const AllTopics = (props: Props) => {
|
||||||
return topics().reduce(
|
return topics().reduce(
|
||||||
(acc, topic) => {
|
(acc, topic) => {
|
||||||
let letter = lang() === 'en' ? topic.slug[0].toUpperCase() : (topic?.title?.[0] || '').toUpperCase()
|
let letter = lang() === 'en' ? topic.slug[0].toUpperCase() : (topic?.title?.[0] || '').toUpperCase()
|
||||||
if (/[^ËА-яё]/.test(letter) && lang() === 'ru') letter = '#'
|
if (enChars.test(letter) && lang() === 'ru') letter = '#'
|
||||||
if (/[^A-z]/.test(letter) && lang() === 'en') letter = '#'
|
if (ruChars.test(letter) && lang() === 'en') letter = '#'
|
||||||
if (!acc[letter]) acc[letter] = []
|
if (!acc[letter]) acc[letter] = []
|
||||||
acc[letter].push(topic)
|
acc[letter].push(topic)
|
||||||
return acc
|
return acc
|
||||||
|
|
|
@ -250,7 +250,7 @@ export const ProfileSecurityView = (_props: any) => {
|
||||||
class={clsx(
|
class={clsx(
|
||||||
styles.socialButton,
|
styles.socialButton,
|
||||||
styles.socialButtonApple,
|
styles.socialButtonApple,
|
||||||
'button' + ' button--light'
|
'button button--light'
|
||||||
)}
|
)}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
|
@ -339,15 +339,15 @@ export const ProfileSettings = () => {
|
||||||
maxLength={120}
|
maxLength={120}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<h4>{t('About the author')}</h4>
|
<h4>{t('About')}</h4>
|
||||||
<SimplifiedEditor
|
<SimplifiedEditor
|
||||||
resetToInitial={clearAbout()}
|
resetToInitial={clearAbout()}
|
||||||
noLimits={true}
|
noLimits={true}
|
||||||
variant="bordered"
|
variant="bordered"
|
||||||
onlyBubbleControls={true}
|
onlyBubbleControls={true}
|
||||||
smallHeight={true}
|
smallHeight={true}
|
||||||
placeholder={t('About the author')}
|
placeholder={t('About')}
|
||||||
label={t('About the author')}
|
label={t('About')}
|
||||||
initialContent={form.about || ''}
|
initialContent={form.about || ''}
|
||||||
autoFocus={false}
|
autoFocus={false}
|
||||||
onChange={(value) => updateFormField('about', value)}
|
onChange={(value) => updateFormField('about', value)}
|
||||||
|
|
|
@ -37,14 +37,12 @@ export const DropArea = (props: Props) => {
|
||||||
const runUpload = async (files: UploadFile[]) => {
|
const runUpload = async (files: UploadFile[]) => {
|
||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
const tkn = session()?.access_token as string
|
||||||
const results = []
|
|
||||||
for (const file of files) {
|
|
||||||
const handler = props.fileType === 'image' ? handleImageUpload : handleFileUpload
|
const handler = props.fileType === 'image' ? handleImageUpload : handleFileUpload
|
||||||
const result = await handler(file, session()?.access_token as string)
|
tkn &&
|
||||||
results.push(result)
|
Promise.all(files.map((file) => handler(file, tkn)))
|
||||||
}
|
.then(props.onUpload)
|
||||||
props.onUpload(results)
|
.catch(console.error)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
|
@ -61,7 +61,7 @@ export const Popover = (props: Props) => {
|
||||||
<>
|
<>
|
||||||
{props.children(setAnchor)}
|
{props.children(setAnchor)}
|
||||||
<Show when={show() && !props.disabled}>
|
<Show when={show() && !props.disabled}>
|
||||||
<div ref={setPopper} class={styles.tooltip} role="tooltip">
|
<div ref={setPopper} class={styles.tooltip}>
|
||||||
{props.content}
|
{props.content}
|
||||||
<div class={styles.arrow} data-popper-arrow={true} />
|
<div class={styles.arrow} data-popper-arrow={true} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -55,7 +55,6 @@ export const ShareLinks = (props: Props) => {
|
||||||
<ul class="nodash">
|
<ul class="nodash">
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
role="button"
|
|
||||||
class={clsx(styles.shareControl, popupStyles.action)}
|
class={clsx(styles.shareControl, popupStyles.action)}
|
||||||
onClick={() => handleShare(FACEBOOK)}
|
onClick={() => handleShare(FACEBOOK)}
|
||||||
>
|
>
|
||||||
|
@ -65,7 +64,6 @@ export const ShareLinks = (props: Props) => {
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
role="button"
|
|
||||||
class={clsx(styles.shareControl, popupStyles.action)}
|
class={clsx(styles.shareControl, popupStyles.action)}
|
||||||
onClick={() => handleShare(TWITTER)}
|
onClick={() => handleShare(TWITTER)}
|
||||||
>
|
>
|
||||||
|
@ -75,7 +73,6 @@ export const ShareLinks = (props: Props) => {
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
role="button"
|
|
||||||
class={clsx(styles.shareControl, popupStyles.action)}
|
class={clsx(styles.shareControl, popupStyles.action)}
|
||||||
onClick={() => handleShare(TELEGRAM)}
|
onClick={() => handleShare(TELEGRAM)}
|
||||||
>
|
>
|
||||||
|
@ -84,11 +81,7 @@ export const ShareLinks = (props: Props) => {
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button class={clsx(styles.shareControl, popupStyles.action)} onClick={() => handleShare(VK)}>
|
||||||
role="button"
|
|
||||||
class={clsx(styles.shareControl, popupStyles.action)}
|
|
||||||
onClick={() => handleShare(VK)}
|
|
||||||
>
|
|
||||||
<Icon name="vk-white" class={clsx(styles.icon, popupStyles.icon)} />
|
<Icon name="vk-white" class={clsx(styles.icon, popupStyles.icon)} />
|
||||||
VK
|
VK
|
||||||
</button>
|
</button>
|
||||||
|
@ -97,11 +90,7 @@ export const ShareLinks = (props: Props) => {
|
||||||
<Show
|
<Show
|
||||||
when={props.variant === 'inModal'}
|
when={props.variant === 'inModal'}
|
||||||
fallback={
|
fallback={
|
||||||
<button
|
<button class={clsx(styles.shareControl, popupStyles.action)} onClick={copyLink}>
|
||||||
role="button"
|
|
||||||
class={clsx(styles.shareControl, popupStyles.action)}
|
|
||||||
onClick={copyLink}
|
|
||||||
>
|
|
||||||
<Icon name="link-white" class={clsx(styles.icon, popupStyles.icon)} />
|
<Icon name="link-white" class={clsx(styles.icon, popupStyles.icon)} />
|
||||||
{t('Copy link')}
|
{t('Copy link')}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -16,7 +16,9 @@ type Props = {
|
||||||
onVideoDelete?: () => void
|
onVideoDelete?: () => void
|
||||||
articleView?: boolean
|
articleView?: boolean
|
||||||
}
|
}
|
||||||
|
const watchPattern = /watch=(\w+)/
|
||||||
|
const ytPattern = /(youtu.be)\/(\w+)/
|
||||||
|
const vimeoPattern = /vimeo.com\/(\d+)/
|
||||||
export const VideoPlayer = (props: Props) => {
|
export const VideoPlayer = (props: Props) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const [videoId, setVideoId] = createSignal<string | undefined>()
|
const [videoId, setVideoId] = createSignal<string | undefined>()
|
||||||
|
@ -27,14 +29,14 @@ export const VideoPlayer = (props: Props) => {
|
||||||
setIsVimeo(!isYoutube)
|
setIsVimeo(!isYoutube)
|
||||||
if (isYoutube) {
|
if (isYoutube) {
|
||||||
if (props.videoUrl.includes('youtube.com')) {
|
if (props.videoUrl.includes('youtube.com')) {
|
||||||
const videoIdMatch = props.videoUrl.match(/watch=(\w+)/)
|
const videoIdMatch = props.videoUrl.match(watchPattern)
|
||||||
setVideoId(videoIdMatch?.[1])
|
setVideoId(videoIdMatch?.[1])
|
||||||
} else {
|
} else {
|
||||||
const videoIdMatch = props.videoUrl.match(/youtu.be\/(\w+)/)
|
const videoIdMatch = props.videoUrl.match(ytPattern)
|
||||||
setVideoId(videoIdMatch?.[1])
|
setVideoId(videoIdMatch?.[1])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const videoIdMatch = props.videoUrl.match(/vimeo.com\/(\d+)/)
|
const videoIdMatch = props.videoUrl.match(vimeoPattern)
|
||||||
setVideoId(videoIdMatch?.[1])
|
setVideoId(videoIdMatch?.[1])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -151,16 +151,6 @@ export const FollowingProvider = (props: { children: JSX.Element }) => {
|
||||||
setFollows((prevFollows: AuthorFollowsResult) => {
|
setFollows((prevFollows: AuthorFollowsResult) => {
|
||||||
const updatedFollows = { ...prevFollows }
|
const updatedFollows = { ...prevFollows }
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case 'AUTHOR': {
|
|
||||||
if (value) {
|
|
||||||
if (!updatedFollows.authors?.some((author) => author.slug === slug)) {
|
|
||||||
updatedFollows.authors = [...(updatedFollows.authors || []), { slug } as Author]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updatedFollows.authors = updatedFollows.authors?.filter((author) => author.slug !== slug) || []
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'TOPIC': {
|
case 'TOPIC': {
|
||||||
if (value) {
|
if (value) {
|
||||||
if (!updatedFollows.topics?.some((topic) => topic.slug === slug)) {
|
if (!updatedFollows.topics?.some((topic) => topic.slug === slug)) {
|
||||||
|
@ -182,6 +172,17 @@ export const FollowingProvider = (props: { children: JSX.Element }) => {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// case 'AUTHOR': {
|
||||||
|
default: {
|
||||||
|
if (value) {
|
||||||
|
if (!updatedFollows.authors?.some((author) => author.slug === slug)) {
|
||||||
|
updatedFollows.authors = [...(updatedFollows.authors || []), { slug } as Author]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updatedFollows.authors = updatedFollows.authors?.filter((author) => author.slug !== slug) || []
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return updatedFollows
|
return updatedFollows
|
||||||
})
|
})
|
||||||
|
|
6
src/intl/chars.ts
Normal file
6
src/intl/chars.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export const allChars = /[^\dA-zА-я]/
|
||||||
|
export const slugChars = /[^\da-z]/g
|
||||||
|
export const enChars = /[^A-z]/
|
||||||
|
export const ruChars = /[^ËА-яё]/
|
||||||
|
export const sentenceSeparator = /{!|\?|:|;}\s/
|
||||||
|
export const cyrillicRegex = /[\u0400-\u04FF]/ // Range for Cyrillic characters
|
|
@ -1,16 +1,18 @@
|
||||||
import { Author } from '~/graphql/schema/core.gen'
|
import { Author } from '~/graphql/schema/core.gen'
|
||||||
import { capitalize } from '~/utils/capitalize'
|
import { capitalize } from '~/utils/capitalize'
|
||||||
|
import { allChars, cyrillicRegex, enChars, ruChars } from './chars'
|
||||||
import { translit } from './translit'
|
import { translit } from './translit'
|
||||||
|
|
||||||
export const isCyrillic = (s: string): boolean => {
|
export const isCyrillic = (s: string): boolean => {
|
||||||
const cyrillicRegex = /[\u0400-\u04FF]/ // Range for Cyrillic characters
|
|
||||||
|
|
||||||
return cyrillicRegex.test(s)
|
return cyrillicRegex.test(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const translateAuthor = (author: Author, lng: string) =>
|
export const translateAuthor = (author: Author, lng: string) =>
|
||||||
lng === 'en' && isCyrillic(author?.name || '')
|
lng === 'en' && isCyrillic(author?.name || '')
|
||||||
? capitalize(translit((author?.name || '').replace(/ё/, 'e').replace(/ь/, '')).replace(/-/, ' '), true)
|
? capitalize(
|
||||||
|
translit((author?.name || '').replaceAll('ё', 'e').replaceAll('ь', '')).replaceAll('-', ' '),
|
||||||
|
true
|
||||||
|
)
|
||||||
: author.name
|
: author.name
|
||||||
|
|
||||||
export const authorLetterReduce = (acc: { [x: string]: Author[] }, author: Author, lng: string) => {
|
export const authorLetterReduce = (acc: { [x: string]: Author[] }, author: Author, lng: string) => {
|
||||||
|
@ -18,7 +20,7 @@ export const authorLetterReduce = (acc: { [x: string]: Author[] }, author: Autho
|
||||||
if (!letter && author && author.name) {
|
if (!letter && author && author.name) {
|
||||||
const name =
|
const name =
|
||||||
translateAuthor(author, lng || 'ru')
|
translateAuthor(author, lng || 'ru')
|
||||||
?.replace(/[^\dA-zА-я]/, ' ')
|
?.replace(allChars, ' ')
|
||||||
.trim() || ''
|
.trim() || ''
|
||||||
const nameParts = name.trim().split(' ')
|
const nameParts = name.trim().split(' ')
|
||||||
const found = nameParts.filter(Boolean).pop()
|
const found = nameParts.filter(Boolean).pop()
|
||||||
|
@ -26,8 +28,8 @@ export const authorLetterReduce = (acc: { [x: string]: Author[] }, author: Autho
|
||||||
letter = found[0].toUpperCase()
|
letter = found[0].toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (/[^ËА-яё]/.test(letter) && lng === 'ru') letter = '@'
|
if (ruChars.test(letter) && lng === 'ru') letter = '@'
|
||||||
if (/[^A-z]/.test(letter) && lng === 'en') letter = '@'
|
if (enChars.test(letter) && lng === 'en') letter = '@'
|
||||||
|
|
||||||
if (!acc[letter]) acc[letter] = []
|
if (!acc[letter]) acc[letter] = []
|
||||||
author.name = translateAuthor(author, lng)
|
author.name = translateAuthor(author, lng)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import translitConfig from './abc-translit.json'
|
import translitConfig from './abc-translit.json'
|
||||||
|
import { ruChars, slugChars } from './chars'
|
||||||
|
|
||||||
const ru2en: { [key: string]: string } = translitConfig
|
const ru2en: { [key: string]: string } = translitConfig
|
||||||
|
|
||||||
|
@ -7,7 +8,7 @@ export const translit = (str: string) => {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const isCyrillic = /[ЁА-яё]/.test(str)
|
const isCyrillic = ruChars.test(str)
|
||||||
|
|
||||||
if (!isCyrillic) {
|
if (!isCyrillic) {
|
||||||
return str
|
return str
|
||||||
|
@ -17,7 +18,5 @@ export const translit = (str: string) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const slugify = (text: string) => {
|
export const slugify = (text: string) => {
|
||||||
return translit(text.toLowerCase())
|
return translit(text.toLowerCase()).replaceAll(' ', '-').replaceAll(slugChars, '')
|
||||||
.replaceAll(' ', '-')
|
|
||||||
.replaceAll(/[^\da-z]/g, '')
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
const audioExts = /\.(wav|flac|mp3|aac|jpg|jpeg|png|gif)$/i
|
||||||
|
|
||||||
const removeMediaFileExtension = (fileName: string) => {
|
const removeMediaFileExtension = (fileName: string) => {
|
||||||
return fileName.replace(/\.(wav|flac|mp3|aac|jpg|jpeg|png|gif)$/i, '')
|
return fileName.replace(audioExts, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const composeMediaItems = (
|
export const composeMediaItems = (
|
||||||
|
|
|
@ -13,6 +13,8 @@ import { loadShouts } from '~/graphql/api/public'
|
||||||
import { LoadShoutsOptions, Shout, Topic } from '~/graphql/schema/core.gen'
|
import { LoadShoutsOptions, Shout, Topic } from '~/graphql/schema/core.gen'
|
||||||
import { SHOUTS_PER_PAGE } from '../(main)'
|
import { SHOUTS_PER_PAGE } from '../(main)'
|
||||||
|
|
||||||
|
const paramPattern = /^(hot|likes)$/
|
||||||
|
|
||||||
export type FeedPeriod = 'week' | 'month' | 'year'
|
export type FeedPeriod = 'week' | 'month' | 'year'
|
||||||
|
|
||||||
export type PeriodItem = {
|
export type PeriodItem = {
|
||||||
|
@ -32,14 +34,15 @@ const getFromDate = (period: FeedPeriod): number => {
|
||||||
d = new Date(now.setDate(now.getDate() - 7))
|
d = new Date(now.setDate(now.getDate() - 7))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'month': {
|
|
||||||
d = new Date(now.setMonth(now.getMonth() - 1))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'year': {
|
case 'year': {
|
||||||
d = new Date(now.setFullYear(now.getFullYear() - 1))
|
d = new Date(now.setFullYear(now.getFullYear() - 1))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// case 'month': {
|
||||||
|
default: {
|
||||||
|
d = new Date(now.setMonth(now.getMonth() - 1))
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Math.floor(d.getTime() / 1000)
|
return Math.floor(d.getTime() / 1000)
|
||||||
}
|
}
|
||||||
|
@ -71,7 +74,6 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
|
||||||
// load more feed
|
// load more feed
|
||||||
const loadMoreFeed = async (offset?: number) => {
|
const loadMoreFeed = async (offset?: number) => {
|
||||||
// /feed/:order: - select order setting
|
// /feed/:order: - select order setting
|
||||||
const paramPattern = /^(hot|likes)$/
|
|
||||||
const order =
|
const order =
|
||||||
(props.params.order && paramPattern.test(props.params.order)
|
(props.params.order && paramPattern.test(props.params.order)
|
||||||
? props.params.order === 'hot'
|
? props.params.order === 'hot'
|
||||||
|
@ -107,9 +109,8 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
|
||||||
})
|
})
|
||||||
|
|
||||||
const order = createMemo(() => {
|
const order = createMemo(() => {
|
||||||
const paramOrderPattern = /^(hot|likes)$/
|
|
||||||
return (
|
return (
|
||||||
(paramOrderPattern.test(props.params.order)
|
(paramPattern.test(props.params.order)
|
||||||
? props.params.order === 'hot'
|
? props.params.order === 'hot'
|
||||||
? 'last_comment'
|
? 'last_comment'
|
||||||
: props.params.order
|
: props.params.order
|
||||||
|
|
|
@ -30,6 +30,8 @@ const feeds = {
|
||||||
export type FeedPeriod = 'week' | 'month' | 'year'
|
export type FeedPeriod = 'week' | 'month' | 'year'
|
||||||
export type FeedSearchParams = { period?: FeedPeriod }
|
export type FeedSearchParams = { period?: FeedPeriod }
|
||||||
|
|
||||||
|
const paramModePattern = /^(followed|discussed|liked|coauthored|unrated)$/
|
||||||
|
const paramPattern = /(hot|likes)/
|
||||||
const getFromDate = (period: FeedPeriod): number => {
|
const getFromDate = (period: FeedPeriod): number => {
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
let d: Date = now
|
let d: Date = now
|
||||||
|
@ -38,14 +40,15 @@ const getFromDate = (period: FeedPeriod): number => {
|
||||||
d = new Date(now.setDate(now.getDate() - 7))
|
d = new Date(now.setDate(now.getDate() - 7))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'month': {
|
|
||||||
d = new Date(now.setMonth(now.getMonth() - 1))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'year': {
|
case 'year': {
|
||||||
d = new Date(now.setFullYear(now.getFullYear() - 1))
|
d = new Date(now.setFullYear(now.getFullYear() - 1))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// case 'month':
|
||||||
|
default: {
|
||||||
|
d = new Date(now.setMonth(now.getMonth() - 1))
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Math.floor(d.getTime() / 1000)
|
return Math.floor(d.getTime() / 1000)
|
||||||
}
|
}
|
||||||
|
@ -67,14 +70,12 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
|
||||||
|
|
||||||
// /feed/my/:mode:
|
// /feed/my/:mode:
|
||||||
const mode = createMemo(() => {
|
const mode = createMemo(() => {
|
||||||
const paramModePattern = /^(followed|discussed|liked|coauthored|unrated)$/
|
|
||||||
return props.params.mode && paramModePattern.test(props.params.mode) ? props.params.mode : 'followed'
|
return props.params.mode && paramModePattern.test(props.params.mode) ? props.params.mode : 'followed'
|
||||||
})
|
})
|
||||||
|
|
||||||
const order = createMemo(() => {
|
const order = createMemo(() => {
|
||||||
const paramOrderPattern = /^(hot|likes)$/
|
|
||||||
return (
|
return (
|
||||||
(paramOrderPattern.test(props.params.order)
|
(paramPattern.test(props.params.order)
|
||||||
? props.params.order === 'hot'
|
? props.params.order === 'hot'
|
||||||
? 'last_comment'
|
? 'last_comment'
|
||||||
: props.params.order
|
: props.params.order
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
const emailPattern = /^[\w%+.-]+@[\d.a-z-]+\.[a-z]{2,}$/i
|
||||||
|
|
||||||
export const validateEmail = (email: string) => {
|
export const validateEmail = (email: string) => {
|
||||||
if (!email) return false
|
if (!email) return false
|
||||||
|
|
||||||
return /^[\w%+.-]+@[\d.a-z-]+\.[a-z]{2,}$/i.test(email)
|
return emailPattern.test(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const validateUrl = (value: string) => {
|
export const validateUrl = (value: string) => {
|
||||||
|
|
|
@ -50,6 +50,7 @@ test.beforeAll(async ({ browser }) => {
|
||||||
page = await browser.newPage()
|
page = await browser.newPage()
|
||||||
test.setTimeout(150000)
|
test.setTimeout(150000)
|
||||||
await page.goto(baseURL)
|
await page.goto(baseURL)
|
||||||
|
// biome-ignore lint/performance/useTopLevelRegex: <explanation>
|
||||||
await expect(page).toHaveTitle(/Дискурс/)
|
await expect(page).toHaveTitle(/Дискурс/)
|
||||||
console.log('Localhost server started successfully!')
|
console.log('Localhost server started successfully!')
|
||||||
})
|
})
|
||||||
|
|
|
@ -50,6 +50,7 @@ test.beforeAll(async ({ browser }) => {
|
||||||
page = await browser.newPage()
|
page = await browser.newPage()
|
||||||
test.setTimeout(150000)
|
test.setTimeout(150000)
|
||||||
await page.goto(baseURL)
|
await page.goto(baseURL)
|
||||||
|
// biome-ignore lint/performance/useTopLevelRegex: <explanation>
|
||||||
await expect(page).toHaveTitle(/Дискурс/)
|
await expect(page).toHaveTitle(/Дискурс/)
|
||||||
await page.getByRole('link', { name: 'Войти' }).click()
|
await page.getByRole('link', { name: 'Войти' }).click()
|
||||||
console.log('Localhost server started successfully!')
|
console.log('Localhost server started successfully!')
|
||||||
|
|
|
@ -50,6 +50,7 @@ test.beforeAll(async ({ browser }) => {
|
||||||
page = await browser.newPage()
|
page = await browser.newPage()
|
||||||
test.setTimeout(150000)
|
test.setTimeout(150000)
|
||||||
await page.goto(baseURL)
|
await page.goto(baseURL)
|
||||||
|
// biome-ignore lint/performance/useTopLevelRegex: <explanation>
|
||||||
await expect(page).toHaveTitle(/Дискурс/)
|
await expect(page).toHaveTitle(/Дискурс/)
|
||||||
console.log('Localhost server started successfully!')
|
console.log('Localhost server started successfully!')
|
||||||
await page.close()
|
await page.close()
|
||||||
|
|
|
@ -54,6 +54,7 @@ test.beforeAll(async ({ browser }) => {
|
||||||
page = await context.newPage()
|
page = await context.newPage()
|
||||||
test.setTimeout(150000)
|
test.setTimeout(150000)
|
||||||
await page.goto(baseURL)
|
await page.goto(baseURL)
|
||||||
|
// biome-ignore lint/performance/useTopLevelRegex: <explanation>
|
||||||
await expect(page).toHaveTitle(/Дискурс/)
|
await expect(page).toHaveTitle(/Дискурс/)
|
||||||
await page.getByRole('link', { name: 'Войти' }).click()
|
await page.getByRole('link', { name: 'Войти' }).click()
|
||||||
console.log('Localhost server started successfully!')
|
console.log('Localhost server started successfully!')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user