|
753 | 753 | paths (grouper (filter-meta-by-ext fileset options))] |
754 | 754 | (if (seq paths) |
755 | 755 | (reduce |
756 | | - (fn [result [path {:keys [entries group-meta]}]] |
| 756 | + (fn [result [path {:keys [entry entries]}]] |
757 | 757 | (let [sorted (->> entries |
758 | 758 | (sort-by sortby comparator) |
759 | 759 | (map #(assoc % :content (->> (:path %) |
760 | 760 | (boot/tmp-get fileset) |
761 | 761 | boot/tmp-file |
762 | 762 | slurp)))) |
763 | 763 | new-path (perun/create-filepath out-dir path) |
764 | | - new-entry (assoc group-meta :out-dir out-dir)] |
765 | | - (perun/report-info task-name (str "rendered " task-name " " path)) |
| 764 | + new-entry (assoc entry :out-dir out-dir)] |
766 | 765 | (assoc result new-path {:meta global-meta |
767 | 766 | :entry new-entry |
768 | 767 | :entries (vec sorted)}))) |
|
772 | 771 | (perun/report-info task-name (str task-name " found nothing to render")) |
773 | 772 | [])))) |
774 | 773 |
|
775 | | -(def ^:private +collection-defaults+ |
| 774 | +(defn assortment-pre-wrap |
| 775 | + "Handles common assortment task orchestration |
| 776 | +
|
| 777 | + `task-name` is used for log messages. `tracer` is a keyword that gets added |
| 778 | + to the `:io.perun/trace` metadata. `grouper` is a function that takes a seq |
| 779 | + of entries and returns a map of paths to render data (see docstring for |
| 780 | + `assortment` for more info) |
| 781 | +
|
| 782 | + Returns a boot `with-pre-wrap` result" |
| 783 | + [{:keys [task-name tracer grouper options]}] |
| 784 | + (cond (not (fn? (:comparator options))) |
| 785 | + (u/fail (str task-name " task :comparator option should implement Fn\n")) |
| 786 | + (not (ifn? (:filterer options))) |
| 787 | + (u/fail (str task-name " task :filterer option value should implement IFn\n")) |
| 788 | + (not (ifn? (:sortby options))) |
| 789 | + (u/fail (str task-name " task :sortby option value should implement IFn\n")) |
| 790 | + (not (ifn? grouper)) |
| 791 | + (u/fail (str task-name " task :grouper option value should implement IFn\n")) |
| 792 | + :else |
| 793 | + (let [;; Make sure task-level metadata gets added to each entry |
| 794 | + meta-grouper (fn [entries] |
| 795 | + (->> entries |
| 796 | + grouper |
| 797 | + (map (fn [[path data]] |
| 798 | + [path (update-in data [:entry] #(merge (:meta options) %))])) |
| 799 | + (into {}))) |
| 800 | + options (assoc options :grouper meta-grouper)] |
| 801 | + (render-pre-wrap {:task-name task-name |
| 802 | + :render-paths-fn (partial grouped-paths task-name) |
| 803 | + :options options |
| 804 | + :tracer tracer})))) |
| 805 | + |
| 806 | +(def ^:private +assortment-defaults+ |
776 | 807 | {:out-dir "public" |
777 | 808 | :filterer identity |
778 | 809 | :extensions [".html"] |
779 | 810 | :sortby (fn [file] (:date-published file)) |
| 811 | + :comparator (fn [i1 i2] (compare i2 i1)) |
| 812 | + :grouper #(-> {"index.html" {:entries %}})}) |
| 813 | + |
| 814 | +(deftask assortment |
| 815 | + "Render multiple collections |
| 816 | + The symbol supplied as `renderer` should resolve to a function |
| 817 | + which will be called with a map containing the following keys: |
| 818 | + - `:meta`, global perun metadata |
| 819 | + - `:entry`, the metadata for this collection |
| 820 | + - `:entries`, all entries |
| 821 | +
|
| 822 | + The `grouper` function will be called with a seq containing the |
| 823 | + entries to be grouped, and it should return a map with keys that |
| 824 | + are filenames and values that are maps with the keys: |
| 825 | + - `:entries`: the entries for each collection |
| 826 | + - `:entry`: (optional) page metadata for this collection |
| 827 | +
|
| 828 | + Entries can optionally be filtered by supplying a function |
| 829 | + to the `filterer` option. |
| 830 | +
|
| 831 | + The `sortby` function can be used for ordering entries before rendering." |
| 832 | + [o out-dir OUTDIR str "the output directory" |
| 833 | + r renderer RENDERER sym "page renderer (fully qualified symbol resolving to a function)" |
| 834 | + g grouper GROUPER code "group posts function, keys are filenames, values are to-be-rendered entries" |
| 835 | + _ filterer FILTER code "predicate to use for selecting entries (default: `identity`)" |
| 836 | + e extensions EXTENSIONS [str] "extensions of files to include" |
| 837 | + s sortby SORTBY code "sort entries by function" |
| 838 | + c comparator COMPARATOR code "sort by comparator function" |
| 839 | + m meta META edn "metadata to set on each collection entry"] |
| 840 | + (let [grouper (or grouper #(-> {"index.html" {:entries %}})) |
| 841 | + options (merge +assortment-defaults+ (dissoc *opts* :grouper))] |
| 842 | + (assortment-pre-wrap {:task-name "assortment" |
| 843 | + :tracer :io.perun/assortment |
| 844 | + :grouper grouper |
| 845 | + :options options}))) |
| 846 | + |
| 847 | +(def ^:private +collection-defaults+ |
| 848 | + {:out-dir "public" |
| 849 | + :filterer identity |
| 850 | + :extensions [".html"] |
| 851 | + :sortby :date-published |
780 | 852 | :comparator (fn [i1 i2] (compare i2 i1))}) |
781 | 853 |
|
782 | 854 | (deftask collection |
|
790 | 862 | Entries can optionally be filtered by supplying a function |
791 | 863 | to the `filterer` option. |
792 | 864 |
|
793 | | - The `sortby` and `groupby` functions can be used for ordering entries |
| 865 | + The `sortby` function can be used for ordering entries |
794 | 866 | before rendering as well as rendering groups of entries to different pages." |
795 | 867 | [o out-dir OUTDIR str "the output directory" |
796 | 868 | r renderer RENDERER sym "page renderer (fully qualified symbol resolving to a function)" |
797 | 869 | _ filterer FILTER code "predicate to use for selecting entries (default: `identity`)" |
798 | 870 | e extensions EXTENSIONS [str] "extensions of files to include" |
799 | 871 | s sortby SORTBY code "sort entries by function" |
800 | | - g groupby GROUPBY code "group posts by function, keys are filenames, values are to-be-rendered entries" |
801 | 872 | c comparator COMPARATOR code "sort by comparator function" |
802 | 873 | p page PAGE str "collection result page path" |
803 | 874 | m meta META edn "metadata to set on each collection entry"] |
804 | | - (let [options (merge +collection-defaults+ |
805 | | - (dissoc *opts* :page) |
806 | | - (if page |
807 | | - {:grouper #(-> {page {:entries % |
808 | | - :group-meta meta}})} |
809 | | - (if groupby |
810 | | - {:grouper #(->> % |
811 | | - (group-by groupby) |
812 | | - (map (fn [[page entries]] |
813 | | - [page {:entries entries |
814 | | - :group-meta meta}])) |
815 | | - (into {}))} |
816 | | - {:grouper #(-> {"index.html" {:entries % |
817 | | - :group-meta meta}})})))] |
818 | | - (cond (not (fn? (:comparator options))) |
819 | | - (u/fail "collection task :comparator option should implement Fn\n") |
820 | | - (not (ifn? (:filterer options))) |
821 | | - (u/fail "collection task :filterer option value should implement IFn\n") |
822 | | - (and (:page options) groupby) |
823 | | - (u/fail "using the :page option will render any :groupby option setting effectless\n") |
824 | | - (and (:groupby options) (not (ifn? (:groupby options)))) |
825 | | - (u/fail "collection task :groupby option value should implement IFn\n") |
826 | | - (not (ifn? (:sortby options))) |
827 | | - (u/fail "collection task :sortby option value should implement IFn\n") |
828 | | - :else |
829 | | - (let [collection-paths (partial grouped-paths "collection")] |
830 | | - (render-pre-wrap {:task-name"collection" |
831 | | - :render-paths-fn collection-paths |
832 | | - :options options |
833 | | - :tracer :io.perun/collection}))))) |
| 875 | + (let [p (or page "index.html")] |
| 876 | + (assortment-pre-wrap {:task-name "collection" |
| 877 | + :tracer :io.perun/collection |
| 878 | + :grouper #(-> {p {:entries %}}) |
| 879 | + :options (merge +collection-defaults+ (dissoc *opts* :page))}))) |
834 | 880 |
|
835 | 881 | (def +inject-scripts-defaults+ |
836 | 882 | {:extensions [".html"]}) |
837 | 883 |
|
| 884 | +(def ^:private +paginate-defaults+ |
| 885 | + {:out-dir "public" |
| 886 | + :prefix "page-" |
| 887 | + :page-size 10 |
| 888 | + :filterer identity |
| 889 | + :extensions [".html"] |
| 890 | + :sortby (fn [file] (:date-published file)) |
| 891 | + :comparator (fn [i1 i2] (compare i2 i1))}) |
| 892 | + |
| 893 | +(deftask paginate |
| 894 | + "Render multiple collections |
| 895 | + The symbol supplied as `renderer` should resolve to a function |
| 896 | + which will be called with a map containing the following keys: |
| 897 | + - `:meta`, global perun metadata |
| 898 | + - `:entry`, the metadata for this collection |
| 899 | + - `:entries`, all entries |
| 900 | +
|
| 901 | + Entries can optionally be filtered by supplying a function |
| 902 | + to the `filterer` option. |
| 903 | +
|
| 904 | + The `sortby` function can be used for ordering entries before rendering." |
| 905 | + [o out-dir OUTDIR str "the output directory" |
| 906 | + f prefix PREFIX str "the prefix for each html file, eg prefix-1.html, prefix-2.html (default: `\"page-\"`)" |
| 907 | + p page-size PAGESIZE int "the number of entries to include in each page (default: `10`)" |
| 908 | + r renderer RENDERER sym "page renderer (fully qualified symbol resolving to a function)" |
| 909 | + _ filterer FILTER code "predicate to use for selecting entries (default: `identity`)" |
| 910 | + e extensions EXTENSIONS [str] "extensions of files to include" |
| 911 | + s sortby SORTBY code "sort entries by function" |
| 912 | + c comparator COMPARATOR code "sort by comparator function" |
| 913 | + m meta META edn "metadata to set on each collection entry"] |
| 914 | + (let [{:keys [sortby comparator page-size prefix] :as options} (merge +paginate-defaults+ *opts*) |
| 915 | + grouper (fn [entries] |
| 916 | + (->> entries |
| 917 | + (sort-by sortby comparator) |
| 918 | + (partition-all page-size) |
| 919 | + (map-indexed #(-> [(str prefix (inc %1) ".html") |
| 920 | + {:entry {:page (inc %1)} |
| 921 | + :entries %2}])) |
| 922 | + (into {})))] |
| 923 | + (assortment-pre-wrap {:task-name "paginate" |
| 924 | + :tracer :io.perun/paginate |
| 925 | + :grouper grouper |
| 926 | + :options options}))) |
| 927 | + |
838 | 928 | (deftask inject-scripts |
839 | 929 | "Inject JavaScript scripts into html files. |
840 | 930 | Use either filter to include only files matching or remove to |
|
0 commit comments