You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.6 KiB

  1. const qs = require('querystring')
  2. const _ = require('lodash')
  3. const crypto = require('crypto')
  4. const path = require('path')
  5. const localeSegmentRegex = /^[A-Z]{2}(-[A-Z]{2})?$/i
  6. const localeFolderRegex = /^([a-z]{2}(?:-[a-z]{2})?\/)?(.*)/i
  7. const contentToExt = {
  8. markdown: 'md',
  9. html: 'html'
  10. }
  11. const extToContent = _.invert(contentToExt)
  12. /* global WIKI */
  13. module.exports = {
  14. /**
  15. * Parse raw url path and make it safe
  16. */
  17. parsePath (rawPath, opts = {}) {
  18. let pathObj = {
  19. locale: WIKI.config.lang.code,
  20. path: 'home',
  21. private: false,
  22. privateNS: '',
  23. explicitLocale: false
  24. }
  25. // Clean Path
  26. rawPath = _.trim(qs.unescape(rawPath))
  27. if (_.startsWith(rawPath, '/')) { rawPath = rawPath.substring(1) }
  28. if (rawPath === '') { rawPath = 'home' }
  29. // Extract Info
  30. let pathParts = _.filter(_.split(rawPath, '/'), p => !_.isEmpty(p))
  31. if (pathParts[0].length === 1) {
  32. pathParts.shift()
  33. }
  34. if (localeSegmentRegex.test(pathParts[0])) {
  35. pathObj.locale = pathParts[0]
  36. pathObj.explicitLocale = true
  37. pathParts.shift()
  38. }
  39. // Strip extension
  40. if (opts.stripExt && pathParts.length > 0) {
  41. const lastPart = _.last(pathParts)
  42. if (lastPart.indexOf('.') > 0) {
  43. pathParts.pop()
  44. const lastPartMeta = path.parse(lastPart)
  45. pathParts.push(lastPartMeta.name)
  46. }
  47. }
  48. pathObj.path = _.join(pathParts, '/')
  49. return pathObj
  50. },
  51. /**
  52. * Generate unique hash from page
  53. */
  54. generateHash(opts) {
  55. return crypto.createHash('sha1').update(`${opts.locale}|${opts.path}|${opts.privateNS}`).digest('hex')
  56. },
  57. /**
  58. * Inject Page Metadata
  59. */
  60. injectPageMetadata(page) {
  61. let meta = [
  62. ['title', page.title],
  63. ['description', page.description],
  64. ['published', page.isPublished.toString()],
  65. ['date', page.updatedAt],
  66. ['tags', page.tags ? page.tags.map(t => t.tag).join(', ') : ''],
  67. ['editor', page.editorKey],
  68. ['dateCreated', page.createdAt],
  69. ]
  70. switch (page.contentType) {
  71. case 'markdown':
  72. return '---\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n---\n\n' + page.content
  73. case 'html':
  74. return '<!--\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n-->\n\n' + page.content
  75. case 'json':
  76. return {
  77. ...page.content,
  78. _meta: _.fromPairs(meta)
  79. }
  80. default:
  81. return page.content
  82. }
  83. },
  84. /**
  85. * Check if path is a reserved path
  86. */
  87. isReservedPath(rawPath) {
  88. const firstSection = _.head(rawPath.split('/'))
  89. if (firstSection.length <= 1) {
  90. return true
  91. } else if (localeSegmentRegex.test(firstSection)) {
  92. return true
  93. } else if (
  94. _.some(WIKI.data.reservedPaths, p => {
  95. return p === firstSection
  96. })) {
  97. return true
  98. } else {
  99. return false
  100. }
  101. },
  102. /**
  103. * Get file extension from content type
  104. */
  105. getFileExtension(contentType) {
  106. return _.get(contentToExt, contentType, 'txt')
  107. },
  108. /**
  109. * Get content type from file extension
  110. */
  111. getContentType (filePath) {
  112. const ext = _.last(filePath.split('.'))
  113. return _.get(extToContent, ext, false)
  114. },
  115. /**
  116. * Get Page Meta object from disk path
  117. */
  118. getPagePath (filePath) {
  119. let fpath = filePath
  120. if (process.platform === 'win32') {
  121. fpath = filePath.replace(/\\/g, '/')
  122. }
  123. let meta = {
  124. locale: WIKI.config.lang.code,
  125. path: _.initial(fpath.split('.')).join('')
  126. }
  127. const result = localeFolderRegex.exec(meta.path)
  128. if (result[1]) {
  129. meta = {
  130. locale: result[1].replace('/', ''),
  131. path: result[2]
  132. }
  133. }
  134. return meta
  135. }
  136. }