path.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import { Folder } from '../../../../../types/folder'
  2. import { FileTreeEntity } from '../../../../../types/file-tree-entity'
  3. import { Doc } from '../../../../../types/doc'
  4. import { FileRef } from '../../../../../types/file-ref'
  5. import { PreviewPath } from '../../../../../types/preview-path'
  6. import { fileUrl } from '../../utils/fileUrl'
  7. type DocFindResult = {
  8. entity: Doc
  9. type: 'doc'
  10. }
  11. type FolderFindResult = {
  12. entity: Folder
  13. type: 'folder'
  14. }
  15. type FileRefFindResult = {
  16. entity: FileRef
  17. type: 'fileRef'
  18. }
  19. export type FindResult = DocFindResult | FolderFindResult | FileRefFindResult
  20. // Finds the entity with a given ID in the tree represented by `folder` and
  21. // returns a path to that entity, represented by an array of folders starting at
  22. // the root plus the entity itself
  23. function pathComponentsInFolder(
  24. folder: Folder,
  25. id: string,
  26. ancestors: FileTreeEntity[] = []
  27. ): FileTreeEntity[] | null {
  28. const docOrFileRef =
  29. folder.docs.find(doc => doc._id === id) ||
  30. folder.fileRefs.find(fileRef => fileRef._id === id)
  31. if (docOrFileRef) {
  32. return ancestors.concat([docOrFileRef])
  33. }
  34. for (const subfolder of folder.folders) {
  35. if (subfolder._id === id) {
  36. return ancestors.concat([subfolder])
  37. } else {
  38. const path = pathComponentsInFolder(
  39. subfolder,
  40. id,
  41. ancestors.concat([subfolder])
  42. )
  43. if (path !== null) {
  44. return path
  45. }
  46. }
  47. }
  48. return null
  49. }
  50. // Finds the entity with a given ID in the tree represented by `folder` and
  51. // returns a path to that entity as a string
  52. export function pathInFolder(folder: Folder, id: string): string | null {
  53. return (
  54. pathComponentsInFolder(folder, id)
  55. ?.map(entity => entity.name)
  56. .join('/') || null
  57. )
  58. }
  59. export function findEntityByPath(
  60. folder: Folder,
  61. path: string
  62. ): FindResult | null {
  63. if (path === '') {
  64. return { entity: folder, type: 'folder' }
  65. }
  66. const parts = path.split('/')
  67. const name = parts.shift()
  68. const rest = parts.join('/')
  69. if (name === '.') {
  70. return findEntityByPath(folder, rest)
  71. }
  72. const doc = folder.docs.find(doc => doc.name === name)
  73. if (doc) {
  74. return { entity: doc, type: 'doc' }
  75. }
  76. const fileRef = folder.fileRefs.find(fileRef => fileRef.name === name)
  77. if (fileRef) {
  78. return { entity: fileRef, type: 'fileRef' }
  79. }
  80. for (const subfolder of folder.folders) {
  81. if (subfolder.name === name) {
  82. if (rest === '') {
  83. return { entity: subfolder, type: 'folder' }
  84. } else {
  85. return findEntityByPath(subfolder, rest)
  86. }
  87. }
  88. }
  89. return null
  90. }
  91. export function previewByPath(
  92. folder: Folder,
  93. projectId: string,
  94. path: string
  95. ): PreviewPath | null {
  96. for (const suffix of [
  97. '',
  98. '.png',
  99. '.jpg',
  100. '.jpeg',
  101. '.pdf',
  102. '.PNG',
  103. '.JPG',
  104. '.JPEG',
  105. '.PDF',
  106. ]) {
  107. const result = findEntityByPath(folder, path + suffix)
  108. if (result?.type === 'fileRef') {
  109. const { name, _id: id, hash } = result.entity
  110. return {
  111. url: fileUrl(projectId, id, hash),
  112. extension: name.slice(name.lastIndexOf('.') + 1),
  113. }
  114. }
  115. }
  116. return null
  117. }
  118. export function dirname(fileTreeData: Folder, id: string) {
  119. const path = pathInFolder(fileTreeData, id)
  120. return path?.split('/').slice(0, -1).join('/') || null
  121. }