Просмотр исходного кода

Merge branch 'master' into support/144785-editor-mobile-appearance

satof3 1 год назад
Родитель
Сommit
3c36ab8df9

+ 3 - 2
apps/app/src/components/Layout/BasicLayout.tsx

@@ -1,4 +1,5 @@
-import React, { ReactNode } from 'react';
+import type { ReactNode } from 'react';
+import React from 'react';
 
 import dynamic from 'next/dynamic';
 import { DndProvider } from 'react-dnd';
@@ -42,7 +43,7 @@ export const BasicLayout = ({ children, className }: Props): JSX.Element => {
             <Sidebar />
           </div>
 
-          <div className="d-flex flex-grow-1 flex-column z-1">{/* neccessary for nested {children} make expanded */}
+          <div className="d-flex flex-grow-1 flex-column mw-0 z-1">{/* neccessary for nested {children} make expanded */}
             <AlertSiteUrlUndefined />
             {children}
           </div>

+ 1 - 15
apps/app/src/components/PageEditor/PageEditor.tsx

@@ -273,26 +273,12 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
     };
   }, [saveAndReturnToViewHandler]);
 
-
-  // TODO: https://redmine.weseek.co.jp/issues/142729
-  // https://regex101.com/r/Wg2Hh6/1
-  // initial caret line
-  useEffect(() => {
-    const untitledPageRegex = /^Untitled-\d+$/;
-    const isNewlyCreatedPage = (
-      currentPage?.wip && currentPage?.latestRevision == null && untitledPageRegex.test(nodePath.basename(currentPage?.path ?? ''))
-    ) ?? false;
-    if (!isNewlyCreatedPage) {
-      codeMirrorEditor?.setCaretLine();
-    }
-  }, [codeMirrorEditor, currentPage]);
-
   // set handler to focus
   useLayoutEffect(() => {
     if (editorMode === EditorMode.Editor) {
       codeMirrorEditor?.focus();
     }
-  }, [codeMirrorEditor, editorMode]);
+  }, [codeMirrorEditor, currentPage, editorMode]);
 
   // Detect indent size from contents (only when users are allowed to change it)
   useEffect(() => {

+ 7 - 5
apps/app/src/components/PageHeader/PageTitleHeader.tsx

@@ -84,11 +84,13 @@ export const PageTitleHeader: FC<Props> = (props) => {
     setRenameInputShown(true);
   }, [currentPagePath, isMovable]);
 
-  useEffect(() => {
-    if (isNewlyCreatedPage) {
-      setRenameInputShown(true);
-    }
-  }, [currentPage._id, isNewlyCreatedPage]);
+  // TODO: auto focus when create new page
+  // https://redmine.weseek.co.jp/issues/136128
+  // useEffect(() => {
+  //   if (isNewlyCreatedPage) {
+  //     setRenameInputShown(true);
+  //   }
+  // }, [currentPage._id, isNewlyCreatedPage]);
 
   return (
     <div className={`d-flex ${moduleClass} ${props.className ?? ''} position-relative`}>

+ 0 - 19
apps/app/src/components/ReactMarkdownComponents/CodeBlock.module.scss

@@ -1,25 +1,6 @@
 @use '~/styles/variables' as var;
 @use '@growi/core/scss/bootstrap/init' as bs;
 
-
-.code-highlighted {
-  // for word wrapping
-  // ref: https://qiita.com/spaceonly/items/9aa8599a082cb72740b7
-  %breaker {
-    word-break: break-all !important;
-    word-wrap: break-word !important;
-    overflow-wrap: break-word !important;
-    white-space: break-spaces !important;
-    line-break: anywhere !important;
-  };
-
-  @extend %breaker;
-
-  code {
-    @extend %breaker;
-  }
-}
-
 .code-highlighted-title {
   position: absolute;
   top: 0;

+ 1 - 4
apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx

@@ -6,8 +6,6 @@ import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
 
 import styles from './CodeBlock.module.scss';
 
-const codeHighlightedClass = styles['code-highlighted'];
-
 // remove font-family
 Object.entries<object>(oneDark).forEach(([key, value]) => {
   if ('fontFamily' in value) {
@@ -50,7 +48,7 @@ function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactN
   const isSimpleString = Array.isArray(children) && children.length === 1 && typeof children[0] === 'string';
   if (!isSimpleString) {
     return (
-      <div className={codeHighlightedClass} style={oneDark['pre[class*="language-"]']}>
+      <div style={oneDark['pre[class*="language-"]']}>
         <code className={`language-${lang}`} style={oneDark['code[class*="language-"]']}>
           {children}
         </code>
@@ -60,7 +58,6 @@ function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactN
 
   return (
     <PrismAsyncLight
-      className={codeHighlightedClass}
       PreTag="div"
       style={oneDark}
       language={lang}

+ 3 - 1
apps/app/test/cypress/e2e/50-sidebar/50-sidebar--access-to-side-bar.cy.ts

@@ -270,7 +270,9 @@ describe('Access to sidebar', () => {
 
         it('Succesfully click all tags button', () => {
           cy.getByTestid('grw-sidebar-content-tags').within(() => {
-            cy.get('.btn-primary').click();
+            cy.get('.btn-primary').as('check-all-tags-button');
+            cy.get('@check-all-tags-button').should('be.visible');
+            cy.get('@check-all-tags-button').click({force: true});
           });
           cy.collapseSidebar(true);
           cy.getByTestid('grw-tags-list').should('be.visible');

+ 5 - 0
packages/editor/src/services/editor-theme/.eslintrc.cjs

@@ -0,0 +1,5 @@
+module.exports = {
+  rules: {
+    camelcase: 'off',
+  },
+};

+ 34 - 0
packages/editor/src/services/editor-theme/eclipse.ts

@@ -0,0 +1,34 @@
+// Ref: https://github.com/uiwjs/react-codemirror/blob/399d127f59a97a64974a65923d477d585d2abee5/themes/eclipse/src/index.ts
+import { tags as t } from '@lezer/highlight';
+import { createTheme } from '@uiw/codemirror-themes';
+
+export const eclipse = createTheme({
+  theme: 'light',
+  settings: {
+    background: '#fff',
+    foreground: '#000',
+    // Change color
+    caret: '#000',
+    selection: '#d7d4f0',
+    selectionMatch: '#d7d4f0',
+    gutterBackground: '#f7f7f7',
+    gutterForeground: '#999',
+    lineHighlight: '#006fff1c',
+    gutterBorder: 'transparent',
+  },
+  styles: [
+    { tag: [t.comment], color: '#3F7F5F' },
+    { tag: [t.documentMeta], color: '#FF1717' },
+    { tag: t.keyword, color: '#7F0055', fontWeight: 'bold' },
+    { tag: t.atom, color: '#00f' },
+    { tag: t.number, color: '#164' },
+    { tag: t.propertyName, color: '#164' },
+    { tag: [t.variableName, t.definition(t.variableName)], color: '#0000C0' },
+    { tag: t.function(t.variableName), color: '#0000C0' },
+    { tag: t.string, color: '#2A00FF' },
+    { tag: t.operator, color: 'black' },
+    { tag: t.tagName, color: '#170' },
+    { tag: t.attributeName, color: '#00c' },
+    { tag: t.link, color: '#219' },
+  ],
+});

+ 3 - 3
packages/editor/src/services/editor-theme/index.ts

@@ -3,7 +3,7 @@ import { Extension } from '@codemirror/state';
 export const getEditorTheme = async(themeName?: EditorTheme): Promise<Extension> => {
   switch (themeName) {
     case 'eclipse':
-      return (await import('@uiw/codemirror-theme-eclipse')).eclipse;
+      return (await import('./eclipse')).eclipse;
     case 'basic':
       return (await import('cm6-theme-basic-light')).basicLight;
     case 'ayu':
@@ -13,9 +13,9 @@ export const getEditorTheme = async(themeName?: EditorTheme): Promise<Extension>
     case 'defaultdark':
       return (await import('./original-dark')).originalDark;
     case 'material':
-      return (await import('cm6-theme-material-dark')).materialDark;
+      return (await import('./material')).materialDark;
     case 'nord':
-      return (await import('cm6-theme-nord')).nord;
+      return (await import('./nord')).nord;
     case 'cobalt':
       return (await import('./cobalt')).cobalt;
     case 'kimbie':

+ 223 - 0
packages/editor/src/services/editor-theme/material.ts

@@ -0,0 +1,223 @@
+// Ref: https://github.com/craftzdog/cm6-themes/blob/289d9e0ca6b500f4cdf68464f4f21dd8e2dd8963/packages/material-dark/src/index.ts
+import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
+import { Extension } from '@codemirror/state';
+import { EditorView } from '@codemirror/view';
+import { tags as t } from '@lezer/highlight';
+
+// Auther: stephen-liu-fipo
+const base00 = '#2e3235';
+const base01 = '#505d64';
+const base02 = '#606f7a';
+const base03 = '#707d8b';
+// base04 = '#a0a4ae',
+const base05 = '#bdbdbd';
+const base06 = '#e0e0e0';
+const base07 = '#fdf6e3';
+const base_red = '#ff5f52';
+const base_deeporange = '#ff6e40';
+const base_pink = '#fa5788';
+const base_yellow = '#facf4e';
+const base_orange = '#ffad42';
+const base_cyan = '#56c8d8';
+const base_indigo = '#7186f0';
+const base_purple = '#cf6edf';
+const base_green = '#6abf69';
+const base_lightgreen = '#99d066';
+const base_teal = '#4ebaaa';
+
+const invalid = base_red;
+// Adjust color
+const darkBackground = '#36383a';
+// Adjust color
+const highlightBackground = '#44494d';
+const background = base00;
+const tooltipBackground = base01;
+const selection = base01;
+// Change color
+const cursor = base05;
+
+// / The editor theme styles for Material Dark.
+export const materialDarkTheme = EditorView.theme(
+  {
+    '&': {
+      color: base05,
+      backgroundColor: background,
+    },
+
+    '.cm-content': {
+      caretColor: cursor,
+    },
+
+    '.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor },
+    '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection':
+      { backgroundColor: selection },
+
+    '.cm-panels': { backgroundColor: darkBackground, color: base03 },
+    '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' },
+    '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' },
+
+    '.cm-searchMatch': {
+      outline: `1px solid ${base_yellow}`,
+      backgroundColor: 'transparent',
+    },
+    '.cm-searchMatch.cm-searchMatch-selected': {
+      backgroundColor: highlightBackground,
+    },
+
+    '.cm-activeLine': { backgroundColor: highlightBackground },
+    '.cm-selectionMatch': {
+      backgroundColor: darkBackground,
+      outline: `1px solid ${base_teal}`,
+    },
+
+    '&.cm-focused .cm-matchingBracket': {
+      color: base06,
+      outline: `1px solid ${base_teal}`,
+    },
+
+    '&.cm-focused .cm-nonmatchingBracket': {
+      color: base_red,
+    },
+
+    '.cm-gutters': {
+      backgroundColor: base00,
+      borderRight: '1px solid #4f5b66',
+      color: base02,
+    },
+
+    '.cm-activeLineGutter': {
+      backgroundColor: highlightBackground,
+      color: base07,
+    },
+
+    '.cm-foldPlaceholder': {
+      backgroundColor: 'transparent',
+      border: 'none',
+      color: '#ddd',
+    },
+
+    '.cm-tooltip': {
+      border: 'none',
+      backgroundColor: tooltipBackground,
+    },
+    '.cm-tooltip .cm-tooltip-arrow:before': {
+      borderTopColor: 'transparent',
+      borderBottomColor: 'transparent',
+    },
+    '.cm-tooltip .cm-tooltip-arrow:after': {
+      borderTopColor: tooltipBackground,
+      borderBottomColor: tooltipBackground,
+    },
+    '.cm-tooltip-autocomplete': {
+      '& > ul > li[aria-selected]': {
+        backgroundColor: highlightBackground,
+        color: base03,
+      },
+    },
+  },
+  { dark: true },
+);
+
+// / The highlighting style for code in the Material Dark theme.
+export const materialDarkHighlightStyle = HighlightStyle.define([
+  { tag: t.keyword, color: base_purple },
+  {
+    tag: [t.name, t.deleted, t.character, t.macroName],
+    color: base_cyan,
+  },
+  { tag: [t.propertyName], color: base_yellow },
+  { tag: [t.variableName], color: base05 },
+  { tag: [t.function(t.variableName)], color: base_cyan },
+  { tag: [t.labelName], color: base_purple },
+  {
+    tag: [t.color, t.constant(t.name), t.standard(t.name)],
+    color: base_yellow,
+  },
+  { tag: [t.definition(t.name), t.separator], color: base_pink },
+  { tag: [t.brace], color: base_purple },
+  {
+    tag: [t.annotation],
+    color: invalid,
+  },
+  {
+    tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],
+    color: base_orange,
+  },
+  {
+    tag: [t.typeName, t.className],
+    color: base_orange,
+  },
+  {
+    tag: [t.operator, t.operatorKeyword],
+    color: base_indigo,
+  },
+  {
+    tag: [t.tagName],
+    color: base_deeporange,
+  },
+  {
+    tag: [t.squareBracket],
+    color: base_red,
+  },
+  {
+    tag: [t.angleBracket],
+    color: base02,
+  },
+  {
+    tag: [t.attributeName],
+    color: base05,
+  },
+  {
+    tag: [t.regexp],
+    color: invalid,
+  },
+  {
+    tag: [t.quote],
+    color: base_green,
+  },
+  { tag: [t.string], color: base_lightgreen },
+  {
+    tag: t.link,
+    color: base_cyan,
+    textDecoration: 'underline',
+    textUnderlinePosition: 'under',
+  },
+  {
+    tag: [t.url, t.escape, t.special(t.string)],
+    color: base_yellow,
+  },
+  { tag: [t.meta], color: base03 },
+  { tag: [t.comment], color: base03, fontStyle: 'italic' },
+  { tag: t.monospace, color: base05 },
+  { tag: t.strong, fontWeight: 'bold', color: base_red },
+  { tag: t.emphasis, fontStyle: 'italic', color: base_lightgreen },
+  { tag: t.strikethrough, textDecoration: 'line-through' },
+  { tag: t.heading, fontWeight: 'bold', color: base_yellow },
+  { tag: t.heading1, fontWeight: 'bold', color: base_yellow },
+  {
+    tag: [t.heading2, t.heading3, t.heading4],
+    fontWeight: 'bold',
+    color: base_yellow,
+  },
+  {
+    tag: [t.heading5, t.heading6],
+    color: base_yellow,
+  },
+  { tag: [t.atom, t.bool, t.special(t.variableName)], color: base_cyan },
+  {
+    tag: [t.processingInstruction, t.inserted],
+    color: base_red,
+  },
+  {
+    tag: [t.contentSeparator],
+    color: base_cyan,
+  },
+  { tag: t.invalid, color: base02, borderBottom: `1px dotted ${base_red}` },
+]);
+
+// / Extension to enable the Material Dark theme (both the editor theme and
+// / the highlight style).
+export const materialDark: Extension = [
+  materialDarkTheme,
+  syntaxHighlighting(materialDarkHighlightStyle),
+];

+ 231 - 0
packages/editor/src/services/editor-theme/nord.ts

@@ -0,0 +1,231 @@
+// Ref: https://github.com/craftzdog/cm6-themes/blob/221936c525dcfc05b298cc4d4a0ba284cb7c7138/packages/nord/src/index.ts
+
+import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
+import { Extension } from '@codemirror/state';
+import { EditorView } from '@codemirror/view';
+import { tags as t } from '@lezer/highlight';
+
+// Author: stephen-liu-fipo
+// Colors from https://www.nordtheme.com/docs/colors-and-palettes
+// Polar Night
+const base00 = '#2e3440'; // black
+const base01 = '#3b4252'; // dark grey
+const base02 = '#434c5e';
+const base03 = '#4c566a'; // grey
+
+// Snow Storm
+const base04 = '#d8dee9'; // grey
+const base05 = '#e5e9f0'; // off white
+const base06 = '#eceff4'; // white
+
+// Frost
+const base07 = '#8fbcbb'; // moss green
+const base08 = '#88c0d0'; // ice blue
+const base09 = '#81a1c1'; // water blue
+const base0A = '#5e81ac'; // deep blue
+
+// Aurora
+const base0b = '#bf616a'; // red
+const base0C = '#d08770'; // orange
+const base0D = '#ebcb8b'; // yellow
+const base0E = '#a3be8c'; // green
+const base0F = '#b48ead'; // purple
+
+const invalid = '#d30102';
+const darkBackground = '#252a33';
+// Cutomize
+const highlightBackground = base02;
+const background = base00;
+const tooltipBackground = base01;
+const selection = base03;
+// Cutomize
+const cursor = base06;
+
+// / The editor theme styles for Nord.
+export const nordTheme = EditorView.theme(
+  {
+    '&': {
+      color: base04,
+      backgroundColor: background,
+    },
+
+    '.cm-content': {
+      caretColor: cursor,
+    },
+
+    '.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor },
+    '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection':
+      { backgroundColor: selection },
+
+    '.cm-panels': { backgroundColor: darkBackground, color: base03 },
+    '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' },
+    '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' },
+
+    '.cm-searchMatch': {
+      backgroundColor: 'transparent',
+      outline: `1px solid ${base07}`,
+    },
+    '.cm-searchMatch.cm-searchMatch-selected': {
+      backgroundColor: base03,
+      color: base00,
+    },
+
+    '.cm-activeLine': { backgroundColor: highlightBackground },
+    '.cm-selectionMatch': {
+      backgroundColor: base05,
+      color: base01,
+    },
+
+    '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
+      // Customize
+      outline: `1px solid ${base03}`,
+    },
+
+    '&.cm-focused .cm-matchingBracket': {
+      // Cutomize
+      backgroundColor: base02,
+      color: base02,
+    },
+
+    '.cm-gutters': {
+      backgroundColor: base00,
+      color: base03,
+      border: 'none',
+    },
+
+    '.cm-activeLineGutter': {
+      backgroundColor: highlightBackground,
+      color: base04,
+    },
+
+    '.cm-foldPlaceholder': {
+      backgroundColor: 'transparent',
+      border: 'none',
+      color: '#ddd',
+    },
+
+    '.cm-tooltip': {
+      border: 'none',
+      backgroundColor: tooltipBackground,
+    },
+    '.cm-tooltip .cm-tooltip-arrow:before': {
+      borderTopColor: 'transparent',
+      borderBottomColor: 'transparent',
+    },
+    '.cm-tooltip .cm-tooltip-arrow:after': {
+      borderTopColor: tooltipBackground,
+      borderBottomColor: tooltipBackground,
+    },
+    '.cm-tooltip-autocomplete': {
+      '& > ul > li[aria-selected]': {
+        backgroundColor: highlightBackground,
+        color: base03,
+      },
+    },
+  },
+  { dark: true },
+);
+
+// / The highlighting style for code in the Nord theme.
+export const nordHighlightStyle = HighlightStyle.define([
+  { tag: t.keyword, color: base0A },
+  {
+    tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
+    color: base08,
+  },
+  { tag: [t.variableName], color: base07 },
+  { tag: [t.function(t.variableName)], color: base07 },
+  { tag: [t.labelName], color: base09 },
+  {
+    tag: [t.color, t.constant(t.name), t.standard(t.name)],
+    color: base0A,
+  },
+  { tag: [t.definition(t.name), t.separator], color: base0E },
+  { tag: [t.brace], color: base07 },
+  {
+    tag: [t.annotation],
+    color: invalid,
+  },
+  {
+    tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],
+    color: base0F,
+  },
+  {
+    tag: [t.typeName, t.className],
+    color: base0D,
+  },
+  {
+    tag: [t.operator, t.operatorKeyword],
+    color: base0E,
+  },
+  {
+    tag: [t.tagName],
+    color: base0F,
+  },
+  {
+    tag: [t.squareBracket],
+    color: base0b,
+  },
+  {
+    tag: [t.angleBracket],
+    color: base0C,
+  },
+  {
+    tag: [t.attributeName],
+    color: base0D,
+  },
+  {
+    tag: [t.regexp],
+    color: base0A,
+  },
+  {
+    tag: [t.quote],
+    color: base0F,
+  },
+  { tag: [t.string], color: base0E },
+  {
+    tag: t.link,
+    color: base0E,
+    textDecoration: 'underline',
+    textUnderlinePosition: 'under',
+  },
+  {
+    tag: [t.url, t.escape, t.special(t.string)],
+    color: base07,
+  },
+  { tag: [t.meta], color: base08 },
+  { tag: [t.monospace], color: base04, fontStyle: 'italic' },
+  { tag: [t.comment], color: base03, fontStyle: 'italic' },
+  { tag: t.strong, fontWeight: 'bold', color: base0A },
+  { tag: t.emphasis, fontStyle: 'italic', color: base0A },
+  { tag: t.strikethrough, textDecoration: 'line-through' },
+  { tag: t.heading, fontWeight: 'bold', color: base0A },
+  { tag: t.special(t.heading1), fontWeight: 'bold', color: base0A },
+  { tag: t.heading1, fontWeight: 'bold', color: base0A },
+  {
+    tag: [t.heading2, t.heading3, t.heading4],
+    fontWeight: 'bold',
+    color: base0A,
+  },
+  {
+    tag: [t.heading5, t.heading6],
+    color: base0A,
+  },
+  { tag: [t.atom, t.bool, t.special(t.variableName)], color: base0C },
+  {
+    tag: [t.processingInstruction, t.inserted],
+    color: base07,
+  },
+  {
+    tag: [t.contentSeparator],
+    color: base0D,
+  },
+  { tag: t.invalid, color: base02, borderBottom: `1px dotted ${invalid}` },
+]);
+
+// / Extension to enable the Nord theme (both the editor theme and
+// / the highlight style).
+export const nord: Extension = [
+  nordTheme,
+  syntaxHighlighting(nordHighlightStyle),
+];

+ 1 - 0
packages/editor/src/services/editor-theme/original-dark.ts

@@ -8,6 +8,7 @@ export const originalDark = createTheme({
   settings: {
     background: '#323132',
     foreground: '#EFEEED',
+    caret: '#A2A9B5',
     selection: '#4C5964',
     selectionMatch: '#3A546E',
     gutterBackground: '#393939',