on master help sign in
Merge branch 'markdown' into dev

Conflicts: Elm.cabal

commitd97fe192e0375fccf3fdc7130864dcd626ff3655 authorEvan Czaplicki <info@elm-lang.org> dateTue 29 Oct 2013, 15:36 (13 years ago) parent737fedcdf8df36
12 files changed+123−33
compiler/Generate/JavaScript.hs+6−3 compiler/Generate/Noscript.hs+1−1 compiler/Parse/Expression.hs+8−6 compiler/SourceSyntax/Expression.hs+2−2 compiler/Transform/Canonicalize.hs+1−1 compiler/Transform/SortDefinitions.hs+1−1 compiler/Transform/Substitute.hs+1−1 compiler/Type/Constrain/Expression.hs+1−1 libraries/Graphics/Element.elm+2−2 libraries/Native/Text.js+30−8 libraries/Native/Utils.js+19−1 runtime/Render/Element.js+51−6
compiler/Generate/JavaScript.hs+6−3
@@ -186,9 +186,12 @@ expression (L span expr) =
186186 ctor = (prop "ctor", string (makeSafe name))
187187 fields = zipWith (\n e -> (prop ("_" ++ show n), e)) [0..]
188188
189− Markdown doc _ -> return $ obj "Text.text" <| string (pad ++ md ++ pad)
190− where pad = "<div style=\"height:0;width:0;\">&nbsp;</div>"
191− md = Pan.writeHtmlString Pan.def doc
189+ Markdown uid doc es ->
190+ do es' <- mapM expression es
191+ return $ obj "Text.markdown" `call` (string md : string uid : es')
192+ where
193+ pad = "<div style=\"height:0;width:0;\">&nbsp;</div>"
194+ md = pad ++ Pan.writeHtmlString Pan.def doc ++ pad
192195
193196definition :: Def () () -> State Int [Statement ()]
194197definition def =
compiler/Generate/Noscript.hs+1−1
@@ -49,7 +49,7 @@ instance Extract (Expr t v) where
4949 Case e cases -> concatMap (f . snd) cases
5050 Data _ es -> concatMap f es
5151 MultiIf es -> concatMap (f . snd) es
52− Markdown doc _ -> [ Pan.writeHtmlString Pan.def doc ]
52+ Markdown _ doc _ -> [ Pan.writeHtmlString Pan.def doc ]
5353 _ -> []
5454
5555extractLink src txt =
compiler/Parse/Expression.hs+8−6
@@ -55,20 +55,22 @@ listTerm = markdown' <|> braces (try range <|> ExplicitList <$> commaSep expr)
5555 Range lo <$> expr
5656
5757 markdown' = do
58− (rawText, exprs) <- markdown interpolation
58+ pos <- getPosition
59+ let uid = show (sourceLine pos) ++ ":" ++ show (sourceColumn pos)
60+ (rawText, exprs) <- markdown (interpolation uid)
5961 let md = Pan.readMarkdown Pan.def (filter (/='\r') rawText)
60− return (Markdown md exprs)
62+ return (Markdown uid md exprs)
6163
62− span xs = "<span id=\"md" ++ show (length xs) ++
63− "\" style=\"font-family:monospace;\">{{ ... }}</span>"
64+ span uid index =
65+ "<span id=\"md-" ++ uid ++ "-" ++ show index ++ "\"></span>"
6466
65− interpolation md exprs = do
67+ interpolation uid md exprs = do
6668 try (string "{{")
6769 whitespace
6870 e <- expr
6971 whitespace
7072 string "}}"
71− return (md ++ span exprs, exprs ++ [e])
73+ return (md ++ span uid (length exprs), exprs ++ [e])
7274
7375parensTerm :: IParser (LExpr t v)
7476parensTerm = try (parens opFn) <|> parens (tupleFn <|> parened)
compiler/SourceSyntax/Expression.hs+2−2
@@ -30,7 +30,7 @@ data Expr t v
3030 | Insert (LExpr t v) String (LExpr t v)
3131 | Modify (LExpr t v) [(String, LExpr t v)]
3232 | Record [(String, LExpr t v)]
33− | Markdown Pandoc.Pandoc [LExpr t v]
33+ | Markdown String Pandoc.Pandoc [LExpr t v]
3434 deriving (Eq, Show, Data, Typeable)
3535
3636data Def tipe var
@@ -96,7 +96,7 @@ instance Pretty (Expr t v) where
9696 where
9797 field (x,e) = variable x <+> P.text "=" <+> pretty e
9898
99− Markdown _ _ -> P.text "[markdown| ... |]"
99+ Markdown _ _ _ -> P.text "[markdown| ... |]"
100100
101101instance Pretty (Def t v) where
102102 pretty def =
compiler/Transform/Canonicalize.hs+1−1
@@ -174,7 +174,7 @@ rename env lexpr@(L s expr) =
174174 branch (pattern,e) = (,) `liftM` format (renamePattern env pattern)
175175 `ap` rename (extend env pattern) e
176176
177− Markdown md es -> Markdown md `liftM` mapM rnm es
177+ Markdown uid md es -> Markdown uid md `liftM` mapM rnm es
178178
179179
180180renamePattern :: Env -> Pattern -> Either String Pattern
compiler/Transform/SortDefinitions.hs+1−1
@@ -97,7 +97,7 @@ reorder lexpr@(L s expr) =
9797 Record fields ->
9898 Record `liftM` mapM reorderField fields
9999
100− Markdown md es -> Markdown md <$> mapM reorder es
100+ Markdown uid md es -> Markdown uid md <$> mapM reorder es
101101
102102 -- Actually do some reordering
103103 Let defs body ->
compiler/Transform/Substitute.hs+1−1
@@ -40,4 +40,4 @@ subst old new expr =
4040 Modify r fs -> Modify (f r) (map (second f) fs)
4141 Record fs -> Record (map (second f) fs)
4242 Literal _ -> expr
43− Markdown md es -> Markdown md (map f es)
43+ Markdown uid md es -> Markdown uid md (map f es)
compiler/Type/Constrain/Expression.hs+1−1
@@ -134,7 +134,7 @@ constrain env (L span expr) tipe =
134134 recordType = record fields' (TermN EmptyRecord1)
135135 return . ex vars . and $ tipe === recordType : cs
136136
137− Markdown _ es ->
137+ Markdown _ _ es ->
138138 do vars <- forM es $ \_ -> liftIO (var Flexible)
139139 let tvars = map VarN vars
140140 cs <- zipWithM (constrain env) es tvars
libraries/Graphics/Element.elm+2−2
@@ -76,7 +76,7 @@ width nw e =
7676 let p = e.props
7777 props = case e.element of
7878 Image _ w h _ -> {p| height <- round (toFloat h / toFloat w * toFloat nw) }
79− RawHtml html -> {p| height <- snd (Native.Utils.htmlHeight nw html)}
79+ RawHtml -> {p| height <- snd (Native.Utils.htmlHeight nw e.element) }
8080 _ -> p
8181 in { element=e.element, props={ props | width <- nw } }
8282
@@ -128,7 +128,7 @@ data ElementPrim
128128 | Container Position Element
129129 | Flow Direction [Element]
130130 | Spacer
131− | RawHtml JSString
131+ | RawHtml
132132 | Custom -- for custom Elements implemented in JS, see collage for example
133133
134134data ImageStyle = Plain | Fitted | Cropped (Int,Int) | Tiled
libraries/Native/Text.js+30−8
@@ -91,17 +91,38 @@ Elm.Native.Text.make = function(elm) {
9191 return Utils.txt("<a href='" + toText(href) + "'>" + text + "</a>");
9292 }
9393
94− function position(pos) {
94+ function position(align) {
9595 return function(text) {
96− var e = {ctor:'RawHtml',
97− _0: '<div style="padding:0;margin:0;text-align:' +
98− pos + '">' + text + '</div>'
99− };
100− var p = A2(Utils.htmlHeight, 0, text);
101− return A3(Element.newElement, p._0, p._1, e);
96+ var raw = {
97+ ctor:'RawHtml',
98+ html: '<span style="text-align:' + align + ';">' + text + '</span>',
99+ guid: '0',
100+ args: [],
101+ };
102+ var pos = A2(Utils.htmlHeight, 0, raw);
103+ return A3(Element.newElement, pos._0, pos._1, raw);
102104 }
103105 }
104106
107+ function markdown(text, guid) {
108+ var raw = {
109+ ctor:'RawHtml',
110+ html: text,
111+ guid: guid,
112+ args: Array.prototype.slice.call(arguments, 2).map(function(arg) {
113+ if (arg.props && arg.element) {
114+ arg.isElement = true;
115+ return arg;
116+ } else if (!arg.isText) {
117+ return Utils.txt('<code>' + show(arg) + '</code>');
118+ }
119+ return arg;
120+ }),
121+ };
122+ var pos = A2(Utils.htmlHeight, 0, raw);
123+ return A3(Element.newElement, pos._0, pos._1, raw);
124+ }
125+
105126 function asText(v) {
106127 return position('left')(monospace(toText(show(v))));
107128 }
@@ -130,7 +151,8 @@ Elm.Native.Text.make = function(elm) {
130151 righted : position('right'),
131152 text : position('left'),
132153 plainText : plainText,
154+ markdown : markdown,
133155
134− asText : asText
156+ asText : asText,
135157 };
136158};
libraries/Native/Utils.js+19−1
@@ -122,7 +122,9 @@ Elm.Native.Utils.make = function(elm) {
122122 return m === b ? 0 : m;
123123 }
124124
125− function htmlHeight(width, html) {
125+ function htmlHeight(width, rawHtml) {
126+ // create dummy node
127+ var html = rawHtml.html;
126128 var t = document.createElement('div');
127129 t.innerHTML = html;
128130 if (width > 0) { t.style.width = width + "px"; }
@@ -131,6 +133,22 @@ Elm.Native.Utils.make = function(elm) {
131133 t.style.cssFloat = "left";
132134
133135 document.body.appendChild(t);
136+
137+ // insert interpolated values
138+ var args = rawHtml.args;
139+ var guid = rawHtml.guid;
140+ for (var i = args.length; i--; ) {
141+ var arg = args[i];
142+ var span = document.getElementById('md-' + guid + '-' + i);
143+ if (arg.isElement) {
144+ span.style.width = arg.props.width + 'px';
145+ span.style.height = arg.props.height + 'px';
146+ } else {
147+ span.innerHTML = arg;
148+ }
149+ }
150+
151+ // get dimensions
134152 var style = window.getComputedStyle(t, null);
135153 var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
136154 var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
runtime/Render/Element.js+51−6
@@ -154,10 +154,31 @@ function container(pos,elem) {
154154 return div;
155155}
156156
157−function rawHtml(html) {
158− var e = newElement('div');
159− e.innerHTML = html;
160− return e;
157+function rawHtml(elem) {
158+ var html = elem.html;
159+ var args = elem.args;
160+ var guid = elem.guid;
161+
162+ var div = newElement('div');
163+ div.innerHTML = html;
164+ div.style.visibility = "hidden";
165+ document.body.appendChild(div);
166+
167+ for (var i = args.length; i--; ) {
168+ var arg = args[i];
169+ var span = document.getElementById('md-' + guid + '-' + i);
170+ if (arg.isText) {
171+ span.innerHTML = arg;
172+ } else {
173+ span.style.display = 'block';
174+ span.style.width = arg.props.width + 'px';
175+ span.style.height = arg.props.height + 'px';
176+ span.appendChild(render(arg));
177+ }
178+ }
179+ document.body.removeChild(div);
180+ div.style.visibility = 'visible';
181+ return div;
161182}
162183
163184function render(elem) { return setProps(elem.props, makeElement(elem)); }
@@ -168,7 +189,7 @@ function makeElement(e) {
168189 case 'Flow': return flow(elem._0, elem._1);
169190 case 'Container': return container(elem._0, elem._1);
170191 case 'Spacer': return newElement('div');
171− case 'RawHtml': return rawHtml(elem._0);
192+ case 'RawHtml': return rawHtml(elem);
172193 case 'Custom': return elem.render(elem.model);
173194 }
174195}
@@ -184,7 +205,31 @@ function update(node, curr, next) {
184205 switch(nextE.ctor) {
185206 case "Spacer": break;
186207 case "RawHtml":
187− if (nextE._0 !== currE._0) node.innerHTML = nextE._0;
208+ if (nextE.guid !== currE.guid) {
209+ node.parentNode.replaceChild(render(next),node);
210+ return true;
211+ }
212+ var nargs = nextE.args;
213+ var cargs = currE.args;
214+ for (var i = nargs.length; i--; ) {
215+ var narg = nargs[i];
216+ var carg = cargs[i]
217+ if (narg == carg) continue;
218+ var span = document.getElementById('md-' + currE.guid + '-' + i);
219+ if (narg.isElement) {
220+ if (carg.isElement) {
221+ update(span, carg, narg);
222+ } else {
223+ span.style.display = 'block';
224+ var e = render(narg);
225+ span.innerHTML = '';
226+ span.appendChild(e);
227+ }
228+ } else {
229+ span.style.display = 'inline';
230+ span.innerHTML = narg;
231+ }
232+ }
188233 break;
189234 case "Image":
190235 if (nextE._0.ctor === 'Plain') {