~subsetpark/bagatto

e1f4d7642760077da2b74d8a4f62c26cb553d745 — Zach Smith 10 months ago 732fbaf
Add defaults
3 files changed, 67 insertions(+), 28 deletions(-)

M bagatto.janet
M demo/index.janet
M main.janet
M bagatto.janet => bagatto.janet +22 -0
@@ 7,6 7,28 @@

(import src/multimarkdown)

(defn set-defaults!
  ``
  Set default values for the attributes specified in data and site
  specifications. For instance, setting the default of `:attrs` to
  `bagatto/json-attrs` will treat all source files as json files,
  unless a different `:attrs` is specified.
  ``
  [defaults]
  (setdyn :bagatto-defaults defaults))

(defn default
  ``
  Get a default value for the given attribute. Can be used for a
  simple form of inheritence; if you have a default callback or value
  set, and you have some specific handler that needs to build on top
  of that functionality, you can call `bagatto/default` to get or
  evaluate it inside of the handler and then implement your more
  specific logic.
  ``
  [attribute]
  (-> (dyn :bagatto-defaults) (in attribute)))

#
# DATA
#

M demo/index.janet => demo/index.janet +13 -2
@@ 74,6 74,14 @@
# Bagatto API
#

## Bagatto offers the ability to set default values for any of the
## attributes that it expects to find in a data or site specification
## (which we'll see below). Here we set the `attrs` default to
## `jdn-attrs`, which means that, in our `data` struct, if we don't
## specify an attrs attribute, Bagatto will assume it refers to a jdn
## file.
(bagatto/set-defaults! {:attrs bagatto/jdn-attrs})

## A Bagatto index module has to define to variables:
## * `data` is a struct mapping data entry *names* to data *specifications*.
## * `site` is a struct describing all of the files that are to be


@@ 89,10 97,13 @@
##   it. Since it will stream multiple files, `post-attrs` is a
##   function which will be called on each file.
(def data {:config {:attrs {:title "A Demo Bagatto Config"}}
           :config-file {:src "config.jdn" :attrs bagatto/jdn-attrs}
           :config-json {:src "config.json" :attrs bagatto/json-attrs}
           :posts {:src (bagatto/* "posts/*.md")
                   :attrs post-attrs}})
                   :attrs post-attrs}
           # NB: We don't specify `:attrs` here; we set a default
           # value above.
           :config-file {:src "config.jdn"}}
  )

(def index-path "site/index.html")
## Likewise, our `site` struct has two entries (though they don't map

M main.janet => main.janet +32 -26
@@ 38,7 38,10 @@
    (f ;args)
    f))

(defn load-data [data-spec]
(defn- struct->table [s] (->> s (kvs) (splice) (table)))
(defn- set-defaults [spec defaults] (table/setproto (struct->table spec) (struct->table defaults)))

(defn load-data [data-spec defaults]
  ``
  First phase of main business logic. `data-spec` contains a
  specification of all the sources necessary to generate our `attrs`


@@ 47,19 50,20 @@
  ``
  (let [res @{}]
    (loop [[entry spec] :pairs data-spec]
      (put res entry (match spec
                       ({:src loader :attrs attrs-f} (fiber? loader))
                       (seq [[filename file-contents] :generate loader]
                            (->> @{:path filename :src file-contents}
                                 (attrs-f file-contents)))
                       ({:src path :attrs attrs-f} (string? path))
                       (let [file-contents (slurp path)]
                         (->> @{:path path :src file-contents} (attrs-f file-contents)))
                       {:attrs attrs}
                       attrs)))
      (let [with-defaults (set-defaults spec defaults)]
        (put res entry (match with-defaults
                         ({:src loader :attrs attrs-f} (fiber? loader))
                         (seq [[filename file-contents] :generate loader]
                              (->> @{:path filename :src file-contents}
                                   (attrs-f file-contents)))
                         ({:src path :attrs attrs-f} (string? path))
                         (let [file-contents (slurp path)]
                           (->> @{:path path :src file-contents} (attrs-f file-contents)))
                         {:attrs attrs}
                         attrs))))
    res))

(defn produce-writers [site data]
(defn produce-writers [site data defaults]
  ``
  Second phase of main business logic. `site` contains a specification
  for generating a website and `data` is all the source data we have to


@@ 68,20 72,21 @@
  ``
  (let [writers @[]]
    (loop [[_entry spec] :pairs site]
      (match spec
        {:each site-selector
         :path path-f
         :contents contents-f}
        (loop [item :in (data site-selector)]
          (let [path (maybe-apply path-f [data item])
                contents (maybe-apply contents-f [data item])
                writer (new-writer path contents)]
            (array/push writers writer)))
        {:path path-f :contents contents-f}
        (let [path (maybe-apply path-f [data])
      (let [with-defaults (set-defaults spec defaults)]
        (match with-defaults
          {:each site-selector
           :path path-f
           :contents contents-f}
          (loop [item :in (data site-selector)]
            (let [path (maybe-apply path-f [data item])
                  contents (maybe-apply contents-f [data item])
                  writer (new-writer path contents)]
              (array/push writers writer)))
          {:path path-f :contents contents-f}
          (let [path (maybe-apply path-f [data])
                contents (maybe-apply contents-f [data])
                writer (new-writer path contents)]
          (array/push writers writer))))
            (array/push writers writer)))))
    writers))

(defn main [& [_ index]]


@@ 91,9 96,10 @@

  (let [env (load-file index)
        _ (merge-into temple/base-env env)
        defaults (env :bagatto-defaults)
        data-spec ((env 'data) :value)
        data (load-data data-spec)
        data (load-data data-spec defaults)
        site ((env 'site) :value)
        writers (produce-writers site data)]
        writers (produce-writers site data defaults)]
    
    (each writer writers (resume writer))))