packages feed

miso 1.6.0.0 → 1.7.0.0

raw patch · 12 files changed

+157/−65 lines, 12 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Miso.Html: [VTextRaw] :: {vText :: Text " Raw TextNode content"} -> VTree action
+ Miso.Html: a_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: abbr_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: address_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: article_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: aside_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: audio_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: b_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: bdi_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: bdo_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: blockquote_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: body_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: br_ :: [Attribute action] -> View action
+ Miso.Html: button_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: canvas_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: caption_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: center_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: cite_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: code_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: col_ :: [Attribute action] -> View action
+ Miso.Html: colgroup_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: datalist_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: dd_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: del_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: details_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: dfn_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: div_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: dl_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: dt_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: em_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: embed_ :: [Attribute action] -> View action
+ Miso.Html: fieldset_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: figcaption_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: figure_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: footer_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: form_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: h1_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: h2_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: h3_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: h4_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: h5_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: h6_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: header_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: hr_ :: [Attribute action] -> View action
+ Miso.Html: i_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: iframe_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: img_ :: [Attribute action] -> View action
+ Miso.Html: input_ :: [Attribute action] -> View action
+ Miso.Html: ins_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: kbd_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: keygen_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: label_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: legend_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: liKeyed_ :: Key -> [Attribute action] -> [View action] -> View action
+ Miso.Html: li_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: link_ :: [Attribute action] -> View action
+ Miso.Html: main_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: mark_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: math_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: menu_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: menuitem_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: meter_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: nav_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: nodeHtml :: MisoString -> [Attribute action] -> [View action] -> View action
+ Miso.Html: nodeHtmlKeyed :: MisoString -> Key -> [Attribute action] -> [View action] -> View action
+ Miso.Html: object_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: ol_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: optgroup_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: option_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: output_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: p_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: param_ :: [Attribute action] -> View action
+ Miso.Html: pre_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: progress_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: q_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: rp_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: rt_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: ruby_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: s_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: samp_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: script_ :: [Attribute action] -> MisoString -> View action
+ Miso.Html: section_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: select_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: small_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: source_ :: [Attribute action] -> View action
+ Miso.Html: span_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: strong_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: sub_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: summary_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: sup_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: table_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: tbody_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: td_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: textarea_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: tfoot_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: th_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: thead_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: time_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: trKeyed_ :: Key -> [Attribute action] -> [View action] -> View action
+ Miso.Html: tr_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: track_ :: [Attribute action] -> View action
+ Miso.Html: u_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: ul_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: var_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: video_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html: wbr_ :: [Attribute action] -> View action
+ Miso.Html.Element: style_ :: [Attribute action] -> MisoString -> View action
- Miso.Html.Element: script_ :: [Attribute action] -> [View action] -> View action
+ Miso.Html.Element: script_ :: [Attribute action] -> MisoString -> View action

Files

README.md view
@@ -130,8 +130,8 @@  ```nix with (import (builtins.fetchTarball {-  url = "https://github.com/dmjio/miso/archive/561ffad.tar.gz";-  sha256 = "1wwzckz2qxb873wdkwqmx9gmh0wshcdxi7gjwkba0q51jnkfdi41";+  url = "https://github.com/dmjio/miso/archive/ea25964565074e73d4052b56b60b6e101fa08bc5.tar.gz";+  sha256 = "1yb9yvc0ln4yn1jk2k5kwwa1s32310abawz40yd8cqqkm1z7w6wg"; }) {}); pkgs.haskell.packages.ghcjs.callCabal2nix "app" ./. {} ```@@ -179,10 +179,10 @@ ## Examples  ### TodoMVC-  - [Link](https://todo-mvc.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/todo-mvc/Main.hs)+  - [Link](http://todo-mvc.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/todo-mvc/Main.hs)  ### Flatris-  - [Link](https://flatris.haskell-miso.org/) / [Source](https://github.com/ptigwe/hs-flatris/)+  - [Link](http://flatris.haskell-miso.org/) / [Source](https://github.com/ptigwe/hs-flatris/)  ### 2048   - [Link](http://2048.haskell-miso.org/) / [Source](https://github.com/ptigwe/hs2048/)@@ -191,25 +191,25 @@   - [Link](http://snake.haskell-miso.org/) / [Source](https://github.com/lbonn/miso-snake)  ### Mario-  - [Link](https://mario.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/mario/Main.hs)+  - [Link](http://mario.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/mario/Main.hs)  ### Miso Plane (Flappy Birds)-  - [Link](https://miso-plane.lermex.net/) / [Source](https://github.com/Lermex/miso-plane)+  - [Link](http://miso-plane.lermex.net/) / [Source](https://github.com/Lermex/miso-plane)  ### Websocket-  - [Link](https://websocket.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/websocket/Main.hs)+  - [Link](http://websocket.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/websocket/Main.hs)  ### SSE-  - [Link](https://sse.haskell-miso.org/) / [Client](https://github.com/dmjio/miso/blob/master/examples/sse/client/Main.hs) / [Server](https://github.com/dmjio/miso/blob/master/examples/sse/server/Main.hs)+  - [Link](http://sse.haskell-miso.org/) / [Client](https://github.com/dmjio/miso/blob/master/examples/sse/client/Main.hs) / [Server](https://github.com/dmjio/miso/blob/master/examples/sse/server/Main.hs)  ### XHR-  - [Link](https://xhr.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/xhr/Main.hs)+  - [Link](http://xhr.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/xhr/Main.hs)  ### Router-  - [Link](https://router.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/router/Main.hs)+  - [Link](http://router.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/router/Main.hs)  ### SVG-  - [Link](https://svg.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/svg/Main.hs)+  - [Link](http://svg.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/svg/Main.hs)  ### Canvas 2D   - [Link](http://canvas.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/canvas2d/Main.hs)@@ -218,13 +218,13 @@   - [Link](http://threejs.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/three/Main.hs)  ### Simple-  - [Link](https://simple.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/exe/Main.hs)+  - [Link](http://simple.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/exe/Main.hs)  ### File Reader-  - [Link](https://file-reader.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/file-reader/Main.hs)+  - [Link](http://file-reader.haskell-miso.org/) / [Source](https://github.com/dmjio/miso/blob/master/examples/file-reader/Main.hs)  ### WebVR-  - [Link](https://fizruk.github.io/fpconf-2017-talk/miso-aframe-demo/dist/demo.jsexe/index.html) / [Source](https://github.com/fizruk/miso-aframe)+  - [Link](http://fizruk.github.io/fpconf-2017-talk/miso-aframe-demo/dist/demo.jsexe/index.html) / [Source](https://github.com/fizruk/miso-aframe)  ## Haddocks @@ -269,6 +269,7 @@     events = defaultEvents        -- default delegated events     subs   = []                   -- empty subscription list     mountPoint = Nothing          -- mount point for application (Nothing defaults to 'body')+    logLevel = Off                -- used during prerendering to see if the VDOM and DOM are in sync (only applies to `miso` function)  -- | Updates model, optionally introduces side effects updateModel :: Action -> Model -> Effect Action Model@@ -342,6 +343,7 @@     events = defaultEvents        -- default delegated events     subs   = []                   -- empty subscription list     mountPoint = Nothing          -- mount point for application (Nothing defaults to 'body')+    logLevel = Off                -- used during prerendering to see if the VDOM and DOM are in sync (only applies to `miso` function)  -- | Updates model, optionally introduces side effects updateModel :: Action -> Transition Action Model ()
exe/Main.hs view
@@ -37,7 +37,7 @@  -- | Entry point for a miso application main :: IO ()-main = runApp $ startApp App {..}+main = runApp $ miso $ \_ -> App {..}   where     initialAction = SayHelloWorld -- initial action to be executed on application load     model  = 0                    -- initial model@@ -46,6 +46,7 @@     events = defaultEvents        -- default delegated events     subs   = []                   -- empty subscription list     mountPoint = Nothing          -- mount point for application (Nothing defaults to 'body')+    logLevel = Off                -- Used to copy DOM into VDOM, applies only to `miso` function  -- | Updates model, optionally introduces side effects updateModel :: Action -> Model -> Effect Action Model
frontend-src/Miso.hs view
@@ -139,7 +139,7 @@     VTree (OI.Object iv) <- flip runView writeEvent initialView     mountEl <- mountElement mountPoint     -- Initial diff can be bypassed, just copy DOM into VTree-    copyDOMIntoVTree mountEl iv+    copyDOMIntoVTree (logLevel == DebugPrerender) mountEl iv     let initialVTree = VTree (OI.Object iv)     -- Create virtual dom, perform initial diff     liftIO (newIORef initialVTree)
frontend-src/Miso/Html/Internal.hs view
@@ -34,6 +34,7 @@   -- * Smart `View` constructors   , node   , text+  , textRaw   -- * Key patch internals   , Key    (..)   , ToKey  (..)@@ -130,7 +131,9 @@   set "tag" tag vnode   set "key" key vnode   setAttrs vnode sink-  flip (set "children") vnode =<< ghcjsPure . jsval =<< setKids sink+  flip (set "children") vnode+    =<< ghcjsPure . jsval+    =<< setKids sink   pure $ VTree vnode     where       setAttrs vnode sink =@@ -162,6 +165,10 @@   set "type" ("vtext" :: JSString) vtree   set "text" t vtree   pure $ VTree vtree++-- | For parity with server-side rendering. Don't use directly.+textRaw :: MisoString -> View m+textRaw = text  -- | `IsString` instance instance IsString (View a) where
frontend-src/Miso/Types.hs view
@@ -9,6 +9,7 @@ ---------------------------------------------------------------------------- module Miso.Types   ( App (..)+  , LogLevel (..)   , Effect   , Sub @@ -53,7 +54,15 @@   -- ^ Initial action that is run after the application has loaded   , mountPoint :: Maybe MisoString   -- ^ Id of the root element for DOM diff. If 'Nothing' is provided, the entire document body is used as a mount point.+  , logLevel :: LogLevel+  -- ^ Display warning messages when prerendering if the DOM and VDOM are not in sync.   }++-- | Optional Logging for debugging miso internals (useful to see if prerendering is successful)+data LogLevel+  = Off+  | DebugPrerender+  deriving (Show, Eq)  -- | A monad for succinctly expressing model transitions in the 'update' function. --
ghc-src/Miso/Html/Internal.hs view
@@ -30,6 +30,7 @@   -- * Smart `View` constructors   , node   , text+  , textRaw   -- * Key patch internals   , Key    (..)   , ToKey  (..)@@ -74,6 +75,14 @@            } -> VTree action   VText :: { vText :: Text -- ^ TextNode content            } -> VTree action+  -- Invariant: To avoid complexity with collapsing mixed VText and+  -- VTextRaw nodes, VTextRaw node is always the only child.+  -- That's not a big limitation, since the intended purpose is to be able+  -- to use <style> and <script> tags. That means we can't support HTML+  -- entities like &nbsp; with VTextRaw, but the same can be achieved with+  -- Unicode.+  VTextRaw :: { vText :: Text -- ^ Raw TextNode content+              } -> VTree action   deriving Functor  instance Show (VTree action) where@@ -84,6 +93,8 @@   toHtmlRaw = L.toHtml   toHtml (VText x) | T.null x = L.toHtml (" " :: MisoString)                    | otherwise = L.toHtml x+  toHtml (VTextRaw x) | T.null x = L.toHtml (" " :: MisoString)+                      | otherwise = L.toHtmlRaw x   toHtml VNode{..} =     let       noEnd = ["img", "input", "br", "hr", "meta"]@@ -114,8 +125,21 @@                      , "autocomplete"                      ]         toTag = T.toLower-        kids = foldMap L.toHtml vChildren+        kids+          = foldMap L.toHtml+          . V.fromList+          . collapseSiblingTextNodes+          . V.toList+          $ vChildren +collapseSiblingTextNodes :: [VTree a] -> [VTree a]+collapseSiblingTextNodes [] = []+collapseSiblingTextNodes (VText x : VText y : xs) =+  collapseSiblingTextNodes (VText (x <> y) : xs)+-- VTextRaw is the only child, so no need to collapse.+collapseSiblingTextNodes (x:xs) =+  x : collapseSiblingTextNodes xs+ -- | Helper for turning JSON into Text -- Object, Array and Null are kind of non-sensical here toHtmlFromJSON :: Value -> Text@@ -170,6 +194,10 @@ -- | `VText` creation text :: MisoString -> View action text = View . VText++-- | `VTextRaw` creation. Don't use directly+textRaw :: MisoString -> View action+textRaw = View . VTextRaw  -- | `IsString` instance instance IsString (View a) where
ghcjs-ffi/Miso/FFI.hs view
@@ -121,7 +121,6 @@ foreign import javascript unsafe "$1.preventDefault();"     eventPreventDefault :: JSVal -> IO () - -- | Window object foreign import javascript unsafe "$r = window;"   getWindow :: IO JSVal@@ -242,9 +241,10 @@  -- | Copies DOM pointers into virtual dom -- entry point into isomorphic javascript-foreign import javascript unsafe "window['copyDOMIntoVTree']($1, $2);"+foreign import javascript unsafe "window['copyDOMIntoVTree']($1, $2, $3);"   copyDOMIntoVTree-    :: JSVal -- ^ mountPoint element of the isomorphic app+    :: Bool  -- ^ Display debugging information when pre-rendering+    -> JSVal -- ^ mountPoint element of the isomorphic app     -> JSVal -- ^ VDom object     -> IO () 
jsaddle-ffi/Miso/FFI.hs view
@@ -18,16 +18,12 @@    , objectToJSVal    , ghcjsPure    , syncPoint-    , addEventListener    , windowAddEventListener-    , windowInnerHeight    , windowInnerWidth-    , eventPreventDefault    , eventStopPropagation-    , now    , consoleLog    , consoleLogJSVal@@ -40,19 +36,14 @@    , getDoc    , getElementById    , diff'-    , integralToJSString    , realFloatToJSString    , jsStringToDouble-    , delegateEvent-    , copyDOMIntoVTree-    , swapCallbacks    , releaseCallbacks    , registerCallback-    , focus    , blur    , scrollIntoView@@ -220,7 +211,7 @@  delegateEvent :: JSVal -> JSVal -> JSM JSVal -> JSM () delegateEvent mountPoint events getVTree = do-  cb' <- function $ \_ _ [continuation] -> do+  cb' <- asyncFunction $ \_ _ [continuation] -> do     res <- getVTree     _ <- call continuation global res     pure ()@@ -231,8 +222,8 @@  -- | Copies DOM pointers into virtual dom -- entry point into isomorphic javascript-copyDOMIntoVTree :: JSVal -> JSVal -> JSM ()-copyDOMIntoVTree mountPoint a = () <$ jsg2 "copyDOMIntoVTree" mountPoint a+copyDOMIntoVTree :: Bool -> JSVal -> JSVal -> JSM ()+copyDOMIntoVTree logLevel mountPoint a = () <$ jsg3 "copyDOMIntoVTree" logLevel mountPoint a  -- TODO For now, we do not free callbacks when compiling with JSaddle 
jsbits/isomorphic.js view
@@ -1,19 +1,57 @@ window = typeof window === 'undefined' ? {} : window;-window['copyDOMIntoVTree'] = function copyDOMIntoVTree(mountPoint, vtree, doc) {+window['collapseSiblingTextNodes'] = function collapseSiblingTextNodes(vs) {+  if (!vs) { return []; }+  var ax = 0, adjusted = vs.length > 0 ? [vs[0]] : [];+  for (var ix = 1; ix < vs.length; ix++) {+    if (adjusted[ax]['type'] === 'vtext' && vs[ix]['type'] === 'vtext') {+	adjusted[ax]['text'] += vs[ix]['text'];+	continue;+    }+    adjusted[++ax] = vs[ix];+  }+  return adjusted;+}++window['copyDOMIntoVTree'] = function copyDOMIntoVTree(logLevel,mountPoint, vtree, doc) {   if (!doc) { doc = window.document; }-  var node = mountPoint ? mountPoint.firstChild : doc.body.firstChild;-  if (!window['walk'](vtree, node, doc)) {-    console.warn('Could not copy DOM into virtual DOM, falling back to diff');+    var mountChildIdx = 0, node;+    // If script tags are rendered first in body, skip them.+    if (!mountPoint) {+	if (doc.body.childNodes.length > 0) {+	    node = doc.body.firstChild;+	} else {+	    node = doc.body.appendChild (doc.createElement('div'));+	}+    } else if (mountPoint.childNodes.length === 0) {+	node = mountPoint.appendChild (doc.createElement('div'));+    } else {+	while (mountPoint.childNodes[mountChildIdx].localName === 'script' || mountPoint.childNodes[mountChildIdx].nodeType === Node.TEXT_NODE){+	  mountChildIdx++;+	}+	node = mountPoint.childNodes[mountChildIdx];+    }++    if (!window['walk'](logLevel,vtree, node, doc)) {+    if (logLevel) {+      console.warn('Could not copy DOM into virtual DOM, falling back to diff');+    }     // Remove all children before rebuilding DOM-    while (node.firstChild)-      node.removeChild(node.lastChild);-    window['diff'](null, vtree, node, doc);+    while (node.firstChild) node.removeChild(node.lastChild);+    vtree['domRef'] = node;+    window['populate'](null, vtree, doc);     return false;   }+  if (logLevel) {+    console.info ('Successfully prendered page');+  }   return true; } -window['walk'] = function walk(vtree, node, doc) {+window['diagnoseError'] = function diagnoseError(logLevel, vtree, node) {+    if (logLevel) console.warn('VTree differed from node', vtree, node);+}++window['walk'] = function walk(logLevel, vtree, node, doc) {   // This is slightly more complicated than one might expect since   // browsers will collapse consecutive text nodes into a single text node.   // There can thus be fewer DOM nodes than VDOM nodes.@@ -25,35 +63,31 @@   // Fire onCreated events as though the elements had just been created.   window['callCreated'](vtree); +  vtree.children = window['collapseSiblingTextNodes'](vtree.children);   for (var i = 0; i < vtree.children.length; i++) {     vdomChild = vtree['children'][i];     domChild = node.childNodes[i];+      if (!domChild) {+	  window['diagnoseError'](logLevel,vdomChild, domChild);+	  return false;+      }     if (vdomChild.type === 'vtext') {-        if (domChild.nodeType !== Node.TEXT_NODE) return false;+        if (domChild.nodeType !== Node.TEXT_NODE) {+  	    window['diagnoseError'](logLevel, vdomChild, domChild);+	    return false;+	}          if (vdomChild['text'] === domChild.textContent) {           vdomChild['domRef'] = domChild;         } else {-          var len = vdomChild.text.length,-              domNodeText = domChild.textContent.substring(0, len);-          if (domNodeText !== vdomChild.text) return false;--          // There are more VDOM nodes than DOM nodes-          // Create new DOM node to ensure synchrony between VDom and DOM-          var partialTxt = doc.createTextNode(domNodeText);-          node.insertBefore(partialTxt, domChild);-          vdomChild['domRef'] = partialTxt;-          domChild.textContent = domChild.textContent.substring(len);-        }+          window['diagnoseError'](logLevel, vdomChild, domChild);+          return false;+	}     } else {       if (domChild.nodeType !== Node.ELEMENT_NODE) return false;-      window['walk'](vdomChild, domChild, doc);+      vdomChild['domRef'] = domChild;+      if(!window['walk'](logLevel, vdomChild, domChild, doc)) return false;     }-   }-  // After walking the sizes of VDom and DOM should be equal-  // Otherwise there are DOM nodes unaccounted for-  if (vtree.children.length !== node.childNodes.length) return false;-   return true; }
miso.cabal view
@@ -1,5 +1,5 @@ name:                miso-version:             1.6.0.0+version:             1.7.0.0 category:            Web, Miso, Data Structures license:             BSD3 license-file:        LICENSE
src/Miso/Html.hs view
@@ -34,7 +34,7 @@    , module Miso.Html.Property    ) where -import Miso.Html.Element+import Miso.Html.Element hiding (style_) import Miso.Html.Event-import Miso.Html.Internal+import Miso.Html.Internal hiding (textRaw) import Miso.Html.Property hiding (form_)
src/Miso/Html/Element.hs view
@@ -52,6 +52,7 @@     , math_     , script_     , link_+    , Miso.Html.Element.style_     -- * Inputs     , select_     , option_@@ -484,9 +485,28 @@ -- | https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q q_ :: [Attribute action] -> [View action] -> View action q_ = nodeHtml "q"--- | https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script-script_ :: [Attribute action] -> [View action] -> View action-script_ = nodeHtml "script" -- | https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link link_ :: [Attribute action] -> View action link_ = flip (nodeHtml "link") []+-- | https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style+-- This takes the raw text to be put in the style tag.+-- That means that if any part of the text is not trusted there's+-- a potential CSS injection. Read more at+-- https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client_Side_Testing/05-Testing_for_CSS_Injection+--+-- You can also easily shoot yourself in the foot with something like:+--+--   style_ [] "</style>"+style_ :: [Attribute action] -> MisoString -> View action+style_ attrs rawText = node HTML "style" Nothing attrs [textRaw rawText]+-- | https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script+-- This takes the raw text to be put in the script tag.+-- That means that if any part of the text is not trusted there's+-- a potential JavaScript injection. Read more at+-- https://owasp.org/www-community/attacks/xss/+--+-- You can also easily shoot yourself in the foot with something like:+--+--   script_ [] "</script>"+script_ :: [Attribute action] -> MisoString -> View action+script_ attrs rawText = node HTML "script" Nothing attrs [textRaw rawText]