{"version":3,"file":"index.cjs","sources":["../../../src/utils/page-path-utils/index.ts"],"sourcesContent":["import { isValidObjectId } from '../objectid-utils';\nimport { addTrailingSlash } from '../path-utils';\nimport { isTopPage as _isTopPage } from './is-top-page';\n\nexport const isTopPage = _isTopPage;\n\nexport * from './generate-children-regexp';\n\n/**\n * Whether path is the top page of users\n * @param path\n */\nexport const isUsersTopPage = (path: string): boolean => {\n  return path === '/user';\n};\n\n/**\n * Whether the path is permalink\n * @param path\n */\nexport const isPermalink = (path: string): boolean => {\n  const pageIdStr = path.substring(1);\n  return isValidObjectId(pageIdStr);\n};\n\n/**\n * Whether path is user's homepage\n * @param path\n */\nexport const isUsersHomepage = (path: string): boolean => {\n  // https://regex101.com/r/utVQct/1\n  if (path.match(/^\\/user\\/[^/]+$/)) {\n    return true;\n  }\n  return false;\n};\n\n/**\n * Whether path is the protected pages for systems\n * @param path\n */\nexport const isUsersProtectedPages = (path: string): boolean => {\n  return isUsersTopPage(path) || isUsersHomepage(path);\n};\n\n/**\n * Whether path is movable\n * @param path\n */\nexport const isMovablePage = (path: string): boolean => {\n  return !isTopPage(path) && !isUsersProtectedPages(path);\n};\n\n/**\n * Whether path belongs to the user page\n * @param path\n */\nexport const isUserPage = (path: string): boolean => {\n  // https://regex101.com/r/MwifLR/1\n  if (path.match(/^\\/user\\/.*?$/)) {\n    return true;\n  }\n\n  return false;\n};\n\n/**\n * Whether path is the top page of users\n * @param path\n */\nexport const isTrashTopPage = (path: string): boolean => {\n  return path === '/trash';\n};\n\n/**\n * Whether path belongs to the trash page\n * @param path\n */\nexport const isTrashPage = (path: string): boolean => {\n  // https://regex101.com/r/BSDdRr/1\n  if (path.match(/^\\/trash(\\/.*)?$/)) {\n    return true;\n  }\n\n  return false;\n};\n\n/**\n * Whether path belongs to the shared page\n * @param path\n */\nexport const isSharedPage = (path: string): boolean => {\n  // https://regex101.com/r/ZjdOiB/1\n  if (path.match(/^\\/share(\\/.*)?$/)) {\n    return true;\n  }\n\n  return false;\n};\n\nconst restrictedPatternsToCreate: Array<RegExp> = [\n  /\\^|\\$|\\*|\\+|#|<|>|%|\\?/,\n  /^\\/-\\/.*/,\n  /^\\/_r\\/.*/,\n  /^\\/_apix?(\\/.*)?/,\n  /^\\/?https?:\\/\\/.+$/, // avoid miss in renaming\n  /\\/{2,}/, // avoid miss in renaming\n  /\\s+\\/\\s+/, // avoid miss in renaming\n  /.+\\/edit$/,\n  /.+\\.md$/,\n  /^(\\.\\.)$/, // see: https://github.com/growilabs/growi/issues/3582\n  /(\\/\\.\\.)\\/?/, // see: https://github.com/growilabs/growi/issues/3582\n  /\\\\/, // see: https://github.com/growilabs/growi/issues/7241\n  /^\\/(_search|_private-legacy-pages|_news)(\\/.*|$)/,\n  /^\\/(installer|register|login|logout|admin|me|files|trash|paste|comments|tags|share|attachment)(\\/.*|$)/,\n  /^\\/user(?:\\/[^/]+)?$/, // https://regex101.com/r/9Eh2S1/1\n  /^(\\/.+){130,}$/, // avoid deep layer path. see: https://regex101.com/r/L0kzOD/1\n];\nexport const isCreatablePage = (path: string): boolean => {\n  return !restrictedPatternsToCreate.some((pattern) => path.match(pattern));\n};\n\n/**\n * return user's homepage path\n * @param user\n */\nexport const userHomepagePath = (\n  user: { username: string } | null | undefined,\n): string => {\n  if (user?.username == null) {\n    return '';\n  }\n  return `/user/${user.username}`;\n};\n\n/**\n * return user path\n * @param parentPath\n * @param childPath\n * @param newPath\n */\nexport const convertToNewAffiliationPath = (\n  oldPath: string,\n  newPath: string,\n  childPath: string,\n): string => {\n  if (newPath == null) {\n    throw new Error('Please input the new page path');\n  }\n  const pathRegExp = new RegExp(`^${RegExp.escape(oldPath)}`, 'i');\n  return childPath.replace(pathRegExp, newPath);\n};\n\n/**\n * Encode SPACE and IDEOGRAPHIC SPACE\n * @param {string} path\n * @returns {string}\n */\nexport const encodeSpaces = (path?: string): string | undefined => {\n  if (path == null) {\n    return undefined;\n  }\n\n  // Encode SPACE and IDEOGRAPHIC SPACE\n  return path.replace(/ /g, '%20').replace(/\\u3000/g, '%E3%80%80');\n};\n\n/**\n * Generate editor path\n * @param {string} paths\n * @returns {string}\n */\nexport const generateEditorPath = (...paths: string[]): string => {\n  const joinedPath = [...paths].join('/');\n\n  if (!isCreatablePage(joinedPath)) {\n    throw new Error('Invalid characters on path');\n  }\n\n  try {\n    const url = new URL(joinedPath, 'https://dummy');\n    return `${url.pathname}#edit`;\n  } catch {\n    throw new Error('Invalid path format');\n  }\n};\n\n/**\n * return paths without duplicate area of regexp /^${path}\\/.+/i\n * ex. expect(omitDuplicateAreaPathFromPaths(['/A', '/A/B', '/A/B/C'])).toStrictEqual(['/A'])\n * @param paths paths to be tested\n * @returns omitted paths\n */\nexport const omitDuplicateAreaPathFromPaths = (paths: string[]): string[] => {\n  const uniquePaths = Array.from(new Set(paths));\n  return uniquePaths.filter((path) => {\n    const isDuplicate =\n      uniquePaths.filter((p) => new RegExp(`^${p}\\\\/.+`, 'i').test(path))\n        .length > 0;\n\n    return !isDuplicate;\n  });\n};\n\n/**\n * return pages with path without duplicate area of regexp /^${path}\\/.+/i\n * if the pages' path are the same, it will NOT omit any of them since the other attributes will not be the same\n * @param paths paths to be tested\n * @returns omitted paths\n */\n// biome-ignore lint/suspicious/noExplicitAny: ignore\nexport const omitDuplicateAreaPageFromPages = (pages: any[]): any[] => {\n  return pages.filter((page) => {\n    const isDuplicate = pages.some((p) =>\n      new RegExp(`^${p.path}\\\\/.+`, 'i').test(page.path),\n    );\n\n    return !isDuplicate;\n  });\n};\n\n/**\n * Check if the area of either path1 or path2 includes the area of the other path\n * The area of path is the same as /^\\/hoge\\//i\n * @param pathToTest string\n * @param pathToBeTested string\n * @returns boolean\n */\nexport const isEitherOfPathAreaOverlap = (\n  path1: string,\n  path2: string,\n): boolean => {\n  if (path1 === path2) {\n    return true;\n  }\n\n  const path1WithSlash = addTrailingSlash(path1);\n  const path2WithSlash = addTrailingSlash(path2);\n\n  const path1Area = new RegExp(`^${RegExp.escape(path1WithSlash)}`, 'i');\n  const path2Area = new RegExp(`^${RegExp.escape(path2WithSlash)}`, 'i');\n\n  if (path1Area.test(path2) || path2Area.test(path1)) {\n    return true;\n  }\n\n  return false;\n};\n\n/**\n * Check if the area of pathToTest includes the area of pathToBeTested\n * The area of path is the same as /^\\/hoge\\//i\n * @param pathToTest string\n * @param pathToBeTested string\n * @returns boolean\n */\nexport const isPathAreaOverlap = (\n  pathToTest: string,\n  pathToBeTested: string,\n): boolean => {\n  if (pathToTest === pathToBeTested) {\n    return true;\n  }\n\n  const pathWithSlash = addTrailingSlash(pathToTest);\n\n  const pathAreaToTest = new RegExp(`^${RegExp.escape(pathWithSlash)}`, 'i');\n  if (pathAreaToTest.test(pathToBeTested)) {\n    return true;\n  }\n\n  return false;\n};\n\n/**\n * Determine whether can move by fromPath and toPath\n * @param fromPath string\n * @param toPath string\n * @returns boolean\n */\nexport const canMoveByPath = (fromPath: string, toPath: string): boolean => {\n  return !isPathAreaOverlap(fromPath, toPath);\n};\n\n/**\n * check if string has '/' in it\n */\nexport const hasSlash = (str: string): boolean => {\n  return str.includes('/');\n};\n\n/**\n * Get username from user page path\n * @param path string\n * @returns string | null\n */\nexport const getUsernameByPath = (path: string): string | null => {\n  let username: string | null = null;\n  // https://regex101.com/r/qj4SfD/1\n  const match = path.match(/^\\/user\\/([^/]+)\\/?/);\n  if (match) {\n    username = match[1];\n  }\n\n  return username;\n};\n\nexport const isGlobPatternPath = (path: string): boolean => {\n  // https://regex101.com/r/IBy7HS/1\n  const globPattern = /^(?:\\/[^/*?[\\]{}]+)*\\/\\*$/;\n  return globPattern.test(path);\n};\n\nexport * from './is-top-page';\n"],"names":["isTopPage","_isTopPage","isUsersTopPage","path","isPermalink","pageIdStr","isValidObjectId","isUsersHomepage","isUsersProtectedPages","isMovablePage","isUserPage","isTrashTopPage","isTrashPage","isSharedPage","restrictedPatternsToCreate","isCreatablePage","pattern","userHomepagePath","user","convertToNewAffiliationPath","oldPath","newPath","childPath","pathRegExp","encodeSpaces","generateEditorPath","paths","joinedPath","omitDuplicateAreaPathFromPaths","uniquePaths","p","omitDuplicateAreaPageFromPages","pages","page","isEitherOfPathAreaOverlap","path1","path2","path1WithSlash","addTrailingSlash","path2WithSlash","path1Area","path2Area","isPathAreaOverlap","pathToTest","pathToBeTested","pathWithSlash","canMoveByPath","fromPath","toPath","hasSlash","str","getUsernameByPath","username","match","isGlobPatternPath"],"mappings":"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"}