Procházet zdrojové kódy

Merge pull request #7289 from weseek/master

Release v6.0.4
Yuki Takei před 3 roky
rodič
revize
ac45f20eef
28 změnil soubory, kde provedl 172 přidání a 126 odebrání
  1. 1 1
      lerna.json
  2. 1 1
      package.json
  3. 10 10
      packages/app/package.json
  4. 10 2
      packages/app/src/components/PageEditor/DrawioModal.tsx
  5. 22 17
      packages/app/src/components/PageEditor/LinkEditModal.jsx
  6. 11 2
      packages/app/src/components/ReactMarkdownComponents/Header.tsx
  7. 13 4
      packages/app/src/components/ReactMarkdownComponents/NextLink.tsx
  8. 22 20
      packages/app/src/components/ShareLink/ShareLinkList.tsx
  9. 20 8
      packages/app/src/server/middlewares/safe-redirect.ts
  10. 3 2
      packages/app/src/stores/editor.tsx
  11. 3 4
      packages/app/src/stores/use-static-swr.tsx
  12. 12 4
      packages/app/test/cypress/integration/20-basic-features/20-basic-features--click-page-icons.spec.ts
  13. 9 2
      packages/app/test/cypress/integration/22-sharelink/22-sharelink--access-to-sharelink.spec.ts
  14. 1 1
      packages/app/tsconfig.build.server.json
  15. 1 1
      packages/codemirror-textlint/package.json
  16. 1 1
      packages/core/package.json
  17. 1 1
      packages/hackmd/package.json
  18. 1 1
      packages/preset-themes/package.json
  19. 1 1
      packages/remark-drawio/package.json
  20. 1 1
      packages/remark-growi-directive/package.json
  21. 9 12
      packages/remark-lsx/package.json
  22. 10 3
      packages/remark-lsx/src/services/renderer/lsx.ts
  23. 0 18
      packages/remark-lsx/tsconfig.build.esm.json
  24. 1 1
      packages/remark-lsx/tsconfig.build.json
  25. 1 1
      packages/slack/package.json
  26. 2 2
      packages/slackbot-proxy/package.json
  27. 2 2
      packages/ui/package.json
  28. 3 3
      yarn.lock

+ 1 - 1
lerna.json

@@ -1,7 +1,7 @@
 {
   "npmClient": "yarn",
   "useWorkspaces": true,
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "packages": [
     "packages/*"
   ]

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "growi",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "description": "Team collaboration software using markdown",
   "tags": [
     "wiki",

+ 10 - 10
packages/app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/app",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "license": "MIT",
   "scripts": {
     "//// for production": "",
@@ -66,14 +66,14 @@
     "@elastic/elasticsearch7": "npm:@elastic/elasticsearch@^7.17.0",
     "@godaddy/terminus": "^4.9.0",
     "@google-cloud/storage": "^5.8.5",
-    "@growi/codemirror-textlint": "^6.0.3",
-    "@growi/core": "^6.0.3",
-    "@growi/hackmd": "^6.0.3",
-    "@growi/preset-themes": "^6.0.3",
-    "@growi/remark-drawio": "^6.0.3",
-    "@growi/remark-growi-directive": "^6.0.3",
-    "@growi/remark-lsx": "^6.0.3",
-    "@growi/slack": "^6.0.3",
+    "@growi/codemirror-textlint": "^6.0.4-RC.0",
+    "@growi/core": "^6.0.4-RC.0",
+    "@growi/hackmd": "^6.0.4-RC.0",
+    "@growi/preset-themes": "^6.0.4-RC.0",
+    "@growi/remark-drawio": "^6.0.4-RC.0",
+    "@growi/remark-growi-directive": "^6.0.4-RC.0",
+    "@growi/remark-lsx": "^6.0.4-RC.0",
+    "@growi/slack": "^6.0.4-RC.0",
     "@promster/express": "^7.0.6",
     "@promster/server": "^7.0.8",
     "@slack/web-api": "^6.2.4",
@@ -202,7 +202,7 @@
     "handsontable": "v7.0.0 or above is no loger MIT lisence."
   },
   "devDependencies": {
-    "@growi/ui": "^6.0.3",
+    "@growi/ui": "^6.0.4-RC.0",
     "@handsontable/react": "=2.1.0",
     "@icon/themify-icons": "1.0.1-alpha.3",
     "@next/bundle-analyzer": "^12.2.3",

+ 10 - 2
packages/app/src/components/PageEditor/DrawioModal.tsx

@@ -9,14 +9,15 @@ import {
   ModalBody,
 } from 'reactstrap';
 
-
 import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
 import { useDrawioUri } from '~/stores/context';
 import { useDrawioModal } from '~/stores/modal';
 import { usePersonalSettings } from '~/stores/personal-settings';
+import loggerFactory from '~/utils/logger';
 
 import { DrawioCommunicationHelper } from './DrawioCommunicationHelper';
 
+const logger = loggerFactory('growi:components:DrawioModal');
 
 const headerColor = '#334455';
 const fontFamily = "Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif";
@@ -52,7 +53,14 @@ export const DrawioModal = (): JSX.Element => {
       return undefined;
     }
 
-    const url = new URL(drawioUri);
+    let url;
+    try {
+      url = new URL(drawioUri);
+    }
+    catch (err) {
+      logger.debug(err);
+      return undefined;
+    }
 
     // refs: https://desk.draw.io/support/solutions/articles/16000042546-what-url-parameters-are-supported-
     url.searchParams.append('spin', '1');

+ 22 - 17
packages/app/src/components/PageEditor/LinkEditModal.jsx

@@ -18,15 +18,19 @@ import validator from 'validator';
 import Linker from '~/client/models/Linker';
 import { apiv3Get } from '~/client/util/apiv3-client';
 import { useCurrentPagePath } from '~/stores/page';
+import loggerFactory from '~/utils/logger';
 
 import PagePreviewIcon from '../Icons/PagePreviewIcon';
 import SearchTypeahead from '../SearchTypeahead';
 
 import Preview from './Preview';
 
+
 import styles from './LinkEditPreview.module.scss';
 
 
+const logger = loggerFactory('growi:components:LinkEditModal');
+
 class LinkEditModal extends React.PureComponent {
 
   constructor(props) {
@@ -96,17 +100,24 @@ class LinkEditModal extends React.PureComponent {
     // create url from link, add dummy origin if link is not valid url.
     // ex-1. link = 'https://growi.org/' -> url = 'https://growi.org/' (case-1,4)
     // ex-2. link = 'hoge' -> url = 'http://example.com/hoge' (case-2,3,5)
-    const url = new URL(link, 'http://example.com');
-    const isUrl = url.origin !== 'http://example.com';
-
+    let isFqcn = false;
     let isUseRelativePath = false;
-    let reshapedLink = link;
+    let url;
+    try {
+      const url = new URL(link, 'http://example.com');
+      isFqcn = url.origin !== 'http://example.com';
+    }
+    catch (err) {
+      logger.debug(err);
+    }
 
-    // if case-1, reshapedLink becomes page path
-    reshapedLink = this.convertUrlToPathIfPageUrl(reshapedLink, url);
+    // case-1: when link is this growi's page url, return pathname only
+    let reshapedLink = url != null && url.origin === window.location.origin
+      ? decodeURIComponent(url.pathname)
+      : link;
 
     // case-3
-    if (!isUrl && !reshapedLink.startsWith('/') && reshapedLink !== '') {
+    if (!isFqcn && !reshapedLink.startsWith('/') && reshapedLink !== '') {
       isUseRelativePath = true;
       const rootPath = this.getRootPath(type);
       reshapedLink = path.resolve(rootPath, reshapedLink);
@@ -118,12 +129,6 @@ class LinkEditModal extends React.PureComponent {
     });
   }
 
-  // return path name of link if link is this growi page url, else return original link.
-  convertUrlToPathIfPageUrl(link, url) {
-    // when link is this growi's page url, url.origin === window.location.origin and return path name
-    return url.origin === window.location.origin ? decodeURI(url.pathname) : link;
-  }
-
   cancel() {
     this.hide();
   }
@@ -161,11 +166,11 @@ class LinkEditModal extends React.PureComponent {
     let previewError = '';
 
     if (path.startsWith('/')) {
-      const pathWithoutFragment = new URL(path, 'http://dummy').pathname;
-      const isPermanentLink = validator.isMongoId(pathWithoutFragment.slice(1));
-      const pageId = isPermanentLink ? pathWithoutFragment.slice(1) : null;
-
       try {
+        const pathWithoutFragment = new URL(path, 'http://dummy').pathname;
+        const isPermanentLink = validator.isMongoId(pathWithoutFragment.slice(1));
+        const pageId = isPermanentLink ? pathWithoutFragment.slice(1) : null;
+
         const { data } = await apiv3Get('/page', { path: pathWithoutFragment, page_id: pageId });
         const { page } = data;
         markdown = page.revision.body;

+ 11 - 2
packages/app/src/components/ReactMarkdownComponents/Header.tsx

@@ -6,12 +6,15 @@ import { useRouter } from 'next/router';
 import { Element } from 'react-markdown/lib/rehype-filter';
 
 import { useIsGuestUser, useIsSharedUser, useShareLinkId } from '~/stores/context';
+import loggerFactory from '~/utils/logger';
 
 import { NextLink } from './NextLink';
 
 import styles from './Header.module.scss';
 
 
+const logger = loggerFactory('growi:components:Header');
+
 declare global {
   // eslint-disable-next-line vars-on-top, no-var
   var globalEmitter: EventEmitter;
@@ -67,8 +70,14 @@ export const Header = (props: HeaderProps): JSX.Element => {
   const CustomTag = `h${level}` as keyof JSX.IntrinsicElements;
 
   const activateByHash = useCallback((url: string) => {
-    const hash = (new URL(url, 'https://example.com')).hash.slice(1);
-    setActive(hash === id);
+    try {
+      const hash = (new URL(url, 'https://example.com')).hash.slice(1);
+      setActive(hash === id);
+    }
+    catch (err) {
+      logger.debug(err);
+      setActive(false);
+    }
   }, [id]);
 
   // init

+ 13 - 4
packages/app/src/components/ReactMarkdownComponents/NextLink.tsx

@@ -3,16 +3,25 @@ import { Link as ScrollLink } from 'react-scroll';
 
 import { DEFAULT_AUTO_SCROLL_OPTS } from '~/client/util/smooth-scroll';
 import { useSiteUrl } from '~/stores/context';
+import loggerFactory from '~/utils/logger';
+
+
+const logger = loggerFactory('growi:components:NextLink');
 
 const isAnchorLink = (href: string): boolean => {
   return href.toString().length > 0 && href[0] === '#';
 };
 
 const isExternalLink = (href: string, siteUrl: string | undefined): boolean => {
-  const baseUrl = new URL(siteUrl ?? 'https://example.com');
-  const hrefUrl = new URL(href, baseUrl);
-
-  return baseUrl.host !== hrefUrl.host;
+  try {
+    const baseUrl = new URL(siteUrl ?? 'https://example.com');
+    const hrefUrl = new URL(href, baseUrl);
+    return baseUrl.host !== hrefUrl.host;
+  }
+  catch (err) {
+    logger.debug(err);
+    return false;
+  }
 };
 
 type Props = Omit<LinkProps, 'href'> & {

+ 22 - 20
packages/app/src/components/ShareLink/ShareLinkList.tsx

@@ -24,21 +24,19 @@ const ShareLinkTr = (props: ShareLinkTrProps): JSX.Element => {
 
   return (
     <tr key={shareLinkId}>
-      <td>
-        <div className="d-flex">
-          <span className="mr-auto my-auto">{shareLinkId}</span>
-
-          { isRelatedPageExists && (
-            <CopyDropdown
-              pagePath={relatedPage.path}
-              dropdownToggleId={`copydropdown-${shareLinkId}`}
-              pageId={shareLinkId}
-              isShareLinkMode
-            >
-              Copy Link
-            </CopyDropdown>
-          ) }
-        </div>
+      <td className="d-flex justify-content-between align-items-center">
+        <span>{shareLinkId}</span>
+
+        { isRelatedPageExists && (
+          <CopyDropdown
+            pagePath={relatedPage.path}
+            dropdownToggleId={`copydropdown-${shareLinkId}`}
+            pageId={shareLinkId}
+            isShareLinkMode
+          >
+            Copy Link
+          </CopyDropdown>
+        ) }
       </td>
       { isAdmin && (
         <td>
@@ -48,9 +46,13 @@ const ShareLinkTr = (props: ShareLinkTrProps): JSX.Element => {
           }
         </td>
       ) }
-      <td>{shareLink.expiredAt && <span>{dateFnsFormat(new Date(shareLink.expiredAt), 'yyyy-MM-dd HH:mm')}</span>}</td>
-      <td>{shareLink.description}</td>
-      <td>
+      <td style={{ verticalAlign: 'middle' }}>
+        {shareLink.description}
+      </td>
+      <td style={{ verticalAlign: 'middle' }}>
+        {shareLink.expiredAt && <span >{dateFnsFormat(new Date(shareLink.expiredAt), 'yyyy-MM-dd HH:mm')}</span>}
+      </td>
+      <td style={{ maxWidth: '0', textAlign: 'center' }}>
         <button className="btn btn-outline-warning" type="button" onClick={onDelete}>
           <i className="icon-trash"></i>{t('Delete')}
         </button>
@@ -96,10 +98,10 @@ const ShareLinkList = (props: Props): JSX.Element => {
       <table className="table table-bordered">
         <thead>
           <tr>
-            <th>{t('share_links.Share Link', { ns: 'commons' })}</th>
+            <th style={{ width: '350px' }}>{t('share_links.Share Link', { ns: 'commons' })}</th>
             {props.isAdmin && <th>{t('share_links.Page Path', { ns: 'commons' })}</th>}
-            <th>{t('share_links.expire', { ns: 'commons' })}</th>
             <th>{t('share_links.description', { ns: 'commons' })}</th>
+            <th style={{ width: '150px' }}>{t('share_links.expire', { ns: 'commons' })}</th>
             <th></th>
           </tr>
         </thead>

+ 20 - 8
packages/app/src/server/middlewares/safe-redirect.js → packages/app/src/server/middlewares/safe-redirect.ts

@@ -4,31 +4,43 @@
  * Usage: app.use(require('middlewares/safe-redirect')(['example.com', 'some.example.com:8080']))
  */
 
+import {
+  Request, Response, NextFunction,
+} from 'express';
+
 import loggerFactory from '~/utils/logger';
 
 const logger = loggerFactory('growi:middleware:safe-redirect');
 
 /**
  * Check whether the redirect url host is in specified whitelist
- * @param {Array<string>} whitelistOfHosts
- * @param {string} redirectToFqdn
  */
-function isInWhitelist(whitelistOfHosts, redirectToFqdn) {
+function isInWhitelist(whitelistOfHosts: string[], redirectToFqdn: string): boolean {
   if (whitelistOfHosts == null || whitelistOfHosts.length === 0) {
     return false;
   }
 
-  const redirectUrl = new URL(redirectToFqdn);
-  return whitelistOfHosts.includes(redirectUrl.hostname) || whitelistOfHosts.includes(redirectUrl.host);
+  try {
+    const redirectUrl = new URL(redirectToFqdn);
+    return whitelistOfHosts.includes(redirectUrl.hostname) || whitelistOfHosts.includes(redirectUrl.host);
+  }
+  catch (err) {
+    logger.warn(err);
+    return false;
+  }
 }
 
 
-module.exports = (whitelistOfHosts) => {
+type ResWithSafeRedirect = Response & {
+  safeRedirect: (redirectTo?: string) => void,
+}
+
+module.exports = (whitelistOfHosts: string[]) => {
 
-  return function(req, res, next) {
+  return function(req: Request, res: ResWithSafeRedirect, next: NextFunction) {
 
     // extend res object
-    res.safeRedirect = function(redirectTo) {
+    res.safeRedirect = function(redirectTo?: string) {
       if (redirectTo == null) {
         return res.redirect('/');
       }

+ 3 - 2
packages/app/src/stores/editor.tsx

@@ -13,12 +13,13 @@ import {
   useCurrentUser, useDefaultIndentSize, useIsGuestUser,
 } from './context';
 // import { localStorageMiddleware } from './middlewares/sync-to-storage';
-import { useSWRxTagsInfo } from './page';
+import { useCurrentPagePath, useSWRxTagsInfo } from './page';
 import { useStaticSWR } from './use-static-swr';
 
 
 export const useEditingMarkdown = (initialData?: string): SWRResponse<string, Error> => {
-  return useStaticSWR('editingMarkdown', initialData);
+  const { data: currentPagePath } = useCurrentPagePath();
+  return useStaticSWR(['editingMarkdown', currentPagePath], initialData);
 };
 
 

+ 3 - 4
packages/app/src/stores/use-static-swr.tsx

@@ -3,7 +3,7 @@ import { useEffect } from 'react';
 import assert from 'assert';
 
 import {
-  Key, SWRConfiguration, SWRResponse,
+  mutate, Key, SWRConfiguration, SWRResponse,
 } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 
@@ -27,10 +27,9 @@ export function useStaticSWR<Data, Error>(
   // Do mutate with `data` from args
   useEffect(() => {
     if (data !== undefined) {
-      swrResponse.mutate(data);
+      mutate(key, data);
     }
-  // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [data]); // Only depends on `data`
+  }, [data, key]);
 
   return swrResponse;
 }

+ 12 - 4
packages/app/test/cypress/integration/20-basic-features/20-basic-features--click-page-icons.spec.ts

@@ -108,8 +108,12 @@ context('Click page icons button', () => {
     cy.get('#grw-subnav-container').within(() => { cy.screenshot(`${ssPrefix}7-bookmark-page`) });
 
     // total bookmarker
-    cy.get('#po-total-bookmarks').click({force: true});
-    cy.get('.user-list-popover').should('be.visible');
+    cy.waitUntil(() => {
+      // do
+      cy.get('#po-total-bookmarks').click({force: true});
+      // wait until
+      return cy.get('.user-list-popover').then($elem => $elem.is(':visible'));
+    });
     cy.waitUntilSpinnerDisappear();
     cy.get('#grw-subnav-container').within(() => { cy.screenshot(`${ssPrefix}8-bookmarks-counter`) });
 
@@ -129,8 +133,12 @@ context('Click page icons button', () => {
     cy.get('#grw-subnav-container').within(() => { cy.screenshot(`${ssPrefix}9-unbookmark-page`) });
 
     // total bookmarker
-    cy.get('#po-total-bookmarks').click({force: true});
-    cy.get('.user-list-popover').should('be.visible');
+    cy.waitUntil(() => {
+      // do
+      cy.get('#po-total-bookmarks').click({force: true});
+      // wait until
+      return cy.get('.user-list-popover').then($elem => $elem.is(':visible'));
+    });
     cy.waitUntilSpinnerDisappear();
     cy.get('#grw-subnav-container').within(() => { cy.screenshot(`${ssPrefix}10-bookmarks-counter`) });
   });

+ 9 - 2
packages/app/test/cypress/integration/22-sharelink/22-sharelink--access-to-sharelink.spec.ts

@@ -8,6 +8,7 @@ context('Access to sharelink by guest', () => {
     cy.fixture("user-admin.json").then(user => {
       cy.login(user.username, user.password);
     });
+
     cy.visit('/Sandbox/Bootstrap4');
 
     // open dropdown
@@ -35,9 +36,15 @@ context('Access to sharelink by guest', () => {
       cy.getByTestid('btn-sharelink-toggleform').should('be.visible').click();
       cy.getByTestid('btn-sharelink-issue').should('be.visible').click();
 
-      // store id
-      cy.get('tbody > tr > td > div > span').first().then((elem) => {
+      cy.get('tbody')
+        .find('tr').first() // the first row
+        .find('td').first() // the first column
+        .find('span').first().then((elem) => {
+
+        // store id
         createdSharelinkId = elem.text();
+        // overwrite the label
+        elem.html('63d100000000000000000000');
       });
     });
 

+ 1 - 1
packages/app/tsconfig.build.server.json

@@ -11,7 +11,7 @@
     "paths": {
       "~/*": ["./src/*"],
       "^/*": ["./*"],
-      "@growi/remark-lsx/*": ["../remark-lsx/dist/cjs/*"],
+      "@growi/remark-lsx/*": ["../remark-lsx/dist/*"],
       "debug": ["./src/utils/logger/alias-for-debug"]
     }
   },

+ 1 - 1
packages/codemirror-textlint/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/codemirror-textlint",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "license": "MIT",
   "main": "dist/index.js",
   "scripts": {

+ 1 - 1
packages/core/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/core",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "description": "GROWI Core Libraries",
   "license": "MIT",
   "keywords": [

+ 1 - 1
packages/hackmd/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/hackmd",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "description": "GROWI js and css files to use hackmd",
   "license": "MIT",
   "main": "dist/index.js",

+ 1 - 1
packages/preset-themes/package.json

@@ -1,7 +1,7 @@
 {
   "name": "@growi/preset-themes",
   "description": "GROWI preset themes",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "license": "MIT",
   "main": "dist/libs/index.js",
   "files": [

+ 1 - 1
packages/remark-drawio/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/remark-drawio",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "description": "remark plugin to draw diagrams with draw.io (diagrams.net)",
   "license": "MIT",
   "keywords": [

+ 1 - 1
packages/remark-growi-directive/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/remark-growi-directive",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "description": "remark plugin to support GROWI plugin (forked from remark-directive@2.0.1)",
   "license": "MIT",
   "keywords": [

+ 9 - 12
packages/remark-lsx/package.json

@@ -1,21 +1,18 @@
 {
   "name": "@growi/remark-lsx",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "description": "GROWI plugin to list pages",
   "license": "MIT",
   "keywords": ["growi", "growi-plugin"],
-  "main": "dist/cjs/index.js",
-  "module": "dist/esm/index.js",
+  "main": "dist/index.js",
   "exports": {
-    "./components": "./dist/cjs/components/index.js",
-    "./services/renderer": "./dist/cjs/services/renderer/index.js",
-    "./server/routes": "./dist/cjs/server/routes/index.js"
+    "./components": "./dist/components/index.js",
+    "./services/renderer": "./dist/services/renderer/index.js",
+    "./server/routes": "./dist/server/routes/index.js"
   },
   "files": ["dist"],
   "scripts": {
-    "build": "run-p build:*",
-    "build:cjs": "tsc -p tsconfig.build.cjs.json && tsc-alias -p tsconfig.build.cjs.json",
-    "build:esm": "tsc -p tsconfig.build.esm.json && tsc-alias -p tsconfig.build.esm.json",
+    "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
     "clean": "npx -y shx rm -rf dist",
     "lint:js": "eslint **/*.{js,jsx,ts,tsx}",
     "lint:styles": "stylelint --allow-empty-input src/**/*.scss src/**/*.css",
@@ -23,9 +20,9 @@
     "test": ""
   },
   "dependencies": {
-    "@growi/core": "^6.0.3",
-    "@growi/remark-growi-directive": "^6.0.3",
-    "@growi/ui": "^6.0.3",
+    "@growi/core": "^6.0.4-RC.0",
+    "@growi/remark-growi-directive": "^6.0.4-RC.0",
+    "@growi/ui": "^6.0.4-RC.0",
     "swr": "^1.3.0"
   },
   "devDependencies": {

+ 10 - 3
packages/remark-lsx/src/services/renderer/lsx.ts

@@ -4,13 +4,14 @@ import { pathUtils } from '@growi/core';
 import { remarkGrowiDirectivePluginType } from '@growi/remark-growi-directive';
 import { Schema as SanitizeOption } from 'hast-util-sanitize';
 import { selectAll, HastNode } from 'hast-util-select';
+import isAbsolute from 'is-absolute-url';
 import { Plugin } from 'unified';
 import { visit } from 'unist-util-visit';
 
 const NODE_NAME_PATTERN = new RegExp(/ls|lsx/);
 const SUPPORTED_ATTRIBUTES = ['prefix', 'num', 'depth', 'sort', 'reverse', 'filter', 'except'];
 
-const { hasHeadingSlash } = pathUtils;
+const { addHeadingSlash, hasHeadingSlash } = pathUtils;
 
 type DirectiveAttributes = Record<string, string>
 
@@ -66,10 +67,16 @@ export type LsxRehypePluginParams = {
   pagePath?: string,
 }
 
-const pathResolver = (relativeHref: string, basePath: string): string => {
+const pathResolver = (href: string, basePath: string): string => {
+  // exclude absolute URL
+  if (isAbsolute(href)) {
+    // remove scheme
+    return href.replace(/^(.+?):\/\//, '/');
+  }
+
   // generate relative pathname
   const baseUrl = new URL(pathUtils.addTrailingSlash(basePath), 'https://example.com');
-  const relativeUrl = new URL(relativeHref, baseUrl);
+  const relativeUrl = new URL(href, baseUrl);
 
   return relativeUrl.pathname;
 };

+ 0 - 18
packages/remark-lsx/tsconfig.build.esm.json

@@ -1,18 +0,0 @@
-{
-  "extends": "./tsconfig.base.json",
-  "compilerOptions": {
-    "module": "esnext",
-
-    "rootDir": "./src",
-    "outDir": "dist/esm",
-    "declaration": true,
-    "noResolve": false,
-    "preserveConstEnums": true,
-    "sourceMap": false,
-    "noEmit": false,
-
-    "baseUrl": ".",
-    "paths": {
-    }
-  }
-}

+ 1 - 1
packages/remark-lsx/tsconfig.build.cjs.json → packages/remark-lsx/tsconfig.build.json

@@ -2,7 +2,7 @@
   "extends": "./tsconfig.base.json",
   "compilerOptions": {
     "rootDir": "./src",
-    "outDir": "dist/cjs",
+    "outDir": "dist",
     "declaration": true,
     "noResolve": false,
     "preserveConstEnums": true,

+ 1 - 1
packages/slack/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/slack",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "license": "MIT",
   "main": "dist/index.js",
   "typings": "dist/index.d.ts",

+ 2 - 2
packages/slackbot-proxy/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/slackbot-proxy",
-  "version": "6.0.3",
+  "version": "6.0.4-slackbot-proxy.0",
   "license": "MIT",
   "scripts": {
     "build": "yarn tsc && tsc-alias -p tsconfig.build.json",
@@ -26,7 +26,7 @@
   },
   "dependencies": {
     "@godaddy/terminus": "^4.9.0",
-    "@growi/slack": "^6.0.3",
+    "@growi/slack": "^6.0.4-RC.0",
     "@slack/oauth": "^2.0.1",
     "@slack/web-api": "^6.2.4",
     "@tsed/common": "^6.43.0",

+ 2 - 2
packages/ui/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/ui",
-  "version": "6.0.3",
+  "version": "6.0.4-RC.0",
   "description": "GROWI UI Libraries",
   "license": "MIT",
   "keywords": ["growi"],
@@ -17,7 +17,7 @@
     "test": "jest --verbose"
   },
   "dependencies": {
-    "@growi/core": "^6.0.3"
+    "@growi/core": "^6.0.4-RC.0"
   },
   "devDependencies": {
     "eslint-plugin-regex": "^1.8.0",

+ 3 - 3
yarn.lock

@@ -22878,9 +22878,9 @@ typpy@2.3.11:
     function.name "^1.0.3"
 
 ua-parser-js@^0.7.18, ua-parser-js@^0.7.9:
-  version "0.7.31"
-  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6"
-  integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==
+  version "0.7.33"
+  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532"
+  integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw==
 
 uberproto@^1.1.0:
   version "1.2.0"