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.

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