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

configure biome for core package utils and models

Futa Arai 9 месяцев назад
Родитель
Сommit
4cc9448547

+ 0 - 2
biome.json

@@ -19,8 +19,6 @@
       ".stylelintrc.json",
       ".stylelintrc.json",
       "package.json",
       "package.json",
       "./apps/**",
       "./apps/**",
-      "./packages/core/src/utils/**",
-      "./packages/core/src/models/**",
       "./packages/editor/**",
       "./packages/editor/**",
       "./packages/pdf-converter-client/**"
       "./packages/pdf-converter-client/**"
     ]
     ]

+ 1 - 5
packages/core/.eslintignore

@@ -1,5 +1 @@
-/dist/**
-/src/consts/**
-/src/interfaces/**
-/src/remark-plugins/**
-/src/swr/**
+*

+ 0 - 3
packages/core/.eslintrc.cjs

@@ -1,3 +0,0 @@
-module.exports = {
-  extends: ['plugin:vitest/recommended'],
-};

+ 1 - 1
packages/core/src/models/devided-page-path.ts

@@ -42,7 +42,7 @@ export class DevidedPagePath {
     let PATTERN_DEFAULT = /^((.*)\/(?!em>))?(.+)$/; // this will ignore em's end tags
     let PATTERN_DEFAULT = /^((.*)\/(?!em>))?(.+)$/; // this will ignore em's end tags
     try { // for non-chrome browsers
     try { // for non-chrome browsers
       // eslint-disable-next-line regex/invalid
       // eslint-disable-next-line regex/invalid
-      PATTERN_DEFAULT = new RegExp('^((.*)(?<!<)\\/)?(.+)$'); // https://regex101.com/r/HJNvMW/1
+      PATTERN_DEFAULT = /^((.*)(?<!<)\\/)?(.+)$/; // https://regex101.com/r/HJNvMW/1
     }
     }
     catch (err) {
     catch (err) {
       // lookbehind regex is not supported on non-chrome browsers
       // lookbehind regex is not supported on non-chrome browsers

+ 28 - 17
packages/core/src/models/serializers/attachment-serializer.ts

@@ -2,23 +2,28 @@ import { Document } from 'mongoose';
 
 
 import type { IAttachment, IUser } from '~/interfaces';
 import type { IAttachment, IUser } from '~/interfaces';
 
 
-import { isPopulated, isRef, type Ref } from '../../interfaces/common';
+import { type Ref, isPopulated, isRef } from '../../interfaces/common';
 
 
-import { serializeUserSecurely, type IUserSerializedSecurely } from './user-serializer';
+import {
+  type IUserSerializedSecurely,
+  serializeUserSecurely,
+} from './user-serializer';
 
 
-export type IAttachmentSerializedSecurely<A extends IAttachment> = Omit<A, 'creator'> & { creator?: Ref<IUserSerializedSecurely<IUser>> };
+export type IAttachmentSerializedSecurely<A extends IAttachment> = Omit<
+  A,
+  'creator'
+> & { creator?: Ref<IUserSerializedSecurely<IUser>> };
 
 
-const omitInsecureAttributes = <A extends IAttachment>(attachment: A): IAttachmentSerializedSecurely<A> => {
-
-  const leanDoc = (attachment instanceof Document)
-    ? attachment.toObject<A>()
-    : attachment;
+const omitInsecureAttributes = <A extends IAttachment>(
+  attachment: A,
+): IAttachmentSerializedSecurely<A> => {
+  const leanDoc =
+    attachment instanceof Document ? attachment.toObject<A>() : attachment;
 
 
   const { creator, ...rest } = leanDoc;
   const { creator, ...rest } = leanDoc;
 
 
-  const secureCreator = creator == null
-    ? undefined
-    : serializeUserSecurely(creator);
+  const secureCreator =
+    creator == null ? undefined : serializeUserSecurely(creator);
 
 
   return {
   return {
     creator: secureCreator,
     creator: secureCreator,
@@ -26,12 +31,18 @@ const omitInsecureAttributes = <A extends IAttachment>(attachment: A): IAttachme
   };
   };
 };
 };
 
 
-
-export function serializeAttachmentSecurely<A extends IAttachment>(attachment?: A): IAttachmentSerializedSecurely<A>;
-export function serializeAttachmentSecurely<A extends IAttachment>(attachment?: Ref<A>): Ref<IAttachmentSerializedSecurely<A>>;
-export function serializeAttachmentSecurely<A extends IAttachment>(attachment?: A | Ref<A>)
-    : undefined | IAttachmentSerializedSecurely<A> | Ref<IAttachmentSerializedSecurely<A>> {
-
+export function serializeAttachmentSecurely<A extends IAttachment>(
+  attachment?: A,
+): IAttachmentSerializedSecurely<A>;
+export function serializeAttachmentSecurely<A extends IAttachment>(
+  attachment?: Ref<A>,
+): Ref<IAttachmentSerializedSecurely<A>>;
+export function serializeAttachmentSecurely<A extends IAttachment>(
+  attachment?: A | Ref<A>,
+):
+  | undefined
+  | IAttachmentSerializedSecurely<A>
+  | Ref<IAttachmentSerializedSecurely<A>> {
   if (attachment == null) return attachment;
   if (attachment == null) return attachment;
 
 
   if (isRef(attachment) && !isPopulated(attachment)) return attachment;
   if (isRef(attachment) && !isPopulated(attachment)) return attachment;

+ 22 - 11
packages/core/src/models/serializers/user-serializer.ts

@@ -1,19 +1,24 @@
 import { Document } from 'mongoose';
 import { Document } from 'mongoose';
 
 
-import { isPopulated, isRef, type Ref } from '../../interfaces/common';
+import { type Ref, isPopulated, isRef } from '../../interfaces/common';
 import type { IUser } from '../../interfaces/user';
 import type { IUser } from '../../interfaces/user';
 
 
-export type IUserSerializedSecurely<U extends IUser> = Omit<U, 'password' | 'apiToken' | 'email'> & { email?: string };
+export type IUserSerializedSecurely<U extends IUser> = Omit<
+  U,
+  'password' | 'apiToken' | 'email'
+> & { email?: string };
 
 
-export const omitInsecureAttributes = <U extends IUser>(user: U): IUserSerializedSecurely<U> => {
-
-  const leanDoc = (user instanceof Document)
-    ? user.toObject<U>()
-    : user;
+export const omitInsecureAttributes = <U extends IUser>(
+  user: U,
+): IUserSerializedSecurely<U> => {
+  const leanDoc = user instanceof Document ? user.toObject<U>() : user;
 
 
   const {
   const {
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
-    password, apiToken, email, ...rest
+    password,
+    apiToken,
+    email,
+    ...rest
   } = leanDoc;
   } = leanDoc;
 
 
   const secureUser: IUserSerializedSecurely<U> = rest;
   const secureUser: IUserSerializedSecurely<U> = rest;
@@ -26,9 +31,15 @@ export const omitInsecureAttributes = <U extends IUser>(user: U): IUserSerialize
   return secureUser;
   return secureUser;
 };
 };
 
 
-export function serializeUserSecurely<U extends IUser>(user?: U): IUserSerializedSecurely<U>;
-export function serializeUserSecurely<U extends IUser>(user?: Ref<U>): Ref<IUserSerializedSecurely<U>>;
-export function serializeUserSecurely<U extends IUser>(user?: U | Ref<U>): undefined | IUserSerializedSecurely<U> | Ref<IUserSerializedSecurely<U>> {
+export function serializeUserSecurely<U extends IUser>(
+  user?: U,
+): IUserSerializedSecurely<U>;
+export function serializeUserSecurely<U extends IUser>(
+  user?: Ref<U>,
+): Ref<IUserSerializedSecurely<U>>;
+export function serializeUserSecurely<U extends IUser>(
+  user?: U | Ref<U>,
+): undefined | IUserSerializedSecurely<U> | Ref<IUserSerializedSecurely<U>> {
   if (user == null) return user;
   if (user == null) return user;
 
 
   if (isRef(user) && !isPopulated(user)) return user;
   if (isRef(user) && !isPopulated(user)) return user;

+ 6 - 3
packages/core/src/models/vo/error-apiv3.ts

@@ -1,15 +1,18 @@
 export class ErrorV3 extends Error {
 export class ErrorV3 extends Error {
-
   code: string;
   code: string;
 
 
   args?: any;
   args?: any;
 
 
-  constructor(message = '', code = '', stack = undefined, args: any = undefined) {
+  constructor(
+    message = '',
+    code = '',
+    stack = undefined,
+    args: any = undefined,
+  ) {
     super(); // do not provide message to the super constructor
     super(); // do not provide message to the super constructor
     this.message = message;
     this.message = message;
     this.code = code;
     this.code = code;
     this.stack = stack;
     this.stack = stack;
     this.args = args;
     this.args = args;
   }
   }
-
 }
 }

+ 4 - 1
packages/core/src/utils/browser-utils.ts

@@ -1,5 +1,8 @@
 export const isClient = (): boolean => {
 export const isClient = (): boolean => {
-  return (typeof window !== 'undefined') || (typeof navigator !== 'undefined' && navigator.webdriver);
+  return (
+    typeof window !== 'undefined' ||
+    (typeof navigator !== 'undefined' && navigator.webdriver)
+  );
 };
 };
 
 
 export const isServer = (): boolean => {
 export const isServer = (): boolean => {

+ 0 - 3
packages/core/src/utils/env-utils.spec.ts

@@ -1,9 +1,7 @@
 import { toBoolean } from './env-utils';
 import { toBoolean } from './env-utils';
 
 
-
 describe('env-utils', () => {
 describe('env-utils', () => {
   describe('.toBoolean', () => {
   describe('.toBoolean', () => {
-
     it('should convert to true', () => {
     it('should convert to true', () => {
       expect(toBoolean('true')).toBe(true);
       expect(toBoolean('true')).toBe(true);
       expect(toBoolean('True')).toBe(true);
       expect(toBoolean('True')).toBe(true);
@@ -16,6 +14,5 @@ describe('env-utils', () => {
       expect(toBoolean('false')).toBe(false);
       expect(toBoolean('false')).toBe(false);
       expect(toBoolean('0')).toBe(false);
       expect(toBoolean('0')).toBe(false);
     });
     });
-
   });
   });
 });
 });

+ 6 - 3
packages/core/src/utils/growi-theme-metadata.ts

@@ -1,8 +1,11 @@
 import type { ColorScheme } from '../interfaces/color-scheme';
 import type { ColorScheme } from '../interfaces/color-scheme';
 import { GrowiThemeSchemeType } from '../interfaces/growi-theme-metadata';
 import { GrowiThemeSchemeType } from '../interfaces/growi-theme-metadata';
 
 
-export const getForcedColorScheme = (growiThemeSchemeType?: GrowiThemeSchemeType): ColorScheme | undefined => {
-  return growiThemeSchemeType == null || growiThemeSchemeType === GrowiThemeSchemeType.BOTH
+export const getForcedColorScheme = (
+  growiThemeSchemeType?: GrowiThemeSchemeType,
+): ColorScheme | undefined => {
+  return growiThemeSchemeType == null ||
+    growiThemeSchemeType === GrowiThemeSchemeType.BOTH
     ? undefined
     ? undefined
-    : growiThemeSchemeType as ColorScheme;
+    : (growiThemeSchemeType as ColorScheme);
 };
 };

+ 11 - 2
packages/core/src/utils/is-deep-equals.ts

@@ -1,8 +1,17 @@
 const isPrimitiveComparison = (value1: unknown, value2: unknown): boolean => {
 const isPrimitiveComparison = (value1: unknown, value2: unknown): boolean => {
-  return value1 === null || value2 === null || typeof value1 !== 'object' || typeof value2 !== 'object';
+  return (
+    value1 === null ||
+    value2 === null ||
+    typeof value1 !== 'object' ||
+    typeof value2 !== 'object'
+  );
 };
 };
 
 
-export const isDeepEquals = <T extends object>(obj1: T, obj2: T, visited = new WeakMap()): boolean => {
+export const isDeepEquals = <T extends object>(
+  obj1: T,
+  obj2: T,
+  visited = new WeakMap(),
+): boolean => {
   // If references are identical, return true
   // If references are identical, return true
   if (obj1 === obj2) {
   if (obj1 === obj2) {
     return true;
     return true;

+ 1 - 3
packages/core/src/utils/objectid-utils.spec.ts

@@ -3,7 +3,6 @@ import ObjectId from 'bson-objectid';
 import { isValidObjectId } from './objectid-utils';
 import { isValidObjectId } from './objectid-utils';
 
 
 describe('isValidObjectId', () => {
 describe('isValidObjectId', () => {
-
   /* eslint-disable indent */
   /* eslint-disable indent */
   describe.concurrent.each`
   describe.concurrent.each`
     arg                                           | expected
     arg                                           | expected
@@ -15,7 +14,7 @@ describe('isValidObjectId', () => {
     ${'594ced02ed345b2b049222c5'}                 | ${true}
     ${'594ced02ed345b2b049222c5'}                 | ${true}
     ${new ObjectId('594ced02ed345b2b049222c5')}   | ${true}
     ${new ObjectId('594ced02ed345b2b049222c5')}   | ${true}
   `('should return $expected', ({ arg, expected }) => {
   `('should return $expected', ({ arg, expected }) => {
-    test(`when the argument is '${arg}'`, async() => {
+    test(`when the argument is '${arg}'`, async () => {
       // when:
       // when:
       const result = isValidObjectId(arg);
       const result = isValidObjectId(arg);
 
 
@@ -23,5 +22,4 @@ describe('isValidObjectId', () => {
       expect(result).toBe(expected);
       expect(result).toBe(expected);
     });
     });
   });
   });
-
 });
 });

+ 3 - 1
packages/core/src/utils/objectid-utils.ts

@@ -1,6 +1,8 @@
 import ObjectId from 'bson-objectid';
 import ObjectId from 'bson-objectid';
 
 
-export function isValidObjectId(id: string | ObjectId | null | undefined): boolean {
+export function isValidObjectId(
+  id: string | ObjectId | null | undefined,
+): boolean {
   if (id == null) {
   if (id == null) {
     return false;
     return false;
   }
   }

+ 28 - 12
packages/core/src/utils/page-path-utils/generate-children-regexp.spec.ts

@@ -19,24 +19,37 @@ describe('generateChildrenRegExp', () => {
     {
     {
       path: '/parent (with brackets)',
       path: '/parent (with brackets)',
       expected: '^\\/parent \\(with brackets\\)(\\/[^/]+)\\/?$',
       expected: '^\\/parent \\(with brackets\\)(\\/[^/]+)\\/?$',
-      validPaths: ['/parent (with brackets)/child', '/parent (with brackets)/test'],
-      invalidPaths: ['/parent (with brackets)', '/parent (with brackets)/child/grandchild'],
+      validPaths: [
+        '/parent (with brackets)/child',
+        '/parent (with brackets)/test',
+      ],
+      invalidPaths: [
+        '/parent (with brackets)',
+        '/parent (with brackets)/child/grandchild',
+      ],
     },
     },
     {
     {
       path: '/parent[with square]',
       path: '/parent[with square]',
       expected: '^\\/parent\\[with square\\](\\/[^/]+)\\/?$',
       expected: '^\\/parent\\[with square\\](\\/[^/]+)\\/?$',
       validPaths: ['/parent[with square]/child', '/parent[with square]/test'],
       validPaths: ['/parent[with square]/child', '/parent[with square]/test'],
-      invalidPaths: ['/parent[with square]', '/parent[with square]/child/grandchild'],
+      invalidPaths: [
+        '/parent[with square]',
+        '/parent[with square]/child/grandchild',
+      ],
     },
     },
     {
     {
       path: '/parent*with+special?chars',
       path: '/parent*with+special?chars',
       expected: '^\\/parent\\*with\\+special\\?chars(\\/[^/]+)\\/?$',
       expected: '^\\/parent\\*with\\+special\\?chars(\\/[^/]+)\\/?$',
-      validPaths: ['/parent*with+special?chars/child', '/parent*with+special?chars/test'],
-      invalidPaths: ['/parent*with+special?chars', '/parent*with+special?chars/child/grandchild'],
+      validPaths: [
+        '/parent*with+special?chars/child',
+        '/parent*with+special?chars/test',
+      ],
+      invalidPaths: [
+        '/parent*with+special?chars',
+        '/parent*with+special?chars/child/grandchild',
+      ],
     },
     },
-  ])('with path: $path', ({
-    path, expected, validPaths, invalidPaths,
-  }) => {
+  ])('with path: $path', ({ path, expected, validPaths, invalidPaths }) => {
     test('should generate correct regexp pattern', () => {
     test('should generate correct regexp pattern', () => {
       const result = generateChildrenRegExp(path);
       const result = generateChildrenRegExp(path);
       expect(result.source).toBe(expected);
       expect(result.source).toBe(expected);
@@ -47,9 +60,12 @@ describe('generateChildrenRegExp', () => {
       expect(validPath).toMatch(result);
       expect(validPath).toMatch(result);
     });
     });
 
 
-    test.each(invalidPaths)('should not match invalid path: %s', (invalidPath) => {
-      const result = generateChildrenRegExp(path);
-      expect(invalidPath).not.toMatch(result);
-    });
+    test.each(invalidPaths)(
+      'should not match invalid path: %s',
+      (invalidPath) => {
+        const result = generateChildrenRegExp(path);
+        expect(invalidPath).not.toMatch(result);
+      },
+    );
   });
   });
 });
 });

+ 80 - 33
packages/core/src/utils/page-path-utils/index.spec.ts

@@ -1,5 +1,11 @@
 import {
 import {
-  isMovablePage, isTopPage, isUsersProtectedPages, convertToNewAffiliationPath, isCreatablePage, omitDuplicateAreaPathFromPaths, getUsernameByPath,
+  convertToNewAffiliationPath,
+  getUsernameByPath,
+  isCreatablePage,
+  isMovablePage,
+  isTopPage,
+  isUsersProtectedPages,
+  omitDuplicateAreaPathFromPaths,
 } from './index';
 } from './index';
 
 
 describe.concurrent('isMovablePage test', () => {
 describe.concurrent('isMovablePage test', () => {
@@ -33,19 +39,34 @@ describe.concurrent('isUsersProtectedPages test', () => {
 
 
 describe.concurrent('convertToNewAffiliationPath test', () => {
 describe.concurrent('convertToNewAffiliationPath test', () => {
   test.concurrent('Child path is not converted normally', () => {
   test.concurrent('Child path is not converted normally', () => {
-    const result = convertToNewAffiliationPath('parent/', 'parent2/', 'parent/child');
+    const result = convertToNewAffiliationPath(
+      'parent/',
+      'parent2/',
+      'parent/child',
+    );
     expect(result).toBe('parent2/child');
     expect(result).toBe('parent2/child');
   });
   });
 
 
   test.concurrent('Parent path is not converted normally', () => {
   test.concurrent('Parent path is not converted normally', () => {
-    const result = convertToNewAffiliationPath('parent/', 'parent3/', 'parent/child');
+    const result = convertToNewAffiliationPath(
+      'parent/',
+      'parent3/',
+      'parent/child',
+    );
     expect(result === 'parent/child').toBe(false);
     expect(result === 'parent/child').toBe(false);
   });
   });
 
 
-  test.concurrent('Parent and Child path names are switched unexpectedly', () => {
-    const result = convertToNewAffiliationPath('parent/', 'parent4/', 'parent/child');
-    expect(result === 'child/parent4').toBe(false);
-  });
+  test.concurrent(
+    'Parent and Child path names are switched unexpectedly',
+    () => {
+      const result = convertToNewAffiliationPath(
+        'parent/',
+        'parent4/',
+        'parent/child',
+      );
+      expect(result === 'child/parent4').toBe(false);
+    },
+  );
 });
 });
 
 
 describe.concurrent('isCreatablePage test', () => {
 describe.concurrent('isCreatablePage test', () => {
@@ -99,8 +120,17 @@ describe.concurrent('isCreatablePage test', () => {
 
 
     expect(isCreatablePage('/ the / path / with / space')).toBeFalsy();
     expect(isCreatablePage('/ the / path / with / space')).toBeFalsy();
 
 
-    const forbidden = ['installer', 'register', 'login', 'logout',
-                       'admin', 'files', 'trash', 'paste', 'comments'];
+    const forbidden = [
+      'installer',
+      'register',
+      'login',
+      'logout',
+      'admin',
+      'files',
+      'trash',
+      'paste',
+      'comments',
+    ];
     for (let i = 0; i < forbidden.length; i++) {
     for (let i = 0; i < forbidden.length; i++) {
       const pn = forbidden[i];
       const pn = forbidden[i];
       expect(isCreatablePage(`/${pn}`)).toBeFalsy();
       expect(isCreatablePage(`/${pn}`)).toBeFalsy();
@@ -114,32 +144,48 @@ describe.concurrent('isCreatablePage test', () => {
       const paths = ['/A', '/B/A', '/C/B/A', '/D'];
       const paths = ['/A', '/B/A', '/C/B/A', '/D'];
       const expectedPaths = paths;
       const expectedPaths = paths;
 
 
-      expect(omitDuplicateAreaPathFromPaths(paths)).toStrictEqual(expectedPaths);
-    });
-
-    test.concurrent('Should omit when some paths are at duplicated area', () => {
-      const paths = ['/A', '/A/A', '/A/B/A', '/B', '/B/A', '/AA'];
-      const expectedPaths = ['/A', '/B', '/AA'];
-
-      expect(omitDuplicateAreaPathFromPaths(paths)).toStrictEqual(expectedPaths);
+      expect(omitDuplicateAreaPathFromPaths(paths)).toStrictEqual(
+        expectedPaths,
+      );
     });
     });
 
 
-    test.concurrent('Should omit when some long paths are at duplicated area', () => {
-      const paths = ['/A/B/C', '/A/B/C/D', '/A/B/C/D/E'];
-      const expectedPaths = ['/A/B/C'];
-
-      expect(omitDuplicateAreaPathFromPaths(paths)).toStrictEqual(expectedPaths);
-    });
-
-    test.concurrent('Should omit when some long paths are at duplicated area [case insensitivity]', () => {
-      const paths = ['/a/B/C', '/A/b/C/D', '/A/B/c/D/E'];
-      const expectedPaths = ['/a/B/C'];
-
-      expect(omitDuplicateAreaPathFromPaths(paths)).toStrictEqual(expectedPaths);
-    });
+    test.concurrent(
+      'Should omit when some paths are at duplicated area',
+      () => {
+        const paths = ['/A', '/A/A', '/A/B/A', '/B', '/B/A', '/AA'];
+        const expectedPaths = ['/A', '/B', '/AA'];
+
+        expect(omitDuplicateAreaPathFromPaths(paths)).toStrictEqual(
+          expectedPaths,
+        );
+      },
+    );
+
+    test.concurrent(
+      'Should omit when some long paths are at duplicated area',
+      () => {
+        const paths = ['/A/B/C', '/A/B/C/D', '/A/B/C/D/E'];
+        const expectedPaths = ['/A/B/C'];
+
+        expect(omitDuplicateAreaPathFromPaths(paths)).toStrictEqual(
+          expectedPaths,
+        );
+      },
+    );
+
+    test.concurrent(
+      'Should omit when some long paths are at duplicated area [case insensitivity]',
+      () => {
+        const paths = ['/a/B/C', '/A/b/C/D', '/A/B/c/D/E'];
+        const expectedPaths = ['/a/B/C'];
+
+        expect(omitDuplicateAreaPathFromPaths(paths)).toStrictEqual(
+          expectedPaths,
+        );
+      },
+    );
   });
   });
 
 
-
   describe.concurrent('Test getUsernameByPath', () => {
   describe.concurrent('Test getUsernameByPath', () => {
     test.concurrent('found', () => {
     test.concurrent('found', () => {
       const username = getUsernameByPath('/user/sotarok');
       const username = getUsernameByPath('/user/sotarok');
@@ -152,9 +198,10 @@ describe.concurrent('isCreatablePage test', () => {
     });
     });
 
 
     test.concurrent('not found', () => {
     test.concurrent('not found', () => {
-      const username = getUsernameByPath('/the/page/is/not/related/to/user/page');
+      const username = getUsernameByPath(
+        '/the/page/is/not/related/to/user/page',
+      );
       expect(username).toBeNull();
       expect(username).toBeNull();
     });
     });
   });
   });
-
 });
 });

+ 29 - 12
packages/core/src/utils/page-path-utils/index.ts

@@ -121,14 +121,16 @@ const restrictedPatternsToCreate: Array<RegExp> = [
   /^(\/.+){130,}$/, // avoid deep layer path. see: https://regex101.com/r/L0kzOD/1
   /^(\/.+){130,}$/, // avoid deep layer path. see: https://regex101.com/r/L0kzOD/1
 ];
 ];
 export const isCreatablePage = (path: string): boolean => {
 export const isCreatablePage = (path: string): boolean => {
-  return !restrictedPatternsToCreate.some(pattern => path.match(pattern));
+  return !restrictedPatternsToCreate.some((pattern) => path.match(pattern));
 };
 };
 
 
 /**
 /**
  * return user's homepage path
  * return user's homepage path
  * @param user
  * @param user
  */
  */
-export const userHomepagePath = (user: { username: string } | null | undefined): string => {
+export const userHomepagePath = (
+  user: { username: string } | null | undefined,
+): string => {
   if (user?.username == null) {
   if (user?.username == null) {
     return '';
     return '';
   }
   }
@@ -141,7 +143,11 @@ export const userHomepagePath = (user: { username: string } | null | undefined):
  * @param childPath
  * @param childPath
  * @param newPath
  * @param newPath
  */
  */
-export const convertToNewAffiliationPath = (oldPath: string, newPath: string, childPath: string): string => {
+export const convertToNewAffiliationPath = (
+  oldPath: string,
+  newPath: string,
+  childPath: string,
+): string => {
   if (newPath == null) {
   if (newPath == null) {
     throw new Error('Please input the new page path');
     throw new Error('Please input the new page path');
   }
   }
@@ -154,7 +160,7 @@ export const convertToNewAffiliationPath = (oldPath: string, newPath: string, ch
  * @param {string} path
  * @param {string} path
  * @returns {string}
  * @returns {string}
  */
  */
-export const encodeSpaces = (path?:string): string | undefined => {
+export const encodeSpaces = (path?: string): string | undefined => {
   if (path == null) {
   if (path == null) {
     return undefined;
     return undefined;
   }
   }
@@ -178,8 +184,7 @@ export const generateEditorPath = (...paths: string[]): string => {
   try {
   try {
     const url = new URL(joinedPath, 'https://dummy');
     const url = new URL(joinedPath, 'https://dummy');
     return `${url.pathname}#edit`;
     return `${url.pathname}#edit`;
-  }
-  catch (err) {
+  } catch (err) {
     throw new Error('Invalid path format');
     throw new Error('Invalid path format');
   }
   }
 };
 };
@@ -193,7 +198,9 @@ export const generateEditorPath = (...paths: string[]): string => {
 export const omitDuplicateAreaPathFromPaths = (paths: string[]): string[] => {
 export const omitDuplicateAreaPathFromPaths = (paths: string[]): string[] => {
   const uniquePaths = Array.from(new Set(paths));
   const uniquePaths = Array.from(new Set(paths));
   return uniquePaths.filter((path) => {
   return uniquePaths.filter((path) => {
-    const isDuplicate = uniquePaths.filter(p => (new RegExp(`^${p}\\/.+`, 'i')).test(path)).length > 0;
+    const isDuplicate =
+      uniquePaths.filter((p) => new RegExp(`^${p}\\/.+`, 'i').test(path))
+        .length > 0;
 
 
     return !isDuplicate;
     return !isDuplicate;
   });
   });
@@ -207,7 +214,9 @@ export const omitDuplicateAreaPathFromPaths = (paths: string[]): string[] => {
  */
  */
 export const omitDuplicateAreaPageFromPages = (pages: any[]): any[] => {
 export const omitDuplicateAreaPageFromPages = (pages: any[]): any[] => {
   return pages.filter((page) => {
   return pages.filter((page) => {
-    const isDuplicate = pages.some(p => (new RegExp(`^${p.path}\\/.+`, 'i')).test(page.path));
+    const isDuplicate = pages.some((p) =>
+      new RegExp(`^${p.path}\\/.+`, 'i').test(page.path),
+    );
 
 
     return !isDuplicate;
     return !isDuplicate;
   });
   });
@@ -220,7 +229,10 @@ export const omitDuplicateAreaPageFromPages = (pages: any[]): any[] => {
  * @param pathToBeTested string
  * @param pathToBeTested string
  * @returns boolean
  * @returns boolean
  */
  */
-export const isEitherOfPathAreaOverlap = (path1: string, path2: string): boolean => {
+export const isEitherOfPathAreaOverlap = (
+  path1: string,
+  path2: string,
+): boolean => {
   if (path1 === path2) {
   if (path1 === path2) {
     return true;
     return true;
   }
   }
@@ -245,14 +257,20 @@ export const isEitherOfPathAreaOverlap = (path1: string, path2: string): boolean
  * @param pathToBeTested string
  * @param pathToBeTested string
  * @returns boolean
  * @returns boolean
  */
  */
-export const isPathAreaOverlap = (pathToTest: string, pathToBeTested: string): boolean => {
+export const isPathAreaOverlap = (
+  pathToTest: string,
+  pathToBeTested: string,
+): boolean => {
   if (pathToTest === pathToBeTested) {
   if (pathToTest === pathToBeTested) {
     return true;
     return true;
   }
   }
 
 
   const pathWithSlash = addTrailingSlash(pathToTest);
   const pathWithSlash = addTrailingSlash(pathToTest);
 
 
-  const pathAreaToTest = new RegExp(`^${escapeStringRegexp(pathWithSlash)}`, 'i');
+  const pathAreaToTest = new RegExp(
+    `^${escapeStringRegexp(pathWithSlash)}`,
+    'i',
+  );
   if (pathAreaToTest.test(pathToBeTested)) {
   if (pathAreaToTest.test(pathToBeTested)) {
     return true;
     return true;
   }
   }
@@ -299,5 +317,4 @@ export const isGlobPatternPath = (path: string): boolean => {
   return globPattern.test(path);
   return globPattern.test(path);
 };
 };
 
 
-
 export * from './is-top-page';
 export * from './is-top-page';

+ 1 - 1
packages/core/src/utils/page-utils.ts

@@ -1,4 +1,4 @@
-import { IPage } from '..';
+import type { IPage } from '..';
 
 
 import { isTopPage } from './page-path-utils/is-top-page';
 import { isTopPage } from './page-path-utils/is-top-page';
 
 

+ 149 - 132
packages/core/src/utils/path-utils.spec.ts

@@ -1,177 +1,194 @@
 import * as pathUtils from './path-utils';
 import * as pathUtils from './path-utils';
 
 
 describe('page-utils', () => {
 describe('page-utils', () => {
-
   describe('.normalizePath', () => {
   describe('.normalizePath', () => {
     test.concurrent.each`
     test.concurrent.each`
-      path                  | expected
-      ${'/'}                | ${'/'}
-      ${''}                 | ${'/'}
-      ${'path'}             | ${'/path'}
-      ${'/path'}            | ${'/path'}
-      ${'path/'}            | ${'/path'}
-      ${'/path/'}           | ${'/path'}
-      ${'path1/path2'}      | ${'/path1/path2'}
-      ${'/path1/path2'}     | ${'/path1/path2'}
-      ${'path1/path2/'}     | ${'/path1/path2'}
-      ${'/path1/path2/'}    | ${'/path1/path2'}
-      ${'//path1/path2//'}  | ${'/path1/path2'}
-      ${'https://example.com'} | ${'/https://example.com'}
+      path                      | expected
+      ${'/'}                    | ${'/'}
+      ${''}                     | ${'/'}
+      ${'path'}                 | ${'/path'}
+      ${'/path'}                | ${'/path'}
+      ${'path/'}                | ${'/path'}
+      ${'/path/'}               | ${'/path'}
+      ${'path1/path2'}          | ${'/path1/path2'}
+      ${'/path1/path2'}         | ${'/path1/path2'}
+      ${'path1/path2/'}         | ${'/path1/path2'}
+      ${'/path1/path2/'}        | ${'/path1/path2'}
+      ${'//path1/path2//'}      | ${'/path1/path2'}
+      ${'https://example.com'}  | ${'/https://example.com'}
       ${'https://example.com/'} | ${'/https://example.com'}
       ${'https://example.com/'} | ${'/https://example.com'}
-    `('should normalize \'$path\' to \'$expected\'', ({ path, expected }) => {
+    `("should normalize '$path' to '$expected'", ({ path, expected }) => {
       expect(pathUtils.normalizePath(path)).toBe(expected);
       expect(pathUtils.normalizePath(path)).toBe(expected);
     });
     });
   });
   });
 
 
   describe('.hasHeadingSlash', () => {
   describe('.hasHeadingSlash', () => {
     test.concurrent.each`
     test.concurrent.each`
-      path                  | expected
-      ${'/'}                | ${true}
-      ${''}                 | ${false}
-      ${'path'}             | ${false}
-      ${'/path'}            | ${true}
-      ${'path/'}            | ${false}
-      ${'/path/'}           | ${true}
-      ${'path1/path2'}      | ${false}
-      ${'/path1/path2'}     | ${true}
-      ${'path1/path2/'}     | ${false}
-      ${'/path1/path2/'}    | ${true}
-      ${'//path1/path2//'}  | ${true}
-      ${'https://example.com'} | ${false}
+      path                      | expected
+      ${'/'}                    | ${true}
+      ${''}                     | ${false}
+      ${'path'}                 | ${false}
+      ${'/path'}                | ${true}
+      ${'path/'}                | ${false}
+      ${'/path/'}               | ${true}
+      ${'path1/path2'}          | ${false}
+      ${'/path1/path2'}         | ${true}
+      ${'path1/path2/'}         | ${false}
+      ${'/path1/path2/'}        | ${true}
+      ${'//path1/path2//'}      | ${true}
+      ${'https://example.com'}  | ${false}
       ${'https://example.com/'} | ${false}
       ${'https://example.com/'} | ${false}
-    `('should return $expected when checking heading slash for \'$path\'', ({ path, expected }) => {
-      expect(pathUtils.hasHeadingSlash(path)).toBe(expected);
-    });
+    `(
+      "should return $expected when checking heading slash for '$path'",
+      ({ path, expected }) => {
+        expect(pathUtils.hasHeadingSlash(path)).toBe(expected);
+      },
+    );
   });
   });
 
 
   describe('.hasTrailingSlash', () => {
   describe('.hasTrailingSlash', () => {
     test.concurrent.each`
     test.concurrent.each`
-      path                  | expected
-      ${'/'}                | ${true}
-      ${''}                 | ${false}
-      ${'path'}             | ${false}
-      ${'/path'}            | ${false}
-      ${'path/'}            | ${true}
-      ${'/path/'}           | ${true}
-      ${'path1/path2'}      | ${false}
-      ${'/path1/path2'}     | ${false}
-      ${'path1/path2/'}     | ${true}
-      ${'/path1/path2/'}    | ${true}
-      ${'//path1/path2//'}  | ${true}
-      ${'https://example.com'} | ${false}
+      path                      | expected
+      ${'/'}                    | ${true}
+      ${''}                     | ${false}
+      ${'path'}                 | ${false}
+      ${'/path'}                | ${false}
+      ${'path/'}                | ${true}
+      ${'/path/'}               | ${true}
+      ${'path1/path2'}          | ${false}
+      ${'/path1/path2'}         | ${false}
+      ${'path1/path2/'}         | ${true}
+      ${'/path1/path2/'}        | ${true}
+      ${'//path1/path2//'}      | ${true}
+      ${'https://example.com'}  | ${false}
       ${'https://example.com/'} | ${true}
       ${'https://example.com/'} | ${true}
-    `('should return $expected when checking trailing slash for \'$path\'', ({ path, expected }) => {
-      expect(pathUtils.hasTrailingSlash(path)).toBe(expected);
-    });
+    `(
+      "should return $expected when checking trailing slash for '$path'",
+      ({ path, expected }) => {
+        expect(pathUtils.hasTrailingSlash(path)).toBe(expected);
+      },
+    );
   });
   });
 
 
   describe('.addHeadingSlash', () => {
   describe('.addHeadingSlash', () => {
     test.concurrent.each`
     test.concurrent.each`
-      path                  | expected
-      ${'/'}                | ${'/'}
-      ${''}                 | ${'/'}
-      ${'path'}             | ${'/path'}
-      ${'/path'}            | ${'/path'}
-      ${'path/'}            | ${'/path/'}
-      ${'/path/'}           | ${'/path/'}
-      ${'path1/path2'}      | ${'/path1/path2'}
-      ${'/path1/path2'}     | ${'/path1/path2'}
-      ${'path1/path2/'}     | ${'/path1/path2/'}
-      ${'/path1/path2/'}    | ${'/path1/path2/'}
-      ${'//path1/path2//'}  | ${'//path1/path2//'}
-      ${'https://example.com'} | ${'/https://example.com'}
+      path                      | expected
+      ${'/'}                    | ${'/'}
+      ${''}                     | ${'/'}
+      ${'path'}                 | ${'/path'}
+      ${'/path'}                | ${'/path'}
+      ${'path/'}                | ${'/path/'}
+      ${'/path/'}               | ${'/path/'}
+      ${'path1/path2'}          | ${'/path1/path2'}
+      ${'/path1/path2'}         | ${'/path1/path2'}
+      ${'path1/path2/'}         | ${'/path1/path2/'}
+      ${'/path1/path2/'}        | ${'/path1/path2/'}
+      ${'//path1/path2//'}      | ${'//path1/path2//'}
+      ${'https://example.com'}  | ${'/https://example.com'}
       ${'https://example.com/'} | ${'/https://example.com/'}
       ${'https://example.com/'} | ${'/https://example.com/'}
-    `('should add heading slash to \'$path\' resulting in \'$expected\'', ({ path, expected }) => {
-      expect(pathUtils.addHeadingSlash(path)).toBe(expected);
-    });
+    `(
+      "should add heading slash to '$path' resulting in '$expected'",
+      ({ path, expected }) => {
+        expect(pathUtils.addHeadingSlash(path)).toBe(expected);
+      },
+    );
   });
   });
 
 
   describe('.addTrailingSlash', () => {
   describe('.addTrailingSlash', () => {
     test.concurrent.each`
     test.concurrent.each`
-      path                  | expected
-      ${'/'}                | ${'/'}
-      ${''}                 | ${'/'}
-      ${'path'}             | ${'path/'}
-      ${'/path'}            | ${'/path/'}
-      ${'path/'}            | ${'path/'}
-      ${'/path/'}           | ${'/path/'}
-      ${'path1/path2'}      | ${'path1/path2/'}
-      ${'/path1/path2'}     | ${'/path1/path2/'}
-      ${'path1/path2/'}     | ${'path1/path2/'}
-      ${'/path1/path2/'}    | ${'/path1/path2/'}
-      ${'//path1/path2//'}  | ${'//path1/path2//'}
-      ${'https://example.com'} | ${'https://example.com/'}
+      path                      | expected
+      ${'/'}                    | ${'/'}
+      ${''}                     | ${'/'}
+      ${'path'}                 | ${'path/'}
+      ${'/path'}                | ${'/path/'}
+      ${'path/'}                | ${'path/'}
+      ${'/path/'}               | ${'/path/'}
+      ${'path1/path2'}          | ${'path1/path2/'}
+      ${'/path1/path2'}         | ${'/path1/path2/'}
+      ${'path1/path2/'}         | ${'path1/path2/'}
+      ${'/path1/path2/'}        | ${'/path1/path2/'}
+      ${'//path1/path2//'}      | ${'//path1/path2//'}
+      ${'https://example.com'}  | ${'https://example.com/'}
       ${'https://example.com/'} | ${'https://example.com/'}
       ${'https://example.com/'} | ${'https://example.com/'}
-    `('should add trailing slash to \'$path\' resulting in \'$expected\'', ({ path, expected }) => {
-      expect(pathUtils.addTrailingSlash(path)).toBe(expected);
-    });
+    `(
+      "should add trailing slash to '$path' resulting in '$expected'",
+      ({ path, expected }) => {
+        expect(pathUtils.addTrailingSlash(path)).toBe(expected);
+      },
+    );
   });
   });
 
 
   describe('.removeHeadingSlash', () => {
   describe('.removeHeadingSlash', () => {
     test.concurrent.each`
     test.concurrent.each`
-      path                  | expected
-      ${'/'}                | ${'/'}
-      ${''}                 | ${''}
-      ${'path'}             | ${'path'}
-      ${'/path'}            | ${'path'}
-      ${'path/'}            | ${'path/'}
-      ${'/path/'}           | ${'path/'}
-      ${'path1/path2'}      | ${'path1/path2'}
-      ${'/path1/path2'}     | ${'path1/path2'}
-      ${'path1/path2/'}     | ${'path1/path2/'}
-      ${'/path1/path2/'}    | ${'path1/path2/'}
-      ${'//path1/path2//'}  | ${'path1/path2//'}
-      ${'https://example.com'} | ${'https://example.com'}
+      path                      | expected
+      ${'/'}                    | ${'/'}
+      ${''}                     | ${''}
+      ${'path'}                 | ${'path'}
+      ${'/path'}                | ${'path'}
+      ${'path/'}                | ${'path/'}
+      ${'/path/'}               | ${'path/'}
+      ${'path1/path2'}          | ${'path1/path2'}
+      ${'/path1/path2'}         | ${'path1/path2'}
+      ${'path1/path2/'}         | ${'path1/path2/'}
+      ${'/path1/path2/'}        | ${'path1/path2/'}
+      ${'//path1/path2//'}      | ${'path1/path2//'}
+      ${'https://example.com'}  | ${'https://example.com'}
       ${'https://example.com/'} | ${'https://example.com/'}
       ${'https://example.com/'} | ${'https://example.com/'}
-      ${'//'}               | ${'/'}                  // from former specific test
-    `('should remove heading slash from \'$path\' resulting in \'$expected\'', ({ path, expected }) => {
-      expect(pathUtils.removeHeadingSlash(path)).toBe(expected);
-    });
+      ${'//'}                   | ${'/'}
+    `(
+      "should remove heading slash from '$path' resulting in '$expected'",
+      ({ path, expected }) => {
+        expect(pathUtils.removeHeadingSlash(path)).toBe(expected);
+      },
+    );
   });
   });
 
 
   describe('.removeTrailingSlash', () => {
   describe('.removeTrailingSlash', () => {
     test.concurrent.each`
     test.concurrent.each`
-      path                  | expected
-      ${'/'}                | ${'/'}
-      ${''}                 | ${''}
-      ${'path'}             | ${'path'}
-      ${'/path'}            | ${'/path'}
-      ${'path/'}            | ${'path'}
-      ${'/path/'}           | ${'/path'}
-      ${'path1/path2'}      | ${'path1/path2'}
-      ${'/path1/path2'}     | ${'/path1/path2'}
-      ${'path1/path2/'}     | ${'path1/path2'}
-      ${'/path1/path2/'}    | ${'/path1/path2'}
-      ${'//path1/path2//'}  | ${'//path1/path2'}
-      ${'https://example.com'} | ${'https://example.com'}
+      path                      | expected
+      ${'/'}                    | ${'/'}
+      ${''}                     | ${''}
+      ${'path'}                 | ${'path'}
+      ${'/path'}                | ${'/path'}
+      ${'path/'}                | ${'path'}
+      ${'/path/'}               | ${'/path'}
+      ${'path1/path2'}          | ${'path1/path2'}
+      ${'/path1/path2'}         | ${'/path1/path2'}
+      ${'path1/path2/'}         | ${'path1/path2'}
+      ${'/path1/path2/'}        | ${'/path1/path2'}
+      ${'//path1/path2//'}      | ${'//path1/path2'}
+      ${'https://example.com'}  | ${'https://example.com'}
       ${'https://example.com/'} | ${'https://example.com'}
       ${'https://example.com/'} | ${'https://example.com'}
-    `('should remove trailing slash from \'$path\' resulting in \'$expected\'', ({ path, expected }) => {
-      expect(pathUtils.removeTrailingSlash(path)).toBe(expected);
-    });
+    `(
+      "should remove trailing slash from '$path' resulting in '$expected'",
+      ({ path, expected }) => {
+        expect(pathUtils.removeTrailingSlash(path)).toBe(expected);
+      },
+    );
   });
   });
 
 
   describe('.getParentPath', () => {
   describe('.getParentPath', () => {
     test.concurrent.each`
     test.concurrent.each`
-      path                  | expected
-      ${'/'}                | ${'/'}
-      ${''}                 | ${'/'}
-      ${'path'}             | ${'/'}
-      ${'/path'}            | ${'/'}
-      ${'path/'}            | ${'/path'}
-      ${'/path/'}           | ${'/path'}
-      ${'path1/path2'}      | ${'/path1'}
-      ${'/path1/path2'}     | ${'/path1'}
-      ${'path1/path2/'}     | ${'/path1/path2'}
-      ${'/path1/path2/'}    | ${'/path1/path2'}
-      ${'//path1/path2//'}  | ${'/path1/path2'}
-      ${'https://example.com'} | ${'/https:'}
+      path                      | expected
+      ${'/'}                    | ${'/'}
+      ${''}                     | ${'/'}
+      ${'path'}                 | ${'/'}
+      ${'/path'}                | ${'/'}
+      ${'path/'}                | ${'/path'}
+      ${'/path/'}               | ${'/path'}
+      ${'path1/path2'}          | ${'/path1'}
+      ${'/path1/path2'}         | ${'/path1'}
+      ${'path1/path2/'}         | ${'/path1/path2'}
+      ${'/path1/path2/'}        | ${'/path1/path2'}
+      ${'//path1/path2//'}      | ${'/path1/path2'}
+      ${'https://example.com'}  | ${'/https:'}
       ${'https://example.com/'} | ${'/https://example.com'}
       ${'https://example.com/'} | ${'/https://example.com'}
-      ${'/page'}            | ${'/'}                  // from former specific test
-      // Note: getParentPath('page') is covered by 'path' -> '/'
-      // Note: getParentPath('/path1/path2') is covered by '/path1/path2' -> '/path1'
-      // Note: getParentPath('/path1/path2/') is covered by '/path1/path2/' -> '/path1/path2'
-    `('should get parent path of \'$path\' as \'$expected\'', ({ path, expected }) => {
-      expect(pathUtils.getParentPath(path)).toBe(expected);
-    });
+      ${'/page'}                | ${'/'}
+    `(
+      "should get parent path of '$path' as '$expected'",
+      ({ path, expected }) => {
+        expect(pathUtils.getParentPath(path)).toBe(expected);
+      },
+    );
   });
   });
 });
 });

+ 0 - 1
packages/core/src/utils/path-utils.ts

@@ -122,7 +122,6 @@ export function normalizePath(path: string): string {
   return `/${parts.content}`;
   return `/${parts.content}`;
 }
 }
 
 
-
 export function attachTitleHeader(path: string): string {
 export function attachTitleHeader(path: string): string {
   return `# ${path}`;
   return `# ${path}`;
 }
 }