ocaml
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix asset routing

authored by

Kento Okura and committed by
Jon Sterling
d1c518c0 f1ce3ed0

+140 -61
+33
bin/forester/main.ml
··· 46 46 let@ dir_to_copy = List.iter @~ dirs_to_copy in 47 47 Forester.copy_contents_of_dir ~env @@ Eio_util.path_of_dir ~env dir_to_copy 48 48 49 + let export ~env _ config_filename dev = 50 + let config = Config_parser.parse_forest_config_file config_filename in 51 + Logs.debug (fun m -> m "Parsed config file %s" config_filename); 52 + let forest = Forester.plant_raw_forest_from_dirs ~env ~dev ~config in 53 + forest 54 + |> State.diagnostics 55 + |> Diagnostic_store.iter (fun _ d -> List.iter Reporter.Tty.display d); 56 + Forester.render_forest ~dev ~forest; 57 + (* let dirs_to_copy = (if not no_theme then [config.theme] else []) in *) 58 + (* let@ dir_to_copy = List.iter @~ dirs_to_copy in *) 59 + Forester.export ~forest 60 + 49 61 let new_tree ~env config_filename prefix template random = 50 62 let@ () = Reporter.silence in 51 63 let config = Config_parser.parse_forest_config_file config_filename in ··· 196 208 $ arg_no_theme 197 209 ) 198 210 211 + let export_cmd ~env = 212 + let arg_dev = 213 + let doc = "Run forester in development mode; this will attach source file locations to the generated json." in 214 + Arg.value @@ Arg.flag @@ Arg.info ["dev"] ~doc 215 + in 216 + let doc = "Export the forest" in 217 + let man = 218 + [ 219 + ] 220 + in 221 + let info = Cmd.info "export" ~version ~doc ~man in 222 + Cmd.v 223 + info 224 + Term.( 225 + const (export ~env) 226 + $ arg_logs 227 + $ arg_config 228 + $ arg_dev 229 + ) 230 + 199 231 let new_tree_cmd ~env = 200 232 let arg_prefix = 201 233 let doc = "The namespace prefix for the created tree." in ··· 351 383 info 352 384 [ 353 385 build_cmd ~env; 386 + export_cmd ~env; 354 387 new_tree_cmd ~env; 355 388 complete_cmd ~env; 356 389 init_cmd ~env;
+12
lib/compiler/Forest.ml
··· 257 257 ) 258 258 |> List.of_seq 259 259 260 + let get_all_assets resources = 261 + resources 262 + |> to_seq_values 263 + |> Seq.filter_map 264 + ( 265 + fun r -> 266 + match r with 267 + | T.Asset a -> Some a 268 + | T.Article _ -> None 269 + ) 270 + |> List.of_seq 271 + 260 272 let get_all_resources resources = 261 273 resources 262 274 |> to_seq_values
+3
lib/compiler/Forest.mli
··· 60 60 val get_all_articles : 61 61 'a T.resource t -> 'a T.article list 62 62 63 + val get_all_assets : 64 + 'a T.resource t -> T.asset list 65 + 63 66 val get_all_resources : 64 67 'a t -> 'a list
+37
lib/compiler/Phases.ml
··· 385 385 match Forest.find_opt forest.resources iri with 386 386 | None -> assert false 387 387 | Some _ -> forest 388 + 389 + let implant_foreign 390 + : Eio.Fs.dir_ty Eio.Path.t list -> transition 391 + = fun foreign_paths state -> 392 + begin 393 + let module EP = Eio.Path in 394 + let@ path = List.iter @~ foreign_paths in 395 + let path_str = EP.native_exn path in 396 + let@ () = Reporter.profile @@ Format.sprintf "Implant foreign forest from `%s'" path_str in 397 + let blob = try EP.load path with _ -> Reporter.fatalf IO_error "Could not read foreign forest blob at `%s`" path_str in 398 + match Repr.of_json_string (T.forest_t T.content_t) blob with 399 + | Ok foreign_forest -> 400 + List.iter (fun r -> Forest.plant_resource r state.graphs state.resources) foreign_forest 401 + | Error (`Msg err) -> 402 + Reporter.fatalf Parse_error "Could not parse foreign forest blob: %s" err 403 + | exception (Iri.Error err) -> 404 + Reporter.fatalf Parse_error "Encountered error while decoding foreign forest blob: %s" (Iri.string_of_error err) 405 + | exception exn -> 406 + Reporter.fatalf Parse_error "Encountered unknown error while decoding foreign forest blob: %s" (Printexc.to_string exn) 407 + end; 408 + state 409 + 410 + let plant_assets 411 + : Eio.Fs.dir_ty Eio.Path.t list -> transition 412 + = fun asset_dirs state -> 413 + let paths = Dir_scanner.scan_directories asset_dirs in 414 + let module EP = Eio.Path in 415 + Logs.debug (fun m -> m "planting %i assets" (Seq.length paths)); 416 + begin 417 + let@ source_path = Seq.iter @~ paths in 418 + let source_path = String.concat "/" source_path in 419 + let cwd = Eio.Stdenv.cwd state.env in 420 + let content = EP.load EP.(cwd / source_path) in 421 + let iri = Asset_router.install ~host: state.config.host ~source_path ~content in 422 + Forest.plant_resource (T.Asset { iri; host = state.config.host; content }) state.graphs state.resources; 423 + end; 424 + state
+2
lib/compiler/Phases.mli
··· 18 18 val expand_only : Forester_core.iri -> transition 19 19 val eval : dev: bool -> transition 20 20 val eval_only : Forester_core.iri -> transition 21 + val implant_foreign : Eio.Fs.dir_ty Eio.Path.t list -> transition 22 + val plant_assets : Eio.Fs.dir_ty Eio.Path.t list -> transition
lib/frontend/Dir_scanner.ml lib/compiler/Dir_scanner.ml
lib/frontend/Dir_scanner.mli lib/compiler/Dir_scanner.mli
+1 -31
lib/frontend/Forester.ml
··· 79 79 let source = EP.native_exn path in 80 80 Eio_util.copy_to_dir ~env ~cwd ~source ~dest_dir: output_dir_name 81 81 82 - (* I think this function does not belong here *) 83 - let plant_assets ~env ~host ~asset_dirs ~(forest : State.t) = 84 - let paths = Dir_scanner.scan_directories asset_dirs in 85 - Logs.debug (fun m -> m "planting %i assets" (Seq.length paths)); 86 - let@ source_path = Seq.iter @~ paths in 87 - let source_path = String.concat "/" source_path in 88 - let cwd = Eio.Stdenv.cwd env in 89 - let content = EP.load EP.(cwd / source_path) in 90 - let iri = Forester_compiler.Asset_router.install ~host ~source_path ~content in 91 - Forest.plant_resource (T.Asset { iri; host; content }) forest.graphs forest.resources 92 - 93 82 let render_tree 94 83 : env: env -> 95 84 config: Config.t -> ··· 105 94 Format.printf "%s" result 106 95 107 96 let plant_raw_forest_from_dirs ~env ~dev ~(config : Config.t) : State.t = 108 - let asset_dirs = Eio_util.paths_of_dirs ~env config.assets in 109 - let foreign_paths = Eio_util.paths_of_dirs ~env config.foreign in 110 - let forest = Phases.init ~env ~config ~dev in 111 - begin 112 - let@ path = List.iter @~ foreign_paths in 113 - let path_str = EP.native_exn path in 114 - let@ () = Reporter.profile @@ Format.sprintf "Implant foreign forest from `%s'" path_str in 115 - let blob = try EP.load path with _ -> Reporter.fatalf IO_error "Could not read foreign forest blob at `%s`" path_str in 116 - match Repr.of_json_string (T.forest_t T.content_t) blob with 117 - | Ok foreign_forest -> 118 - List.iter (fun r -> Forest.plant_resource r forest.graphs forest.resources) foreign_forest 119 - | Error (`Msg err) -> 120 - Reporter.fatalf Parse_error "Could not parse foreign forest blob: %s" err 121 - | exception (Iri.Error err) -> 122 - Reporter.fatalf Parse_error "Encountered error while decoding foreign forest blob: %s" (Iri.string_of_error err) 123 - | exception exn -> 124 - Reporter.fatalf Parse_error "Encountered unknown error while decoding foreign forest blob: %s" (Printexc.to_string exn) 125 - end; 126 - plant_assets ~env ~host: config.host ~asset_dirs ~forest; 127 97 State_machine.batch_run ~env ~config ~dev 128 98 129 99 let json_manifest ~dev ~(forest : State.t) : string = ··· 179 149 end 180 150 end 181 151 182 - let _export ~(forest : State.t) : unit = 152 + let export ~(forest : State.t) : unit = 183 153 let@ () = Reporter.profile "Export forest" in 184 154 let local_resources = 185 155 let@ resource = List.filter @~ Forest.get_all_resources forest.resources in
+2 -10
lib/frontend/Forester.mli
··· 12 12 13 13 type target = Target : 'a Render.target -> target 14 14 15 - val plant_assets : 16 - env: 17 - < cwd: [> Eio.Fs.dir_ty] Eio.Path.t; 18 - fs: Eio.Fs.dir_ty Eio.Path.t; 19 - .. > -> 20 - host: string -> 21 - asset_dirs: Eio.Fs.dir_ty Eio.Path.t list -> 22 - forest: State.t -> 23 - unit 24 - 25 15 val plant_raw_forest_from_dirs : 26 16 env: env -> 27 17 dev: bool -> ··· 66 56 forest: State.t -> 67 57 string -> 68 58 (iri * string) Seq.t 59 + 60 + val export : forest: State.t -> unit
+36 -14
lib/frontend/State_machine.ml
··· 4 4 * SPDX-License-Identifier: GPL-3.0-or-later 5 5 *) 6 6 7 + open Forester_prelude 7 8 open Forester_core 8 9 open Forester_compiler 9 10 10 11 module T = Types 11 - module Cmp = Phases 12 12 13 13 type state = State.t 14 14 ··· 16 16 | Quit 17 17 | Build_import_graph 18 18 | Build_dependency_graph of iri 19 + | Plant_assets of (Eio.Fs.dir_ty Eio.Path.t list [@opaque ]) 20 + | Plant_foreign of (Eio.Fs.dir_ty Eio.Path.t list [@opaque ]) 19 21 | Do_nothing 20 22 | Load_all 21 23 | Parse_all ··· 67 69 end 68 70 | Quit -> exit 0 69 71 | Load_all -> 70 - (Parse_all, Cmp.load_configured_dirs state, Nothing) 72 + (Parse_all, Phases.load_configured_dirs state, Nothing) 71 73 | Parse_all -> 72 74 log "Parse trees"; 73 75 ( 74 76 Build_import_graph, 75 - Cmp.parse ~quit_on_error: false state, 77 + Phases.parse ~quit_on_error: false state, 76 78 Nothing 77 79 ) 78 80 | Build_import_graph -> 79 81 ( 80 82 Expand_all, 81 - Cmp.build_import_graph state, 83 + Phases.build_import_graph state, 82 84 Nothing 83 85 ) 84 86 | Build_dependency_graph iri -> 85 87 ( 86 88 Expand_only iri, 87 - Cmp.build_import_graph_for ~addr: iri state, 89 + Phases.build_import_graph_for ~addr: iri state, 88 90 Nothing 89 91 ) 90 92 | Expand_all -> 91 93 log "Expand, evaluate and analyse forest"; 92 94 ( 93 95 Eval_all, 94 - Cmp.expand ~quit_on_error: false state, 96 + Phases.expand ~quit_on_error: false state, 95 97 Nothing 96 98 ) 97 99 | Expand_only iri -> 98 100 ( 99 101 Eval_only iri, 100 - Cmp.expand_only iri state, 102 + Phases.expand_only iri state, 101 103 Nothing 102 104 ) 103 105 | Eval_all -> 104 106 ( 105 107 Do_nothing, 106 - Cmp.eval ~dev: true state, 108 + Phases.eval ~dev: true state, 107 109 Nothing 108 110 ) 109 111 | Eval_only iri -> 110 112 ( 111 113 Do_nothing, 112 - Cmp.eval_only iri state, 114 + Phases.eval_only iri state, 113 115 Nothing 114 116 ) 117 + | Plant_assets paths -> 118 + (Do_nothing, Phases.plant_assets paths state, Nothing) 119 + | Plant_foreign path -> 120 + (Do_nothing, Phases.implant_foreign path state, Nothing) 115 121 | Parse _ 116 122 | Cache_results _ -> 117 123 (Do_nothing, state, Nothing) 118 124 | Do_nothing -> 119 125 (Do_nothing, state, Nothing) 120 126 121 - let run_action action ~(until : 'a action) state : state * ('r, 'e) result = 127 + let run_action action ~(until : 'a action) state : state = 122 128 let rec go action state = 123 129 match update action state with 124 130 | (new_action, new_state, result) -> ··· 127 133 go new_action new_state 128 134 in 129 135 go action state 136 + |> fst 130 137 131 138 let rec force 132 139 : 'a action list -> state -> ('r, 'e) result ··· 137 144 let _discard, new_state, _ = update msg state in 138 145 force remaining new_state 139 146 140 - let batch_run ~env ~config ~dev = 147 + let implant_foreign paths state = 148 + state 149 + |> run_action 150 + (Plant_foreign paths) 151 + ~until: Do_nothing 152 + 153 + let plant_assets paths state = 154 + state 155 + |> run_action 156 + (Plant_assets paths) 157 + ~until: Do_nothing 158 + 159 + let batch_run ~env ~(config : Config.t) ~dev = 160 + let asset_paths = Eio_util.paths_of_dirs ~env config.assets in 161 + let foreign_paths = Eio_util.paths_of_dirs ~env config.foreign in 141 162 Phases.init ~env ~config ~dev 163 + |> plant_assets asset_paths 164 + |> implant_foreign foreign_paths 142 165 |> run_action Load_all ~until: Do_nothing 143 - |> fst 144 166 145 167 let language_server 146 168 : state -> unit 147 169 = fun _ -> () 148 170 149 171 let render_tree ~env ~config ~dev target iri = 150 - let (forest, _) = 151 - Cmp.init ~env ~config ~dev 172 + let forest = 173 + Phases.init ~env ~config ~dev 152 174 |> run_action (Build_dependency_graph iri) ~until: Do_nothing 153 175 in 154 176 match Forest.get_article iri forest.resources with
+1 -4
test/Test_import_graph.ml
··· 16 16 let () = 17 17 let@ env = Eio_main.run in 18 18 let open Alcotest in 19 - let forest, _ = 19 + let forest = 20 20 State_machine.( 21 21 Phases.init ~env ~config ~dev: false 22 22 |> run_action Load_all ~until: Expand_all 23 23 ) 24 - (* load (Eio_util.paths_of_dirs ~env config.trees) *) 25 - (* |> parse ~quit_on_error: false *) 26 - (* ) *) 27 24 in 28 25 let batch_graph = 29 26 Imports.run_builder
+1 -1
test/Test_transclusion.ml
··· 45 45 let@ () = Reporter.easy_run in 46 46 (* Needs to be false to make tests reproducible. The source path depends on the host *) 47 47 let tree_dirs = Eio_util.paths_of_dirs ~env config.trees in 48 - let forest, _ = 48 + let forest = 49 49 Phases.init ~env ~config ~dev: false 50 50 |> State_machine.(run_action Load_all ~until: Do_nothing) 51 51 in
+1
test/forest/assets/asset.md
··· 1 + # I am a static asset
+7
test/forest/export.toml
··· 1 + [forest] 2 + host = "foreign" 3 + trees = ["for_export" ] # The directories in which your trees are stored 4 + assets = [] # The directories in which your assets are stored 5 + theme = "theme" # The directory in which your theme is stored 6 + home = "index" 7 + prefixes = ["test"]
+1
test/forest/for_export/index.tree
··· 1 + \title{I am exported}
+2 -1
test/forest/forest.toml
··· 1 1 [forest] 2 2 host = "lsp-test" 3 3 trees = ["trees" ] # The directories in which your trees are stored 4 - assets = [] # The directories in which your assets are stored 4 + assets = ["assets"] # The directories in which your assets are stored 5 5 theme = "theme" # The directory in which your theme is stored 6 6 home = "index" 7 7 prefixes = ["test"] 8 + foreign = ["export/foreign.json"]
+1
test/forest/trees/asset.tree
··· 1 + \route-asset{assets/asset.md}