<commit_before>xquery version "3.1";

(: http://limpet.net/mbrubeck/2014/09/08/toy-layout-engine-5-boxes.html :)
(: https://github.com/tel/frame :)
(: https://github.com/tel/frame/blob/master/src/frame/fstate.clj :)
(: http://www.ibm.com/developerworks/library/j-treevisit/ :)
(: https://github.com/akhudek/zip-visit :)

module namespace ex = 'http://xokomola.com/xquery/origami/examples';

import module namespace o = 'http://xokomola.com/xquery/origami'
    at '../../origami/origami.xqm';

declare function ex:report($node)
{
    let $report := trace(o:tag($node), 'TAG: ')
    return
        $node
};

declare function ex:advise-dimensions($node, $width, $height)
{
    array {
        o:tag($node),
        map:merge((
            map { 
                'width': $width,
                'height': $height
            },
            o:attrs($node)
        )),
        o:children($node)
    }
};

declare function ex:collect-attribute($nodes, $attribute)
{
    fold-left(
        $nodes,
        [],
        function($result,$item) {
            array:append($result,o:attrs($item)($attribute))
        }
    )
};

declare function ex:count-attribute($nodes, $attribute)
as xs:integer
{
    sum(
        for $node in $nodes
        where o:attrs($node)($attribute)
        return 1
    )
};

declare function ex:layout-node-children($node)
{
    let $tag := o:tag($node)
    let $attrs := o:attrs($node)
    let $children := o:children($node)
    let $child-count := count($children)
    let $width := $attrs?width
    let $height := $attrs?height
    return
        array {
            $tag,
            $attrs,
            if ($tag = 'hbox') then
                let $child-widths := ex:collect-attribute($children,'width')
                let $advised-width := 
                    ($width - sum($child-widths)) 
                    div ($child-count - ex:count-attribute($children,'width'))
                for $child in $children
                return
                    ex:advise-dimensions($child, $advised-width, $height)
            else
                let $child-heights := ex:collect-attribute($children,'height') 
                let $advised-height := 
                    ($height - sum($child-heights)) 
                    div ($child-count - ex:count-attribute($children,'height'))
                for $child in $children
                return
                    ex:advise-dimensions($child, $width, $advised-height)
        }
};

declare function ex:layout-node($node)
{
    let $tag := o:tag($node)
    let $attrs := o:attrs($node)
    let $children := o:children($node)
    let $height := 40
    let $width := 100
    return
        if (count($children) = 0) then
            ex:advise-dimensions($node,
                $width,
                $height
            )        
        else if ($tag = 'hbox') then
            ex:advise-dimensions($node,
                sum(o:map($children, function($n) { o:attrs($n)?width })),
                max(o:map($children, function($n) { o:attrs($n)?height }))
            )
        else
            ex:advise-dimensions($node,
                max(o:map($children, function($n) { o:attrs($n)?width })),
                sum(o:map($children, function($n) { o:attrs($n)?height }))<commit_msg>Preparing for positioning<commit_after>xquery version "3.1";

(: http://limpet.net/mbrubeck/2014/09/08/toy-layout-engine-5-boxes.html :)
(: https://github.com/tel/frame :)
(: https://github.com/tel/frame/blob/master/src/frame/fstate.clj :)
(: http://www.ibm.com/developerworks/library/j-treevisit/ :)
(: https://github.com/akhudek/zip-visit :)

module namespace ex = 'http://xokomola.com/xquery/origami/examples';

import module namespace o = 'http://xokomola.com/xquery/origami'
    at '../../origami/origami.xqm';

declare function ex:report($node)
{
    let $report := trace(o:tag($node), 'TAG: ')
    return
        $node
};

declare function ex:advise-dimensions($node, $width, $height)
{
    array {
        o:tag($node),
        map:merge((
            map { 
                'width': $width,
                'height': $height
            },
            o:attrs($node)
        )),
        o:children($node)
    }
};

declare function ex:collect-attribute($nodes, $attribute)
{
    fold-left(
        $nodes,
        [],
        function($result,$item) {
            array:append($result,o:attrs($item)($attribute))
        }
    )
};

declare function ex:count-attribute($nodes, $attribute)
as xs:integer
{
    sum(
        for $node in $nodes
        where o:attrs($node)($attribute)
        return 1
    )
};

declare function ex:advise($a,$b)
{
    let $b :=
        if ($b instance of array(*)) then 
            $b
        else
            array { for $i in 1 to array:size($a) return $b }
    return
        array:for-each-pair($a,$b, function($a,$b) { ($a,$b)[1] })
};

declare function ex:layout-node-children($node)
{
    let $tag := o:tag($node)
    let $attrs := o:attrs($node)
    let $children := o:children($node)
    let $child-count := count($children)
    let $width := $attrs?width
    let $height := $attrs?height
    return
        array {
            $tag,
            $attrs,
            if ($tag = 'hbox') then
                let $child-widths := ex:collect-attribute($children,'width')
                let $advised-width := 
                    ($width - sum($child-widths)) 
                    div ($child-count - ex:count-attribute($children,'width'))
                let $advice := ex:advise($child-widths, $advised-width)
                for $child at $pos in $children
                return 
                    $child => o:set-attr(map { 'height': $height, 'width': $advice($pos) })
            else
                let $child-heights := ex:collect-attribute($children,'height') 
                let $advised-height := 
                    ($height - sum($child-heights)) 
                    div ($child-count - ex:count-attribute($children,'height'))
                let $advice := ex:advise($child-heights, $advised-height)
                for $child at $pos in $children
                return
                    $child => o:set-attr(map { 'width': $width, 'height': $advice($pos) })
        }
};

declare function ex:layout-node($node)
{
    let $tag := o:tag($node)
    let $attrs := o:attrs($node)
    let $children := o:children($node)
    let $height := 40
    let $width := 100
    return
        if (count($children) = 0) then
            ex:advise-dimensions($node,
                $width,
                $height
            )        
        else if ($tag = 'hbox') then
            ex:advise-dimensions($node,
                sum(o:map($children, function($n) { o:attrs($n)?width })),
                max(o:map($children, function($n) { o:attrs($n)?height }))
            )
        else
            ex:advise-dimensions($node,
                max(o:map($children, function($n) { o:attrs($n)?width })),
                sum(o:map($children, function($n) { o:attrs($n)?height }))
{'fraction_non_alphanumeric': 0.16368579195879238, 'fraction_numerical': 0.005437115467162685, 'mean_word_length': 1.916145181476846, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 6, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3575130', 'n_tokens_mistral': 2221, 'n_tokens_neox': 2112, 'n_words': 402}