Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions examples/components/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
{-# LANGUAGE CPP #-}
module Main where

import Control.Monad.IO.Class (liftIO)
import Control.Monad.IO.Class (liftIO)

import Miso
import Miso.String
import Miso
import Miso.String

type Model = Int

Expand Down Expand Up @@ -37,7 +37,7 @@ main :: IO ()
main = run (startComponent mainComponent)

mainComponent :: Component "main" MainModel MainAction
mainComponent = component app
mainComponent = component app { logLevel = DebugPrerender }

app :: App MainModel MainAction
app = defaultApp True updateModel1 viewModel1 MainNoOp
Expand All @@ -53,7 +53,7 @@ component4 = component counterApp4

-- | Constructs a virtual DOM from a model
viewModel1 :: MainModel -> View MainAction
viewModel1 x = div_ [ id_ "Main application" ]
viewModel1 x = div_ []
[ "Component 1 - Three sub components nested recursively below me"
, br_ []
, "The +/- for Components 3 and 4 will affect the state of Component 2"
Expand Down
2 changes: 1 addition & 1 deletion examples/shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ then miso-examples-ghc.env.overrideAttrs (d: {
'';
})
else
miso-examples-ghcjs.env
miso-examples.env
118 changes: 116 additions & 2 deletions jsbits/isomorphic.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@ window['copyDOMIntoVTree'] = function copyDOMIntoVTree(logLevel,mountPoint, vtre
window['populate'](null, vtree, doc);
return false;
}
if (logLevel) {
console.info ('Successfully prendered page');
if (logLevel) {
var result = window['integrityCheck'](true, vtree);
if (!result) {
console.warn ('Integrity check completed with errors');
} else {
console.info ('Successfully prerendered page');
}
}
return true;
}
Expand All @@ -53,6 +58,115 @@ window['diagnoseError'] = function diagnoseError(logLevel, vtree, node) {
if (logLevel) console.warn('VTree differed from node', vtree, node);
}

// https://stackoverflow.com/questions/11068240/what-is-the-most-efficient-way-to-parse-a-css-color-in-javascript
window['parseColor'] = function(input) {
if (input.substr(0,1)=="#") {
var collen=(input.length-1)/3;
var fact=[17,1,0.062272][collen-1];
return [
Math.round(parseInt(input.substr(1,collen),16)*fact),
Math.round(parseInt(input.substr(1+collen,collen),16)*fact),
Math.round(parseInt(input.substr(1+2*collen,collen),16)*fact)
];
}
else return input.split("(")[1].split(")")[0].split(",").map(x=>+x);
}

// dmj: Does deep equivalence check, spine and leaves of virtual DOM to DOM.
window['integrityCheck'] = function (result, vtree) {
// text nodes must be the same
if (vtree['type'] == 'vtext') {
if (vtree['text'] !== vtree['domRef'].textContent) {
console.warn ('VText node content differs', vtree);
result = false;
} else {
console.info('VText nodes are identical proceed', '"' + vtree['text'] + '"');
}
}

// if vnode / vcomp, must be the same
else {

// tags must be identical
if (vtree['tag'].toUpperCase() !== vtree['domRef'].tagName) {
console.warn ('Integrity check failed, tags differ', vtree['tag'].toUpperCase(), vtree['domRef'].tagName);
result = false;
} else if (vtree['type'] === 'vnode') {
console.info('VNode tags are identical proceed', vtree['tag']);
} else {
console.info('VComp tags are identical proceed', vtree['tag']);
}

// Child lengths must be identical
if ('children' in vtree && vtree['children'].length !== vtree['domRef'].childNodes.length) {
console.warn ('Integrity check failed, children lengths differ', vtree, vtree.children, vtree['domRef'].childNodes);
result = false;
}

// properties must be identical
var keyLength = Object.keys(vtree['props']).length; key = null;
for (var i = 0; i < keyLength; i++) {
key = Object.keys(vtree['props'])[i];
if (key === 'height' || key === 'width') {
if (parseFloat(vtree['props'][key]) !== parseFloat(vtree['domRef'][key])) {
console.warn ('Property ' + key + ' differs', vtree['props'][key], vtree['domRef'][key]);
result = false;
} else {
console.log('Properties are identical', '{ ' + key + ' : ' + vtree['props'][key] + ' }');
}
}
else if (key === 'class' || key === 'className') {
if (vtree['props'][key] !== vtree['domRef'].className) {
console.warn ('Property class differs', vtree['props'][key], vtree['domRef'].className)
result = false;
} else {
console.log('Properties are identical', '{ ' + key + ' : ' + vtree['props'][key] + ' }');
}
} else if (!vtree['domRef'][key]) {
if (vtree['props'][key] !== vtree['domRef'].getAttribute(key)) {
console.warn ('Property ' + key + ' differs', vtree['props'][key], vtree['domRef'].getAttribute(key));
result = false;
} else {
console.log('Properties are identical', '{ ' + key + ' : ' + vtree['props'][key] + ' }');
}
}
else if (vtree['props'][key] !== vtree['domRef'][key]) {
console.warn ('Property ' + key + ' differs', vtree['props'][key], vtree['domRef'][key]);
result = false;
} else {
console.log('Properties are identical', '{ ' + key + ' : ' + vtree['props'][key] + ' }');
}
}

// styles must be identical
keyLength = Object.keys(vtree['css']).length;
for (var i = 0; i < keyLength; i++) {
key = Object.keys(vtree['css'])[i];
if (key === 'color') {
if (window['parseColor'](vtree['domRef'].style[key]).toString() !== window['parseColor'](vtree['css'][key]).toString()) {
console.warn ('Style ' + key + ' differs', vtree['css'][key], vtree['domRef'].style[key]);
result = false;
} else {
console.log('Styles are identical', key + ' : ' + vtree['css'][key] + ';');
}
}
else if (vtree['css'][key] !== vtree['domRef'].style[key]) {
console.warn ('Style ' + key + ' differs', vtree['css'][key], vtree['domRef'].style[key]);
result = false;
} else {
console.log('Styles are identical', key + ' : ' + vtree['css'][key] + ';');
}
}

// recursive call for `vnode` / `vcomp`
for (var i = 0; i < vtree.children.length; i++) {
result &= window['integrityCheck'](result, vtree.children[i]);
}
}
return result;
}


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.
Expand Down
1 change: 0 additions & 1 deletion src/Miso.hs
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,3 @@ withJS action = void $ do
_ <- eval ($(embedStringFile "jsbits/util.js") :: JSString)
#endif
action

25 changes: 12 additions & 13 deletions src/Miso/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -206,19 +206,15 @@ initComponent
-> Sink action
-> JSM (MisoString, JSVal, IORef VTree)
initComponent prerender name App {..} snk = do
vtree@(VTree (Object jval)) <- runView prerender (view model) snk
vtree <- runView prerender (view model) snk
el <- getComponent name
if prerender == Prerender
then
copyDOMIntoVTree (logLevel == DebugPrerender) el jval
else
diff el Nothing (Just vtree)
when (prerender == DontPrerender) $
diff el Nothing (Just vtree)
ref <- liftIO (newIORef vtree)
pure (name, el, ref)

runView :: Prerender -> View action -> Sink action -> JSM VTree
runView prerender (Embed (SomeComponent (Component name app)) (ComponentOptions {..})) snk = do
vcomp <- create
let mount = name
-- By default components should be mounted sychronously.
-- We also include async mounting for tools like jsaddle-warp.
Expand All @@ -245,17 +241,20 @@ runView prerender (Embed (SomeComponent (Component name app)) (ComponentOptions
liftIO (killThread tid)
liftIO $ modifyIORef' componentMap (M.delete mount)

set "type" ("vcomp" :: JSString) vcomp
set "tag" ("div" :: JSString) vcomp
forM_ componentKey $ \(Key key) -> set "key" key vcomp
vcomp <- create
cssObj <- create
propsObj <- create
set "props" propsObj vcomp
eventsObj <- create
setAttrs vcomp attributes snk
set "css" cssObj vcomp
set "props" propsObj vcomp
set "events" eventsObj vcomp
set "type" ("vcomp" :: JSString) vcomp
set "ns" HTML vcomp
set "data-component-id" mount vcomp
set "tag" ("div" :: JSString) vcomp
set "key" componentKey vcomp
setAttrs vcomp attributes snk
flip (set "children") vcomp =<< toJSVal ([] :: [MisoString])
set "data-component-id" mount vcomp
flip (set "mount") vcomp =<< toJSVal mountCb
set "unmount" unmountCb vcomp
pure (VTree vcomp)
Expand Down