router.coffee 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. class app.Router
  2. $.extend @prototype, Events
  3. @routes: [
  4. ['*', 'before' ]
  5. ['/', 'root' ]
  6. ['/offline', 'offline' ]
  7. ['/about', 'about' ]
  8. ['/news', 'news' ]
  9. ['/help', 'help' ]
  10. ['/:doc-:type/', 'type' ]
  11. ['/:doc/', 'doc' ]
  12. ['/:doc/:path(*)', 'entry' ]
  13. ['*', 'notFound']
  14. ]
  15. constructor: ->
  16. for [path, method] in @constructor.routes
  17. page path, @[method].bind(@)
  18. @setInitialPath()
  19. start: ->
  20. page.start()
  21. return
  22. show: (path) ->
  23. page.show(path)
  24. return
  25. triggerRoute: (name) ->
  26. @trigger name, @context
  27. @trigger 'after', name, @context
  28. return
  29. before: (context, next) ->
  30. @context = context
  31. @trigger 'before', context
  32. next()
  33. return
  34. doc: (context, next) ->
  35. if doc = app.docs.findBy('slug', context.params.doc) or app.disabledDocs.findBy('slug', context.params.doc)
  36. context.doc = doc
  37. context.entry = doc.toEntry()
  38. @triggerRoute 'entry'
  39. else
  40. next()
  41. return
  42. type: (context, next) ->
  43. doc = app.docs.findBy 'slug', context.params.doc
  44. if type = doc?.types.findBy 'slug', context.params.type
  45. context.doc = doc
  46. context.type = type
  47. @triggerRoute 'type'
  48. else
  49. next()
  50. return
  51. entry: (context, next) ->
  52. doc = app.docs.findBy 'slug', context.params.doc
  53. if entry = doc?.findEntryByPathAndHash(context.params.path, context.hash)
  54. context.doc = doc
  55. context.entry = entry
  56. @triggerRoute 'entry'
  57. else
  58. next()
  59. return
  60. root: ->
  61. if app.isSingleDoc()
  62. setTimeout (-> window.location = '/'), 0
  63. else
  64. @triggerRoute 'root'
  65. return
  66. offline: ->
  67. @triggerRoute 'offline'
  68. return
  69. about: (context) ->
  70. context.page = 'about'
  71. @triggerRoute 'page'
  72. return
  73. news: (context) ->
  74. context.page = 'news'
  75. @triggerRoute 'page'
  76. return
  77. help: (context) ->
  78. context.page = 'help'
  79. @triggerRoute 'page'
  80. return
  81. notFound: (context) ->
  82. @triggerRoute 'notFound'
  83. return
  84. isRoot: ->
  85. location.pathname is '/'
  86. setInitialPath: ->
  87. # Remove superfluous forward slashes at the beginning of the path
  88. if (path = location.pathname.replace /^\/{2,}/g, '/') isnt location.pathname
  89. page.replace path + location.search + location.hash, null, true
  90. if @isRoot()
  91. if path = @getInitialPathFromHash()
  92. page.replace path + location.search, null, true
  93. else if path = @getInitialPathFromCookie()
  94. page.replace path + location.search + location.hash, null, true
  95. return
  96. getInitialPathFromHash: ->
  97. try
  98. (new RegExp "#/(.+)").exec(decodeURIComponent location.hash)?[1]
  99. catch
  100. getInitialPathFromCookie: ->
  101. if path = Cookies.get('initial_path')
  102. Cookies.expire('initial_path')
  103. path
  104. replaceHash: (hash) ->
  105. page.replace location.pathname + location.search + (hash or ''), null, true
  106. return