aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2019-10-27 19:22:00 +0000
committers-ol <s-ol@users.noreply.github.com>2019-10-27 19:22:00 +0000
commit28653c9ae46b2b3e42c2c75879589138c731f37b (patch)
tree640251211409bcfada73438f3345c5b03dc7e0e0
parentmove converts into plugins (diff)
downloadmmm-28653c9ae46b2b3e42c2c75879589138c731f37b.tar.gz
mmm-28653c9ae46b2b3e42c2c75879589138c731f37b.zip
facet editing with CodeMirror!
-rw-r--r--build/server.moon5
-rw-r--r--mmm/mmmfs/browser.moon39
-rw-r--r--mmm/mmmfs/fileder.moon4
-rw-r--r--mmm/mmmfs/plugins/code.moon48
-rw-r--r--mmm/mmmfs/plugins/init.moon18
-rw-r--r--scss/_browser.scss2
-rw-r--r--scss/_footer.scss1
-rw-r--r--scss/codemirror.scss72
-rw-r--r--scss/main.scss1
9 files changed, 160 insertions, 30 deletions
diff --git a/build/server.moon b/build/server.moon
index 33853c9..906f89a 100644
--- a/build/server.moon
+++ b/build/server.moon
@@ -64,6 +64,11 @@ class Server
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/svg.js/2.6.6/svg.min.js"></script>
<script type="text/javascript" src="//unpkg.com/mermaid@8.4.0/dist/mermaid.min.js"></script>
<script type="text/javascript" src="//unpkg.com/marked@0.7.0/marked.min.js"></script>
+ <link rel="stylesheet" type="text/css" href="//unpkg.com/codemirror@5.49.2/lib/codemirror.css" />
+ <script type="text/javascript" src="//unpkg.com/codemirror@5.49.2/lib/codemirror.js"></script>
+ <script type="text/javascript" src="//unpkg.com/codemirror@5.49.2/mode/lua/lua.js"></script>
+ <script type="text/javascript" src="//unpkg.com/codemirror@5.49.2/mode/markdown/markdown.js"></script>
+ <script type="text/javascript" src="//unpkg.com/codemirror@5.49.2/addon/display/autorefresh.js"></script>
<script type="text/javascript" src="/static/fengari-web/:text/javascript"></script>
<script type="text/lua" src="/static/mmm/:text/lua"></script>
<script type="text/lua">require 'mmm'; require 'mmm.mmmfs'</script>
diff --git a/mmm/mmmfs/browser.moon b/mmm/mmmfs/browser.moon
index 35925d3..b63010b 100644
--- a/mmm/mmmfs/browser.moon
+++ b/mmm/mmmfs/browser.moon
@@ -1,9 +1,9 @@
require = relative ..., 1
import Key from require '.fileder'
-import converts from require '.plugins'
+import converts, editors from require '.plugins'
import get_conversions, apply_conversions from require '.conversion'
import ReactiveVar, get_or_create, text, elements, tohtml from require 'mmm.component'
-import pre, div, nav, span, button, a, code, select, option from elements
+import pre, div, nav, span, button, a, code, option from elements
import languages from require 'mmm.highlighting'
keep = (var) ->
@@ -12,25 +12,24 @@ keep = (var) ->
last = val or last
last
+combine = (...) ->
+ res = {}
+ lists = {...}
+ for list in *lists
+ for val in *list
+ table.insert res, val
+
+ res
+
casts = {
{
- inp: 'text/.*',
- out: 'mmm/dom',
- cost: 0
- transform: (val) =>
- lang = @from\match 'text/(.*)'
- languages[lang] val
- }
- {
inp: 'URL.*'
out: 'mmm/dom'
cost: 0
transform: (href) => span a (code href), :href
}
}
-
-for convert in *converts
- table.insert casts, convert
+casts = combine casts, converts, editors
export BROWSER
class Browser
@@ -128,7 +127,7 @@ class Browser
current = @facet\get!
current = current and current.name
- with select :onchange, disabled: not fileder, value: @facet\map (f) -> f and f.name
+ with elements.select :onchange, disabled: not fileder, value: @facet\map (f) -> f and f.name
has_main = fileder and fileder\has_facet ''
\append option '(main)', value: '', disabled: not has_main, selected: current == ''
if fileder
@@ -146,11 +145,11 @@ class Browser
-- append or patch #browser-content
main\append with get_or_create 'div', 'browser-content', class: 'content'
- content = ReactiveVar if rehydrate then .node.lastChild else @get_content @facet\get!
- \append keep content
+ @content = ReactiveVar if rehydrate then .node.lastChild else @get_content @facet\get!
+ \append keep @content
if MODE == 'CLIENT'
@facet\subscribe (p) ->
- window\setTimeout (-> content\set @get_content p), 150
+ window\setTimeout (-> @refresh p), 150
if rehydrate
-- force one rerender to set onclick handlers etc
@@ -166,6 +165,10 @@ class Browser
err_and_trace = (msg) -> debug.traceback msg, 2
default_convert = (key) => @get key.name, 'mmm/dom'
+ -- rerender main content
+ refresh: (facet=@facet\get!) =>
+ @content\set @get_content facet
+
-- render #browser-content
get_content: (prop, err=@error, convert=default_convert) =>
clear_error = ->
@@ -218,7 +221,7 @@ class Browser
{ :name } = @facet\get!
@inspect_prop\set Key e.target.value
- with select :onchange
+ with elements.select :onchange
\append option '(none)', value: '', disabled: true, selected: not value
if fileder
for value in pairs fileder.facet_keys
diff --git a/mmm/mmmfs/fileder.moon b/mmm/mmmfs/fileder.moon
index cdfc649..f545bd8 100644
--- a/mmm/mmmfs/fileder.moon
+++ b/mmm/mmmfs/fileder.moon
@@ -134,8 +134,8 @@ class Fileder
rawset t, k, v
- v = k unless v == nil
- @facet_keys[k] = v
+ if not v
+ @facet_keys[k] = nil
}
-- this fails with JS objects from JSON.parse
diff --git a/mmm/mmmfs/plugins/code.moon b/mmm/mmmfs/plugins/code.moon
index ec22f71..3024c99 100644
--- a/mmm/mmmfs/plugins/code.moon
+++ b/mmm/mmmfs/plugins/code.moon
@@ -1,6 +1,42 @@
-import pre from require 'mmm.dom'
+import div from require 'mmm.dom'
import languages from require 'mmm.highlighting'
+class Editor
+ o = do
+ mkobj = window\eval "(function () { return {}; })"
+ (tbl) ->
+ with obj = mkobj!
+ for k,v in pairs(tbl)
+ obj[k] = v
+
+ new: (value, mode, @fileder, @key) =>
+ @node = div class: 'editor'
+ @cm = window\CodeMirror @node, o {
+ :value
+ :mode
+ lineNumber: true
+ lineWrapping: true
+ autoRefresh: true
+ theme: 'hybrid'
+ }
+
+ @cm\on 'changes', (_, mirr) ->
+ window\clearTimeout @timeout if @timeout
+ @timeout = window\setTimeout (-> @change!), 300
+
+ change: =>
+ @timeout = nil
+ doc = @cm\getDoc!
+ if @lastState and doc\isClean @lastState
+ -- no changes since last event
+ return
+
+ @lastState = doc\changeGeneration true
+ value = doc\getValue!
+
+ @fileder.facets[@key] = value
+ BROWSER\refresh!
+
-- syntax-highlighted code
{
converts: {
@@ -13,4 +49,14 @@ import languages from require 'mmm.highlighting'
pre languages[lang] val
}
}
+ editors: if MODE == 'CLIENT' then {
+ {
+ inp: 'text/([^ ]*).*'
+ out: 'mmm/dom'
+ cost: 0
+ transform: (value, fileder, key) =>
+ mode = @from\match @convert.inp
+ Editor value, mode, fileder, key
+ }
+ }
}
diff --git a/mmm/mmmfs/plugins/init.moon b/mmm/mmmfs/plugins/init.moon
index af4a2aa..12fb061 100644
--- a/mmm/mmmfs/plugins/init.moon
+++ b/mmm/mmmfs/plugins/init.moon
@@ -4,12 +4,6 @@ import find_fileder, link_to, embed from (require 'mmm.mmmfs.util') require 'mmm
import render from require '.layout'
import tohtml from require 'mmm.component'
-keep = (var) ->
- last = var\get!
- var\map (val) ->
- last = val or last
- last
-
-- fix JS null values
js_fix = if MODE == 'CLIENT'
(arg) ->
@@ -24,13 +18,14 @@ loadwith = (_load) -> (val, fileder, key) =>
func = assert _load val, "#{fileder}##{key}"
func!
--- list of converts
+-- list of converts, editors
-- converts each have
-- * inp - input type. can capture subtypes using `(.+)`
-- * out - output type. can substitute subtypes from inp with %1, %2 etc.
-- * cost - conversion cost
-- * transform - function (val: inp, fileder) => val: out
-- @convert, @from, @to contain the convert and the concrete types
+editors = {}
converts = {
{
inp: 'fn -> (.+)',
@@ -256,6 +251,10 @@ add_converts = (module) ->
for convert in *plugin.converts
table.insert converts, convert
+ if plugin.editors
+ for editor in *plugin.editors
+ table.insert editors, editor
+
add_converts 'code'
add_converts 'markdown'
add_converts 'mermaid'
@@ -289,4 +288,7 @@ else
f!
}
-:converts
+{
+ :converts
+ :editors
+}
diff --git a/scss/_browser.scss b/scss/_browser.scss
index b9910e8..b843916 100644
--- a/scss/_browser.scss
+++ b/scss/_browser.scss
@@ -15,7 +15,7 @@
&.inspector {
top: 0;
position: sticky;
- max-height: 100vh;
+ max-height: calc(100vh - 3rem);
color: #c5c8c6;
@include left-border;
diff --git a/scss/_footer.scss b/scss/_footer.scss
index 727ebda..4f1c8bd 100644
--- a/scss/_footer.scss
+++ b/scss/_footer.scss
@@ -1,6 +1,7 @@
footer {
display: flex;
padding: 1rem 2rem;
+ height: 1rem;
position: sticky;
bottom: 0;
diff --git a/scss/codemirror.scss b/scss/codemirror.scss
new file mode 100644
index 0000000..1967f8c
--- /dev/null
+++ b/scss/codemirror.scss
@@ -0,0 +1,72 @@
+/*
+ vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid)
+*/
+
+/*background color*/
+.CodeMirror.cm-s-hybrid {
+ color: #c5c8c6;
+ background: #1d1f21;
+
+ height: auto;
+
+ /*selection color*/
+ .CodeMirror-selected,
+ .CodeMirror-line::selection,
+ .CodeMirror-line > span::selection,
+ .CodeMirror-line > span > span::selection, {
+ background: #373b41;
+ }
+
+ /*foreground color*/
+ .CodeMirror-cursor {
+ border-color: #c5c8c6;
+ }
+
+ /*color: fg_yellow*/
+ .cm-keyword {
+ color: #f0c674;
+ }
+
+ /*color: fg_comment*/
+ .cm-comment,
+ .cm-meta {
+ color: #707880;
+ }
+
+ /*color: fg_red*/
+ .cm-number,
+ .cm-atom {
+ color: #cc6666
+ }
+
+ /*color: fg_green*/
+ .cm-string,
+ .cm-string-2,
+ .cm-operator {
+ color: #b5bd68;
+ }
+
+ /*color: fg_purple*/
+ .cm-attribute,
+ .cm-propery {
+ color: #b294bb;
+ }
+
+ /*color: fg_blue*/
+ .cm-tag,
+ .cm-qualifier {
+ color: #81a2be;
+ }
+
+ /*color: fg_aqua*/
+ .cm-link,
+ .cm-header,
+ .cm-hr {
+ color: #8abeb7;
+ }
+
+ /*color: fg_orange*/
+ .cm-builtin, {
+ color: #de935f;
+ }
+}
diff --git a/scss/main.scss b/scss/main.scss
index c1e9d38..08ce942 100644
--- a/scss/main.scss
+++ b/scss/main.scss
@@ -1,6 +1,7 @@
@import 'defs';
@import 'reset';
@import 'hljs';
+@import 'codemirror';
@import 'header';
@import 'footer';
@import 'browser';