diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2018-11-06 09:45:19 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2018-11-06 09:45:19 +0000 |
| commit | 33ec5f940f9bd180b6bf1e847f3c6d6b1f644dcc (patch) | |
| tree | 4e28fcfa45aed08f1543ae84c9f0ea5e2956a63b | |
| parent | fix mmmfs article for now (diff) | |
| download | mmm-33ec5f940f9bd180b6bf1e847f3c6d6b1f644dcc.tar.gz mmm-33ec5f940f9bd180b6bf1e847f3c6d6b1f644dcc.zip | |
add inspector
| -rw-r--r-- | mmm/component/init.client.moon | 1 | ||||
| -rw-r--r-- | mmm/component/init.server.moon | 16 | ||||
| -rw-r--r-- | mmm/mmmfs/browser.moon | 153 | ||||
| -rw-r--r-- | mmm/mmmfs/conversion.moon | 17 | ||||
| -rw-r--r-- | mmm/mmmfs/fileder.moon | 12 | ||||
| -rw-r--r-- | scss/browser.scss | 51 |
6 files changed, 154 insertions, 96 deletions
diff --git a/mmm/component/init.client.moon b/mmm/component/init.client.moon index 86432e4..19074c5 100644 --- a/mmm/component/init.client.moon +++ b/mmm/component/init.client.moon @@ -14,7 +14,6 @@ tohtml = (val) -> assert (js.instanceof val, js.global.Node), "userdata is not a Node" val else - warn "NOT A NODE: #{val}, ", debug.traceback! error "not a Node: #{val}, #{type val}" -- shorthand to form a text node from strings diff --git a/mmm/component/init.server.moon b/mmm/component/init.server.moon index c9f2109..dce09e1 100644 --- a/mmm/component/init.server.moon +++ b/mmm/component/init.server.moon @@ -9,9 +9,7 @@ void_tags = { t,t for t in *void_tags } -- * string tohtml = (val) -> if 'table' == type val - if not val.render - warn val - assert val.render, "Table doesn't have .render" + assert val.render, "Table doesn't have .render" val = val\render! if 'string' == type val val @@ -42,7 +40,7 @@ class ReactiveElement new: (element, ...) => @element = element - @attrs = { style: {} } + @attrs = {} @children = {} children = { ... } @@ -73,11 +71,6 @@ class ReactiveElement if 'table' == (type value) and ReactiveVar.isinstance value value = value\get! - if attr == 'style' and 'table' == type value - for k,v in opairs value - @attrs.style[k] = v - return - @attrs[attr] = value append: (child, last) => @@ -85,8 +78,9 @@ class ReactiveElement if ReactiveVar.isinstance child child = child\get! - child = tohtml child - table.insert @children, child + if child + child = tohtml child + table.insert @children, child remove: (child) => error "remove called serverside" diff --git a/mmm/mmmfs/browser.moon b/mmm/mmmfs/browser.moon index 50de0f8..9bcf294 100644 --- a/mmm/mmmfs/browser.moon +++ b/mmm/mmmfs/browser.moon @@ -1,8 +1,24 @@ require = relative ..., 1 import Key from require '.fileder' -import get_conversions from require '.conversion' +import converts, get_conversions, apply_conversions from require '.conversion' import ReactiveVar, get_or_create, text, elements from require 'mmm.component' -import div, span, a, select, option from elements +import pre, code, div, nav, span, button, a, select, option from elements + +code_cast = (lang) -> { + inp: "text/#{lang}.*", + out: 'mmm/dom', + transform: (val) -> pre code val + } + +casts = { + code_cast 'moonscript', + code_cast 'lua', + code_cast 'markdown', + code_cast 'html', +} + +for convert in *converts + table.insert casts, convert class Browser new: (@root, path='/', rehydrate=false) => @@ -12,8 +28,8 @@ class Browser -- active path @path = ReactiveVar path + -- update URL bar if MODE == 'CLIENT' - -- update URL bar @path\subscribe (path) -> path ..= '/' unless '/' == path\sub -1 window.history\pushState nil, '', path @@ -23,21 +39,24 @@ class Browser @active = @path\map @root\walk -- currently active property - -- (re)set to default every time @active changes + -- (re)set to default when @active changes @prop = @active\map (fileder) -> return unless fileder last = @prop and @prop\get! -- (fileder\find 'mmm/dom') or next fileder.props Key if last then last.type else 'mmm/dom' - -- retrieve or create the root - @dom = get_or_create 'div', 'browser-root' + -- whether inspect tab is active + @inspect = ReactiveVar false + + -- retrieve or create the wrapper and main elements + main = get_or_create 'div', 'browser-root', class: 'main view' -- prepend the navbar if MODE == 'SERVER' - @dom\append div 'please stand by... interactivity loading :)', id: 'browser-navbar' + main\append nav { id: 'browser-navbar', span 'please stand by... interactivity loading :)' } else - @dom\prepend with get_or_create 'div', 'browser-navbar' + main\prepend with get_or_create 'nav', 'browser-navbar' .node.innerHTML = '' \append span 'path: ', @path\map (path) -> with div style: { display: 'inline-block' } path_segment = (name, href) -> @@ -61,9 +80,8 @@ class Browser \append '/' \append path_segment name, href - \append span { - 'view property: ', - @active\map (fileder) -> + \append span 'view property:', style: { 'margin-right': '0' } + \append @active\map (fileder) -> onchange = (_, e) -> { :type } = @prop\get! @prop\set Key name: e.target.value, :type @@ -75,69 +93,86 @@ class Browser for i, value in ipairs fileder\get_prop_names! label = if value == '' then '(main)' else value \append option label, :value, selected: value == current --- ' as ', --- @active\map (fileder) -> --- onchange = (_, e) -> --- { :name } = @prop\get! --- @prop\set Key :name, type: e.target.value --- --- current = @prop\get! --- curent = current and current.type --- with select :onchange --- opt = (value) -> option value, :value, selected: value == current --- \append opt 'mmm/dom' --- \append opt 'text/plain' --- -- if fileder --- -- for key, _ in pairs fileder.props --- -- value = key.type --- -- \append option value, :value, selected: value == current - } + \append @inspect\map (enabled) -> + if not enabled + button 'inspect', onclick: (_, e) -> @inspect\set true -- append or patch #browser-content - @dom\append with get_or_create 'div', 'browser-content' - \append @get_content!, (rehydrate and .node.lastChild) + main\append with get_or_create 'div', 'browser-content', class: 'content' + \append (@prop\map (p) -> @get_content p), (rehydrate and .node.lastChild) if rehydrate -- force one rerender to set onclick handlers etc @prop\set @prop\get! + inspector = @inspect\map (enabled) -> if enabled then @get_inspector! + -- export mmm/component interface - @node = @dom.node - @render = @dom\render + wrapper = get_or_create 'div', 'browser-wrapper', main, inspector, class: 'browser' + @node = wrapper.node + @render = wrapper\render + + err_and_trace = (err) -> err, debug.traceback! + default_convert = (key) => @get key.name, 'mmm/dom' -- render #browser-content - get_content: () => + get_content: (prop, convert=default_convert) => disp_error = (msg) -> span msg, style: { color: '#f00' } - @prop\map (prop) -> - active = @active\get! + active = @active\get! - return disp_error "fileder not found!" unless active - return disp_error "property not found!" unless prop + return disp_error "fileder not found!" unless active + return disp_error "property not found!" unless prop - convert = -> - value = active\get prop + ok, res, trace = xpcall convert, err_and_trace, active, prop - return unless value - - conversions = get_conversions 'mmm/dom', prop.type - - for i=#conversions,1,-1 - { :inp, :out, :transform } = conversions[i] - value = transform value, active, prop - - value - - ok, res, trace = xpcall convert, (err) -> err, debug.traceback! + if ok + res or disp_error "[no conversion path to #{prop.type}]" + elseif res\match '%[nossr%]$' + warn '(SSR disabled)' + div! + else + warn "error: #{res}", trace + disp_error "error: #{res}" - if ok - res or disp_error "[no conversion path to #{prop.type}]" - elseif res\match '%[nossr%]$' - warn '(SSR disabled)' - div! - else - warn "error: ", res - warn trace - disp_error "[unknown error displaying]" + get_inspector: => + -- active property in inspect tab + -- (re)set to match when @prop changes + @inspect_prop = @prop\map (prop) -> + active = @active\get! + key = active\find prop + key = key.original if key and key.original + key + + with div class: 'view inspector' + \append nav { + span 'inspector' + @inspect_prop\map (current) -> + current = current and current\tostring! + fileder = @active\get! + + onchange = (_, e) -> + { :name } = @prop\get! + @inspect_prop\set Key e.target.value + + with select :onchange + if fileder + for key, _ in pairs fileder.props + value = key\tostring! + \append option value, :value, selected: value == current + @inspect\map (enabled) -> + if enabled + button 'close', onclick: (_, e) -> @inspect\set false + } + \append with div class: 'content' + \append @inspect_prop\map (prop) -> + @get_content prop, (prop) => + value, key = @get prop + + conversions = get_conversions 'mmm/dom', key.type, casts + assert conversions, "cannot cast '#{key.type}'" + apply_conversions conversions, value, @, prop + + default_convert = (key) => @get key.name, 'mmm/dom' navigate: (new) => @path\set new diff --git a/mmm/mmmfs/conversion.moon b/mmm/mmmfs/conversion.moon index df7318a..6896c7d 100644 --- a/mmm/mmmfs/conversion.moon +++ b/mmm/mmmfs/conversion.moon @@ -105,7 +105,7 @@ escape_inp = (inp) -> "^#{inp\gsub '([-/])', '%%%1'}$" -- * want - stop type string -- * limit - limit conversion amount -- returns a list of conversion steps -get_conversions = (want, have, limit=3) -> +get_conversions = (want, have, _converts=converts, limit=3) -> assert have, 'need starting type(s)' if 'string' == type have @@ -122,7 +122,7 @@ get_conversions = (want, have, limit=3) -> if want == rest return conversions, start else - for convert in *converts + for convert in *_converts inp = escape_inp convert.inp matches = { rest\match inp } continue unless #matches > 0 @@ -138,7 +138,20 @@ get_conversions = (want, have, limit=3) -> have = next_have return unless #have > 0 +-- apply transforms for conversion path sequentially +-- * conversions - conversions from get_conversions +-- * value - value +-- * ... - other transform parameters (fileder, key) +-- returns converted value +apply_conversions = (conversions, value, ...) -> + for i=#conversions,1,-1 + { :inp, :out, :transform } = conversions[i] + value = transform value, ... + + value + { :converts :get_conversions + :apply_conversions } diff --git a/mmm/mmmfs/fileder.moon b/mmm/mmmfs/fileder.moon index cd4bbe6..63fc9f8 100644 --- a/mmm/mmmfs/fileder.moon +++ b/mmm/mmmfs/fileder.moon @@ -1,5 +1,5 @@ require = relative ..., 1 -import get_conversions from require '.conversion' +import get_conversions, apply_conversions from require '.conversion' -- Key of a Fileder Property -- contains: @@ -143,13 +143,7 @@ class Fileder key, conversions = @find want if key - value = @props[key] - - -- apply conversions (in reverse order) - for i=#conversions,1,-1 - { :inp, :out, :transform } = conversions[i] - value = transform value, @, key - + value = apply_conversions conversions, @props[key], @, key value, key -- like @get, throw if no value or conversion path @@ -157,7 +151,7 @@ class Fileder want = Key ... value, key = @get want - assert value, "#{@} doesn't have value for '#{want\tostring!}'" + assert value, "#{@} doesn't have value for '#{want}'" value, key __tostring: => "Fileder:#{@path}" diff --git a/scss/browser.scss b/scss/browser.scss index 611a157..ce93604 100644 --- a/scss/browser.scss +++ b/scss/browser.scss @@ -1,24 +1,47 @@ -#browser-root { +.browser { position: absolute; + display: flex; top: 0; bottom: 0; left: 0; right: 0; - display: flex; - flex-direction: column; - justify-content: space-between; - #browser-navbar { + .view { display: flex; - flex: 0 0 1.2em; - padding: 1em; - justify-content: space-between; - background: #eeeeee; - } + flex-direction: column; + + flex: 1 1 0; + min-width: 0; + + &.inspector { + border-left: 8px solid #eeeeee; + } + + nav { + display: flex; + flex: 0 0 3.2em; + justify-content: space-between; + background: #eeeeee; + + /* + > * { + flex: 0 0 auto; + } + */ + + > span:first-of-type { + flex: 1 0 auto; + } + + > * { + margin: 1em; + } + } - #browser-content { - flex: 1 0 0; - overflow: auto; - padding: 1em 2em; + .content { + flex: 1 1 auto; + overflow: auto; + padding: 1em 2em; + } } } |
