diff --git a/.gitignore b/.gitignore index b067edd..cdddca6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /Manifest.toml +.DS_Store diff --git a/Project.toml b/Project.toml index 8d36288..8bfbfb9 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "PlutoPages" uuid = "d5dc3dd1-4774-47c7-8860-0a1ad9e34b8c" -authors = ["Luca Ferranti and Fons van Der Plas"] +authors = ["Luca Ferranti", "Fons van Der Plas"] version = "0.1.0" [deps] @@ -9,6 +9,7 @@ CommonMark = "a80b9123-70ca-4bc0-993e-6e3bcb318db6" Gumbo = "708ec375-b3d6-5a57-a7ce-8257bf98657a" HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" MarkdownLiteral = "736d6165-7244-6769-4267-6b50796e6954" @@ -16,7 +17,9 @@ Pluto = "c3e4b0f8-55cb-11ea-2926-15256bba5781" PlutoHooks = "0ff47ea0-7a50-410d-8455-4348d5de0774" PlutoLinks = "0ff47ea0-7a50-410d-8455-4348d5de0420" PlutoSliderServer = "2fc8631c-6f24-4c5b-bca7-cbb509c42db4" +PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" ProgressLogging = "33c8b6b6-d38a-422a-b730-caa89a2f386c" +RelocatableFolders = "05181044-ff0b-4ac5-8273-598c1e38db00" SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" ThreadsX = "ac1d9e8a-700a-412c-b207-f0111f4b6c0d" Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" @@ -28,14 +31,17 @@ CommonMark = "0.8" Gumbo = "0.8" HypertextLiteral = "0.9" InteractiveUtils = "1" +LiveServer = "1.2" Logging = "1" Markdown = "1" MarkdownLiteral = "0.1" -Pluto = "0.19.36" +Pluto = "0.19.38" PlutoHooks = "0.0.5" PlutoLinks = "0.1.6" PlutoSliderServer = "0.3.28" +PlutoUI = "0.7.55" ProgressLogging = "0.1" +RelocatableFolders = "1" SHA = "0.7" ThreadsX = "0.1" Unicode = "1" diff --git a/README.md b/README.md index 7c8d650..1c21bee 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,33 @@ This repository will contain "PlutoPages", the site generation system that power Currently this code is in https://github.com/mitmath/computational-thinking/blob/Fall23/PlutoPages.jl Contact https://github.com/LucaFerranti for more info! + + +## During development +Use `PlutoPages.develop` to start developing your website. It will launch two browser tabs: one with the PlutoPages development dashboard, and one with a preview of your website. + +When you make edits to the website source files, they should get detected automatically, and the site is regenerated. If changes are not detected, go to the PlutoPages dashboard and click "Read input files again". + +```julia +import PlutoPages + +# replace this with the path of your own website +my_site_source = PlutoPages.create_test_basic_site() + +PlutoPages.develop(my_site_source) +``` + + +## Generating the site +Use `PlutoPages.generate` if you want to generate your website once, without a development server. + + + +```julia +import PlutoPages + +# replace this with the path of your own website +my_site_source = PlutoPages.create_test_basic_site() + +output_dir = PlutoPages.generate(my_site_source) +``` diff --git a/src/PlutoPages.jl b/src/PlutoPages.jl index 98ad19d..4bfee0f 100644 --- a/src/PlutoPages.jl +++ b/src/PlutoPages.jl @@ -1,5 +1,146 @@ module PlutoPages -include("plutopages.jl") +import Pluto +using RelocatableFolders +import LiveServer +include("./pluto control.jl") +include("./open in browser.jl") + + +# """ +# Generate +# """ +# function generate() + + + +# end + +const PlutoPages_notebook_path = @path joinpath(dirname(@__DIR__), "src", "notebook.jl") + + +function run_plutopages_notebook(; + input_dir::String, + output_dir::String, + cache_dir::String, + kwargs... +) + mkpath(output_dir) + mkpath(cache_dir) + run_with_replacements( + PlutoPages_notebook_path, + Dict( + :input_dir => input_dir, + :output_dir => output_dir, + :cache_dir => cache_dir, + ); + kwargs... + ) +end + + + +function create_subdirs(root_dir::String) + @assert(isdir(root_dir)) + @assert(isdir(joinpath(root_dir, "src"))) + + (; + input_dir = joinpath(root_dir, "src"), + output_dir = joinpath(root_dir, "_site"), + cache_dir = joinpath(root_dir, "_cache"), + ) +end + +function develop(root_dir::String) + develop(;create_subdirs(root_dir)...) +end + + + +const isolated_cell_ids = ( + "cf27b3d3-1689-4b3a-a8fe-3ad639eb2f82", + "7f7f1981-978d-4861-b840-71ab611faf74", + "7d9cb939-da6b-4961-9584-a905ad453b5d", + "4e88cf07-8d85-4327-b310-6c71ba951bba", + "079a6399-50eb-4dee-a36d-b3dcb81c8456", + "b0006e61-b037-41ed-a3e4-9962d15584c4", + "06edb2d7-325f-4f80-8c55-dc01c7783054", + "e0a25f24-a7de-4eac-9f88-cb7632de09eb", +) +const isolated_cell_query = join("&isolated_cell_id=$(i)" for i in isolated_cell_ids) + + +function develop(; + input_dir::String, + output_dir::String, + cache_dir::String, +) + app = run_plutopages_notebook(; input_dir, output_dir, cache_dir, run_server=true) + + notebook = fetch(app.notebook_task) + + ccall(:jl_exit_on_sigint, Cvoid, (Cint,), 0) + @info "PlutoPages: Press Ctrl+C multiple times to stop the server." + file_server_port = rand(8100:8900) + + file_server_task = Threads.@spawn LiveServer.serve(port=file_server_port, dir=output_dir) + + sleep(2) + + dev_server_url = "http://localhost:$(file_server_port)/" + pluto_server_url = "http://localhost:$(app.pluto_server_port)/edit?secret=$(app.session.secret)&id=$(notebook.notebook_id)$(isolated_cell_query)" + + + @info """ + + ✅✅✅ + + Ready! To see the website, visit: + ➡️ $(dev_server_url) + + To inspect the generation process, go to: + ➡️ $(pluto_server_url) + + ✅✅✅ + + """ + + open_in_default_browser(dev_server_url) + open_in_default_browser(pluto_server_url) + + wait(file_server_task) + wait(app.pluto_server_instance) + app +end + + + + +function generate(; + input_dir::String, + output_dir::String, + cache_dir::String, +) + app = run_plutopages_notebook(; input_dir, output_dir, cache_dir, run_server=false) + fetch(app.notebook_task) + @info "PlutoPages: cleaning up..." + shutdown(app) + + return output_dir +end + +generate(root_dir::String) = generate(;create_subdirs(root_dir)...) + + +function create_test_basic_site() + original = joinpath(dirname(@__DIR__), "test", "basic_site") + new_dir = mktempdir() + cp(original, new_dir; force=true) + new_dir end + + + + +end \ No newline at end of file diff --git a/src/notebook.jl b/src/notebook.jl index a317c23..f8469a9 100644 --- a/src/notebook.jl +++ b/src/notebook.jl @@ -390,7 +390,7 @@ md""" """ # ╔═╡ c52c9786-a25f-11ec-1fdc-9b13922d7ccb -const dir = joinpath(@__DIR__, "src") +const input_dir = joinpath(@__DIR__, "src") # ╔═╡ cf27b3d3-1689-4b3a-a8fe-3ad639eb2f82 md""" @@ -409,7 +409,7 @@ const this_file = split(@__FILE__, "#==#")[1] # ╔═╡ d38dc2aa-d5ba-4cf7-9f9e-c4e4611a57ac function ignore(abs_path; allow_special_dirs::Bool=false) - p = relpath(abs_path, dir) + p = relpath(abs_path, input_dir) # (_cache, _site, _andmore) any(x -> ignored_dirname(x; allow_special_dirs), splitpath(p)) || @@ -424,8 +424,8 @@ dir_changed_time = let @info "Starting watch task" - @use_task([dir]) do - BetterFileWatching.watch_folder(dir) do e + @use_task([input_dir]) do + BetterFileWatching.watch_folder(input_dir) do e @debug "File event" e try is_caused_by_me = all(x -> ignore(x; allow_special_dirs=true), e.paths) @@ -444,12 +444,12 @@ dir_changed_time = let end # ╔═╡ 7d9cb939-da6b-4961-9584-a905ad453b5d -allfiles = filter(PlutoSliderServer.list_files_recursive(dir)) do p +allfiles = filter(PlutoSliderServer.list_files_recursive(input_dir)) do p # reference to retrigger when files change dir_changed_time manual_update_trigger - !ignore(joinpath(dir, p)) + !ignore(joinpath(input_dir, p)) end # ╔═╡ d314ab46-b866-44c6-bfca-9a413bc06514 @@ -737,7 +737,7 @@ template_results = let # let's go! running all the template handlers progressmap_async(allfiles; ntasks=NUM_PARALLEL_WORKERS) do f - absolute_path = joinpath(dir, f) + absolute_path = joinpath(input_dir, f) input = TemplateInput(; contents=read(absolute_path), @@ -803,7 +803,7 @@ function process_layouts(page::Page)::Page layoutname = output.frontmatter["layout"] @assert layoutname isa String - layout_file = joinpath(dir, "_includes", layoutname) + layout_file = joinpath(input_dir, "_includes", layoutname) @assert isfile(layout_file) "$layout_file is not a valid layout path" @@ -816,7 +816,7 @@ function process_layouts(page::Page)::Page input = TemplateInput(; contents=read(layout_file), absolute_path=layout_file, - relative_path=relpath(layout_file, dir), + relative_path=relpath(layout_file, input_dir), frontmatter=merge(output.frontmatter, FrontMatter( "content" => content, diff --git a/src/open in browser.jl b/src/open in browser.jl new file mode 100644 index 0000000..e010a8c --- /dev/null +++ b/src/open in browser.jl @@ -0,0 +1,25 @@ +# copy paste from pluto source code +function detectwsl() + Sys.islinux() && + isfile("/proc/sys/kernel/osrelease") && + occursin(r"Microsoft|WSL"i, read("/proc/sys/kernel/osrelease", String)) +end + +function open_in_default_browser(url::AbstractString)::Bool + try + if Sys.isapple() + Base.run(`open $url`) + true + elseif Sys.iswindows() || detectwsl() + Base.run(`powershell.exe Start "'$url'"`) + true + elseif Sys.islinux() + Base.run(`xdg-open $url`) + true + else + false + end + catch ex + false + end +end \ No newline at end of file diff --git a/src/pluto control.jl b/src/pluto control.jl new file mode 100644 index 0000000..c8ab90e --- /dev/null +++ b/src/pluto control.jl @@ -0,0 +1,104 @@ +import Pluto: Pluto, PlutoDependencyExplorer + +function run_with_replacements(notebook_path::AbstractString, inputs::Dict{Symbol,<:Any}; + run_server::Bool=false, +) + port_channel = Channel{UInt16}(1) + + function on_event(e::Pluto.ServerStartEvent) + put!(port_channel, e.port) + end + function on_event(e) end + + options=Pluto.Configuration.from_flat_kwargs(; + workspace_use_distributed=true, + disable_writing_notebook_files=true, + launch_browser=false, + show_file_system=false, + dismiss_update_notification=true, + on_event, + port_hint=6872, + ) + session = Pluto.ServerSession(;options) + + @info "PlutoPages: Starting Pluto server..." + notebook_task = Threads.@spawn try + notebook = Pluto.SessionActions.open( + session, notebook_path; + run_async=false, + execution_allowed=false, # start in "Safe mode", to allow us to inject some code before running the notebook :) + ) + + notebook.topology = Pluto.static_resolve_topology(Pluto.updated_topology(notebook.topology, notebook, notebook.cells)) + + for (name, value) in pairs(inputs) + # Find the cell that currently defines a variable with this name. + cs = PlutoDependencyExplorer.where_assigned(notebook.topology, Set([name])) + if length(cs) != 1 + error("The variable $(name) is not defined in this notebook: it cannot be used as input to the app.") + else + c = only(cs)::Pluto.Cell + + c.code = "const $(name) = $(repr(value))" + c.code_folded = true + end + end + + log_progress = Ref(true) + let + last_progress = (0,0) + Threads.@spawn while log_progress[] + progress = ( + notebook.process_status == Pluto.ProcessStatus.ready ? + length(notebook.cells) - count(c -> c.running || c.queued, notebook.cells) : + 0, + length(notebook.cells) + ) + if progress != last_progress + @info "Notebook: $(progress[1])/$(progress[2]) done..." + last_progress = progress + end + sleep(.5) + end + end + + # disable "Safe preview" mode + notebook.process_status = Pluto.ProcessStatus.starting + # run all cells + Pluto.update_save_run!(session, notebook, notebook.cells; run_async=false) + @info "Pluto app: notebook finished!" + log_progress[] = false + + notebook + catch e + @error "Error while running notebook" exception=(e,catch_backtrace()) + end + + pluto_server_instance = if run_server + Pluto.run!(session) + end + + pluto_server_port = run_server ? take!(port_channel) : nothing + @info "Pluto app: waiting for notebook to finish..." + + return (; + session, + notebook_task, + pluto_server_instance, + pluto_server_port, + ) +end + + + +function shutdown(app) + # uhhh this will wait for it to finish but whatever + notebook = fetch(app.notebook_task) + + Pluto.SessionActions.shutdown(app.session, notebook) + + if app.pluto_server_instance !== nothing + Base.close(app.pluto_server_instance) + end +end + diff --git a/test/basic_site/src/_includes/layout.jlhtml b/test/basic_site/src/_includes/layout.jlhtml new file mode 100644 index 0000000..e6a2851 --- /dev/null +++ b/test/basic_site/src/_includes/layout.jlhtml @@ -0,0 +1,90 @@ +$(begin + import Pluto + "The contents of `` from a Pluto HTML export." + const pluto_head = let + default = Pluto.generate_html(; + pluto_cdn_root=Pluto.PLUTO_VERSION < v"0.19" ? "https://cdn.jsdelivr.net/gh/fonsp/Pluto.jl@9ca70c36/frontend/" : nothing) + m = match(r"(.*)"s, default) + reduce([ + # r""s + r"" + r"" + r"" + r"" + ]; init=m[1]) do s,r + replace(s, r => "") + end |> HTML + end + nothing +end) + + +$(get(page.output.frontmatter, "title", splitext(basename(page.input.relative_path))[1])) — Pluto.jl +$(let d = get(page.output.frontmatter, "description", nothing) + if d !== nothing + @htl("""""") + end +end) + + + + + + + + + +$(pluto_head) + + +
+ + +
+ $(content) +
+
+ + \ No newline at end of file diff --git a/test/basic_site/src/_includes/md.jlmd b/test/basic_site/src/_includes/md.jlmd new file mode 100644 index 0000000..a4b4579 --- /dev/null +++ b/test/basic_site/src/_includes/md.jlmd @@ -0,0 +1,9 @@ +--- +layout: "layout.jlhtml" +--- + +
+
+$(content) +
+
\ No newline at end of file diff --git a/test/basic_site/src/_includes/welcome.jlhtml b/test/basic_site/src/_includes/welcome.jlhtml new file mode 100644 index 0000000..08362b2 --- /dev/null +++ b/test/basic_site/src/_includes/welcome.jlhtml @@ -0,0 +1,24 @@ + + + + + + + + + + PlutoPages Test website + + + + + + + + +
+ $(content) +
+ + + diff --git a/test/basic_site/src/assets/favicon.ico b/test/basic_site/src/assets/favicon.ico new file mode 100755 index 0000000..8ea641a Binary files /dev/null and b/test/basic_site/src/assets/favicon.ico differ diff --git a/test/basic_site/src/assets/favicon.svg b/test/basic_site/src/assets/favicon.svg new file mode 100755 index 0000000..9b8ad13 --- /dev/null +++ b/test/basic_site/src/assets/favicon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/test/basic_site/src/assets/scripts/sidebar.js b/test/basic_site/src/assets/scripts/sidebar.js new file mode 100644 index 0000000..34071b9 --- /dev/null +++ b/test/basic_site/src/assets/scripts/sidebar.js @@ -0,0 +1,18 @@ +const sidebar = document.querySelector("#pages-sidebar") +const layout = document.querySelector("#pages-layout") +const navtoggle = document.querySelector("#toggle-nav") + +document.querySelector("#toggle-nav").addEventListener("click", function (e) { + console.log(e) + layout.classList.toggle("pages_show_sidebar") + e.stopPropagation() +}) + +window.addEventListener("click", function (e) { + if (!sidebar.contains(e.target) && !navtoggle.contains(e.target)) { + layout.classList.remove("pages_show_sidebar") + } +}) + +console.info("zzzz") +console.info(layout) diff --git a/test/basic_site/src/assets/styles/index.css b/test/basic_site/src/assets/styles/index.css new file mode 100644 index 0000000..d536328 --- /dev/null +++ b/test/basic_site/src/assets/styles/index.css @@ -0,0 +1,114 @@ +/* a minimalist set of CSS resets */ + +@import url("https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.css"); + +/* @import url('https://cdn.jsdelivr.net/gh/fonsp/Pluto.jl@0.18.0/frontend/vollkorn.css'); */ +/* @import url('https://fonts.googleapis.com/css2?family=Jaldi:wght@400;700&display=swap'); */ +/* @import url('https://fonts.googleapis.com/css2?family=Jaldi:wght@400;700&family=Work+Sans:ital,wght@0,400;0,500;0,600;0,700;0,800;0,900;1,400;1,500;1,600;1,700;1,800;1,900&family=Yantramanav:wght@400;500;700;900&display=swap'); */ + +/* default to border-box */ +html { + box-sizing: border-box; + font-size: 17px; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +:root { + --system-fonts: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Cantarell, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", + system-ui, sans-serif; + --system-fonts-mono: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} +/* adjust typography defaults */ +body { + font-family: var(--system-fonts); + margin: 0; + padding: 0; + width: 100vw; + overflow-x: hidden; + background: white; + color: var(--pluto-output-color); +} + +body { + /* background: url(bg.svg); */ + /* background-color: hsl(231deg 14% 57%); */ + /* background-size: cover; */ + word-break: break-word; +} + +p, +ol { + line-height: 1.5; +} + +h1, +h2 { + font-weight: 800; +} + +pre { + tab-size: 4; + white-space: pre-wrap; + word-break: break-word; +} + +pre, +code { + font-family: var(--system-fonts-mono); +} + +/* images and videos max out at full width */ +img, +video { + height: auto; + max-width: 100%; +} + +a { + font-weight: 500; + text-decoration: none; +} +a, +a:visited { + color: #4674bc; +} +a:hover { + text-decoration: underline; +} +h1 a, +h2 a, +h3 a { + font-weight: inherit; +} + +a.arrow { + font-weight: 700; +} +a.arrow::after { + content: " →"; +} +card-text > a.arrow { + margin-top: auto; +} + +/* SIDEBAR LOGO */ + +a.pluto_home_link img { + height: 1.2em; + width: 1.2em; +} +a.pluto_home_link { + font-size: 1.7em; + font-weight: 800; + color: inherit; + padding: 0.3em; + display: flex; + flex-direction: row; + align-items: center; + gap: 0.5ch; +} diff --git a/test/basic_site/src/assets/styles/layout.css b/test/basic_site/src/assets/styles/layout.css new file mode 100644 index 0000000..c554b89 --- /dev/null +++ b/test/basic_site/src/assets/styles/layout.css @@ -0,0 +1,192 @@ +body { + font-size: 17px; +} + +/* COLOR */ + +#pages-layout { + /* --bg-color: set by pluto */ + --sidebar-bg: #fafafa; + --sidebar-color: rgb(82, 82, 82); + --sidebar-li-active-bg: rgb(235, 235, 235); + --sidebar-li-hover-bg: rgb(247, 240, 190); +} +@media (prefers-color-scheme: dark) { + #pages-layout { + --sidebar-bg: #303030; + --sidebar-color: rgb(255, 255, 255); + --sidebar-li-active-bg: rgb(82, 82, 82); + --sidebar-li-hover-bg: rgb(108, 94, 70); + } +} + +/* LAYOUT */ + +#pages-layout { + display: flex; + flex-direction: row; + min-height: 100vh; + align-items: stretch; +} + +#pages-sidebar { + font-family: system-ui; + flex: 0 0 auto; + width: 16rem; + font-weight: 400; + z-index: 23400; +} + +#pages-content { + display: block; + flex: 1 1 auto; + min-width: 0; +} + +#pages-sidebar > div { + position: sticky; + top: 1rem; + margin: 1rem; + padding: 0.5rem; + padding-bottom: 2rem; + border-radius: 1rem; + background: var(--sidebar-bg); + color: var(--sidebar-color); +} + +#toggle-nav { + display: none; +} + +/* SIDEBAR COLLAPSING */ + +#pages-content::after { + content: ""; + z-index: 23400; + touch-action: none; + pointer-events: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + transition: background-color 0.2s ease-out; +} + +@media screen and (max-width: 768px) { + #pages-layout { + flex-direction: column; + } + #toggle-nav { + display: inline-flex; + align-self: start; + border: none; + background: none; + } + #toggle-nav::after { + --size: 40px; + content: " "; + display: inline-block; + width: var(--size); + height: var(--size); + background-image: url(https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/menu-outline.svg); + background-size: var(--size) var(--size); + filter: var(--image-filters); + } + #pages-sidebar { + position: fixed; + top: 0; + bottom: 0; + right: 100%; + overflow-y: auto; + transition: transform 300ms cubic-bezier(0.18, 0.89, 0.45, 1.12); + } + @media (prefers-reduced-motion) { + #pages-sidebar { + transition: none; + } + } + + .pages_show_sidebar #pages-sidebar { + transform: translateX(100%); + z-index: 23401; + } + .pages_show_sidebar #pages-content::after { + display: block; + background-color: rgba(0, 0, 0, 0.5); + } +} + +/* SIDEBAR */ + +#pages-sidebar > div > ul { + margin-block-start: 0px; + margin-block-end: 0px; +} + +#pages-sidebar li, +#pages-sidebar ul { + padding: 0px; + list-style-type: none; +} + +#pages-sidebar a { + color: unset; + text-decoration: none; +} + +#pages-sidebar li li a, +#pages-sidebar li h3 { + border-radius: 0.5em; + padding: 0.2em 0.6em; +} + +#pages-sidebar li h3 { + opacity: 0.6; + font-variant-caps: all-petite-caps; + margin-block-start: 3rem; + margin-block-end: 0; +} + +#pages-sidebar li:first-of-type h3 { + margin-block-start: 0; +} + +#pages-sidebar li, +#pages-sidebar ul { + display: flex; + flex-direction: column; + align-items: stretch; +} + +#pages-sidebar li li.active a { + background-color: var(--sidebar-li-active-bg); +} +#pages-sidebar li li:hover a { + background-color: var(--sidebar-li-hover-bg); +} + +/* SIDEBAR LOGO */ + +#pages-sidebar .home_link img { + height: 1.2em; + width: 1.2em; +} +#pages-sidebar a.home_link { + font-size: 1.7rem; + padding: 0.3em; + font-weight: 800; + display: flex; + flex-direction: row; + align-items: center; + gap: 0.5ch; +} + +/* Markdown content */ + +.pages-markdown main { + max-width: 700px; + margin-left: auto; + margin-right: auto; + margin-top: 5rem; +} diff --git a/test/basic_site/src/en/blog/something.jl b/test/basic_site/src/en/blog/something.jl new file mode 100644 index 0000000..d5f30a8 --- /dev/null +++ b/test/basic_site/src/en/blog/something.jl @@ -0,0 +1,510 @@ +### A Pluto.jl notebook ### +# v0.18.2 + +#> [frontmatter] +#> title = "Basic syntax" +#> description = "A simple notebook demonstrating the Julia syntax essentials" +#> layout = "layout.jlhtml" +#> date = "2020-06-01" +#> tags = ["blog"] + +using Markdown +using InteractiveUtils + +# ╔═╡ 0d3aec92-edeb-11ea-3adb-cd0dc17cbdab + + +# ╔═╡ 3b038ee0-edeb-11ea-0977-97cc30d1c6ff +md" +# This is a test page for PlutoPages.jl + +## Variables + +We can define a variable using `=` (assignment). Then we can use its value in other expressions: +" + +# ╔═╡ 3e8e0ea0-edeb-11ea-22e0-c58f7c2168ce +x = 3 + +# ╔═╡ 59b66862-edeb-11ea-2d62-71dcc79dbfab +y = 2x + +# ╔═╡ 5e062a24-edeb-11ea-256a-d938f77d7815 +md"By default Julia displays the output of the last operation. (You can suppress the output by adding `;` (a semicolon) at the end.) +" + +# ╔═╡ 7e46f0e8-edeb-11ea-1092-4b5e8acd9ee0 +md"We can ask what type a variable has using `typeof`:" + +# ╔═╡ 8a695b86-edeb-11ea-08cc-17263bec09df +typeof(y) + +# ╔═╡ 8e2dd3be-edeb-11ea-0703-354fb31c12f5 +md"## Functions" + +# ╔═╡ 96b5a28c-edeb-11ea-11c0-597615962f54 +md"We can use a short-form, one-line function definition for simple functions:" + +# ╔═╡ a7453572-edeb-11ea-1e27-9f710fd856a6 +f(x) = 2 + x + +# ╔═╡ b341db4e-edeb-11ea-078b-b71ac00089d7 +md"Typing the function's name gives information about the function. To call it we must use parentheses:" + +# ╔═╡ 23f9afd4-eded-11ea-202a-9f0f1f91e5ad +f + +# ╔═╡ cc1f6872-edeb-11ea-33e9-6976fd9b107a +f(10) + +# ╔═╡ ce9667c2-edeb-11ea-2665-d789032abd11 +md"For longer functions we use the following syntax with the `function` keyword and `end`:" + +# ╔═╡ d73d3400-edeb-11ea-2dea-95e8c4a6563b +function g(x, y) + z = x + y + return z^2 +end + +# ╔═╡ e04ccf10-edeb-11ea-36d1-d11969e4b2f2 +g(1, 2) + +# ╔═╡ e297c5cc-edeb-11ea-3bdd-090f415685ab +md"## For loops" + +# ╔═╡ ec751446-edeb-11ea-31ba-2372e7c71b42 +md"Use `for` to loop through a pre-determined set of values:" + +# ╔═╡ fe3fa290-edeb-11ea-121e-7114e5c573c1 +let s = 0 + + for i in 1:10 + s += i # Equivalent to s = s + i + end + + s +end + +# ╔═╡ 394b0ec8-eded-11ea-31fb-27392068ef8f +md"Here, `1:10` is a **range** representing the numbers from 1 to 10:" + +# ╔═╡ 4dc00908-eded-11ea-25c5-0f7b2b7e18f9 +typeof(1:10) + +# ╔═╡ 6c44abb4-edec-11ea-16bd-557800b5f9d2 +md"Above we used a `let` block to define a new local variable `s`. +But blocks of code like this are usually better inside functions, so that they can be reused. For example, we could rewrite the above as follows: +" + +# ╔═╡ 683af3e2-eded-11ea-25a5-0d90bf099d98 +function mysum(n) + s = 0 + + for i in 1:n + s += i + end + + return s +end + +# ╔═╡ 76764ea2-eded-11ea-1aa6-296f3421de1c +mysum(100) + +# ╔═╡ 93a231f4-edec-11ea-3b39-299b3be2da78 +md"## Conditionals: `if`" + +# ╔═╡ 82e63a24-eded-11ea-3887-15d6bfabea4b +md"We can evaluate whether a condition is true or not by simply writing the condition:" + +# ╔═╡ 9b339b2a-eded-11ea-10d7-8fc9a907c892 +a = 3 + +# ╔═╡ 9535eb40-eded-11ea-1651-e33c9c23dbfb +a < 5 + +# ╔═╡ a16299a2-eded-11ea-2b56-93eb7a1010a7 +md"We see that conditions have a Boolean (`true` or `false`) value. + +We can then use `if` to control what we do based on that value:" + +# ╔═╡ bc6b124e-eded-11ea-0290-b3760cb81024 +if a < 5 + "small" + +else + "big" + +end + +# ╔═╡ cfb21014-eded-11ea-1261-3bc30952a88e +md"""Note that the `if` also returns the last value that was evaluated, in this case the string `"small"` or `"big"`, Since Pluto is reactive, changing the definition of `a` above will automatically cause this to be reevaluated!""" + +# ╔═╡ ffee7d80-eded-11ea-26b1-1331df204c67 +md"## Arrays" + +# ╔═╡ cae4137e-edee-11ea-14af-59a32227de1b +md"### 1D arrays (`Vector`s)" + +# ╔═╡ 714f4fca-edee-11ea-3410-c9ab8825d836 +md"We can make a `Vector` (1-dimensional, or 1D array) using square brackets:" + +# ╔═╡ 82cc2a0e-edee-11ea-11b7-fbaa5ad7b556 +v = [1, 2, 3] + +# ╔═╡ 85916c18-edee-11ea-0738-5f5d78875b86 +typeof(v) + +# ╔═╡ 881b7d0c-edee-11ea-0b4a-4bd7d5be2c77 +md"The `1` in the type shows that this is a 1D array. + +We access elements also using square brackets:" + +# ╔═╡ a298e8ae-edee-11ea-3613-0dd4bae70c26 +v[2] + +# ╔═╡ a5ebddd6-edee-11ea-2234-55453ea59c5a +v[2] = 10 + +# ╔═╡ a9b48e54-edee-11ea-1333-a96181de0185 +md"Note that Pluto does not automatically update cells when you modify elements of an array, but the value does change." + +# ╔═╡ 68c4ead2-edef-11ea-124a-03c2d7dd6a1b +md"A nice way to create `Vector`s following a certain pattern is to use an **array comprehension**:" + +# ╔═╡ 84129294-edef-11ea-0c77-ffa2b9592a26 +v2 = [i^2 for i in 1:10] + +# ╔═╡ d364fa16-edee-11ea-2050-0f6cb70e1bcf +md"### 2D arrays (matrices)" + +# ╔═╡ db99ae9a-edee-11ea-393e-9de420a545a1 +md"We can make small matrices (2D arrays) with square brackets too:" + +# ╔═╡ 04f175f2-edef-11ea-0882-712548ebb7a3 +M = [1 2 + 3 4] + +# ╔═╡ 0a8ac112-edef-11ea-1e99-cf7c7808c4f5 +typeof(M) + +# ╔═╡ 1295f48a-edef-11ea-22a5-61e8a2e1d005 +md"The `2` in the type confirms that this is a 2D array." + +# ╔═╡ 3e1fdaa8-edef-11ea-2f03-eb41b2b9ea0f +md"This won't work for larger matrices, though. For that we can use e.g." + +# ╔═╡ 48f3deca-edef-11ea-2c18-e7419c9030a0 +zeros(5, 5) + +# ╔═╡ a8f26af8-edef-11ea-2fc7-2b776f515aea +md"Note that `zeros` gives `Float64`s by default. We can also specify a type for the elements:" + +# ╔═╡ b595373e-edef-11ea-03e2-6599ef14af20 +zeros(Int, 4, 5) + +# ╔═╡ 4cb33c04-edef-11ea-2b35-1139c246c331 +md"We can then fill in the values we want by manipulating the elements, e.g. with a `for` loop." + +# ╔═╡ 54e47e9e-edef-11ea-2d75-b5f550902528 +md"A nice alternative syntax to create matrices following a certain pattern is an array comprehension with a *double* `for` loop:" + +# ╔═╡ 6348edce-edef-11ea-1ab4-019514eb414f +[i + j for i in 1:5, j in 1:6] + +# ╔═╡ e03be0e6-160c-46ac-a417-32e7299be02d +md""" +# Acknowledgement +""" + +# ╔═╡ 2548306d-ed5d-4793-b925-7b36e932841c +Markdown.MD( + Markdown.Admonition("warning", "This notebook is taken from", +[md""" + +_**Computational Thinking**, a live online Julia/Pluto textbook._ ([computationalthinking.mit.edu](https://computationalthinking.mit.edu), [original notebook](https://github.com/mitmath/18S191/blob/Fall20/lecture_notebooks/Basic%20Julia%20syntax.jl)) +"""] + )) + +# ╔═╡ 6e618eb2-037a-4688-bc7b-53fda57993a1 +using PlutoUI + +# ╔═╡ f15d5b3e-7639-4d20-9cfd-ef6bc07451c3 +TableOfContents() + +# ╔═╡ 00000000-0000-0000-0000-000000000001 +PLUTO_PROJECT_TOML_CONTENTS = """ +[deps] +PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" + +[compat] +PlutoUI = "~0.7.34" +""" + +# ╔═╡ 00000000-0000-0000-0000-000000000002 +PLUTO_MANIFEST_TOML_CONTENTS = """ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.7.2" +manifest_format = "2.0" + +[[deps.AbstractPlutoDingetjes]] +deps = ["Pkg"] +git-tree-sha1 = "8eaf9f1b4921132a4cff3f36a1d9ba923b14a481" +uuid = "6e696c72-6542-2067-7265-42206c756150" +version = "1.1.4" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.11.0" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.Downloads]] +deps = ["ArgTools", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" + +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.4" + +[[deps.Hyperscript]] +deps = ["Test"] +git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9" +uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91" +version = "0.0.4" + +[[deps.HypertextLiteral]] +git-tree-sha1 = "2b078b5a615c6c0396c77810d92ee8c6f470d238" +uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" +version = "0.9.3" + +[[deps.IOCapture]] +deps = ["Logging", "Random"] +git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a" +uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" +version = "0.2.2" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "3c837543ddb02250ef42f4738347454f95079d4e" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.3" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" + +[[deps.LibGit2]] +deps = ["Base64", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" + +[[deps.Parsers]] +deps = ["Dates"] +git-tree-sha1 = "13468f237353112a01b2d6b32f3d0f80219944aa" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.2.2" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" + +[[deps.PlutoUI]] +deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"] +git-tree-sha1 = "8979e9802b4ac3d58c503a20f2824ad67f9074dd" +uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" +version = "0.7.34" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[deps.Random]] +deps = ["SHA", "Serialization"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[deps.SparseArrays]] +deps = ["LinearAlgebra", "Random"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[deps.Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl", "OpenBLAS_jll"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +""" + +# ╔═╡ Cell order: +# ╟─f5450eab-0f9f-4b7f-9b80-992d3c553ba9 +# ╟─0d3aec92-edeb-11ea-3adb-cd0dc17cbdab +# ╟─3b038ee0-edeb-11ea-0977-97cc30d1c6ff +# ╠═3e8e0ea0-edeb-11ea-22e0-c58f7c2168ce +# ╠═59b66862-edeb-11ea-2d62-71dcc79dbfab +# ╟─5e062a24-edeb-11ea-256a-d938f77d7815 +# ╟─7e46f0e8-edeb-11ea-1092-4b5e8acd9ee0 +# ╠═8a695b86-edeb-11ea-08cc-17263bec09df +# ╟─8e2dd3be-edeb-11ea-0703-354fb31c12f5 +# ╟─96b5a28c-edeb-11ea-11c0-597615962f54 +# ╠═a7453572-edeb-11ea-1e27-9f710fd856a6 +# ╟─b341db4e-edeb-11ea-078b-b71ac00089d7 +# ╠═23f9afd4-eded-11ea-202a-9f0f1f91e5ad +# ╠═cc1f6872-edeb-11ea-33e9-6976fd9b107a +# ╟─ce9667c2-edeb-11ea-2665-d789032abd11 +# ╠═d73d3400-edeb-11ea-2dea-95e8c4a6563b +# ╠═e04ccf10-edeb-11ea-36d1-d11969e4b2f2 +# ╟─e297c5cc-edeb-11ea-3bdd-090f415685ab +# ╟─ec751446-edeb-11ea-31ba-2372e7c71b42 +# ╠═fe3fa290-edeb-11ea-121e-7114e5c573c1 +# ╟─394b0ec8-eded-11ea-31fb-27392068ef8f +# ╠═4dc00908-eded-11ea-25c5-0f7b2b7e18f9 +# ╟─6c44abb4-edec-11ea-16bd-557800b5f9d2 +# ╠═683af3e2-eded-11ea-25a5-0d90bf099d98 +# ╠═76764ea2-eded-11ea-1aa6-296f3421de1c +# ╟─93a231f4-edec-11ea-3b39-299b3be2da78 +# ╟─82e63a24-eded-11ea-3887-15d6bfabea4b +# ╠═9b339b2a-eded-11ea-10d7-8fc9a907c892 +# ╠═9535eb40-eded-11ea-1651-e33c9c23dbfb +# ╟─a16299a2-eded-11ea-2b56-93eb7a1010a7 +# ╠═bc6b124e-eded-11ea-0290-b3760cb81024 +# ╟─cfb21014-eded-11ea-1261-3bc30952a88e +# ╟─ffee7d80-eded-11ea-26b1-1331df204c67 +# ╟─cae4137e-edee-11ea-14af-59a32227de1b +# ╟─714f4fca-edee-11ea-3410-c9ab8825d836 +# ╠═82cc2a0e-edee-11ea-11b7-fbaa5ad7b556 +# ╠═85916c18-edee-11ea-0738-5f5d78875b86 +# ╟─881b7d0c-edee-11ea-0b4a-4bd7d5be2c77 +# ╠═a298e8ae-edee-11ea-3613-0dd4bae70c26 +# ╠═a5ebddd6-edee-11ea-2234-55453ea59c5a +# ╟─a9b48e54-edee-11ea-1333-a96181de0185 +# ╟─68c4ead2-edef-11ea-124a-03c2d7dd6a1b +# ╠═84129294-edef-11ea-0c77-ffa2b9592a26 +# ╟─d364fa16-edee-11ea-2050-0f6cb70e1bcf +# ╟─db99ae9a-edee-11ea-393e-9de420a545a1 +# ╠═04f175f2-edef-11ea-0882-712548ebb7a3 +# ╠═0a8ac112-edef-11ea-1e99-cf7c7808c4f5 +# ╟─1295f48a-edef-11ea-22a5-61e8a2e1d005 +# ╟─3e1fdaa8-edef-11ea-2f03-eb41b2b9ea0f +# ╠═48f3deca-edef-11ea-2c18-e7419c9030a0 +# ╟─a8f26af8-edef-11ea-2fc7-2b776f515aea +# ╠═b595373e-edef-11ea-03e2-6599ef14af20 +# ╟─4cb33c04-edef-11ea-2b35-1139c246c331 +# ╟─54e47e9e-edef-11ea-2d75-b5f550902528 +# ╠═6348edce-edef-11ea-1ab4-019514eb414f +# ╟─e03be0e6-160c-46ac-a417-32e7299be02d +# ╟─2548306d-ed5d-4793-b925-7b36e932841c +# ╠═6e618eb2-037a-4688-bc7b-53fda57993a1 +# ╠═f15d5b3e-7639-4d20-9cfd-ef6bc07451c3 +# ╟─00000000-0000-0000-0000-000000000001 +# ╟─00000000-0000-0000-0000-000000000002 diff --git a/test/basic_site/src/en/blog/yayy.md b/test/basic_site/src/en/blog/yayy.md new file mode 100644 index 0000000..7b818fe --- /dev/null +++ b/test/basic_site/src/en/blog/yayy.md @@ -0,0 +1,21 @@ +--- +tags: ["blog"] +layout: "md.jlmd" +--- + +# Hello there! + +My name is fons + +
    +$(map(1:3) do i + @mdx """
  • That's $i cool
  • """ +end) +
+ +Want to embed some HTML? *Easy!* Just type the HTML! + +```math +\\sqrt{\\frac{1}{2}} +```` + diff --git a/test/basic_site/src/en/docs/index.jlmd b/test/basic_site/src/en/docs/index.jlmd new file mode 100644 index 0000000..e2d6062 --- /dev/null +++ b/test/basic_site/src/en/docs/index.jlmd @@ -0,0 +1,9 @@ +--- +title: "🙋 Introduction" +tags: ["docs", "introduction"] +layout: "md.jlmd" +--- + +# Welcome to Pluto! + +Welcome to the docs! We are still working on this website ☺️ \ No newline at end of file diff --git a/test/basic_site/src/en/docs/packages-advanced.jlmd b/test/basic_site/src/en/docs/packages-advanced.jlmd new file mode 100644 index 0000000..d88544d --- /dev/null +++ b/test/basic_site/src/en/docs/packages-advanced.jlmd @@ -0,0 +1,146 @@ +--- +title: "📦 Packages: advanced" +tags: ["docs", "reproducibility"] +order: 2 +layout: "md.jlmd" +--- + +# Advanced: set up an environment with `Pkg.activate` + +Pluto's package manager is enabled for all users, for ease of use and to promote reproducibility in scientific computing. There is no option to disable the behaviour _globally_ (for your entire Pluto session). Instead, Pluto will detect notebooks that use `Pkg.activate` to set up an environment explicitly, and uses the old behaviour for those notebooks. + +The philosophy here is that everyone should have a reproducible package environment **by default**, without having to do anything. This takes priority over other use cases, and hence _not_ using the built-in package manager requires some extra work. + +
+ + +**Any notebook that calls [`Pkg.activate`](https://pkgdocs.julialang.org/v1/api/#Pkg.activate) will not use Pluto's package management,** and run in 'backwards compatibility mode'. The `Pkg.activate` call should be placed directly in your notebook code: it is detecting using the same syntax analysis used for reactivity. + +
+
+ +## Pattern: The "global environment" +If you do not intend on sharing a notebook file and you want to use your global package environment (called `(v1.6)` or similar, the one you get when you launch the Julia REPL), then you can call `Pkg.activate()` without any arguments. + +> 🙋 If you are developing a package, then activating your global environment is an easy way to test your local version in Pluto. + +This "global environment" pattern can be placed at the top of a notebook: + +```julia +begin + import Pkg + # careful: this is _not_ a reproducible environment + # activate the global environment + Pkg.activate() + + using Plots, PlutoUI, LinearAlgebra +end +``` + + +When running this in Pluto (try it out!), you will notice that the status marks next to packages disappear, and Pluto is running in 'backwards compatibility mode'. Packages will no longer be installed or removed automatically, you have to use the Pkg REPL to do this yourself. + + +
+
+ +## Pattern: The "shared environment" +If you have multiple notebooks in a repository and you want to use share a Pkg environment between them, then you can call `Pkg.activate(path_to_environment)`. You can use `@__DIR__` to get the path of the notebook's folder, and `joinpath(@__DIR__, "..")` to get its parent, `joinpath(@__DIR__, "..", "..")` for the parent's parent, etc. + +The function `Base.current_project()` can be used to **automatically** find the closest parent directory that contains a `Project.toml`, in most cases this is what you want. + +For example, if your project looks like this: + +``` +my_project/ + data/ + ... + notebooks/ + Interesting analysis.jl + ... + Project.toml + Manifest.toml + ... +``` + +then the "shared environment" pattern can be placed at the top of a notebook: + +```julia +begin + import Pkg + # activate the shared project environment + Pkg.activate(Base.current_project()) + # instantiate, i.e. make sure that all packages are downloaded + Pkg.instantiate() + + using Plots, PlutoUI, LinearAlgebra +end +``` + + +When running this in Pluto, you will notice that the status marks next to packages disappear, and Pluto is running in 'backwards compatibility mode'. Packages will no longer be installed or removed automatically, you have to use the Pkg REPL to do this yourself. + + +
+
+ +## Pattern: The "Pkg cell" +When adding packages, Pluto's default package management will always install the latest version from the registry. If you need to install a specific version or branch of a package, or a package is not registered, you can use a "Pkg cell". + +A common pattern is a so-called "Pkg cell", placed at the top of a notebook: + +```julia +begin + import Pkg + # activate a temporary environment + Pkg.activate(mktempdir()) + Pkg.add([ + Pkg.PackageSpec(name="Plots", version="1"), + Pkg.PackageSpec(name="PlutoUI", version="0.7"), + ]) + using Plots, PlutoUI, LinearAlgebra +end +``` + +This will 1) activate a temporary environment using `Pkg.activate`, 2) add the required packages, 3) import them with `using`. When running this in Pluto (try it out!), you will notice that the status marks next to packages disappear, and Pluto is running in 'backwards compatibility mode'. Packages will no longer be installed or removed automatically, you have to use the Pkg REPL to do this yourself. + +Placing all code in a single `begin` block ensures that the lines will run in the correct order. + + + + + + + + + +
+
+
+
+
+
+
+
+
+ + +# Advanced: edit the notebook environment + +Pluto.jl includes a helper function `Pluto.activate_notebook_environment` that activates a notebook Pkg environment in the REPL: + +```julia +julia> import Pluto + +julia> Pluto.activate_notebook_environment("~/Documents/hello.jl") + +julia> ] + +(hello.jl) > status +``` + +After activating a notebook environment, you can use the [Pkg REPL](https://pkgdocs.julialang.org/v1/repl/) to view or modify the embedded environment. Changes from either side are synchronised (i.e. Pkg REPL changes are written to the notebook, editing the notebook updates the Pkg REPL env). Watch the demo video: + + + + diff --git a/test/basic_site/src/en/docs/packages.jlmd b/test/basic_site/src/en/docs/packages.jlmd new file mode 100644 index 0000000..c01e755 --- /dev/null +++ b/test/basic_site/src/en/docs/packages.jlmd @@ -0,0 +1,120 @@ +--- +title: "📦 Packages" +tags: ["docs", "reproducibility"] +order: 1 +layout: "md.jlmd" +--- + +# Pluto's built-in _package management_ + +Starting with version 0.15, Pluto has a _built-in_ package manager, which means: +1. 🎈 Packages are **automatically installed** when you use `import` or `using`. +2. 🎈 Your package environment is **stored inside the notebook file**. When someone else opens your notebook with Pluto, the exact same package environment will be used, and packages will work on their computer. + +> 🙋 These two features are designed to make it easy to write and share **reproducible notebooks**. + +
+
+
+ +# Basic usage + +## Installing and using packages + +Pluto will automatically install or remove packages while you work on your notebook. When you import a new package, Pluto will install it: + +Schermafbeelding 2021-06-10 om 20 35 52 + + + + +> 🙋 Most packages will write _installation instructions_ in their documentation: like "Run `julia> ] install Example` to install `Example`". If you are using Pluto, you can skip these instructions, and import the package directly, using `import Example` or `using Example`. + +#### Logs + +Installing packages can take some time, especially when starting Julia for the first time. Click on the status mark next to a package to view the installation progress. You can click on the 📄 icon to view the logs. + + + + +
+
+ + +## Removing packages + +When you delete the code that imports a package, it will be uninstalled from the package environment. It is _recommended_ to restart the notebook process afterwards to get a fresh start. + + + +
+
+ + +## Updating packages + +You can search for and install any available updates by clicking on the 📄 icon. A backup of your notebook file will be created in the same folder as your notebook, in case the new versions do not work as expected. + +Update button + +
+
+
+
+
+
+
+ + +# Good to know + +### Based on Pkg + +Pluto's package management is a wrapper around [Pkg.jl](https://pkgdocs.julialang.org/v1/), Julia's built-in package manager. Packages are installed from the [General registry](https://github.com/JuliaRegistries/General). + +> 🙋 You can discover all available packages on [juliahub.com](https://juliahub.com/ui/Home). + +### Isolated package environment + +Every notebook runs in its own isolated package environment. This ensures that your notebook code will not be influenced by packages installed elsewhere. (The `LOAD_PATH` is set to `["@", "@stdlib"]`.) + +### Notebook file + +Pluto stores the contents of [`Project.toml` and `Manifest.toml`](https://pkgdocs.julialang.org/v1/toml-files/) directly in the notebook file. For forwards-backwards compatibility, this is done using two extra "cells" at the bottom of the file, containing the two files as string literals. For example, here is a notebook that imports `HypertextLiteral` and `PlutoUI`: [`fonsp/Pluto file format demo.jl`](https://gist.github.com/fonsp/44e72741cefb6041506cb8c7040db1a7). + +> 🙋 We encourage you to open Pluto, import some packages and look at the file! + +### Fully reproducible environments + +When someone else opens your notebook for the first time, Pluto will install all required packages based on the information in the [`Manifest.toml`](https://pkgdocs.julialang.org/v1/toml-files/#Manifest.toml) file. This means that the exact same versions of all packages you used in the notebook will be installed, ensuring your work is fully reproducible when shared with others. + +### Compatibility across Pluto versions + +When opening an old Pluto notebook that does not have embedded project files, Pluto will generate them as if you typed those imports for the first time. If a call to `Pkg.activate` is made, the notebook will run in 'backwards compatibility mode', using the same environment and behaviour as old Pluto versions. + +### Compatibility across Julia versions + +The `Manifest.toml` is designed to be (generally) _backwards compatible_: you can upgrade Julia and use an old manifest. However, the `Manifest.toml` is not always _forwards compatible_: a manifest generated generated with a newer version of Julia might not run on older versions. + +Pluto will always try to load the embedded manifest, and if it fails, it will _discard the manifest_ (leaving only `Project.toml`) and try again. This is one reason why Pluto automatically adds `[compat]` ranges for each package in the `Project.toml`. + +### Package installations are shared between environments + +In Julia, packages are always installed globally, while _environments_ (including notebooks) only store **version information**, not the package code itself. This means that multiple notebooks that use the same version of `Plots` will not lead to more disk usage or precompile time. (This is different from `venv` in Python/pip, or `node_modules` in NodeJS/npm, where every environment contains copies of package code by default.) Julia's package manager is designed to work well with many package environments on the same computer. + +Of course, if different notebooks use different version of the same package, and you work on both in parallel, then source files for both versions will exist on your computer. A small price to pay for simpler reproducibility! + +In Julia 1.5 and 1.6, you can clean up package files that have not been used in a while using `import Pkg; Pkg.gc()`. In Julia 1.7 and up, this will be done [automatically](https://github.com/JuliaLang/Pkg.jl/pull/2567). + +### Custom registries + +Pkg.jl supports additional private or public registries, which can be added in the Julia REPL with `] registry add https://github.com/myuser/MyRegistry.git`, and this is also supported by Pluto's package managemer. + +However, note that registries are not stored in the `Project.toml`/`Manifest.toml` files, which means that other people can only open your notebook if they added the custom registry before doing so. Alternatively, you can use a "Pkg cell" (more on this later) where you add the registry before adding packages. + +
+
+
+
+ +Learn more: advanced Pkg management \ No newline at end of file diff --git a/test/basic_site/src/examples/how are you.jl b/test/basic_site/src/examples/how are you.jl new file mode 100644 index 0000000..d5f30a8 --- /dev/null +++ b/test/basic_site/src/examples/how are you.jl @@ -0,0 +1,510 @@ +### A Pluto.jl notebook ### +# v0.18.2 + +#> [frontmatter] +#> title = "Basic syntax" +#> description = "A simple notebook demonstrating the Julia syntax essentials" +#> layout = "layout.jlhtml" +#> date = "2020-06-01" +#> tags = ["blog"] + +using Markdown +using InteractiveUtils + +# ╔═╡ 0d3aec92-edeb-11ea-3adb-cd0dc17cbdab + + +# ╔═╡ 3b038ee0-edeb-11ea-0977-97cc30d1c6ff +md" +# This is a test page for PlutoPages.jl + +## Variables + +We can define a variable using `=` (assignment). Then we can use its value in other expressions: +" + +# ╔═╡ 3e8e0ea0-edeb-11ea-22e0-c58f7c2168ce +x = 3 + +# ╔═╡ 59b66862-edeb-11ea-2d62-71dcc79dbfab +y = 2x + +# ╔═╡ 5e062a24-edeb-11ea-256a-d938f77d7815 +md"By default Julia displays the output of the last operation. (You can suppress the output by adding `;` (a semicolon) at the end.) +" + +# ╔═╡ 7e46f0e8-edeb-11ea-1092-4b5e8acd9ee0 +md"We can ask what type a variable has using `typeof`:" + +# ╔═╡ 8a695b86-edeb-11ea-08cc-17263bec09df +typeof(y) + +# ╔═╡ 8e2dd3be-edeb-11ea-0703-354fb31c12f5 +md"## Functions" + +# ╔═╡ 96b5a28c-edeb-11ea-11c0-597615962f54 +md"We can use a short-form, one-line function definition for simple functions:" + +# ╔═╡ a7453572-edeb-11ea-1e27-9f710fd856a6 +f(x) = 2 + x + +# ╔═╡ b341db4e-edeb-11ea-078b-b71ac00089d7 +md"Typing the function's name gives information about the function. To call it we must use parentheses:" + +# ╔═╡ 23f9afd4-eded-11ea-202a-9f0f1f91e5ad +f + +# ╔═╡ cc1f6872-edeb-11ea-33e9-6976fd9b107a +f(10) + +# ╔═╡ ce9667c2-edeb-11ea-2665-d789032abd11 +md"For longer functions we use the following syntax with the `function` keyword and `end`:" + +# ╔═╡ d73d3400-edeb-11ea-2dea-95e8c4a6563b +function g(x, y) + z = x + y + return z^2 +end + +# ╔═╡ e04ccf10-edeb-11ea-36d1-d11969e4b2f2 +g(1, 2) + +# ╔═╡ e297c5cc-edeb-11ea-3bdd-090f415685ab +md"## For loops" + +# ╔═╡ ec751446-edeb-11ea-31ba-2372e7c71b42 +md"Use `for` to loop through a pre-determined set of values:" + +# ╔═╡ fe3fa290-edeb-11ea-121e-7114e5c573c1 +let s = 0 + + for i in 1:10 + s += i # Equivalent to s = s + i + end + + s +end + +# ╔═╡ 394b0ec8-eded-11ea-31fb-27392068ef8f +md"Here, `1:10` is a **range** representing the numbers from 1 to 10:" + +# ╔═╡ 4dc00908-eded-11ea-25c5-0f7b2b7e18f9 +typeof(1:10) + +# ╔═╡ 6c44abb4-edec-11ea-16bd-557800b5f9d2 +md"Above we used a `let` block to define a new local variable `s`. +But blocks of code like this are usually better inside functions, so that they can be reused. For example, we could rewrite the above as follows: +" + +# ╔═╡ 683af3e2-eded-11ea-25a5-0d90bf099d98 +function mysum(n) + s = 0 + + for i in 1:n + s += i + end + + return s +end + +# ╔═╡ 76764ea2-eded-11ea-1aa6-296f3421de1c +mysum(100) + +# ╔═╡ 93a231f4-edec-11ea-3b39-299b3be2da78 +md"## Conditionals: `if`" + +# ╔═╡ 82e63a24-eded-11ea-3887-15d6bfabea4b +md"We can evaluate whether a condition is true or not by simply writing the condition:" + +# ╔═╡ 9b339b2a-eded-11ea-10d7-8fc9a907c892 +a = 3 + +# ╔═╡ 9535eb40-eded-11ea-1651-e33c9c23dbfb +a < 5 + +# ╔═╡ a16299a2-eded-11ea-2b56-93eb7a1010a7 +md"We see that conditions have a Boolean (`true` or `false`) value. + +We can then use `if` to control what we do based on that value:" + +# ╔═╡ bc6b124e-eded-11ea-0290-b3760cb81024 +if a < 5 + "small" + +else + "big" + +end + +# ╔═╡ cfb21014-eded-11ea-1261-3bc30952a88e +md"""Note that the `if` also returns the last value that was evaluated, in this case the string `"small"` or `"big"`, Since Pluto is reactive, changing the definition of `a` above will automatically cause this to be reevaluated!""" + +# ╔═╡ ffee7d80-eded-11ea-26b1-1331df204c67 +md"## Arrays" + +# ╔═╡ cae4137e-edee-11ea-14af-59a32227de1b +md"### 1D arrays (`Vector`s)" + +# ╔═╡ 714f4fca-edee-11ea-3410-c9ab8825d836 +md"We can make a `Vector` (1-dimensional, or 1D array) using square brackets:" + +# ╔═╡ 82cc2a0e-edee-11ea-11b7-fbaa5ad7b556 +v = [1, 2, 3] + +# ╔═╡ 85916c18-edee-11ea-0738-5f5d78875b86 +typeof(v) + +# ╔═╡ 881b7d0c-edee-11ea-0b4a-4bd7d5be2c77 +md"The `1` in the type shows that this is a 1D array. + +We access elements also using square brackets:" + +# ╔═╡ a298e8ae-edee-11ea-3613-0dd4bae70c26 +v[2] + +# ╔═╡ a5ebddd6-edee-11ea-2234-55453ea59c5a +v[2] = 10 + +# ╔═╡ a9b48e54-edee-11ea-1333-a96181de0185 +md"Note that Pluto does not automatically update cells when you modify elements of an array, but the value does change." + +# ╔═╡ 68c4ead2-edef-11ea-124a-03c2d7dd6a1b +md"A nice way to create `Vector`s following a certain pattern is to use an **array comprehension**:" + +# ╔═╡ 84129294-edef-11ea-0c77-ffa2b9592a26 +v2 = [i^2 for i in 1:10] + +# ╔═╡ d364fa16-edee-11ea-2050-0f6cb70e1bcf +md"### 2D arrays (matrices)" + +# ╔═╡ db99ae9a-edee-11ea-393e-9de420a545a1 +md"We can make small matrices (2D arrays) with square brackets too:" + +# ╔═╡ 04f175f2-edef-11ea-0882-712548ebb7a3 +M = [1 2 + 3 4] + +# ╔═╡ 0a8ac112-edef-11ea-1e99-cf7c7808c4f5 +typeof(M) + +# ╔═╡ 1295f48a-edef-11ea-22a5-61e8a2e1d005 +md"The `2` in the type confirms that this is a 2D array." + +# ╔═╡ 3e1fdaa8-edef-11ea-2f03-eb41b2b9ea0f +md"This won't work for larger matrices, though. For that we can use e.g." + +# ╔═╡ 48f3deca-edef-11ea-2c18-e7419c9030a0 +zeros(5, 5) + +# ╔═╡ a8f26af8-edef-11ea-2fc7-2b776f515aea +md"Note that `zeros` gives `Float64`s by default. We can also specify a type for the elements:" + +# ╔═╡ b595373e-edef-11ea-03e2-6599ef14af20 +zeros(Int, 4, 5) + +# ╔═╡ 4cb33c04-edef-11ea-2b35-1139c246c331 +md"We can then fill in the values we want by manipulating the elements, e.g. with a `for` loop." + +# ╔═╡ 54e47e9e-edef-11ea-2d75-b5f550902528 +md"A nice alternative syntax to create matrices following a certain pattern is an array comprehension with a *double* `for` loop:" + +# ╔═╡ 6348edce-edef-11ea-1ab4-019514eb414f +[i + j for i in 1:5, j in 1:6] + +# ╔═╡ e03be0e6-160c-46ac-a417-32e7299be02d +md""" +# Acknowledgement +""" + +# ╔═╡ 2548306d-ed5d-4793-b925-7b36e932841c +Markdown.MD( + Markdown.Admonition("warning", "This notebook is taken from", +[md""" + +_**Computational Thinking**, a live online Julia/Pluto textbook._ ([computationalthinking.mit.edu](https://computationalthinking.mit.edu), [original notebook](https://github.com/mitmath/18S191/blob/Fall20/lecture_notebooks/Basic%20Julia%20syntax.jl)) +"""] + )) + +# ╔═╡ 6e618eb2-037a-4688-bc7b-53fda57993a1 +using PlutoUI + +# ╔═╡ f15d5b3e-7639-4d20-9cfd-ef6bc07451c3 +TableOfContents() + +# ╔═╡ 00000000-0000-0000-0000-000000000001 +PLUTO_PROJECT_TOML_CONTENTS = """ +[deps] +PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" + +[compat] +PlutoUI = "~0.7.34" +""" + +# ╔═╡ 00000000-0000-0000-0000-000000000002 +PLUTO_MANIFEST_TOML_CONTENTS = """ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.7.2" +manifest_format = "2.0" + +[[deps.AbstractPlutoDingetjes]] +deps = ["Pkg"] +git-tree-sha1 = "8eaf9f1b4921132a4cff3f36a1d9ba923b14a481" +uuid = "6e696c72-6542-2067-7265-42206c756150" +version = "1.1.4" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.11.0" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.Downloads]] +deps = ["ArgTools", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" + +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.4" + +[[deps.Hyperscript]] +deps = ["Test"] +git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9" +uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91" +version = "0.0.4" + +[[deps.HypertextLiteral]] +git-tree-sha1 = "2b078b5a615c6c0396c77810d92ee8c6f470d238" +uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" +version = "0.9.3" + +[[deps.IOCapture]] +deps = ["Logging", "Random"] +git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a" +uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" +version = "0.2.2" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "3c837543ddb02250ef42f4738347454f95079d4e" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.3" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" + +[[deps.LibGit2]] +deps = ["Base64", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" + +[[deps.Parsers]] +deps = ["Dates"] +git-tree-sha1 = "13468f237353112a01b2d6b32f3d0f80219944aa" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.2.2" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" + +[[deps.PlutoUI]] +deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"] +git-tree-sha1 = "8979e9802b4ac3d58c503a20f2824ad67f9074dd" +uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" +version = "0.7.34" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[deps.Random]] +deps = ["SHA", "Serialization"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[deps.SparseArrays]] +deps = ["LinearAlgebra", "Random"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[deps.Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl", "OpenBLAS_jll"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +""" + +# ╔═╡ Cell order: +# ╟─f5450eab-0f9f-4b7f-9b80-992d3c553ba9 +# ╟─0d3aec92-edeb-11ea-3adb-cd0dc17cbdab +# ╟─3b038ee0-edeb-11ea-0977-97cc30d1c6ff +# ╠═3e8e0ea0-edeb-11ea-22e0-c58f7c2168ce +# ╠═59b66862-edeb-11ea-2d62-71dcc79dbfab +# ╟─5e062a24-edeb-11ea-256a-d938f77d7815 +# ╟─7e46f0e8-edeb-11ea-1092-4b5e8acd9ee0 +# ╠═8a695b86-edeb-11ea-08cc-17263bec09df +# ╟─8e2dd3be-edeb-11ea-0703-354fb31c12f5 +# ╟─96b5a28c-edeb-11ea-11c0-597615962f54 +# ╠═a7453572-edeb-11ea-1e27-9f710fd856a6 +# ╟─b341db4e-edeb-11ea-078b-b71ac00089d7 +# ╠═23f9afd4-eded-11ea-202a-9f0f1f91e5ad +# ╠═cc1f6872-edeb-11ea-33e9-6976fd9b107a +# ╟─ce9667c2-edeb-11ea-2665-d789032abd11 +# ╠═d73d3400-edeb-11ea-2dea-95e8c4a6563b +# ╠═e04ccf10-edeb-11ea-36d1-d11969e4b2f2 +# ╟─e297c5cc-edeb-11ea-3bdd-090f415685ab +# ╟─ec751446-edeb-11ea-31ba-2372e7c71b42 +# ╠═fe3fa290-edeb-11ea-121e-7114e5c573c1 +# ╟─394b0ec8-eded-11ea-31fb-27392068ef8f +# ╠═4dc00908-eded-11ea-25c5-0f7b2b7e18f9 +# ╟─6c44abb4-edec-11ea-16bd-557800b5f9d2 +# ╠═683af3e2-eded-11ea-25a5-0d90bf099d98 +# ╠═76764ea2-eded-11ea-1aa6-296f3421de1c +# ╟─93a231f4-edec-11ea-3b39-299b3be2da78 +# ╟─82e63a24-eded-11ea-3887-15d6bfabea4b +# ╠═9b339b2a-eded-11ea-10d7-8fc9a907c892 +# ╠═9535eb40-eded-11ea-1651-e33c9c23dbfb +# ╟─a16299a2-eded-11ea-2b56-93eb7a1010a7 +# ╠═bc6b124e-eded-11ea-0290-b3760cb81024 +# ╟─cfb21014-eded-11ea-1261-3bc30952a88e +# ╟─ffee7d80-eded-11ea-26b1-1331df204c67 +# ╟─cae4137e-edee-11ea-14af-59a32227de1b +# ╟─714f4fca-edee-11ea-3410-c9ab8825d836 +# ╠═82cc2a0e-edee-11ea-11b7-fbaa5ad7b556 +# ╠═85916c18-edee-11ea-0738-5f5d78875b86 +# ╟─881b7d0c-edee-11ea-0b4a-4bd7d5be2c77 +# ╠═a298e8ae-edee-11ea-3613-0dd4bae70c26 +# ╠═a5ebddd6-edee-11ea-2234-55453ea59c5a +# ╟─a9b48e54-edee-11ea-1333-a96181de0185 +# ╟─68c4ead2-edef-11ea-124a-03c2d7dd6a1b +# ╠═84129294-edef-11ea-0c77-ffa2b9592a26 +# ╟─d364fa16-edee-11ea-2050-0f6cb70e1bcf +# ╟─db99ae9a-edee-11ea-393e-9de420a545a1 +# ╠═04f175f2-edef-11ea-0882-712548ebb7a3 +# ╠═0a8ac112-edef-11ea-1e99-cf7c7808c4f5 +# ╟─1295f48a-edef-11ea-22a5-61e8a2e1d005 +# ╟─3e1fdaa8-edef-11ea-2f03-eb41b2b9ea0f +# ╠═48f3deca-edef-11ea-2c18-e7419c9030a0 +# ╟─a8f26af8-edef-11ea-2fc7-2b776f515aea +# ╠═b595373e-edef-11ea-03e2-6599ef14af20 +# ╟─4cb33c04-edef-11ea-2b35-1139c246c331 +# ╟─54e47e9e-edef-11ea-2d75-b5f550902528 +# ╠═6348edce-edef-11ea-1ab4-019514eb414f +# ╟─e03be0e6-160c-46ac-a417-32e7299be02d +# ╟─2548306d-ed5d-4793-b925-7b36e932841c +# ╠═6e618eb2-037a-4688-bc7b-53fda57993a1 +# ╠═f15d5b3e-7639-4d20-9cfd-ef6bc07451c3 +# ╟─00000000-0000-0000-0000-000000000001 +# ╟─00000000-0000-0000-0000-000000000002 diff --git a/test/basic_site/src/htmlpage.html b/test/basic_site/src/htmlpage.html new file mode 100644 index 0000000..778711e --- /dev/null +++ b/test/basic_site/src/htmlpage.html @@ -0,0 +1,13 @@ + + + + + + Hello + + +

This is a test page for PlutoPages.jl

+

This is written in

+ HTML!!! + + diff --git a/test/basic_site/src/index.jlmd b/test/basic_site/src/index.jlmd new file mode 100644 index 0000000..e081626 --- /dev/null +++ b/test/basic_site/src/index.jlmd @@ -0,0 +1,15 @@ +--- +authors: ["myself"] +tags: ["welcome"] +layout: "welcome.jlhtml" +--- + +# This is a test page for PlutoPages.jl + + +Check out these pages: +- [Docs](/en/docs/) +- [Blog 1](/en/blog/something/) +- [Blog 2](/en/blog/yayy/) +- [Example](/examples/how are you/) +- [some html page](/htmlpage/) diff --git a/test/basic_site/src/sidebar data.jl b/test/basic_site/src/sidebar data.jl new file mode 100644 index 0000000..e702096 --- /dev/null +++ b/test/basic_site/src/sidebar data.jl @@ -0,0 +1,14 @@ +Dict( + "en" => Dict( + "docs" => [ + "Introduction" => collections["docs"].pages ∩ collections["introduction"].pages, + "Reproducibility" => collections["docs"].pages ∩ collections["reproducibility"].pages, + ], + # "examples" => [ + # "Getting started" => collections["examples"].pages, + # ], + "blog" => [ + "Asdfsafd" => collections["blog"].pages + ], + ) +) \ No newline at end of file