git.s-ol.nu mmm / 8cdf5d4
change ?interactive pseudofacet to text/html+interactive pseudo-type fix browser push/popstate s-ol 3 years ago
5 changed file(s) with 70 addition(s) and 49 deletion(s). Raw diff Collapse all Expand all
4646 switch method
4747 when 'GET', 'HEAD'
4848 val = switch facet.name
49 when '?interactive'
50 export BROWSER
51
52 root = Fileder @store
53 BROWSER = Browser root, path
54 render BROWSER\todom!, fileder, noview: true, scripts: "
55 <script type=\"application/lua\">
56 on_load = on_load or {}
57 table.insert(on_load, function()
58 local path = #{string.format '%q', path}
59 local browser = require 'mmm.mmmfs.browser'
60 local fileder = require 'mmm.mmmfs.fileder'
61 local web = require 'mmm.mmmfs.stores.web'
62
63 local store = web.WebStore({ verbose = true })
64 local index = store:get_index(path, -1)
65 local root = fileder.Fileder(store, index)
66
67 BROWSER = browser.Browser(root, path, true)
68 end)
69 </script>"
70
7149 when '?index', '?tree'
7250 -- serve fileder index
7351 -- '?index': one level deep
8058 if not fileder\has_facet facet.name
8159 return 404, "facet '#{facet.name}' not found in fileder '#{path}'"
8260
83 fileder\get facet
61 if facet.type == 'text/html+interactive'
62 export BROWSER
63
64 root = Fileder @store
65 BROWSER = Browser root, path, facet.name
66 render BROWSER\todom!, fileder, noview: true, scripts: "
67 <script type=\"application/lua\">
68 on_load = on_load or {}
69 table.insert(on_load, function()
70 local path = #{string.format '%q', path}
71 local facet = #{string.format '%q', facet.name}
72 local browser = require 'mmm.mmmfs.browser'
73 local fileder = require 'mmm.mmmfs.fileder'
74 local web = require 'mmm.mmmfs.stores.web'
75
76 local store = web.WebStore({ verbose = true })
77 local index = store:get_index(path, -1)
78 local root = fileder.Fileder(store, index)
79
80 BROWSER = browser.Browser(root, path, facet, true)
81 end)
82 </script>"
83 else
84 fileder\get facet
8485
8586 if val
8687 200, val
99100 path_facet or= path
100101 path, facet = path_facet\match '(.*)/([^/]*)'
101102
102 type or= 'text/html'
103 type or= 'text/html+interactive'
103104 type = type\match '%s*(.*)'
104105 facet = Key facet, type
105106
111112
112113 res = headers.new!
113114 response_type = if status > 299 then 'text/plain'
114 else if facet then facet.type
115 else 'text/json'
115 else if facet.type == 'text/html+interactive' then 'text/html'
116 else facet.type
116117 res\append ':status', tostring status
117118 res\append 'content-type', response_type
118119
3939 table.insert casts, convert
4040
4141 class Browser
42 new: (@root, path, rehydrate=false) =>
42 new: (@root, path, facet, rehydrate=false) =>
4343 -- root fileder
4444 assert @root, 'root fileder is nil'
4545
4646 -- active path
4747 @path = ReactiveVar path or ''
48
49 -- active fileder
50 -- (re)set every time @path changes
51 @active = @path\map @root\walk
52
53 -- currently active facet
54 -- (re)set to default when @active changes
55 @facet = ReactiveVar Key facet, 'mmm/dom'
56 if MODE == 'CLIENT'
57 @active\subscribe (fileder) ->
58 return unless fileder
59 last = @facet and @facet\get!
60 @facet\set Key if last then last.type else 'mmm/dom'
4861
4962 -- update URL bar
5063 if MODE == 'CLIENT'
5366 logo.classList\add 'spin'
5467 logo.parentElement.offsetWidth
5568 logo.classList\remove 'spin'
56 @path\subscribe (path) ->
69
70 @facet\subscribe (facet) ->
5771 document.body.classList\add 'loading'
5872 spin!
5973
6074 return if @skip
61 vis_path = path .. (if '/' == path\sub -1 then '' else '/')
62 window.history\pushState path, '', vis_path
75
76 path = @path\get!
77 state = js.global\eval 'new Object()'
78 state.path = path
79 state.name = facet.name
80 state.type = facet.type
81
82 window.history\pushState state, '', "#{path}/#{(Key facet.name, 'text/html+interactive')\tostring true}"
6383
6484 window.onpopstate = (_, event) ->
65 if event.state and not event.state == js.null
85 state = event.state
86 if state != js.null
6687 @skip = true
67 @path\set event.state
88 @path\set state.path
89 @facet\set Key state.name, state.type
6890 @skip = nil
69
70 -- active fileder
71 -- (re)set every time @path changes
72 @active = @path\map @root\walk
73
74 -- currently active facet
75 -- (re)set to default when @active changes
76 @facet = @active\map (fileder) ->
77 return unless fileder
78 last = @facet and @facet\get!
79 Key if last then last.type else 'mmm/dom'
8091
8192 -- whether inspect tab is active
8293 @inspect = ReactiveVar (MODE == 'CLIENT' and window.location.search\match '[?&]inspect')
120131
121132 current = @facet\get!
122133 current = current and current.name
123 with select :onchange, disabled: not fileder
134 with select :onchange, disabled: not fileder, value: @facet\map (f) -> f and f.name
124135 has_main = fileder and fileder\has_facet ''
125136 \append option '(main)', value: '', disabled: not has_main, selected: current == ''
126137 if fileder
3333 assert ('string' == type @type), "type is not a string: '#{@type}'"
3434
3535 -- format as a string (see constructor)
36 tostring: =>
37 if @name == ''
36 -- in strict mode never omit name
37 tostring: (strict=false) =>
38 if not strict and @name == ''
3839 @type
3940 else
4041 "#{@name}: #{@type}"
2828 else
2929 val
3030
31 (string) ->
32 print fix JSON\parse string
33 fix JSON\parse string
31 (string) -> fix JSON\parse string
3432
3533 class WebStore extends Store
3634 new: (opts = {}) =>
5555 assert.is.equal 'facet: and -> long -> type', tostring Key 'facet: and -> long -> type'
5656 assert.is.equal 'facet: and -> long -> type', tostring Key 'facet', 'and -> long -> type'
5757 assert.is.equal 'facet: and -> long -> type', tostring Key 'facet: and -> long -> type'
58
59 it ":tostring formats the key", ->
60 assert.is.equal 'type/only', (Key 'type/only')\tostring!
61 assert.is.equal 'type/only', (Key '', 'type/only')\tostring!
62 assert.is.equal 'type/only', (Key ": type/only")\tostring!
63
64 it ":tostring supports strict mode", ->
65 assert.is.equal ': type/only', (Key 'type/only')\tostring true
66 assert.is.equal ': type/only', (Key '', 'type/only')\tostring true
67 assert.is.equal ': type/only', (Key ": type/only")\tostring true