path.ts 3.2 KB

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