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.

143 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. ]
  69. switch (page.contentType) {
  70. case 'markdown':
  71. return '---\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n---\n\n' + page.content
  72. case 'html':
  73. return '<!--\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n-->\n\n' + page.content
  74. case 'json':
  75. return {
  76. ...page.content,
  77. _meta: _.fromPairs(meta)
  78. }
  79. default:
  80. return page.content
  81. }
  82. },
  83. /**
  84. * Check if path is a reserved path
  85. */
  86. isReservedPath(rawPath) {
  87. const firstSection = _.head(rawPath.split('/'))
  88. if (firstSection.length <= 1) {
  89. return true
  90. } else if (localeSegmentRegex.test(firstSection)) {
  91. return true
  92. } else if (
  93. _.some(WIKI.data.reservedPaths, p => {
  94. return p === firstSection
  95. })) {
  96. return true
  97. } else {
  98. return false
  99. }
  100. },
  101. /**
  102. * Get file extension from content type
  103. */
  104. getFileExtension(contentType) {
  105. return _.get(contentToExt, contentType, 'txt')
  106. },
  107. /**
  108. * Get content type from file extension
  109. */
  110. getContentType (filePath) {
  111. const ext = _.last(filePath.split('.'))
  112. return _.get(extToContent, ext, false)
  113. },
  114. /**
  115. * Get Page Meta object from disk path
  116. */
  117. getPagePath (filePath) {
  118. let fpath = filePath
  119. if (process.platform === 'win32') {
  120. fpath = filePath.replace(/\\/g, '/')
  121. }
  122. let meta = {
  123. locale: WIKI.config.lang.code,
  124. path: _.initial(fpath.split('.')).join('')
  125. }
  126. const result = localeFolderRegex.exec(meta.path)
  127. if (result[1]) {
  128. meta = {
  129. locale: result[1].replace('/', ''),
  130. path: result[2]
  131. }
  132. }
  133. return meta
  134. }
  135. }