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

Merge branch 'master' into fix/enable-i18n-tags-page

Ryoji Shimizu 3 лет назад
Родитель
Сommit
38f78b0b79

+ 4 - 0
.github/workflows/reusable-app-prod.yml

@@ -237,6 +237,10 @@ jobs:
       run: |
         npx lerna bootstrap -- --production
 
+    - name: lerna add packages needed for CI
+      run: |
+        npx lerna add yargs
+
     - name: Download production files artifact
       uses: actions/download-artifact@v3
       with:

+ 5 - 3
packages/app/src/components/InstallerForm.tsx

@@ -106,11 +106,13 @@ const InstallerForm = memo((): JSX.Element => {
       <div className="row">
         <form role="form" id="register-form" className="col-md-12" onSubmit={submitHandler}>
           <div className="dropdown mb-3">
-            <div className="d-flex dropdown-with-icon">
-              <i className="icon-bubbles border-0 rounded-0" />
+            <div className="input-group">
+              <div className="input-group-prepend dropdown-with-icon">
+                <i className="input-group-text icon-bubbles border-0 rounded-0" />
+              </div>
               <button
                 type="button"
-                className="btn btn-secondary dropdown-toggle text-right w-100 border-0 shadow-none"
+                className="btn btn-secondary dropdown-toggle form-control text-right rounded-right"
                 id="dropdownLanguage"
                 data-testid="dropdownLanguage"
                 data-toggle="dropdown"

+ 0 - 2
packages/app/src/components/Layout/BasicLayout.tsx

@@ -22,7 +22,6 @@ const PageDeleteModal = dynamic(() => import('../PageDeleteModal'), { ssr: false
 const PageRenameModal = dynamic(() => import('../PageRenameModal'), { ssr: false });
 const PagePresentationModal = dynamic(() => import('../PagePresentationModal'), { ssr: false });
 const PageAccessoriesModal = dynamic(() => import('../PageAccessoriesModal'), { ssr: false });
-const DrawioModal = dynamic(() => import('../PageEditor/DrawioModal').then(mod => mod.DrawioModal), { ssr: false });
 // Fab
 const Fab = dynamic(() => import('../Fab').then(mod => mod.Fab), { ssr: false });
 
@@ -64,7 +63,6 @@ export const BasicLayout = ({
         <PageDeleteModal />
         <PageRenameModal />
         <PageAccessoriesModal />
-        <DrawioModal />
       </DndProvider>
 
       <PagePresentationModal />

+ 0 - 10
packages/app/src/components/Layout/NoLoginLayout.module.scss

@@ -63,16 +63,6 @@
     }
   }
 
-  .dropdown-with-icon {
-    .dropdown-toggle {
-      @extend .form-control;
-    }
-    i {
-      @extend .input-group-text;
-      margin-right: -1px;
-    }
-  }
-
   .input-group {
     margin-bottom: 10px;
 

+ 6 - 3
packages/app/src/components/Sidebar/CustomSidebar.tsx

@@ -1,6 +1,7 @@
 import React, { FC } from 'react';
 
 import { useTranslation } from 'next-i18next';
+import Link from 'next/link';
 
 import { IRevision } from '~/interfaces/revision';
 import { useSWRxPageByPath } from '~/stores/page';
@@ -19,9 +20,11 @@ const logger = loggerFactory('growi:cli:CustomSidebar');
 const SidebarNotFound = () => {
   return (
     <div className="grw-sidebar-content-header h5 text-center p-3">
-      <a href="/Sidebar#edit">
-        <i className="icon-magic-wand"></i> Create <strong>/Sidebar</strong> page
-      </a>
+      <Link href="/Sidebar#edit">
+        <a href="/Sidebar#edit">
+          <i className="icon-magic-wand"></i> Create <strong>/Sidebar</strong> page
+        </a>
+      </Link>
     </div>
   );
 };

+ 2 - 0
packages/app/src/pages/[[...path]].page.tsx

@@ -86,6 +86,7 @@ const UnsavedAlertDialog = dynamic(() => import('../components/UnsavedAlertDialo
 const GrowiSubNavigationSwitcher = dynamic(() => import('../components/Navbar/GrowiSubNavigationSwitcher'), { ssr: false });
 const UsersHomePageFooter = dynamic<UsersHomePageFooterProps>(() => import('../components/UsersHomePageFooter')
   .then(mod => mod.UsersHomePageFooter), { ssr: false });
+const DrawioModal = dynamic(() => import('../components/PageEditor/DrawioModal').then(mod => mod.DrawioModal), { ssr: false });
 const HandsontableModal = dynamic(() => import('../components/PageEditor/HandsontableModal').then(mod => mod.HandsontableModal), { ssr: false });
 
 const logger = loggerFactory('growi:pages:all');
@@ -361,6 +362,7 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
 
           <UnsavedAlertDialog />
           <DescendantsPageListModal />
+          <DrawioModal />
           <HandsontableModal />
           {shouldRenderPutbackPageModal && <PutbackPageModal />}
         </div>

+ 1 - 1
packages/app/src/styles/organisms/_wiki-custom-sidebar.scss

@@ -39,7 +39,7 @@
     margin: 10px 0;
   }
 
-  .page-list .page-list-ul {
+  .lsx.page-list > .page-list-ul {
     padding-left: 0;
     margin: 0;
   }

+ 27 - 12
packages/remark-growi-plugin/src/micromark-extension-growi-plugin/lib/factory-attributes.js

@@ -82,13 +82,6 @@ export function factoryAttributes(
       return shortcutStart(code);
     }
 
-    if (code === codes.colon || code === codes.underscore || code === codes.slash || asciiAlpha(code)) {
-      effects.enter(attributeType);
-      effects.enter(attributeNameType);
-      effects.consume(code);
-      return name;
-    }
-
     if (disallowEol && markdownSpace(code)) {
       return factorySpace(effects, between, types.whitespace)(code);
     }
@@ -97,6 +90,19 @@ export function factoryAttributes(
       return factoryAttributesDevider(effects, between)(code);
     }
 
+    if (code !== codes.rightParenthesis
+      && code !== codes.eof
+      && code !== codes.carriageReturn
+      && code !== codes.lineFeed
+      && code !== codes.carriageReturnLineFeed
+      && code !== codes.ampersand
+    ) {
+      effects.enter(attributeType);
+      effects.enter(attributeNameType);
+      effects.consume(code);
+      return name;
+    }
+
     return end(code);
   }
 
@@ -166,11 +172,20 @@ export function factoryAttributes(
   /** @type {State} */
   function name(code) {
     if (
-      code === codes.dash
-      || code === codes.dot
-      || code === codes.colon
-      || code === codes.underscore
-      || asciiAlphanumeric(code)
+      code !== codes.eof
+        && code !== codes.carriageReturn
+        && code !== codes.lineFeed
+        && code !== codes.carriageReturnLineFeed
+        && code !== codes.quotationMark
+        && code !== codes.numberSign
+        && code !== codes.apostrophe
+        && code !== codes.dot
+        && code !== codes.lessThan
+        && code !== codes.equalsTo
+        && code !== codes.greaterThan
+        && code !== codes.graveAccent
+        && code !== codes.rightParenthesis
+        && code !== codes.space
     ) {
       effects.consume(code);
       return name;

+ 69 - 2
packages/remark-growi-plugin/test/micromark-extension-growi-plugin.test.js

@@ -113,7 +113,7 @@ test('micromark-extension-directive (syntax)', (t) => {
     t.equal(
       micromark('$a(', options()),
       '<p>(</p>',
-      'should support a name followed by an unclosed `{`',
+      'should support a name followed by an unclosed `(`',
     );
 
     t.equal(
@@ -125,7 +125,7 @@ test('micromark-extension-directive (syntax)', (t) => {
     t.equal(
       micromark('$a(b', options()),
       '<p>(b</p>',
-      'should support a name followed by an unclosed `{` w/ content',
+      'should support a name followed by an unclosed `(` w/ content',
     );
 
     t.equal(
@@ -326,6 +326,12 @@ test('micromark-extension-directive (syntax)', (t) => {
       'should not support a grave accent in an unquoted attribute value',
     );
 
+    t.equal(
+      micromark('a $a(b💚=a💚b)', options()),
+      '<p>a </p>',
+      'should support most other characters in attribute keys',
+    );
+
     t.equal(
       micromark('a $a(b=a💚b)', options()),
       '<p>a </p>',
@@ -547,6 +553,12 @@ test('micromark-extension-directive (syntax)', (t) => {
     //   'should not support `=` to start an unquoted attribute value',
     // );
 
+    t.equal(
+      micromark('$a(b💚=a💚b)', options()),
+      '',
+      'should support most other characters in attribute keys',
+    );
+
     t.equal(
       micromark('$a(b=a💚b)', options()),
       '',
@@ -772,6 +784,41 @@ test('micromark-extension-directive (compile)', (t) => {
     'should support directives (youtube)',
   );
 
+  t.equal(
+    micromark(
+      [
+        'Text:',
+        'a $lsx',
+        'a $lsx()',
+        'a $lsx(num=1)',
+        'a $lsx(/)',
+        'a $lsx(💚)',
+        'Leaf:',
+        '$lsx',
+        '$lsx()',
+        '$lsx(num=1)',
+        '$lsx(/)',
+        '$lsx(💚)',
+      ].join('\n\n'),
+      options({ lsx }),
+    ),
+    [
+      '<p>Text:</p>',
+      '<p>a <lsx ></lsx></p>',
+      '<p>a <lsx ></lsx></p>',
+      '<p>a <lsx num="1"></lsx></p>',
+      '<p>a <lsx prefix="/"></lsx></p>',
+      '<p>a <lsx prefix="💚"></lsx></p>',
+      '<p>Leaf:</p>',
+      '<lsx ></lsx>',
+      '<lsx ></lsx>',
+      '<lsx num="1"></lsx>',
+      '<lsx prefix="/"></lsx>',
+      '<lsx prefix="💚"></lsx>',
+    ].join('\n'),
+    'should support directives (lsx)',
+  );
+
   t.equal(
     micromark('a $youtube[Cat in a box]\n$br a', options({ youtube, '*': h })),
     '<p>a <youtube>Cat in a box</youtube>\n<br> a</p>',
@@ -1051,6 +1098,26 @@ function youtube(d) {
   this.tag('</iframe>');
 }
 
+/** @type {Handle} */
+function lsx(d) {
+  const attrs = d.attributes || {};
+
+  const props = [];
+
+  // eslint-disable-next-line no-restricted-syntax
+  for (const key in attrs) {
+    if (attrs[key].length === 0) {
+      props.push(`prefix="${key}"`);
+    }
+    else {
+      props.push(`${key}="${attrs[key]}"`);
+    }
+  }
+
+  this.tag(`<lsx ${props.join(' ')}>`);
+  this.tag('</lsx>');
+}
+
 /** @type {Handle} */
 function h(d) {
   const content = d.content || d.label;