├── .gitignore ├── LICENSE ├── README.md ├── config.toml ├── content ├── about.md ├── book │ └── _index.md ├── concurrency │ ├── _index.md │ ├── example │ │ ├── _index.md │ │ └── tla │ │ │ ├── await_macro.tla │ │ │ ├── if_macro.tla │ │ │ ├── init.tla │ │ │ ├── limit_process.tla │ │ │ ├── with_delay.tla │ │ │ └── with_reserves.tla │ ├── invariants.md │ ├── labels.md │ ├── procedures-and-macros.md │ └── processes │ │ ├── _index.md │ │ └── tla │ │ ├── fail1.tla │ │ ├── fail2.tla │ │ ├── in.tla │ │ ├── pass1.tla │ │ └── processes.tla ├── introduction │ ├── _index.md │ ├── about-this-guide.md │ └── example │ │ ├── _index.md │ │ ├── img │ │ ├── Error Stack.png │ │ ├── basic_transfer.png │ │ ├── if_screenshot.png │ │ ├── intro_toolbox.png │ │ ├── make_spec.png │ │ ├── model.png │ │ ├── model_assert_fail.png │ │ ├── model_moneyinvariant1.png │ │ ├── model_moneyinvariant2.png │ │ ├── model_moneyinvariant_fail.png │ │ ├── multiprocess_fail.png │ │ └── translated.png │ │ └── tla │ │ ├── 3.tla │ │ ├── 4.tla │ │ ├── 5.tla │ │ ├── 6.tla │ │ ├── 7.tla │ │ ├── 8.tla │ │ ├── assertion.tla │ │ └── init.tla ├── models │ ├── _index.md │ ├── constants │ │ ├── _index.md │ │ ├── img │ │ │ ├── edit.png │ │ │ ├── show.png │ │ │ └── solution.png │ │ └── tla │ │ │ ├── constants.tla │ │ │ ├── hanoi.tla │ │ │ └── sensical.tla │ ├── example │ │ ├── _index.md │ │ ├── img │ │ │ └── failure.png │ │ └── tla │ │ │ ├── market.tla │ │ │ ├── market2.tla │ │ │ └── trade.tla │ └── model-values │ │ ├── _index.md │ │ └── img │ │ └── null.png ├── pluscal │ ├── _index.md │ ├── a-simple-spec.md │ ├── behaviors │ │ ├── _index.md │ │ └── tla │ │ │ ├── gates.tla │ │ │ └── gates2.tla │ └── toolbox │ │ ├── _index.md │ │ └── img │ │ ├── error_trace.png │ │ ├── invariant.png │ │ ├── model_overview.png │ │ └── model_run.png ├── reference │ ├── _index.md │ ├── expressions.md │ ├── structure │ │ ├── _index.md │ │ └── tla │ │ │ └── structure.tla │ └── types.md ├── techniques │ ├── _index.md │ ├── cond-steps.md │ ├── history.md │ ├── img │ │ ├── depth-first.png │ │ └── state-constraint.png │ ├── infinite-loops.md │ ├── merging-functions.md │ ├── model-values.md │ └── performance.md ├── temporal-logic │ ├── _index.md │ ├── operators │ │ ├── _index.md │ │ └── livelock.png │ ├── termination │ │ ├── _index.md │ │ ├── img │ │ │ ├── stuttering.png │ │ │ └── termination.png │ │ └── tla │ │ │ ├── fairness.tla │ │ │ └── finish.tla │ └── usage │ │ └── _index.md └── tla │ ├── _index.md │ ├── expressions.md │ ├── functions.md │ ├── logic.md │ ├── operators.md │ ├── sets.md │ └── tuples │ ├── _index.md │ ├── img │ └── solution.png │ └── tla │ └── hanoi.tla ├── layouts ├── index.html ├── partials │ ├── custom-footer.html │ ├── footer.html │ ├── logo.html │ ├── menu-footer.html │ └── script.html └── shortcodes │ ├── ans.html │ ├── code.html │ └── q.html ├── staging-content ├── example-specs │ └── _index.md └── patterns │ └── messages.md ├── static ├── css │ ├── bootstrap.css │ ├── hugo-theme.css │ └── theme.css └── js │ └── bootstrap.min.js └── themes └── hugo-theme-learn ├── .commit ├── LICENSE.md ├── README.md ├── archetypes ├── chapter.md └── default.md ├── exampleSite ├── LICENSE.md ├── config.toml ├── content │ ├── _index.en.md │ ├── _index.fr.md │ ├── basics │ │ ├── _index.en.md │ │ ├── _index.fr.md │ │ ├── configuration │ │ │ ├── _index.en.md │ │ │ └── _index.fr.md │ │ ├── installation │ │ │ ├── _index.en.md │ │ │ ├── _index.fr.md │ │ │ └── images │ │ │ │ └── chapter.png │ │ ├── requirements │ │ │ ├── _index.en.md │ │ │ ├── _index.fr.md │ │ │ └── images │ │ │ │ └── magic.gif │ │ └── style-customization │ │ │ ├── _index.en.md │ │ │ ├── _index.fr.md │ │ │ └── images │ │ │ ├── blue-variant.png │ │ │ ├── green-variant.png │ │ │ └── red-variant.png │ ├── cont │ │ ├── _index.en.md │ │ ├── _index.fr.md │ │ ├── archetypes.en.md │ │ ├── archetypes.fr.md │ │ ├── i18n │ │ │ ├── _index.en.md │ │ │ ├── _index.fr.md │ │ │ └── images │ │ │ │ └── i18n-menu.gif │ │ ├── markdown.en.md │ │ ├── markdown.fr.md │ │ ├── menushortcuts.en.md │ │ ├── menushortcuts.fr.md │ │ └── pages │ │ │ ├── _index.en.md │ │ │ ├── _index.fr.md │ │ │ └── images │ │ │ ├── frontmatter-icon.png │ │ │ ├── pages-chapter.png │ │ │ └── pages-default.png │ ├── credits.en.md │ ├── credits.fr.md │ ├── shortcodes │ │ ├── _index.en.md │ │ ├── _index.fr.md │ │ ├── attachments.en.files │ │ │ ├── BachGavotteShort.mp3 │ │ │ ├── Carroll_AliceAuPaysDesMerveilles.pdf │ │ │ ├── adivorciarsetoca00cape.pdf │ │ │ ├── hugo.png │ │ │ └── movieselectricsheep-flock-244-32500-2.mp4 │ │ ├── attachments.en.md │ │ ├── attachments.fr.files │ │ │ ├── BachGavotteShort.mp3 │ │ │ ├── Carroll_AliceAuPaysDesMerveilles.pdf │ │ │ ├── adivorciarsetoca00cape.pdf │ │ │ ├── hugo.png │ │ │ └── movieselectricsheep-flock-244-32500-2.mp4 │ │ ├── attachments.fr.md │ │ ├── button.en.md │ │ ├── button.fr.md │ │ ├── children │ │ │ ├── _index.en.md │ │ │ ├── _index.fr.md │ │ │ ├── children-1 │ │ │ │ ├── _index.en.md │ │ │ │ ├── _index.fr.md │ │ │ │ └── children-1-1 │ │ │ │ │ ├── _index.en.md │ │ │ │ │ ├── _index.fr.md │ │ │ │ │ └── children-1-1-1 │ │ │ │ │ ├── _index.en.md │ │ │ │ │ ├── _index.fr.md │ │ │ │ │ └── children-1-1-1-1 │ │ │ │ │ ├── _index.en.md │ │ │ │ │ ├── _index.fr.md │ │ │ │ │ └── children-1-1-1-1-1 │ │ │ │ │ ├── _index.en.md │ │ │ │ │ └── _index.fr.md │ │ │ ├── children-2 │ │ │ │ ├── _index.en.md │ │ │ │ ├── _index.fr.md │ │ │ │ ├── test3.en.md │ │ │ │ └── test3.fr.md │ │ │ ├── children-3 │ │ │ │ ├── _index.en.md │ │ │ │ └── _index.fr.md │ │ │ ├── children-4 │ │ │ │ ├── _index.en.md │ │ │ │ └── _index.fr.md │ │ │ ├── test.en.md │ │ │ └── test.fr.md │ │ ├── expand.en.md │ │ ├── expand.fr.md │ │ ├── mermaid.en.md │ │ ├── mermaid.fr.md │ │ ├── notice.en.md │ │ ├── notice.fr.md │ │ ├── siteparam.en.md │ │ └── siteparam.fr.md │ ├── showcase.en.md │ └── showcase.fr.md ├── layouts │ ├── partials │ │ ├── custom-footer.html │ │ ├── logo.html │ │ └── menu-footer.html │ └── shortcodes │ │ └── ghcontributors.html └── static │ ├── css │ └── theme-mine.css │ ├── fonts │ ├── monogramos-webfont.eot │ ├── monogramos-webfont.svg │ ├── monogramos-webfont.ttf │ ├── monogramos-webfont.woff │ └── monogramos-webfont.woff2 │ └── images │ └── showcase │ └── tat.png ├── i18n ├── en.toml └── fr.toml ├── images ├── screenshot.png └── tn.png ├── layouts ├── 404.html ├── _default │ ├── list.html │ └── single.html ├── index.html ├── index.json ├── partials │ ├── custom-footer.html │ ├── custom-header.html │ ├── favicon.html │ ├── footer.html │ ├── header.html │ ├── logo.html │ ├── menu-footer.html │ ├── menu.html │ ├── meta.html │ ├── search.html │ └── toc.html └── shortcodes │ ├── attachments.html │ ├── button.html │ ├── children.html │ ├── expand.html │ ├── mermaid.html │ ├── notice.html │ ├── ref.html │ ├── relref.html │ └── siteparam.html ├── static ├── css │ ├── auto-complete.css │ ├── featherlight.min.css │ ├── font-awesome.min.css │ ├── hugo-theme.css │ ├── hybrid.css │ ├── nucleus.css │ ├── perfect-scrollbar.min.css │ ├── theme-blue.css │ ├── theme-green.css │ ├── theme-red.css │ └── theme.css ├── fonts │ ├── FontAwesome.otf │ ├── Inconsolata.eot │ ├── Inconsolata.svg │ ├── Inconsolata.ttf │ ├── Inconsolata.woff │ ├── Novecentosanswide-Normal-webfont.eot │ ├── Novecentosanswide-Normal-webfont.svg │ ├── Novecentosanswide-Normal-webfont.ttf │ ├── Novecentosanswide-Normal-webfont.woff │ ├── Novecentosanswide-Normal-webfont.woff2 │ ├── Novecentosanswide-UltraLight-webfont.eot │ ├── Novecentosanswide-UltraLight-webfont.svg │ ├── Novecentosanswide-UltraLight-webfont.ttf │ ├── Novecentosanswide-UltraLight-webfont.woff │ ├── Novecentosanswide-UltraLight-webfont.woff2 │ ├── Work_Sans_200.eot │ ├── Work_Sans_200.svg │ ├── Work_Sans_200.ttf │ ├── Work_Sans_200.woff │ ├── Work_Sans_200.woff2 │ ├── Work_Sans_300.eot │ ├── Work_Sans_300.svg │ ├── Work_Sans_300.ttf │ ├── Work_Sans_300.woff │ ├── Work_Sans_300.woff2 │ ├── Work_Sans_500.eot │ ├── Work_Sans_500.svg │ ├── Work_Sans_500.ttf │ ├── Work_Sans_500.woff │ ├── Work_Sans_500.woff2 │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 ├── images │ ├── clippy.svg │ ├── favicon.png │ └── gopher-404.jpg ├── js │ ├── auto-complete.js │ ├── clipboard.min.js │ ├── featherlight.min.js │ ├── highlight.pack.js │ ├── html5shiv-printshiv.min.js │ ├── hugo-learn.js │ ├── jquery-2.x.min.js │ ├── jquery.sticky-kit.min.js │ ├── learn.js │ ├── lunr.min.js │ ├── modernizr.custom.71422.js │ ├── perfect-scrollbar.jquery.min.js │ ├── perfect-scrollbar.min.js │ └── search.js └── mermaid │ ├── mermaid.css │ ├── mermaid.dark.css │ ├── mermaid.forest.css │ └── mermaid.js ├── theme.toml └── wercker.yml /.gitignore: -------------------------------------------------------------------------------- 1 | public/ 2 | *~ 3 | .DS_Store 4 | .htpasswd 5 | .vscode 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **THIS HAS BEEN REPLACED BY https://github.com/hwayne/learntla-v2/** 2 | 3 | This is the source code used to build the site [Learn TLA+](http://www.learntla.com). The guide is aimed at beginners to formal method who want to use it for simple (but useful!) specifications. "Keep the server from exploding", not "Keep the spaceship from exploding". 4 | 5 | ### Setup 6 | 7 | 1. Clone repo 8 | 2. Get [Hugo](https://gohugo.io/) 9 | 3. Run with `hugo server` (on port 1313) 10 | 4. Either set up my [sad depressing Pygments plugin](https://github.com/hwayne/tla-pygments) or set `PygmentsCodeFences` to false in `config.toml` 11 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | languageCode = "en-us" 2 | baseurl = "http://learntla.com" 3 | title = "Learn TLA+" 4 | theme = "hugo-theme-learn" 5 | googleAnalytics = "UA-90708265-1" 6 | pygmentsUseClassic = true 7 | PygmentsCodeFences = true 8 | 9 | [Params] 10 | Author = "Hillel Wayne" 11 | disableSearch = true 12 | disableInlineCopyToClipBoard = true 13 | disableAssetsBusting = true 14 | -------------------------------------------------------------------------------- /content/about.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "About" 3 | +++ 4 | 5 | This is an introductory guide for TLA+ (Temporal Logic of Actions), a specification language used for writing code blueprints. 6 | 7 | ### About the Author 8 | 9 | I have a personal site at [hillelwayne.com](http://hillelwayne.com) I never update and a [Twitter account](https://twitter.com/Hillelogram) I never use. 10 | -------------------------------------------------------------------------------- /content/book/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Book" 3 | weight = 800 4 | +++ 5 | 6 | 7 | I am delighted to announce that my book, [Practical TLA+](https://www.apress.com/us/book/9781484238288), is now available! 8 | 9 | _Practical TLA+_ is the spiritual sequel to _Learn TLA+_. It's designed for the same audience, people who are unfamiliar with formal methods but could benefit from using it at work. Part two is where the book really shines: it's all about _using_ TLA+. It covers all sorts of different approaches, techniques, and pitfalls to writing specs. Everything from fleshing out abstract specs to modeling adversarial agents to why you always want a `TypeInvariant`. 10 | 11 | The book is also designed to be _accessible_. My technical editor and I went through the book together, line by line, making sure every explanation was clear and every step was explained. On average, we spent a half hour on each page. I honestly believe this is the best introduction to TLA+ available. 12 | 13 | Of course, you're already at a free, beginner-focused resource for TLA+, one I'm still incredibly proud of. I think it's worth talking about how the two resources relate to each other. 14 | 15 | ### FAQ 16 | 17 | **What makes this different from _Learn TLA+_?** 18 | 19 | _Practical TLA+_ is much more comprehensive. It covers the same material with greater depth, properly explains temporal logic, and actually talks about the module system. More importantly, it focuses much more on how to _use_ TLA+. The second half of the book is packed with applications, techniques, and large scale examples. To give a sense of scale, the last two proper chapters are each about a single spec. Those two chapters combined are about as long as _the entirety_ of _Learn TLA+_. 20 | 21 | Most importantly, I wrote _Learn TLA+_ as I was, well, _learning_ TLA+. I wrote _Practical TLA+_ with two more years of experience with writing specs, teaching people, and communicating the ideas. I think it shows in the quality of the text. 22 | 23 | On the other hand, _Learn TLA+_ is free and has exercises in it. Tradeoffs! 24 | 25 | **What's happening to _Learn TLA+_?** 26 | 27 | _Learn TLA+_ will always be freely available online. In fact, I'm planning two more big updates to it. The first will clean up any confusing parts and correct any technical errors. I'm about halfway through that and hope to have it finished relatively soon. The second will be adding the option to switch between P-syntax (the current style) and C-syntax. That's a little further out. 28 | 29 | Past that I plan to let _Learn TLA+_ stand on its own. I will still be reviewing pull requests, of course, if people want to [contribute fixes or additions](https://github.com/hwayne/learntla). Ultimately I see it being a shared project of the community. I wrote it because I believe free, online documentation is critical to the success of any project, and _Learn TLA+_ will stay that way. 30 | 31 | **If I've already read _Learn TLA+_, how should I read _Practical TLA+_?** 32 | 33 | Read the introduction so you know how to set up the PT module. Chapter 1 uses the same introductory example here and can be skipped. Chapters 2, 3, and 5 cover similar ground as the website, but more carefully and with more detail. Skim these if you feel comfortable with the basics. Chapter 4 is new material: in addition to constants and model values, it also has using multiple modules in a project and parameterization. Chapter 6 is a much better treatment of temporal logic than the site currently has. 34 | 35 | Chapters 7-12 are entirely new material. 36 | -------------------------------------------------------------------------------- /content/concurrency/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Concurrency" 3 | weight = 400 4 | +++ 5 | 6 | This chapter will cover _concurrent systems_: ones where multiple processes, sharing a global state, run simultaneously. As a simple example of a concurrent system, you have one model and three different kinds of jobs that can affect the state of that model, all running in an asynchronous worker pool. How do you guarantee that just the right ordering of run jobs doesn’t cause data to somehow break? 7 | 8 | Reasoning about concurrent systems gets intractable quickly, which is why we get a model checker to reason about it for us. 9 | -------------------------------------------------------------------------------- /content/concurrency/example/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Example: Rate Limiting" 3 | weight = 7 4 | +++ 5 | 6 | ## The Problem 7 | 8 | As part of your project, you need to call a third party API. There are two types of calls you need to make: 9 | 10 | 1. A GET for a collection of objects. Each call will return some results and, potentially, a pagination token. 11 | 1. A GET for a single object, followed by, if necessary, a PUT to update it. 12 | 13 | There is a known rate limit of N calls per unit of time on this API, and you do not want to exceed this. The first type may make an arbitrary number of calls, but it's less critical and you are comfortable waiting between calls. For the second, it will make either 1 or 2 calls; however, being higher priority, you want to _immediately_ update the object if necessary. With these constraints in mind, how do you guarantee you never exceed the rate limit? 14 | 15 | ### Initial Design 16 | 17 | We start with the minimum possible case. 18 | 19 | {{% code init %}} 20 | 21 | Since most of the business logic is irrelevant to our use case, we simply leave it out. `get_collection` makes an arbitrary number of calls, represented by the `either goto`. Every time TLC reaches that branch point it will explore both branches, so we know this can be an arbitrary number of calls. Similarly, the `get_put` makes either one or two calls in a transaction. Finally, every time the `made_calls` changes we check that we haven't gone over the maximum. 22 | 23 | If we run this, we'll get an error: the assert fails pretty trivially. We can fix this by adding a check in the macro, so that we only make a call if we have enough rate left. One fix is this: 24 | 25 | {{% code if_macro %}} 26 | 27 | Which makes the call fail silently if it would take us past the limit. 28 | 29 | ### Deadlocks 30 | 31 | Our solution works, but misses the business case: we don't want to not make the calls, we want to _wait_ on them until the rate limit refreshes. We can simulate that with an _await_: 32 | 33 | {{% code await_macro %}} 34 | 35 | If we run this, though, we get a deadlock. That's because all of our processes are waiting for the limit to refresh, which we never actually coded. Here's one way of doing this: 36 | 37 | {{% code limit_process %}} 38 | 39 | If we add that, the spec passes as normal. 40 | 41 | ### Asynchronous Workers 42 | 43 | Let's add a complication: all of the processes are running on different workers, so they don't automatically know the number of calls made. In order to avoid going past the limit, we need to share that information, which takes time. One way we can do this is by having each process query a central cache that only move forward if there's enough calls remaining. One representation would be 44 | 45 | {{% code with_delay %}} 46 | 47 | When we run this, we see it fails, as between the get and the request another process can make a call. If we want to resolve this we need some form of locking or priority. This will work, but it also explodes the diameter. Every process needs to wait on every other process, even when there's plenty of calls to go around. We should instead look for a more optimized way of handling this issue. 48 | 49 | ### Semaphores 50 | 51 | One solution we can use is to reserve calls: when a process checks that there are calls remaining, it reserves N calls that are considered made in our cache but not in the API endpoint. Then, once we make the appropriate calls, we return the necessary reserves. 52 | 53 | {{% code with_reserves %}} 54 | -------------------------------------------------------------------------------- /content/concurrency/example/tla/await_macro.tla: -------------------------------------------------------------------------------- 1 | macro make_calls(n) 2 | begin 3 | await made_calls <= max_calls - n; 4 | made_calls := made_calls + n; 5 | assert made_calls <= max_calls; 6 | end macro; 7 | -------------------------------------------------------------------------------- /content/concurrency/example/tla/if_macro.tla: -------------------------------------------------------------------------------- 1 | macro make_calls(n) 2 | begin 3 | if made_calls <= max_calls - n then 4 | made_calls := made_calls + n; 5 | assert made_calls <= max_calls; 6 | end if; 7 | end macro; 8 | -------------------------------------------------------------------------------- /content/concurrency/example/tla/init.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE api ---- 2 | EXTENDS Integers, TLC 3 | (* --algorithm api 4 | variables made_calls = 0, max_calls \in 5..10; 5 | 6 | macro make_calls(n) 7 | begin 8 | made_calls := made_calls + n; 9 | assert made_calls <= max_calls; 10 | end macro; 11 | 12 | process get_collection = 0 13 | begin 14 | Request: 15 | make_calls(1); 16 | either goto Request 17 | or skip 18 | end either; 19 | end process; 20 | 21 | process get_put \in 1..3 22 | begin 23 | Call: 24 | with c \in {1, 2} do 25 | make_calls(c) 26 | end with; 27 | end process; 28 | 29 | end algorithm; *) 30 | ==== 31 | -------------------------------------------------------------------------------- /content/concurrency/example/tla/limit_process.tla: -------------------------------------------------------------------------------- 1 | process reset_limit = -1 2 | begin 3 | Reset: 4 | while TRUE do 5 | made_calls := 0; 6 | end while 7 | end process 8 | -------------------------------------------------------------------------------- /content/concurrency/example/tla/with_delay.tla: -------------------------------------------------------------------------------- 1 | EXTENDS Integers, TLC 2 | (* --algorithm api 3 | variables made_calls = 0, max_calls \in 5..10; 4 | 5 | macro make_calls(n) 6 | begin 7 | made_calls := made_calls + n; 8 | assert made_calls <= max_calls; 9 | end macro; 10 | 11 | process reset_limit = -1 12 | begin 13 | Reset: 14 | while TRUE do 15 | made_calls := 0; 16 | end while 17 | end process 18 | 19 | 20 | process get_collection = 0 21 | begin 22 | GCGetCalls: 23 | await made_calls <= max_calls - 1; 24 | Request: 25 | make_calls(1); 26 | either goto GCGetCalls 27 | or skip 28 | end either; 29 | end process; 30 | 31 | process get_put \in 1..3 32 | begin 33 | GPGetCalls: 34 | await made_calls <= max_calls - 2; 35 | Call: 36 | with c \in {1, 2} do 37 | make_calls(c) 38 | end with; 39 | end process; 40 | 41 | end algorithm; *) 42 | -------------------------------------------------------------------------------- /content/concurrency/example/tla/with_reserves.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE api ---- 2 | EXTENDS Integers, TLC 3 | (* --algorithm api 4 | variables made_calls = 0, max_calls \in 5..10, reserved_calls = 0; 5 | 6 | 7 | macro make_calls(n) begin 8 | made_calls := made_calls + n; 9 | assert made_calls <= max_calls; 10 | end macro; 11 | 12 | 13 | macro reserve(n) begin 14 | await made_calls + reserved_calls + n <= max_calls; 15 | reserved_calls := reserved_calls + n; 16 | end macro 17 | 18 | process reset_limit = -1 19 | begin 20 | Reset: 21 | while TRUE do 22 | made_calls := 0; 23 | end while 24 | end process 25 | 26 | process get_collection = 0 27 | begin 28 | GCGetCalls: 29 | reserve(1); 30 | Request: 31 | make_calls(1); 32 | reserved_calls := reserved_calls - 1; 33 | either goto GCGetCalls 34 | or skip 35 | end either; 36 | end process; 37 | 38 | process get_put \in 1..3 39 | begin 40 | GPGetCalls: 41 | reserve(2); 42 | Call: 43 | with c \in {1, 2} do 44 | make_calls(c) 45 | end with; 46 | reserved_calls := reserved_calls - 2; 47 | end process; 48 | 49 | end algorithm; *) 50 | -------------------------------------------------------------------------------- /content/concurrency/invariants.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Concurrent Invariants" 3 | weight = 4 4 | +++ 5 | 6 | Sometimes, we want to enforce invariants _between_ processes. For example, only one thread may have a lock at the same time, or the total values across all processes must be less than a certain threshold. Here's one example: 7 | 8 | ``` tla 9 | process foo \in 1..2 10 | variable x \in 1..2 11 | begin 12 | Skip: 13 | skip 14 | end process 15 | ``` 16 | 17 | How do we assert the variant "the sum of x between the two processes is not 4?" With a single process algorithm, we could write `x /= 4`. But to do the same with multiple processes, we have to let the PlusCal abstraction leak. 18 | 19 | When we translate an algorithm, TLA+ will create all of the corresponding variables. When we have multiple processes, TLA+ will instead create a function with a domain on the process identifiers and the range the actual values of x per process. So instead of having for example `x \in 1..2`, we instead have `x == [ProcSet -> 1..2]`. So in this case, the appropriate invariant is `x[1] + x[2] /= 4`. 20 | -------------------------------------------------------------------------------- /content/concurrency/labels.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Labels" 3 | weight = 3 4 | +++ 5 | 6 | ### Valid Labels 7 | 8 | Since labels represent steps, single moments of time, there are some rules on how you have to place them. 9 | 10 | - The first line in a process has to have a label. That includes the first `begin` if it's a single-process algorithm. 11 | 12 | ``` 13 | begin 14 | Foo: 15 | skip; 16 | ``` 17 | 18 | - A label must come before a `while` statement. 19 | 20 | ``` 21 | Foo: 22 | while FALSE do 23 | skip; 24 | end while; 25 | ``` 26 | 27 | - A label must come right after a `call`, `return`, or `goto`. 28 | 29 | ``` 30 | A: 31 | skip; 32 | B: 33 | goto A; 34 | Foo: \* this one is necessary even if it's never reached 35 | skip; 36 | ``` 37 | 38 | - If you have a control statement, such as `if` or `either`, and one possible branch has a label in it, then the whole control structure must be followed with a label. 39 | 40 | ``` 41 | either 42 | A: 43 | skip; 44 | or 45 | skip; 46 | end either; 47 | Foo: \* Necessary because of the A label 48 | ``` 49 | 50 | - You cannot put labels in a `with` statement. 51 | 52 | ``` 53 | with x \in {1, 2} do 54 | Foo: \* INVALID 55 | skip 56 | end with; 57 | ``` 58 | 59 | - You cannot assign to any given variable more than once in a label. 60 | 61 | ``` 62 | Foo: 63 | x := 1; 64 | q := 2; \* VALID 65 | 66 | Bar: 67 | x := 1; 68 | x := 2; \* INVALID 69 | ``` 70 | 71 | Sometimes this can cause issues: for example, switching two variables, or assigning to different records of the same structure. In these cases you can use `||` to chain assignments: `x := y || y := x;`. 72 | 73 | ### Optimization 74 | 75 | Every label specifies a branch point in your system: any process with an available label can run as the next step. For N processes with M sequential labels the total number of behaviors is `(MN)!/M!^N`, not counting initial states or nondeterministic labels (`either` or `with`). The more labels you have, the more exact your concurrency testing. The fewer labels you have, the faster your model will run. As always, there are tradeoffs. -------------------------------------------------------------------------------- /content/concurrency/processes/tla/fail1.tla: -------------------------------------------------------------------------------- 1 | variables x = 0; 2 | process one = 1 3 | begin 4 | A: 5 | x := x - 1; 6 | B: 7 | x := x * 3; 8 | end process 9 | 10 | process two = 2 11 | begin 12 | C: 13 | x := x + 1; 14 | D: 15 | assert x /= 0; 16 | end process 17 | -------------------------------------------------------------------------------- /content/concurrency/processes/tla/fail2.tla: -------------------------------------------------------------------------------- 1 | (* --algorithm foo 2 | variables x = 0; 3 | process cycle \in 1..3 4 | begin 5 | A: 6 | x := x + 1; 7 | B: 8 | x := 0; 9 | C: 10 | assert x /= 2; 11 | end process 12 | end algorithm; *) 13 | -------------------------------------------------------------------------------- /content/concurrency/processes/tla/in.tla: -------------------------------------------------------------------------------- 1 | process p \in 1..3 2 | variable x \in 1..4 3 | begin 4 | A: 5 | skip 6 | end process; 7 | -------------------------------------------------------------------------------- /content/concurrency/processes/tla/pass1.tla: -------------------------------------------------------------------------------- 1 | process one = 1 2 | begin 3 | A: 4 | x := x - 1; 5 | B: 6 | x := x * 3; 7 | end process 8 | 9 | process two = 2 10 | begin 11 | C: 12 | await x < -1; 13 | x := x + 1; 14 | D: 15 | assert x /= 0; 16 | end process 17 | -------------------------------------------------------------------------------- /content/concurrency/processes/tla/processes.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE module_name ---- 2 | \* TLA+ code 3 | 4 | (* --algorithm algorithm_name 5 | variables global_variables 6 | 7 | process p_name = foo 8 | variables local_variables 9 | begin 10 | \* pluscal code 11 | end process 12 | 13 | process p_group \in bar \* set 14 | variables local_variables 15 | begin 16 | \* pluscal code 17 | end process 18 | 19 | end algorithm; *) 20 | ==== 21 | -------------------------------------------------------------------------------- /content/introduction/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Introduction" 3 | weight = 1 4 | +++ 5 | 6 | {{% notice note %}} 7 | I now have a [book available](/book)! You can check it out [here](https://www.apress.com/us/book/9781484238288) and read more about it [here](/book). 8 | {{% /notice %}} 9 | ### What is TLA+? 10 | 11 | TLA+ is a _formal specification language_. It's a tool to design systems and algorithms, then programmatically verify that those systems don't have critical bugs. It's the software equivalent of a blueprint. 12 | 13 | ### Why should I use it? 14 | 15 | Here's a simple TLA+ specification, representing people trading unique items. Can you find the bug? 16 | 17 | ```tla 18 | People == {"alice", "bob"} 19 | Items == {"ore", "sheep", "brick"} 20 | (* --algorithm trade 21 | variable owner_of \in [Items -> People] 22 | 23 | process giveitem \in 1..3 \* up to three possible trades made 24 | variables item \in Items, 25 | owner = owner_of[item], 26 | to \in People, 27 | origin_of_trade \in People 28 | begin Give: 29 | if origin_of_trade = owner then 30 | owner_of[item] := to; 31 | end if; 32 | end process; 33 | end algorithm; *) 34 | ``` 35 | 36 | Since we check that the owner of an item is the one trading it away, we should be safe against scams, right? But if we run the model checker, we find that's not true: Alice could trade an item to _herself_ and, before that process finishes running, resolve a parallel trade giving that same item to Bob. Then the first trade resolves and Alice gets the item back. Our algorithm fails for race conditions, and we know this because TLA+ explored every possible state and timeline. 37 | 38 | There's a few different ways of fixing this. But does our fix work for more than two people? In TLA+, checking that is as simple as `People == {"alice", "bob", "eve"}`. Does it work if we can trade multiple items at once? `variable items \in SUBSET Items`. What about if there's multiple sheep, ore, and bricks? `amount_owned = [People \X Items -> 0..5]`. What if three people are all trading 1 ore and 1 sheep with each of the other players while Eve also trades Alice 0 brick? If it's in the possible state space, TLA+ will check it. 39 | 40 | ### Is it hard to use? 41 | 42 | Formal methods have a reputation for being difficult to the point where they're only worth it for critical systems. This means that all of the guides are written under the assumption that the reader is working on a critical system, where they have to know TLA+ inside and out to make absolutely sure that their system won't accidentally _kill people_. 43 | 44 | If a dangerous bug to you is "somebody dies", then yes, formal methods are hard. If a dangerous bug to you is "nobody dies but our customers get really mad and we have to spend two weeks tracking down and fixing the bug", then the small subset of TLA+ you'll need is actually pretty easy to learn. Just find a beginner-friendly guide and you're all set. 45 | 46 | ### Where's a beginner-friendly guide? 47 | 48 | Hello! This guide covers the basics of TLA+ in an easy, hands-on way. If you want to start from the beginning, you can learn more about what we'll cover [here](about-this-guide). If you want to dive in right away, why not try a [whirlwind tour](example)? 49 | 50 | Either way, welcome to TLA+! 51 | -------------------------------------------------------------------------------- /content/introduction/about-this-guide.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "About This Guide" 3 | weight = 3 4 | +++ 5 | 6 | This guide focuses on the bare minimum required to get you up and running as fast as possible as well as some intermediate techniques to improve your models. This approach will ignore or skim over the vast majority of TLA+ in order to make that small chunk easier to learn. This doesn't mean the other parts boring, difficult, or useless. Far from it. But they're outside the scope of this guide. 7 | 8 | I'm assuming you have the following background: 9 | 10 | * __You're an experienced programmer.__ This is not an introduction to programming, and TLA+ is not a user-friendly tool. 11 | * __You're familiar with testing.__ If you haven't used unit tests before, that'll be a lot more useful than learning this. 12 | * __You know some math.__ TLA+ borrows heavily from mathematical structures and syntax. If you've heard of de Morgan's laws, know what a set is, and can understand what `(P => Q) => (~Q => ~P)` means, you're fine. Otherwise, this should still be accessible but might be a little less intuitive. 13 | 14 | __You need to download the [TLA+ Toolbox](https://github.com/tlaplus/tlaplus/releases/latest).__ You should also have access to the following resources: 15 | 16 | * [The PlusCal Manual](https://lamport.azurewebsites.net/tla/p-manual.pdf): PlusCal is the algorithmic interface to TLA+. We'll be covering everything about it in this guide, but it's nice to have a complete grammar reference. We will be using the p-version of the manual. 17 | * [The TLA+ Cheat Sheet](http://lamport.azurewebsites.net/tla/summary-standalone.pdf): Exactly what it sounds like. Includes syntax for things out of this guide's scope. 18 | * [Specifying Systems](https://research.microsoft.com/en-us/um/people/lamport/tla/book.html): _Specifying Systems_ was written by Leslie Lamport, the inventor of TLA+, and remains the most comprehensive book on the subject. It's a lot more advanced than this guide is, but you should know it exists. 19 | 20 | {{% notice info %}} 21 | As of version 1.5.4 the TLA+ Toolbox bundles all of these files under "help". 22 | {{% /notice %}} 23 | -------------------------------------------------------------------------------- /content/introduction/example/img/Error Stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/Error Stack.png -------------------------------------------------------------------------------- /content/introduction/example/img/basic_transfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/basic_transfer.png -------------------------------------------------------------------------------- /content/introduction/example/img/if_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/if_screenshot.png -------------------------------------------------------------------------------- /content/introduction/example/img/intro_toolbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/intro_toolbox.png -------------------------------------------------------------------------------- /content/introduction/example/img/make_spec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/make_spec.png -------------------------------------------------------------------------------- /content/introduction/example/img/model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model.png -------------------------------------------------------------------------------- /content/introduction/example/img/model_assert_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model_assert_fail.png -------------------------------------------------------------------------------- /content/introduction/example/img/model_moneyinvariant1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model_moneyinvariant1.png -------------------------------------------------------------------------------- /content/introduction/example/img/model_moneyinvariant2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model_moneyinvariant2.png -------------------------------------------------------------------------------- /content/introduction/example/img/model_moneyinvariant_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/model_moneyinvariant_fail.png -------------------------------------------------------------------------------- /content/introduction/example/img/multiprocess_fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/multiprocess_fail.png -------------------------------------------------------------------------------- /content/introduction/example/img/translated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/introduction/example/img/translated.png -------------------------------------------------------------------------------- /content/introduction/example/tla/3.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE transfer ---- 2 | EXTENDS Naturals, TLC 3 | 4 | (* --algorithm transfer 5 | variables alice_account = 10, bob_account = 10, money \in 1..20; 6 | 7 | begin 8 | A: alice_account := alice_account - money; 9 | B: bob_account := bob_account + money; 10 | C: assert alice_account >= 0; 11 | end algorithm *) 12 | ===== 13 | -------------------------------------------------------------------------------- /content/introduction/example/tla/4.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE transfer ---- 2 | EXTENDS Naturals, TLC 3 | 4 | (* --algorithm transfer 5 | variables alice_account = 10, bob_account = 10, money \in 1..20; 6 | 7 | begin 8 | Transfer: 9 | if alice_account >= money then 10 | A: alice_account := alice_account - money; 11 | B: bob_account := bob_account + money; 12 | end if; 13 | C: assert alice_account >= 0; 14 | end algorithm *) 15 | ===== 16 | -------------------------------------------------------------------------------- /content/introduction/example/tla/5.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE Transfer ---- 2 | EXTENDS Naturals, TLC 3 | 4 | (* --algorithm transfer 5 | variables alice_account = 10, bob_account = 10, money \in 1..20; 6 | 7 | begin 8 | Transfer: 9 | if alice_account >= money then 10 | A: alice_account := alice_account - money; 11 | B: bob_account := bob_account + money; 12 | end if; 13 | C: assert alice_account >= 0; 14 | 15 | end algorithm *) 16 | 17 | \* BEGIN TRANSLATION 18 | \* Removed for clarity... 19 | \* END TRANSLATION 20 | 21 | MoneyNotNegative == money >= 0 22 | 23 | ==== 24 | 25 | -------------------------------------------------------------------------------- /content/introduction/example/tla/6.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE Transfer ---- 2 | EXTENDS Naturals, TLC 3 | 4 | (* --algorithm transfer 5 | variables alice_account = 10, bob_account = 10, money \in 1..20, 6 | account_total = alice_account + bob_account; 7 | 8 | begin 9 | Transfer: 10 | if alice_account >= money then 11 | A: alice_account := alice_account - money; 12 | B: bob_account := bob_account + money; 13 | end if; 14 | C: assert alice_account >= 0; 15 | 16 | end algorithm *) 17 | 18 | MoneyNotNegative == money >= 0 19 | MoneyInvariant == alice_account + bob_account = account_total 20 | 21 | ==== 22 | 23 | -------------------------------------------------------------------------------- /content/introduction/example/tla/7.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE Transfer ---- 2 | EXTENDS Naturals, TLC 3 | 4 | (* --algorithm transfer 5 | variables alice_account = 10, bob_account = 10, money \in 1..20, 6 | account_total = alice_account + bob_account; 7 | 8 | begin 9 | Transfer: 10 | if alice_account >= money then 11 | A: alice_account := alice_account - money; 12 | bob_account := bob_account + money; \* Both now part of A 13 | end if; 14 | C: assert alice_account >= 0; 15 | 16 | end algorithm *) 17 | 18 | MoneyNotNegative == money >= 0 19 | MoneyInvariant == alice_account + bob_account = account_total 20 | 21 | ==== 22 | 23 | -------------------------------------------------------------------------------- /content/introduction/example/tla/8.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE Transfer ---- 2 | EXTENDS Naturals, TLC 3 | 4 | (* --algorithm transfer 5 | variables alice_account = 10, bob_account = 10, 6 | account_total = alice_account + bob_account; 7 | 8 | process Transfer \in 1..2 9 | variable money \in 1..20; 10 | begin 11 | Transfer: 12 | if alice_account >= money then 13 | A: alice_account := alice_account - money; 14 | bob_account := bob_account + money; 15 | end if; 16 | C: assert alice_account >= 0; 17 | end process 18 | 19 | end algorithm *) 20 | 21 | MoneyNotNegative == money >= 0 22 | MoneyInvariant == alice_account + bob_account = account_total 23 | 24 | ==== 25 | 26 | -------------------------------------------------------------------------------- /content/introduction/example/tla/assertion.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE transfer ---- 2 | EXTENDS Naturals, TLC 3 | 4 | (* --algorithm transfer 5 | variables alice_account = 10, bob_account = 10, money = 5; 6 | 7 | begin 8 | A: alice_account := alice_account - money; 9 | B: bob_account := bob_account + money; 10 | C: assert alice_account >= 0; 11 | end algorithm *) 12 | ===== 13 | 14 | -------------------------------------------------------------------------------- /content/introduction/example/tla/init.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE transfer ---- 2 | EXTENDS Naturals, TLC 3 | 4 | (* --algorithm transfer 5 | variables alice_account = 10, bob_account = 10, money = 5; 6 | 7 | begin 8 | A: alice_account := alice_account - money; 9 | B: bob_account := bob_account + money; 10 | 11 | end algorithm *) 12 | ==== 13 | -------------------------------------------------------------------------------- /content/models/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Models" 3 | weight = 300 4 | +++ 5 | 6 | In the past few chapters, we covered how to write complex specifications. However, our models have always been fairly crude: drop an operator or expression into Invariants and check that it's satisfied. This is useful, but as you can probably guess by now, there's also a lot more we can do with them. This chapter will cover some of the tools TLC provides to manage larger and more complex models. 7 | -------------------------------------------------------------------------------- /content/models/constants/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Constants" 3 | weight = 5 4 | +++ 5 | 6 | Let's go back to our old [Hanoi solver](/tla/tuples/#example). As a refresher, this is the code we started with. 7 | 8 | {{% code hanoi %}} 9 | 10 | It works, but what if we wanted to change one of the parameters (more towers, more disks in a tower), we'd have to directly edit the code. It would be better to make a generic spec and test different parameters in the models instead. To do this, we introduce _constants_. 11 | 12 | {{% code constants %}} 13 | 14 | This is the same as the old code, except that we now define the tower in terms of constants. Instead of the spec assigning the constant a value, the model does instead. 15 | 16 | ![](img/show.png) 17 | 18 | When we click edit we can assign a specific value to each constant. 19 | 20 | ![](img/edit.png) 21 | 22 | 23 | ### Assumptions 24 | 25 | What if we also wanted to vary the solution? For example, we all know that it's possible to move the entire tower over. But is it possible to reach `<<<<1, 2>>, <<>>, <<3, 4>>>>`? By moving the solution to a constant, we can vary that in the model, too: 26 | 27 | ``` tla 28 | CONSTANT SOLUTION 29 | \* ... 30 | assert tower /= SOLUTION 31 | ``` 32 | 33 | And now we can put the new solution in an ordinary assignment: 34 | 35 | ![](img/solution.png) 36 | 37 | One problem: this solution is nonsensical. It has four numbers when `TSIZE` is 3. In these cases, TLA+ can't find a solution because the solution isn't even defined! One way to catch this kind of error is with an `ASSUME` statement: 38 | 39 | {{% code sensical %}} 40 | 41 | TLC will check that our assignments don't break any of the `ASSUME` expressions, so we can use `ASSUME` to make sure nobody makes a bad model. Of course, it can only check what we remember to check: for example, a solution with two "5"s can still slip through. As always, with programming, be paranoid. 42 | -------------------------------------------------------------------------------- /content/models/constants/img/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/constants/img/edit.png -------------------------------------------------------------------------------- /content/models/constants/img/show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/constants/img/show.png -------------------------------------------------------------------------------- /content/models/constants/img/solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/constants/img/solution.png -------------------------------------------------------------------------------- /content/models/constants/tla/constants.tla: -------------------------------------------------------------------------------- 1 | CONSTANTS TSIZE, TSPACES 2 | 3 | FullTower[n \in 1..TSIZE] == n \* <<1, 2, 3, ...>> 4 | Board[n \in 1..TSPACES] == IF n = 1 THEN FullTower ELSE <<>> 5 | 6 | (* --algorithm hanoi 7 | variables tower = Board; 8 | 9 | define 10 | D == DOMAIN tower 11 | end define; 12 | 13 | begin 14 | while TRUE do 15 | assert tower[TSPACES] /= FullTower; 16 | \* rest is the same 17 | -------------------------------------------------------------------------------- /content/models/constants/tla/hanoi.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE hanoi ---- 2 | EXTENDS TLC, Sequences, Integers 3 | 4 | (* --algorithm hanoi 5 | variables tower = <<<<1, 2, 3>>, <<>>, <<>>>>, 6 | 7 | define 8 | D == DOMAIN tower 9 | end define; 10 | 11 | begin 12 | while TRUE do 13 | assert tower[3] /= <<1, 2, 3>>; 14 | with from \in {x \in D : tower[x] /= <<>>}, 15 | to \in { 16 | y \in D : 17 | \/ tower[y] = <<>> 18 | \/ Head(tower[from]) < Head(tower[y]) 19 | } 20 | do 21 | tower[from] := Tail(tower[from]) || 22 | tower[to] := <> \o tower[to]; 23 | end with; 24 | end while; 25 | end algorithm; *) 26 | ==== 27 | 28 | -------------------------------------------------------------------------------- /content/models/constants/tla/sensical.tla: -------------------------------------------------------------------------------- 1 | IsSensical(state) == /\ Len(state) = TSPACES \* Correct spaces 2 | /\ \A tower \in DOMAIN state: \* Numbers do not exceed TSIZE 3 | \A disc \in DOMAIN state[tower]: 4 | state[tower][disc] \in 1..TSIZE 5 | /\ \A n \in 1..TSIZE : \* All numbers appear 6 | \E tower \in DOMAIN state: 7 | \E disc \in DOMAIN state[tower]: 8 | n = state[tower][disc] 9 | \* ... 10 | 11 | ASSUME IsSensical(SOLUTION) 12 | -------------------------------------------------------------------------------- /content/models/example/img/failure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/example/img/failure.png -------------------------------------------------------------------------------- /content/models/example/tla/market.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE market ---- 2 | EXTENDS Integers 3 | CONSTANTS Items, MaxPrice, Vendors, MaxActions 4 | 5 | I == Items 6 | V == Vendors 7 | P == 1..MaxPrice 8 | 9 | ValidMarkets == [V \X I -> [buy : P, sell : P]] 10 | 11 | (* --algorithm market 12 | variables market \in ValidMarkets, 13 | backpack = {}, \* items we have 14 | actions = 0, 15 | profit = 0; 16 | 17 | begin 18 | Act: 19 | while actions < MaxActions do 20 | either 21 | Buy: 22 | with v \in V, i \in Items \ backpack do 23 | profit := profit - market[<>].sell; 24 | backpack := backpack \union {i}; 25 | end with; 26 | or 27 | Sell: 28 | with v \in V, i \in backpack do 29 | profit := profit + market[<>].buy; 30 | backpack := backpack \ {i}; 31 | end with; 32 | end either; 33 | Loop: 34 | actions := actions + 1; 35 | end while; 36 | end algorithm; *) 37 | 38 | \* Translation 39 | 40 | NoArbitrage == profit <= 0 41 | ==== 42 | -------------------------------------------------------------------------------- /content/models/example/tla/market2.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE market ---- 2 | EXTENDS Integers 3 | CONSTANTS Items, MaxPrice, Vendors, MaxActions 4 | 5 | I == Items 6 | V == Vendors 7 | P == 1..MaxPrice 8 | 9 | ValidMarkets == LET Markets == [V \X I -> [buy : P, sell : P]] 10 | IN {m \in Markets : 11 | \A item \in I, vendors \in V \X V: 12 | m[<>].buy <= m[<>].sell 13 | } 14 | 15 | (* --algorithm market 16 | variables market \in ValidMarkets, 17 | backpack = {}, \* items we have 18 | actions = 0, 19 | profit = 0; 20 | 21 | begin 22 | Act: 23 | while actions < MaxActions do 24 | either 25 | Buy: 26 | with v \in V, i \in Items \ backpack do 27 | profit := profit - market[<>].sell; 28 | backpack := backpack \union {i}; 29 | end with; 30 | or 31 | Sell: 32 | with v \in V, i \in backpack do 33 | profit := profit + market[<>].buy; 34 | backpack := backpack \ {i}; 35 | end with; 36 | end either; 37 | Loop: 38 | actions := actions + 1; 39 | end while; 40 | end algorithm; *) 41 | 42 | \* Translation 43 | 44 | NoArbitrage == profit <= 0 45 | ==== 46 | -------------------------------------------------------------------------------- /content/models/example/tla/trade.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE market ---- 2 | EXTENDS Integers, FiniteSets 3 | CONSTANTS Items, MaxPrice, Vendors, MaxActions 4 | 5 | I == Items 6 | V == Vendors 7 | P == 1..MaxPrice 8 | 9 | ValidMarkets == LET Markets == [V \X I -> [buy : P, sell : P]] 10 | IN {m \in Markets : 11 | \A item \in I, vendors \in V \X V: 12 | m[<>].buy <= m[<>].sell 13 | } 14 | 15 | ValidTrades == [{ i \in SUBSET I : Cardinality(i) > 1} -> I] 16 | 17 | (* --algorithm market 18 | variables market \in ValidMarkets, 19 | trades \in ValidTrades, 20 | backpack = {}, \* items we have 21 | actions = 0, 22 | profit = 0; 23 | 24 | begin 25 | Act: 26 | while actions < MaxActions do 27 | either 28 | Buy: 29 | with v \in V, i \in Items \ backpack do 30 | profit := profit - market[<>].sell; 31 | backpack := backpack \union {i}; 32 | end with; 33 | or 34 | Sell: 35 | with v \in V, i \in backpack do 36 | profit := profit + market[<>].buy; 37 | backpack := backpack \ {i}; 38 | end with; 39 | or 40 | Trade: 41 | with items \in (SUBSET backpack) \intersect (DOMAIN trades) do 42 | backpack := (backpack \ items) \union {trades[items]}; 43 | end with; 44 | end either; 45 | Loop: 46 | actions := actions + 1; 47 | end while; 48 | end algorithm; *) 49 | 50 | \* Translation 51 | 52 | NoArbitrage == profit <= 0 53 | ==== 54 | -------------------------------------------------------------------------------- /content/models/model-values/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Model Values" 3 | weight = 10 4 | +++ 5 | 6 | Up until now we've used three basic types of values: strings ("a"), numbers, and booleans. While these work, it doesn't scale very well. For example, if your spec has both students and teachers, you may want to enforce that no students are teaching other students. If you represent every student and teacher with a number, enforcing this quickly becomes painful. 7 | 8 | To resolve this, we have a fourth basic type: the model value. The only way to use it is to define a constant and then assign it such a value in the model overview. A constant with a "model value" is only equal to itself. 9 | 10 | ``` 11 | CONSTANT NULL 12 | ``` 13 | 14 | ![](img/null.png) 15 | 16 | We can also define a set of model values: 17 | 18 | ``` 19 | \* Imagine this is a screenshot 20 | Apps <- [ model value ] {facebook, twitter, espark} 21 | Users <- [ model value ] {user1, user2} 22 | ``` 23 | 24 | Once we define a set of model values, we can then use the elements of the set as part of other constants: 25 | 26 | ``` 27 | \* This too 28 | StartingApp == facebook 29 | ``` 30 | 31 | Emphasis on "other __constants__"; model values can't be referred to in your TLA+ spec itself. They're exclusively a model checker property. 32 | 33 | ### Symmetry Sets 34 | 35 | Imagine an extremely simple setup as follows: 36 | 37 | ``` tla 38 | CONSTANT Foos 39 | \* ... 40 | variables x \in Foos, y \in Foos; 41 | \* ... 42 | ``` 43 | 44 | If Foos is the model set `{f1, f2, f3}`, that's nine possible starting states. To a rough approximation, your program will take nine times as long to finish as it would if `Foos` just had one element. That's comprehensive, but not always necessary. 45 | 46 | _Symmetry sets_ are one possible optimization you can make here. It tells TLC to ignore any states that are just permutations of model values of an existing state. `<> = <> = <> ...`, and `<> = <> = <>`. In this case, there are only two initial states: `x = y` and `x /= y`. 47 | 48 | In most cases, this is a safe optimization: all you care about are the similiarities and differences of values, not the exact values themselves. There are some cases where this can cause problems, though. If you ever use a model value in an ordinary assignment, it's possible to miss states that could violate safety invariants. And as we'll see later, combining temporal properties and symmetry sets is almost always a bad idea. 49 | -------------------------------------------------------------------------------- /content/models/model-values/img/null.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/models/model-values/img/null.png -------------------------------------------------------------------------------- /content/pluscal/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "PlusCal" 3 | weight = 100 4 | +++ 5 | 6 | PlusCal is a tool for working with TLA+: it adds a pseudocode-like interface to the specs, making them easier for programmers to understand. While not every interesting spec can be written with PlusCal, quite a few can, and it's a great entry point into modelling. All of the specs we'll write over the course of this guide will run with PlusCal at the core. 7 | -------------------------------------------------------------------------------- /content/pluscal/behaviors/tla/gates.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE flags ---- 2 | EXTENDS TLC, Integers 3 | (* --algorithm flags 4 | variables f1 \in BOOLEAN, f2 \in BOOLEAN, f3 \in BOOLEAN 5 | begin 6 | while TRUE do 7 | with f \in {1, 2, 3} do 8 | if f = 1 then 9 | either 10 | f1 := TRUE; 11 | or 12 | f1 := FALSE; 13 | end either; 14 | elsif f = 2 then 15 | either 16 | f2 := TRUE; 17 | or 18 | f2 := FALSE; 19 | end either; 20 | else 21 | either 22 | f3 := TRUE; 23 | or 24 | f3 := FALSE; 25 | end either; 26 | end if; 27 | end with; 28 | end while; 29 | end algorithm; *) 30 | 31 | ==== 32 | -------------------------------------------------------------------------------- /content/pluscal/behaviors/tla/gates2.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE flags ---- 2 | EXTENDS TLC, Integers 3 | (* --algorithm flags 4 | variables flags \in [1..3 -> BOOLEAN], next = TRUE; 5 | begin 6 | while next do 7 | with f \in DOMAIN flags, n \in BOOLEAN do 8 | flags[f] := ~flags[f]; 9 | next := n; 10 | end with; 11 | end while; 12 | end algorithm; *) 13 | 14 | ==== 15 | 16 | -------------------------------------------------------------------------------- /content/pluscal/toolbox/img/error_trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/pluscal/toolbox/img/error_trace.png -------------------------------------------------------------------------------- /content/pluscal/toolbox/img/invariant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/pluscal/toolbox/img/invariant.png -------------------------------------------------------------------------------- /content/pluscal/toolbox/img/model_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/pluscal/toolbox/img/model_overview.png -------------------------------------------------------------------------------- /content/pluscal/toolbox/img/model_run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/pluscal/toolbox/img/model_run.png -------------------------------------------------------------------------------- /content/reference/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Appendix" 3 | weight = 700 4 | reference = true 5 | +++ 6 | 7 | General reference materials, such as cheat sheets etc 8 | -------------------------------------------------------------------------------- /content/reference/expressions.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Expressions" 3 | weight = 0 4 | +++ 5 | 6 | ### Operators 7 | 8 | ```tla 9 | Add(a,b) == a + b 10 | 11 | Apply(Op(_,_), a) == Op(a, 3) 12 | Apply(Add, 5) = 8 13 | 14 | RECURSIVE IsOdd(_) 15 | 16 | IsOdd(n) == CASE n = 1 -> TRUE 17 | [] n = 0 -> FALSE 18 | [] OTHER -> ~IsOdd(n-1) 19 | 20 | IsOdd(3) = TRUE 21 | ``` 22 | 23 | ### Expressions 24 | 25 | ```tla 26 | AddOrMult(a, b, add) == IF add 27 | THEN a + b 28 | ELSE a * b 29 | AddOrMult(4, 6, TRUE) = AddOrMult(2, 5, FALSE) 30 | 31 | SubtractSquares(a, b) == 32 | LET sum == a + b 33 | diff == a - b 34 | IN sum * diff 35 | SubtractSquares(6, 4) = 20 36 | 37 | Bool(bool) == 38 | LET op1 == LET op2 == LET op3 == 39 | IF bool 40 | THEN TRUE ELSE 41 | FALSE IN 42 | op3 IN op2 43 | IN op1 44 | Bool(TRUE) = TRUE 45 | Bool(FALSE) = FALSE 46 | ``` 47 | 48 | ### Logic 49 | 50 | ```tla 51 | (\E x \in {1, 2, 3} : x > 2) = TRUE 52 | (CHOOSE x \in {1, 2, 3} : x > 2) = 3 53 | (CHOOSE x \in {1, 2, 3} : x <= 2) = \* 1 or 2, deterministic, always the same 54 | 55 | (\A x \in {1, 2, 3} : x > 4) = FALSE 56 | (CHOOSE x \in {1, 2, 3} : x > 4) = \* error 57 | 58 | EvenSquare(n) == 59 | /\ n % 2 = 0 60 | /\ \E x \in 1..n : x*x = n 61 | 62 | EvenSquareOrOdd(n) == 63 | \/ /\ n % 2 = 0 64 | /\ \E x \in 1..n : x*x = n 65 | \/ n % 2 = 1 66 | 67 | EvenSquareOrOddNonsquare(n) == 68 | (\E x \in 1..n : x*x = n) <=> (n % 2 = 0) 69 | ``` -------------------------------------------------------------------------------- /content/reference/structure/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Structure of a Spec" 3 | weight = 2 4 | +++ 5 | 6 | {{% code structure %}} 7 | -------------------------------------------------------------------------------- /content/reference/structure/tla/structure.tla: -------------------------------------------------------------------------------- 1 | pluscal options 2 | ---- MODULE name_of_file ---- 3 | (* import statements *) 4 | EXTENDS , , ... 5 | 6 | (* 7 | Constants are values that are dependent on the particular model. 8 | All constants must be specified for the model to run. 9 | *) 10 | CONSTANTS , , ... \* CONSTANT also works 11 | ASSUME \* Optional. If Expression is false, model cannot run. 12 | ASSUME \* ASSUME expression can only depend on constants 13 | 14 | RECURSIVE \* recursive operators must be declared in advance 15 | 16 | Op == 17 | Op(a, b, c) == 18 | Op(op2(_), a) == \* Syntax to use a higher-order operator 19 | 20 | (* --algorithm 21 | \* variables global to algorithm 22 | variables v1 = , 23 | v2 \in , \* v2 can be any element in the set 24 | v3 \in ; \* All <> possibilities will be tested 25 | 26 | \* Any operators in a define block can reference PlusCal variables 27 | define 28 | Op == 29 | end define; 30 | 31 | macro Macro(, ...) 32 | begin 33 | 34 | end macro; 35 | 36 | procedure Procedure(, ) 37 | variables proc_v1 = , ... \* no \in 38 | begin 39 | 40 | return; 41 | end procedure; 42 | 43 | (* 44 | Each process has a value. All values must be comparable 45 | Inside a process you can retrieve its value with `self` 46 | *) 47 | process Single_Process = 48 | variables v1 = , v2 \in ; \* local to process 49 | begin 50 | 51 | end process; 52 | 53 | \* making a process fair means it cannot 'stutter', or stall out. 54 | fair process Process \in \* one process per element 55 | variables v1 \in ; \* similar processes can choose different elements 56 | begin 57 | 58 | end process; 59 | 60 | (* For a single process system, instead of processes you do 61 | 62 | 63 | 64 | 65 | begin 66 | 67 | end algorithm; *) 68 | 69 | end algorithm; *) 70 | 71 | ==== 72 | 73 | -------------------------------------------------------------------------------- /content/reference/types.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Data Types" 3 | weight = 1 4 | +++ 5 | 6 | ## Primitives 7 | 8 | ### Boolean 9 | 10 | TRUE, FALSE. 11 | 12 | ``` 13 | BOOLEAN = {TRUE, FALSE} 14 | ``` 15 | 16 | ### Numbers 17 | 18 | 1, -1, -2, etc. You need to `EXTENDS Integers` to perform arithmetic operations. 19 | 20 | ### Strings 21 | 22 | "a", "b", "ab", etc. 23 | 24 | ### Model Values 25 | 26 | Defined in the model options. Only assignable to constants. A model value is unequal to anything but itself. 27 | 28 | ## Sets 29 | 30 | ```tla 31 | {"a", "bc"} = {"a", "bc"} 32 | 33 | S == {1, 2, 3} 34 | 35 | 3 \in S = TRUE; 4 \in S = FALSE; 36 | {2, 3} \subseteq S = TRUE; {2, 4} \subseteq S = FALSE 37 | 38 | S \union {3, 4} = {1, 2, 3, 4} 39 | S \intersect {3, 4} = {3} 40 | S \ {3, 4} = {1, 2} 41 | 42 | UNION {{1}, {2}} = {1, 2} 43 | SUBSET {1, 2} = {{}, {1}, {2}, {1, 2}} 44 | 45 | EXTENDS Integers 46 | 1..3 = S 47 | 48 | {x*x : x \in S} = {1, 4, 9} 49 | {x*y : x \in S, y \in S} = {1, 2, 3, 4, 6, 9} 50 | 51 | {x \in S : x >= 2} = {3} 52 | {<> \in S \X S : x + y > 4} = {<<2, 3>>, <<3, 2>> <<3, 3>>} 53 | 54 | EXTENDS FiniteSets 55 | IsFiniteSet(S) = TRUE 56 | Cardinality(S) = 3 57 | ``` 58 | 59 | ## Functions 60 | 61 | ```tla 62 | S == {1, 2, 3} 63 | 64 | F(S) == [x \in S |-> x + 1] 65 | F(1..10)[4] = 5 66 | 67 | F(S) == [x \in S, y \in S |-> x + y] 68 | F(1..10)[2, 3] = 5 69 | F(1..10)[<<2, 3>>] = 5 70 | 71 | F[x \in 1..10] == x + 1 72 | F[2] = 3 73 | 74 | DOMAIN [x \in S |-> P(x)] = S 75 | 76 | [{1, 2} -> BOOLEAN] = { 77 | <>, <>, 78 | <>, <> 79 | } 80 | ``` 81 | 82 | ## Tuples 83 | 84 | All function operations also apply to tuples. A tuple has domain 1..N, where N is the length of the tuple. 85 | 86 | ```tla 87 | T == <<"a", "b">> 88 | 89 | DOMAIN T = 1..2 90 | <<"a", "b">>[1] = "a" 91 | 92 | {1, 2} \X T = { 93 | <<1, "a">>, <<1, "b">>, 94 | <<2, "a">>, <<2, "b">> 95 | } 96 | 97 | EXTENDS Sequences 98 | T == <<"a", "b", "c", "d">> 99 | 100 | Len(T) = 4 101 | Head(T) = "a" 102 | Tail(T) = <<"b", "c", "d">> 103 | 104 | <<"e">> \o T = <<"e", "a", "b", "c", "d">> 105 | Append(T, "e") = <<"a", "b", "c", "d", "e">> 106 | SubSeq(T, 2, 3) = <<"b", "c">> 107 | SelectSeq(T, LAMBDA x: x \in {"a", "d"}) = <<"a", "d">> 108 | ``` 109 | 110 | ## Structures 111 | 112 | All function operations also apply to structures. The domain is the set of strings corresponding to the structure's keys. 113 | 114 | ```tla 115 | S == [a |-> 1, b |-> 2] 116 | DOMAIN S = {"a", "b"} 117 | S['a'] = 1 118 | S.b = 2 119 | 120 | [a: {1, 2}, b: {"x", "y"}] = 121 | { 122 | [a |-> 1, b |-> "x"], [a |-> 1, b |-> "y"], 123 | [a |-> 2, b |-> "x"], [a |-> 2, b |-> "y"] 124 | } 125 | ``` 126 | 127 | ## Bags 128 | 129 | See [Specifying Systems](https://lamport.azurewebsites.net/tla/book.html). 130 | -------------------------------------------------------------------------------- /content/techniques/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Techniques" 3 | weight = 600 4 | +++ 5 | 6 | While TLA+ is a powerful tool, it does not provide a lot of guidance on how to write good specifications. This section will cover some of the problems you might run into with your specs, as well as ways around them. 7 | -------------------------------------------------------------------------------- /content/techniques/cond-steps.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Conditional Steps" 3 | weight = 1 4 | +++ 5 | 6 | Sometimes you may want to combine `either` with labels, so that branching steps are possible. For example: 7 | 8 | ``` 9 | either 10 | Push: 11 | \* code 12 | or 13 | Pop: 14 | \* code 15 | end either 16 | After: 17 | \* code 18 | ``` 19 | 20 | However, you may also want some steps to only be possible in certain cases. For example, we might want that we can only pop a non-empty stack. Here are two ways of doing that: 21 | 22 | ``` 23 | either 24 | Push: 25 | \* code 26 | or 27 | if stack_not_empty() then 28 | Pop: 29 | \* code 30 | end if 31 | end either 32 | After: 33 | \* code 34 | ``` 35 | 36 | ``` 37 | either 38 | Push: 39 | \* code 40 | or 41 | await stack_not_empty() 42 | Pop: 43 | \* code 44 | end either 45 | After: 46 | \* code 47 | ``` 48 | 49 | While the both will prevent you from running `Pop` if `stack_not_empty` is false, they mean different things for the rest of your system. Here's how TLC interprets each of them: 50 | 51 | * _If Case_: TLC can run either the first or second branch. In the second branch, it checks the conditional, sees that the conditional is false, and then jumps to the end of the if block. So on reaching the `either`, TLC checks two behaviors: "go to `Push`" or "skip to `After`". 52 | * _Await Case_: In order run the second branch, `stack_not_empty` must be true. Since it's false, the second branch can't run, meaning only the first branch is possible. So there is only one possible behavior: "go to `Push`". 53 | 54 | In other words, in the `if` spec, depending on the state of the stack, there are three possible behaviors: `Push->After`, `Pop->After`, and `After`. In the `await` spec, there's only `Push->After` and `Pop->After`. Generally, the latter is what you want, so you should use `await` in this case unless you're sure that the skipping the `either` is something you want. 55 | 56 | One thing that **does not** work is putting the `await` in `Pop`: 57 | 58 | ``` 59 | either 60 | Push: 61 | \* code 62 | or 63 | Pop: 64 | await stack_not_empty() 65 | \* code 66 | end either 67 | After: 68 | \* code 69 | ``` 70 | This is because there's nothing stopping TLC from _reaching_ Pop; the `await` only matters afterwards. In this case, if the stack is empty, there's no way for TLC to run the `Pop` step and no other processes to run instead, so this is a deadlock. 71 | 72 | All of this, of course, assumes this is a single-process system. In a multiprocess system, other processes may potentially alter the stack, so `Pop` is not an automatic deadlock. 73 | 74 | ## Conditional Processes 75 | 76 | We can also guard a process in the same way: 77 | 78 | ```tla 79 | await condition; 80 | call process; 81 | ``` 82 | 83 | Similar to above, we can't put the `await` inside the process.. So we have to have an `await` every time we want to call the process, which is error prone. While we can't avoid this, we can ensure that we raise an error if we miss the guard: 84 | 85 | ```tla 86 | process p() 87 | begin 88 | P: 89 | assert condition; 90 | \* code 91 | end 92 | ``` 93 | We still need to manually include the `await` statements, but if we forget the assertion fails and spec is broken. -------------------------------------------------------------------------------- /content/techniques/history.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Multistep Invariants" 3 | weight = 3 4 | +++ 5 | 6 | If we want to check an invariant only after a specific action, we can use `assert`. But what if we want to check an invariant only after a specific sequence of actions? For example, if we move forward and then backwards, we should be in the same position as we started. TLA+ doesn't provide a native way to test those, but we can use sequences to write our own. 7 | 8 | Let's begin with some framework code: 9 | 10 | ```tla 11 | variables xpos = 0, t = 0 12 | begin 13 | Move: 14 | while t < 10 do 15 | either 16 | xpos := xpos + 1 17 | or 18 | xpos := xpos - 1 19 | end either; 20 | t := t + 1; 21 | end while; 22 | ``` 23 | 24 | In order to test our invariant, we need some way of knowing the previous action, as well as how it changed the position. We can do this by adding a "history" variable, and then appending the last action and state with each step. In the following example, the history variable is named `actions`. 25 | 26 | ```tla 27 | EXTENDS Integers, TLC, Sequences 28 | CONSTANTS EAST, WEST, INIT 29 | 30 | Action(action, state) == [action |-> action, state |-> state] 31 | 32 | (* --algorithm alg 33 | variables 34 | xpos = 0, 35 | t = 0, 36 | action = INIT 37 | actions = <>; 38 | 39 | begin 40 | Move: 41 | while t < 10 do 42 | either 43 | xpos := xpos + 1; 44 | action := EAST; 45 | or 46 | xpos := xpos - 1; 47 | action := WEST; 48 | end either; 49 | actions := Append(actions, Action(action, xpos)); 50 | t := t + 1; 51 | end while; 52 | end algorithm; *) 53 | ``` 54 | 55 | Our invariant is now definable over pairs of the most recent action. 56 | 57 | ```tla 58 | define MoveInvariant == 59 | IF Len(actions) > 2 THEN \* require two after init 60 | LET 61 | len == Len(actions) 62 | recent == SubSeq(actions, len-2, len) 63 | from == recent[1].state 64 | to == recent[3].state 65 | a == <> 67 | IN CASE 68 | a = <> -> TRUE 69 | []a = <> -> from = to 70 | []a = <> -> from = to 71 | []a = <> -> TRUE 72 | ELSE TRUE 73 | end define; 74 | ``` 75 | 76 | {{% notice note %}} 77 | We could have replaced two of the cases with `[] OTHERWISE -> TRUE`, but by enumerating them explicitly, any missed cases will raise an error. Pattern matching! 78 | {{% /notice %}} 79 | 80 | ### Advanced Cases 81 | 82 | With a full history, we can also write more sophisticated invariants. For example, in this case, we don't need to compare the last two actions, since we can operate over the whole history: 83 | 84 | ```tla 85 | MoveInvariant == 86 | LET count(token) == 87 | Len(SelectSeq(actions, LAMBDA y: y.action = token)) 88 | IN xpos = count(EAST) - count(WEST) 89 | ``` 90 | 91 | ### Limitations 92 | 93 | Multistep invariants get clunky when you have multiple processes, since you have to store the state, action, and process. Additionally, it gets less useful when applying invariants to complex states. 94 | -------------------------------------------------------------------------------- /content/techniques/img/depth-first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/techniques/img/depth-first.png -------------------------------------------------------------------------------- /content/techniques/img/state-constraint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/techniques/img/state-constraint.png -------------------------------------------------------------------------------- /content/techniques/infinite-loops.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Infinite Loops" 3 | weight = 11 4 | +++ 5 | 6 | Infinite loops are useful to model, as they are a great way of representing things like cronjobs or worker pools. You can add infinite loops in the same way as any other language, by using `while` or `goto`. 7 | 8 | ```tla 9 | process whileprocess = "while" 10 | begin While: 11 | while TRUE do 12 | skip 13 | end while 14 | end process 15 | 16 | process gotoprocess = "goto" 17 | begin Goto: 18 | skip; 19 | goto Goto; 20 | end process; 21 | ``` 22 | 23 | There are two specific problems with using infinite loops in TLA+. The first is that if the infinite loop produces a state change, TLC might try to check an infinite state space. The second is that it makes checking termination harder: your program is done when everything _but_ the infinite loop has terminated. 24 | 25 | ### State Space Restriction 26 | 27 | If we try to check the following spec, TLC will run out of memory: 28 | 29 | ``` 30 | variable x = 0; 31 | begin Adder: 32 | while TRUE do 33 | x := x + 1; 34 | end while 35 | end algorithm; 36 | ``` 37 | 38 | There's an infinite number of possible states here: `x = 1`, `x = 2`, etc. The naive way of fixing this would be to add a time counter: 39 | 40 | ``` 41 | variable x = 0, time = 0; 42 | begin Adder: 43 | while time < 10 do 44 | x := x + 1; 45 | time := time + 1; 46 | end while 47 | end algorithm; 48 | ``` 49 | 50 | However, this can quickly get untenable. Another options is to use the regular loops and switch to a depth-first search. This lets you force the model to terminate in a finite number of steps. 51 | ![](../img/depth-first.png) 52 | 53 | The last option is to use a state constraint. A state constraint is a formula restricting the possible states: When a state does not comply with the constraint, model will finish running. 54 | ![](../img/state-constraint.png) 55 | 56 | One pitfall with depth-first search and state constraint is that your model might have an error, but you don't reach it in the specified time. 57 | -------------------------------------------------------------------------------- /content/techniques/merging-functions.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Merging Functions" 3 | weight = 1.5 4 | +++ 5 | 6 | In addition to general debugging tools, extending TLC adds two function operators: 7 | 8 | * `a :> b` is the function `[x \in {a} |-> b]`, or the function that maps a to b. 9 | * `f1 @@ f2` merges both functions into a new one with the same domain and values. If some element is in both domains, it uses f1. 10 | 11 | `@@` in particular is a great tool for simplifying PlusCal specs. As a toy example, imagine we have a sequence of digits and want to count the number of occurrences of each digit. Here's one way to write that: 12 | 13 | ```tla 14 | EXTENDS TLC, Integers, Sequences, FiniteSets 15 | 16 | Digits == 0..9 17 | Count(seq) == 18 | [x \in Digits |-> Cardinality({y \in DOMAIN seq: seq[y] = x})] 19 | 20 | (* --algorithm counter 21 | 22 | variables seq \in [1..5 -> Digits], 23 | counter = [x \in Digits |-> 0], 24 | pos = 1; 25 | 26 | begin 27 | while pos <= Len(seq) do 28 | counter[seq[pos]] := counter[seq[pos]] + 1; 29 | pos := pos + 1; 30 | end while; 31 | assert counter = Count(seq); 32 | end algorithm; *) 33 | ``` 34 | 35 | That works, but what if instead of a sequence of digits, it was a sequence of sets of digits? The solution gets a little messy (and the state space is much larger): 36 | 37 | ```tla 38 | Digits == 0..2 39 | Count(seq) == 40 | [x \in Digits |-> Cardinality({y \in DOMAIN seq: x \in seq[y]})] 41 | 42 | (* --algorithm counter 43 | 44 | variables seq \in [1..5 -> SUBSET Digits], 45 | counter = [x \in Digits |-> 0], 46 | pos = 1; 47 | 48 | begin 49 | while pos <= Len(seq) do 50 | counter := [ 51 | x \in Digits |-> 52 | IF x \in seq[pos] 53 | THEN counter[x] + 1 54 | ELSE counter[x] 55 | ]; 56 | pos := pos + 1; 57 | end while; 58 | assert counter = Count(seq); 59 | end algorithm; *) 60 | ``` 61 | 62 | With `@@`, we can make the assignment much cleaner: 63 | 64 | ```tla 65 | counter := [x \in seq[pos] |-> counter[x] + 1] @@ counter; 66 | ``` -------------------------------------------------------------------------------- /content/techniques/model-values.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Using Model Values" 3 | weight = 2 4 | +++ 5 | 6 | When should you be using model values instead of strings and numbers? The main advantage of model values is they compare false to everything but themselves. If `M` is a model value, `M = 0`, `M = "0"`, and `M = {0}` are all false. In contrast, `0 = "0"` isn't false. It's an error in your spec. 7 | 8 | In theory, you'll never want to compare two incomparables. In practice, we sometimes need to work around limitations in TLA+. As a good rule of thumb, if you're not directly processing strings as part of your system, **prefer model values to strings**. 9 | 10 | ### Processes 11 | 12 | How do we represent N clients and one server? The following way seems reasonable, but it fails: 13 | 14 | ```tla 15 | process clients \in 1..N 16 | process server = 1 17 | ``` 18 | 19 | The problem here is that each process must be assigned to a separate value, and 1 is used twice. We could instead assign `server = 0`, but that just hides the problem. We might try to use a string instead, like this: 20 | 21 | ```tla 22 | process clients \in 1..N 23 | process server = "server" 24 | ``` 25 | 26 | But this also fails: 1 and "server" are not comparable. However, if we instead use a model value for server, it's valid: 27 | 28 | ```tla 29 | process clients \in 1..N 30 | process server = Server 31 | ``` 32 | 33 | ### Sets 34 | 35 | If a value could be true, false, or unknown, how do we best represent it? For two of those we'd want to use booleans, however "unknown" is a string and can't be compare to booleans. Instead, we can write `{TRUE, FALSE, UNKNOWN}` and make `UNKNOWN` a model value. 36 | 37 | This is especially important when working with functions. A function's domain must be a set, and all elements in a set must be comparable to each other. So you can't have a function that mixes strings and numbers, but you can have one that mixes strings and model values. 38 | 39 | ## Sets of Model Values 40 | 41 | What about model sets? They're obviously useful in cases where we're using numbers just to distinguish processes. For example, the ideal way to write the server-client proccesses would be 42 | 43 | ```tla 44 | process clients \in Clients 45 | process server = Server 46 | ``` 47 | 48 | Where `Clients = {c1, c2, ...}`. Why is this better than numbers? Aside from being easier to understand, it means you can make the set symmetrical. This, as mentioned before, makes your specs take considerably less time to run. This is true even outside of processes. For example, given the following simple algorithm: 49 | 50 | ```tla 51 | begin 52 | with x \in S do 53 | skip; 54 | end with; 55 | ``` 56 | 57 | If `S = {1, 2, 3}`, then TLC will check three behaviors. If `S = {s1, s2, s3}` _and_ `S` is symmetric, TLC will check only one behavior and infer the rest. In cases where this is a safe assumption (no liveness tests), it's a good optimization. -------------------------------------------------------------------------------- /content/techniques/performance.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Optimizing TLC" 3 | draft = true 4 | weight = 90 5 | +++ 6 | 7 | One of the biggest challenges in specification is not writing the spec, but running it. Since TLC looks through the entire state space, TK -------------------------------------------------------------------------------- /content/temporal-logic/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Temporal Properties" 3 | weight = 500 4 | +++ 5 | 6 | When I said we were barely going to cover TLA+, I wasn't kidding. 7 | 8 | Temporal Properties are the heart and soul of TLA+. It's how the language does _anything_ in the first place. Which is why it's kind of depressing that I'm going to spend almost no time on it. That's because of PlusCal abstracts away most of it for us. This section explains a little bit of the parts we, as startup folk, might find useful, and assuage my guilt at not covering a pretty major part of the system. 9 | -------------------------------------------------------------------------------- /content/temporal-logic/operators/livelock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/temporal-logic/operators/livelock.png -------------------------------------------------------------------------------- /content/temporal-logic/termination/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Termination" 3 | weight = 0.5 4 | +++ 5 | 6 | Will the following PlusCal snippet ever finish? 7 | 8 | {{% code finish %}} 9 | 10 | The most common temporal logic you'll want to check is _Termination_, and TLC provides a handy button to test just that. 11 | 12 | ![](img/termination.png) 13 | 14 | This will succeed if, for all behaviors, the spec _ends_. Let's see what happens when we run this: 15 | 16 | ![](img/stuttering.png) 17 | 18 | Well, that was certainly unexpected! This is called _stuttering_. The problem is that the system can choose not to run any step at all. This has never been a problem before because we were making sure things didn't break if time passed, but now things break if time doesn't pass. 19 | 20 | How do we get around this? What we want is something called _fairness_: the property that if a given label is always enabled, we will eventually run it. We make this happen by specifying the process as a `fair process`. 21 | 22 | {{% code fairness %}} 23 | 24 | Confirm this works as expected. 25 | 26 | {{% notice note %}} 27 | There's a way to enforce fairness for a single process app, but it's a bit finicky so I'm leaving it out. 28 | {{% /notice %}} -------------------------------------------------------------------------------- /content/temporal-logic/termination/img/stuttering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/temporal-logic/termination/img/stuttering.png -------------------------------------------------------------------------------- /content/temporal-logic/termination/img/termination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/temporal-logic/termination/img/termination.png -------------------------------------------------------------------------------- /content/temporal-logic/termination/tla/fairness.tla: -------------------------------------------------------------------------------- 1 | EXTENDS TLC, Integers 2 | 3 | (* --algorithm counter 4 | variable x = 0; 5 | 6 | fair process counter = "counter" 7 | begin Count: 8 | while x < 10 do 9 | x := x + 1; 10 | end while; 11 | end process; 12 | 13 | end algorithm; *) -------------------------------------------------------------------------------- /content/temporal-logic/termination/tla/finish.tla: -------------------------------------------------------------------------------- 1 | EXTENDS TLC, Integers 2 | 3 | (* --algorithm counter 4 | variable x = 0; 5 | begin 6 | while x < 10 do 7 | x := x + 1; 8 | end while; 9 | end algorithm; *) 10 | -------------------------------------------------------------------------------- /content/temporal-logic/usage/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Using Temporal Properties" 3 | weight = 2 4 | +++ 5 | 6 | Most often, you're not interested in checking temporal properties. If you are, though, here are some things to watch out for. 7 | 8 | ### Liveness is Slow 9 | 10 | It's easy to check that reachable states satisfy invariants. But to check liveness, _how you reach those states_ also matters. If a thousand routes lead through state S, that's 1,000 routes that need to be checked for liveness and only one state that needs to be checked for safety. So liveness is intrinsically much, _much_ slower than checking invariants. 11 | 12 | ### Temporal Properties are Very Slow 13 | 14 | The Toolbox has a number of optimizations to make it easier to check invariants: multithreading, model symmetry sets, cloud computing, etc. These all assume, though, that we only care about individual states. None of these apply to temporal properties. So it's even slower to check than you'd think at first. 15 | 16 | An especially important one to watch out for are symmetric models. TLC can check them for temporal properties. _However_, the symmetry properties can provide false negatives: it can say that your spec satisfies the properties when it actually doesn't. 17 | 18 | ### Stuttering and Fairness 19 | 20 | Regular processes can stutter. Sometimes this is part of what you expect in your system- maybe you can't rely on the message queue always being available. If not, though, you need to explicitly use `fair process`. 21 | 22 | ## Recommendations 23 | 24 | * Use separate models for invariants and temporal properties. 25 | * Use smaller sets of model values to check invariants than you do for temporal properties. 26 | * Consider testing the same temporal property among several models with different setups. 27 | * Do not use symmetric model sets when testing liveness. 28 | -------------------------------------------------------------------------------- /content/tla/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "TLA+" 3 | weight = 200 4 | +++ 5 | 6 | Now that we have our PlusCal scaffold, it's time to learn TLA+ proper. TLA+ is a mathematical description language. Instead of saying how to find the value you want, you instead say the properties of what you want. For example, the largest element of a set is `CHOOSE x \in S : \A y \in S : y <= x`. That's not an algorithm. It's just "the number that's bigger than the other numbers." 7 | 8 | This gives us incredible specification power. Complex properties and invariants can be expressed in just a few lines. On the downside, it can also be very intimidating. It's also possible to accidentally build uncheckable models. It's easy, for example, to define the set of all universal turing machines that halt. If you feed that into TLC, though, it will throw an error back. There's a bit of an art to writing TLA+ specs. Let's get started. 9 | 10 | Point of note: we're going to be almost completely ignoring the "temporal" part of "Temporal Logic of Actions". As a simple heuristic, we're never, _ever_ going to be talking about "primed and unprimed operators", which make up like 95% of _Specifying Systems._ At its core, TLA+ is a beautiful way to elegantly express the temporal properties of a complicated system. For our uses, TLA+ is a way of writing better PlusCal specs. Sacrilegious? Probably. Easier? Yup. 11 | -------------------------------------------------------------------------------- /content/tla/expressions.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Expressions" 3 | weight = 2 4 | +++ 5 | 6 | We've been implicitly using _expressions_ up until now; we just haven't clarified them. For our purposes, an expression is __anything that follows a `==`, `=`, `:=`, or `\in`__. In this section we'll cover some general expression modifiers. 7 | 8 | ### Logical Junctions 9 | 10 | We've used these for a while now: `/\` is "and", `\/` is "or". We can join expressions with them. The one subtlety is that this is the _only_ case where TLA+ is whitespace sensitive. If you start a line with an indented junction, TLA+ considers that the start of a subclause. For example, 11 | 12 | ```tla 13 | /\ TRUE 14 | \/ TRUE 15 | /\ FALSE \* (T \/ T) /\ F 16 | 17 | /\ TRUE 18 | \/ TRUE 19 | \/ FALSE \* (T \/ T \/ F) 20 | 21 | \/ TRUE 22 | \/ TRUE 23 | /\ FALSE \* T \/ (T /\ F) 24 | ``` 25 | 26 | Etc. As a general rule of thumb: 27 | 28 | * If two logical operators are on the same level of indentation, they are part of the same level of expression. 29 | * If a logical operator is on a higher level of indentation, it's part of the previous operator statement. 30 | * Use only one type of operator per level of indentation. 31 | 32 | Generally if you mess this up the spec will crash, so you're unlikely to get a logic bug through this. 33 | 34 | ### LET-IN 35 | 36 | Any expression can use LET-IN to add local operators and definitions to just that expression alone. 37 | 38 | ```tla 39 | LET IsEven(x) == x % 2 = 0 40 | IN IsEven(5) 41 | 42 | LET IsEven(x) == x % 2 = 0 43 | Five == 5 44 | IN IsEven(Five) 45 | 46 | LET IsEven(x) == LET Two == 2 47 | Zero == 0 48 | IN x % Two = Zero 49 | Five == 5 50 | IN IsEven(Five) 51 | ``` 52 | 53 | The whitespace does not matter: we can write `LET IsEven(x) == x % 2 = 0 Five == 5 IN IsEven(Five)` and it will correctly parse it as two separate operators in the LET. You should use newlines though, because you care about legibility. 54 | 55 | ### IF-THEN-ELSE 56 | 57 | This is exactly what you expect it to be. 58 | 59 | ```tla 60 | IsEven(x) == IF x % 2 = 0 61 | THEN TRUE 62 | ELSE FALSE 63 | ``` 64 | 65 | As before, alignment doesn't matter, but you should align them anyway unless you really hate your coworkers. 66 | 67 | ### CASE 68 | 69 | Case is _mostly_ how you'd expect it to act, with one subtle difference. 70 | 71 | ```tla 72 | CASE x = 1 -> TRUE 73 | [] x = 2 -> TRUE 74 | [] x = 3 -> 7 75 | [] OTHER -> FALSE 76 | ``` 77 | 78 | OTHER is the default. If none of the cases match and you leave out an OTHER, TLC considers that an error. If _more than one match_, though, TLC will pick one for you and _not_ branch. In other words, the following code 79 | 80 | ```tla 81 | CASE TRUE -> FALSE 82 | [] TRUE -> TRUE 83 | ``` 84 | 85 | _May or may not be true._ Be careful. 86 | 87 | ## Nesting 88 | 89 | All parts of expressions are expressions or identifiers, so you can put expressions inside other expressions. Additionally, all expressions can be used inside PlusCal code. 90 | -------------------------------------------------------------------------------- /content/tla/operators.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Operators" 3 | weight = 1 4 | +++ 5 | 6 | An operator is a thing that does a thing. It's what programmers might refer to as a function. You use a `==` to define them. 7 | 8 | ``` 9 | Five == 5 10 | Five + 5 \* 10 11 | ``` 12 | 13 | You can also give them arguments. 14 | 15 | ``` 16 | IsFive(x) == x = 5 17 | ``` 18 | 19 | Or multiple arguments. 20 | 21 | ``` 22 | SumWithFive(a, b) == a + b + 5 23 | ``` 24 | 25 | You can use them anywhere you use any other expression. 26 | 27 | ``` 28 | { Five, SumWithFive(Five, Five) } \* { 5, 15 } 29 | ``` 30 | 31 | {{% notice tip %}} 32 | Remember, you can use the "No Behavior Spec" option in your TLC model to test various operators and cases. 33 | {{% /notice %}} 34 | 35 | {{% q %}} 36 | Write an operator that tests if two numbers are not equal. 37 | 38 | {{% ans neq %}} 39 | `Neq(a,b) == a /= b` works, as does `Neq(a,b) == ~(a = b)`. 40 | {{% /ans %}} 41 | {{%/q %}} 42 | 43 | ### Higher-Order Operators 44 | 45 | You can write operators that take other operators if you use a special syntax: 46 | 47 | ``` tla 48 | Sum(a, b) == a + b 49 | Do(op(_,_), a, b) == op(a, b) 50 | 51 | Do(Sum, 1, 2) = 3 52 | ``` 53 | 54 | You can also make operators recursive if you specify them with the `RECURSIVE` keyword before invocation: 55 | 56 | ``` tla 57 | RECURSIVE SetReduce(_, _, _) 58 | 59 | SetReduce(Op(_, _), S, value) == IF S = {} THEN value 60 | ELSE LET s == CHOOSE s \in S: TRUE 61 | IN SetReduce(Op, S \ {s}, Op(s, value)) 62 | 63 | CandlesOnChannukah == SetReduce(Sum, 2..9, 0) \* 44 64 | ``` 65 | 66 | {{% q %}} 67 | Write an operator that determines whether a second operator is commutative over two given numbers. An operator is commutative if `f(a,b) = f(b,a)`. 68 | 69 | {{% ans commutative %}} 70 | `IsCommutative(f(_, _), a, b) == f(a, b) = f(b, a)` 71 | {{% /ans %}} 72 | {{%/q %}} 73 | 74 | ## Integrating with PlusCal 75 | 76 | If your operator doesn't reference any PlusCal variables (such as `IsEmpty(S) == S = {}`), you can put it above the start of the PlusCal algorithm and it will be usable like any other expression. 77 | 78 | If your operator _does_ reference any PlusCal variables (such as `HasMoneyLeft == money > 0`), it has to appear in or after the algorithm. The first way to do this is to put it after the TLA+ translation. This is simple, but it also means the PlusCal can't call the operator. Fine for invariants, less-fine for conditionals. To place the operator directly in your code, you can use a `define` block: 79 | 80 | ``` 81 | define 82 | Foo(bar) == baz 83 | \* ... 84 | end define 85 | ``` 86 | 87 | Your `define` block must come before the `begin`. 88 | -------------------------------------------------------------------------------- /content/tla/tuples/img/solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/content/tla/tuples/img/solution.png -------------------------------------------------------------------------------- /content/tla/tuples/tla/hanoi.tla: -------------------------------------------------------------------------------- 1 | ---- MODULE hanoi ---- 2 | EXTENDS TLC, Sequences, Integers 3 | 4 | (* --algorithm hanoi 5 | variables tower = <<<<1, 2, 3>>, <<>>, <<>>>>, 6 | 7 | define 8 | D == DOMAIN tower 9 | end define; 10 | 11 | begin 12 | while TRUE do 13 | assert tower[3] /= <<1, 2, 3>>; 14 | with from \in {x \in D : tower[x] /= <<>>}, 15 | to \in { 16 | y \in D : 17 | \/ tower[y] = <<>> 18 | \/ Head(tower[from]) < Head(tower[y]) 19 | } 20 | do 21 | tower[from] := Tail(tower[from]) || 22 | tower[to] := <> \o tower[to]; 23 | end with; 24 | end while; 25 | end algorithm; *) 26 | ==== 27 | -------------------------------------------------------------------------------- /layouts/index.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /layouts/partials/custom-footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ template "_internal/google_analytics.html" . }} 4 | -------------------------------------------------------------------------------- /layouts/partials/footer.html: -------------------------------------------------------------------------------- 1 | {{ if .Params.chapter }} 2 | 3 | {{ end }} 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | {{ partial "custom-footer.html" . }} 25 | 26 | 27 | -------------------------------------------------------------------------------- /layouts/partials/logo.html: -------------------------------------------------------------------------------- 1 | Written by Hillel Wayne. This work is licensed under a Creative Commons Attribution 4.0 International License. 2 | About 3 | ● Ask for Help 4 | ● Github 5 | ● Donate 6 | -------------------------------------------------------------------------------- /layouts/partials/menu-footer.html: -------------------------------------------------------------------------------- 1 |

Built with from Grav and Hugo

because I can't do websites to save my life 2 | -------------------------------------------------------------------------------- /layouts/partials/script.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /layouts/shortcodes/ans.html: -------------------------------------------------------------------------------- 1 | 2 | 5 |
6 | {{ .Inner }} 7 |
8 | 9 | -------------------------------------------------------------------------------- /layouts/shortcodes/code.html: -------------------------------------------------------------------------------- 1 | {{$path := printf "content/%s/tla/%s.tla" (.Page.File.Dir) (.Get 0)}} 2 | {{ printf "```tla\n%s\n```" (readFile $path) | markdownify }} 3 | -------------------------------------------------------------------------------- /layouts/shortcodes/q.html: -------------------------------------------------------------------------------- 1 |
2 |

{{ .Inner }}

3 |
4 |

5 | -------------------------------------------------------------------------------- /staging-content/example-specs/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Example Specs" 3 | reference = true 4 | weight = 0 5 | +++ 6 | 7 | This section provides examples systems, how to think about designing them, and final specs. 8 | -------------------------------------------------------------------------------- /static/css/bootstrap.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2017 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | /*! 8 | * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=920d6d97aece97d31f12d823bf829701) 9 | * Config saved to config.json and https://gist.github.com/920d6d97aece97d31f12d823bf829701 10 | */ 11 | /*! 12 | * Bootstrap v3.3.7 (http://getbootstrap.com) 13 | * Copyright 2011-2016 Twitter, Inc. 14 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15 | */ 16 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ 17 | .collapse { 18 | display: none; 19 | } 20 | .collapse.in { 21 | display: block; 22 | } 23 | tr.collapse.in { 24 | display: table-row; 25 | } 26 | tbody.collapse.in { 27 | display: table-row-group; 28 | } 29 | .collapsing { 30 | position: relative; 31 | height: 0; 32 | overflow: hidden; 33 | -webkit-transition-property: height, visibility; 34 | -o-transition-property: height, visibility; 35 | transition-property: height, visibility; 36 | -webkit-transition-duration: 0.35s; 37 | -o-transition-duration: 0.35s; 38 | transition-duration: 0.35s; 39 | -webkit-transition-timing-function: ease; 40 | -o-transition-timing-function: ease; 41 | transition-timing-function: ease; 42 | } 43 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/.commit: -------------------------------------------------------------------------------- 1 | ff5ef7c0205721295cce57f94e00999f9d1864dd 2 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Grav 4 | Copyright (c) 2016 MATHIEU CORNIC 5 | Copyright (c) 2017 Valere JEANTET 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the "Software"), to deal in 9 | the Software without restriction, including without limitation the rights to 10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | the Software, and to permit persons to whom the Software is furnished to do so, 12 | subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/README.md: -------------------------------------------------------------------------------- 1 | # Hugo Learn Theme 2 | 3 | This repository contains a theme for [Hugo](https://gohugo.io/), based on great [Grav Learn Theme](http://learn.getgrav.org/). 4 | 5 | Visit the [theme documentation](https://learn.netlify.com/en/) to see what is going on. It is actually built with this theme. 6 | 7 | ## Main features 8 | 9 | - Automatic Search 10 | - Multilingual mode 11 | - Unlimited menu levels 12 | - Automatic next/prev buttons to navigate through menu entries 13 | - Image resizing, shadow… 14 | - Attachments files 15 | - List child pages 16 | - Mermaid diagram (flowchart, sequence, gantt) 17 | - Customizable look and feel and themes variants 18 | - Buttons, Tip/Note/Info/Warning boxes, Expand 19 | 20 | ## Installation 21 | 22 | Navigate to your themes folder in your Hugo site and use the following commands: 23 | 24 | ``` 25 | $ cd themes 26 | $ git clone https://github.com/matcornic/hugo-theme-learn.git 27 | ``` 28 | 29 | Check that your Hugo version is minimum `0.25` with `hugo version`. 30 | 31 | ![Overview](https://github.com/matcornic/hugo-theme-learn/raw/master/images/tn.png) 32 | 33 | ## Usage 34 | 35 | - [Visit the documentation](https://learn.netlify.com/en/) 36 | 37 | ## Download old versions (prior to 2.0.0) 38 | 39 | If you need old version for compatibility purpose, either download [theme source code from releases](https://github.com/matcornic/hugo-theme-learn/releases) or use the right git tag. For example, with `1.1.0` 40 | 41 | - Direct download way: https://github.com/matcornic/hugo-theme-learn/archive/1.1.0.zip 42 | - Git way: 43 | 44 | ```shell 45 | cd themes/hugo-theme-learn 46 | git checkout tags/1.1.0 47 | ``` 48 | 49 | For both solutions, the documentation is available at https://github.com/matcornic/hugo-theme-learn/releases/download/1.1.0/hugo-learn-doc-1.1.0.zip 50 | 51 | ## Credits 52 | 53 | Many thanks to [@vjeantet](https://github.com/vjeantet/) for the fork [docdock](https://github.com/vjeantet/hugo-theme-docdock). The v2 of this theme is mainly based on his work ! 54 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/archetypes/chapter.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "{{ replace .TranslationBaseName "-" " " | title }}" 3 | date = {{ .Date }} 4 | weight = 5 5 | chapter = true 6 | pre = "X. " 7 | +++ 8 | 9 | ### Chapter X 10 | 11 | # Some Chapter title 12 | 13 | Lorem Ipsum. -------------------------------------------------------------------------------- /themes/hugo-theme-learn/archetypes/default.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "{{ replace .TranslationBaseName "-" " " | title }}" 3 | date = {{ .Date }} 4 | weight = 5 5 | +++ 6 | 7 | Lorem Ipsum. -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 MATHIEU CORNIC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/config.toml: -------------------------------------------------------------------------------- 1 | baseURL = "/" 2 | languageCode = "en-US" 3 | defaultContentLanguage = "en" 4 | 5 | title = "Hugo Learn Documentation" 6 | theme = "hugo-theme-learn" 7 | themesdir = "../.." 8 | metaDataFormat = "yaml" 9 | defaultContentLanguageInSubdir= true 10 | 11 | [params] 12 | editURL = "https://github.com/matcornic/hugo-theme-learn/edit/master/exampleSite/content/" 13 | description = "Documentation for Hugo Learn Theme" 14 | author = "Mathieu Cornic" 15 | showVisitedLinks = true 16 | 17 | [outputs] 18 | home = [ "HTML", "RSS", "JSON"] 19 | 20 | [Languages] 21 | [Languages.en] 22 | title = "Documentation for Hugo Learn Theme" 23 | weight = 1 24 | languageName = "English" 25 | 26 | [[Languages.en.menu.shortcuts]] 27 | name = " Github repo" 28 | identifier = "ds" 29 | url = "https://github.com/matcornic/hugo-theme-learn" 30 | weight = 10 31 | 32 | [[Languages.en.menu.shortcuts]] 33 | name = " Showcases" 34 | url = "showcase" 35 | weight = 11 36 | 37 | [[Languages.en.menu.shortcuts]] 38 | name = " Hugo Documentation" 39 | identifier = "hugodoc" 40 | url = "https://gohugo.io/" 41 | weight = 20 42 | 43 | [[Languages.en.menu.shortcuts]] 44 | name = " Credits" 45 | url = "/credits" 46 | weight = 30 47 | 48 | [Languages.fr] 49 | title = "Documentation du thème Hugo Learn" 50 | weight = 2 51 | languageName = "Français" 52 | 53 | [[Languages.fr.menu.shortcuts]] 54 | name = " Repo Github" 55 | identifier = "ds" 56 | url = "https://github.com/matcornic/hugo-theme-learn" 57 | weight = 10 58 | 59 | [[Languages.fr.menu.shortcuts]] 60 | name = " Vitrine" 61 | url = "/showcase" 62 | weight = 11 63 | 64 | [[Languages.fr.menu.shortcuts]] 65 | name = " Documentation Hugo" 66 | identifier = "hugodoc" 67 | url = "https://gohugo.io/" 68 | weight = 20 69 | 70 | [[Languages.fr.menu.shortcuts]] 71 | name = " Crédits" 72 | url = "/credits" 73 | weight = 30 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/_index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Learn Theme for Hugo" 3 | --- 4 | 5 | # Hugo learn theme 6 | 7 | [Hugo-theme-learn](http://github.com/matcornic/hugo-theme-learn) is a theme for [Hugo](https://gohugo.io/), a fast and modern static website engine written in Go. Where Hugo is often used for blogs, this multilingual-ready theme is **fully designed for documentation**. 8 | 9 | This theme is a partial porting of the [Learn theme](http://learn.getgrav.org/) of [Grav](https://getgrav.org/), a modern flat-file CMS written in PHP. 10 | 11 | {{% notice tip %}}Learn theme works with a _page tree structure_ to organize content : All contents are pages, which belong to other pages. [read more about this]({{%relref "cont/pages/_index.md"%}}) 12 | {{% /notice %}} 13 | 14 | ## Main features 15 | 16 | * [Automatic Search]({{%relref "basics/configuration/_index.md#activate-search" %}}) 17 | * [Multilingual mode]({{%relref "cont/i18n/_index.md" %}}) 18 | * **Unlimited menu levels** 19 | * **Automatic next/prev buttons to navigate through menu entries** 20 | * [Image resizing, shadow...]({{%relref "cont/markdown.en.md#images" %}}) 21 | * [Attachments files]({{%relref "shortcodes/attachments.en.md" %}}) 22 | * [List child pages]({{%relref "shortcodes/children/_index.md" %}}) 23 | * [Mermaid diagram]({{%relref "shortcodes/mermaid.en.md" %}}) (flowchart, sequence, gantt) 24 | * [Customizable look and feel and themes variants]({{%relref "basics/style-customization/_index.md"%}}) 25 | * [Buttons]({{%relref "shortcodes/button.en.md" %}}), [Tip/Note/Info/Warning boxes]({{%relref "shortcodes/notice.en.md" %}}), [Expand]({{%relref "shortcodes/expand.en.md" %}}) 26 | 27 | ![Screenshot](https://github.com/matcornic/hugo-theme-learn/raw/master/images/screenshot.png?width=40pc&classes=shadow) 28 | 29 | ## Contribute to this documentation 30 | Feel free to update this content, just click the **Edit this page** link displayed on top right of each page, and pullrequest it 31 | 32 | {{% notice info %}} 33 | Your modification will be deployed automatically when merged. 34 | {{% /notice %}} 35 | 36 | ## Documentation website 37 | This current documentation has been statically generated with Hugo with a simple command : `hugo -t hugo-theme-learn` -- source code is [available here at GitHub](https://github.com/matcornic/hugo-theme-learn) 38 | 39 | {{% notice note %}} 40 | Automatically published and hosted thanks to [Netlify](https://www.netlify.com/). Read more about [Automated HUGO deployments with Netlify](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/) 41 | {{% /notice %}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/_index.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Learn Theme for Hugo" 3 | --- 4 | 5 | # Thème Hugo learn 6 | 7 | [Hugo-theme-learn](http://github.com/matcornic/hugo-theme-learn) est un thème pour [Hugo](https://gohugo.io/), un générateur de site statique, rapide et modern, écrit en Go. Tandis que Hugo est souvent utilisé pour des blogs, ce thème multi-langue est **entièrement conçu pour la documentation**. 8 | 9 | Ce thème est un portage partiel du [thème Learn](http://learn.getgrav.org/) de [Grav](https://getgrav.org/), un CMS modern écrit en PHP. 10 | 11 | {{% notice tip %}}Le thème Learn fonctionne grâce à la structure de page aborescentes pour organiser le contenu: tous les contenus sont des pages qui appartiennent à d'autres pages. [Plus d'infos]({{%relref "cont/pages/_index.md"%}}) 12 | {{% /notice %}} 13 | 14 | ## Fonctionnalités principales 15 | 16 | * [Recherche automatique]({{%relref "basics/configuration/_index.md#activer-recherche" %}}) 17 | * [Mode multi-langue]({{%relref "cont/i18n/_index.md" %}}) 18 | * **Nombre de niveau infini dans le menu** 19 | * **Boutons suivant/précédent automatiquement générés pour naviguer entre les items du menu** 20 | * [Taille d'image, ombres...]({{%relref "cont/markdown.fr.md#images" %}}) 21 | * [Fichiers joints]({{%relref "shortcodes/attachments.fr.md" %}}) 22 | * [Lister les pages filles]({{%relref "shortcodes/children/_index.md" %}}) 23 | * [Diagrammes Mermaid]({{%relref "shortcodes/mermaid.fr.md" %}}) (flowchart, sequence, gantt) 24 | * [Style configurable and variantes de couleurs]({{%relref "basics/style-customization/_index.md"%}}) 25 | * [Boutons]({{%relref "shortcodes/button.fr.md" %}}), [Messages Astuce/Note/Info/Attention]({{%relref "shortcodes/notice.fr.md" %}}), [Expand]({{%relref "shortcodes/expand.fr.md" %}}) 26 | 27 | ![Screenshot](https://github.com/matcornic/hugo-theme-learn/raw/master/images/screenshot.png?width=40pc&classes=shadow) 28 | 29 | ## Contribuer à cette documentation 30 | 31 | N'hésitez pas à mettre à jour ce contenu en cliquant sur le lien **Modifier cette page** en haut de chaque page, et créer la Pull Request associée. 32 | 33 | {{% notice info %}} 34 | Votre modification sera déployée automatiquement quand elle sera mergée. 35 | {{% /notice %}} 36 | 37 | ## Site de documentation 38 | 39 | Cette documentation statique a été générée avec Hugo avec une simple commande : `hugo -t hugo-theme-learn` -- le code source est [disponible sur Github](https://github.com/matcornic/hugo-theme-learn) 40 | 41 | {{% notice note %}} 42 | Le site est auomatiquement publié et hébergé par [Netlify](https://www.netlify.com/). Plus d'infos sur le [déploiement de site Hugo avec Netlify](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/)(En anglais) 43 | {{% /notice %}} 44 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/_index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Basics 3 | weight: 5 4 | pre: "1. " 5 | chapter: true 6 | --- 7 | 8 | ### Chapter 1 9 | 10 | # Basics 11 | 12 | Discover what this Hugo theme is all about and the core-concepts behind it. 13 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/_index.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Démarrage 3 | weight: 5 4 | pre: "1. " 5 | chapter: true 6 | --- 7 | 8 | ### Chapitre 1 9 | 10 | # Démarrage 11 | 12 | Découvrez comment utiliser ce thème Hugo et apprenez en les concepts 13 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/configuration/_index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-04-09T16:50:16+02:00 3 | title: Configuration 4 | weight: 20 5 | --- 6 | 7 | ## Global site parameters 8 | 9 | On top of [Hugo global configuration](https://gohugo.io/overview/configuration/), **Hugo-theme-learn** lets you define the following parameters in your `config.toml` (here, values are default). 10 | 11 | Note that some of these parameters are explained in details in other sections of this documentation. 12 | 13 | ```toml 14 | [params] 15 | # Prefix URL to edit current page. Will display an "Edit this page" button on top right hand corner of every page. 16 | # Useful to give opportunity to people to create merge request for your doc. 17 | # See the config.toml file from this documentation site to have an example. 18 | editURL = "" 19 | # Author of the site, will be used in meta information 20 | author = "" 21 | # Description of the site, will be used in meta information 22 | description = "" 23 | # Shows a checkmark for visited pages on the menu 24 | showVisitedLinks = false 25 | # Disable search function. It will hide search bar 26 | disableSearch = false 27 | # Javascript and CSS cache are automatically busted when new version of site is generated. 28 | # Set this to true to disable this behavior (some proxies don't handle well this optimization) 29 | disableAssetsBusting = false 30 | # Set this to true to disable copy-to-clipboard button for inline code. 31 | disableInlineCopyToClipBoard = false 32 | # A title for shortcuts in menu is set by default. Set this to true to disable it. 33 | disableShortcutsTitle = false 34 | # When using mulitlingual website, disable the switch language button. 35 | disableLanguageSwitchingButton = false 36 | # Order sections in menu by "weight" or "title". Default to "weight" 37 | ordersectionsby = "weight" 38 | # Change default color scheme with a variant one. Can be "red", "blue", "green". 39 | themeVariant = "" 40 | ``` 41 | 42 | ## Activate search 43 | 44 | If not already present, add the follow lines in the same `config.toml` file. 45 | 46 | ```toml 47 | [outputs] 48 | home = [ "HTML", "RSS", "JSON"] 49 | ``` 50 | 51 | Learn theme uses the last improvement available in hugo version 20+ to generate a json index file ready to be consumed by lunr.js javascript search engine. 52 | 53 | > Hugo generate lunrjs index.json at the root of public folder. 54 | > When you build the site with hugo server, hugo generates it internally and of course it don’t show up in the filesystem -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/configuration/_index.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-04-09T16:50:16+02:00 3 | title: Configuration 4 | weight: 20 5 | --- 6 | 7 | ## Paramètres globaux du site 8 | 9 | En plus de la [configuration globale d'Hugo](https://gohugo.io/overview/configuration/), **Hugo-theme-learn** vous permet de définir les paramètres suivant dans votre fichier `config.toml` (ci-dessous sont affichées les valeurs par défaut). 10 | 11 | Notez que certains de ces paramètres sont expliqués en détails dans d'autres sections de cette documentation. 12 | 13 | ```toml 14 | [params] 15 | # L'URL préfixe pour éditer la page courante. Ce paramètre affichera un bouton "Modifier cette page" on haut de de chacune des pages. 16 | # Pratique pour donner les possibilité à vos utilisateurs de créer une merge request pour votre doc. 17 | # Allez voir le fichier config.toml de cette documentation pour avoir un exemple. 18 | editURL = "" 19 | # Autheur du site, est utilisé dans les informations meta 20 | author = "" 21 | # Description du site, est utilisé dans les informations meta 22 | description = "" 23 | # Affiche une icône lorsque la page a été visitée 24 | showVisitedLinks = false 25 | # Désactive la fonction de recherche. Une valeur à true cache la barre de recherche. 26 | disableSearch = false 27 | # Par défaut, le cache Javascript et CSS est automatiquement vidé lorsqu'une nouvelle version du site est générée. 28 | # Utilisez ce paramètre lorsque vous voulez désactiver ce comportement (c'est parfois incompatible avec certains proxys) 29 | disableAssetsBusting = false 30 | # Utilisez ce paramètre pour désactiver le bouton copy-to-clipboard pour le code formatté sur une ligne. 31 | disableInlineCopyToClipBoard = false 32 | # Un titre est défini par défaut lorsque vous utilisez un raccourci dans le menu. Utilisez ce paramètre pour le cacher. 33 | disableShortcutsTitle = false 34 | # Quand vous utilisez un site multi-langue, utilisez ce paramètre pour désactiver le bouton de changement de langue. 35 | disableLanguageSwitchingButton = false 36 | # Ordonne les sections dans menu par poids ("weight") ou titre ("title"). Défaut à "weight" 37 | ordersectionsby = "weight" 38 | # Utilisez ce paramètre pour modifier le schéma de couleur du site. Les valeurs par défaut sont "red", "blue", "green". 39 | themeVariant = "" 40 | ``` 41 | 42 | ## Activer la recherche {#activer-recherche} 43 | 44 | Si ce n'est pas déjà présent, ajoutez les lignes suivantes dans le fichier `config.toml`. 45 | 46 | ```toml 47 | [outputs] 48 | home = [ "HTML", "RSS", "JSON"] 49 | ``` 50 | 51 | Le thème *Learn* utilise les dernières amélioraions d'Hugo pour générer un fichier d'index JSON, prêt à être consommé par le moteur de recherche lunr.js. 52 | 53 | > Hugo génère lunrjs index.json à la racine du dossier `public`. 54 | > Quand vous générez le site avec `hugo server`, Hugo génère le fichier en mémoire, il n'est donc pas disponible sur le disque. -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/installation/images/chapter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/installation/images/chapter.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/requirements/_index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Requirements 3 | weight: 10 4 | disableToc: true 5 | --- 6 | 7 | Thanks to the simplicity of Hugo, this page is as empty as this theme needs requirements. 8 | 9 | Just download latest version of [Hugo binary (> 0.25)](https://gohugo.io/getting-started/installing/) for your OS (Windows, Linux, Mac) : it's that simple. 10 | 11 | ![Magic](/basics/requirements/images/magic.gif?classes=shadow) 12 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/requirements/_index.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Prérequis 3 | weight: 10 4 | disableToc: true 5 | --- 6 | 7 | Grâce à la simplicité d'Hugo, cette page est vide car il n'y a quasi pas de prérequis pour utiliser le thème. 8 | 9 | Téléchargez la dernière version du [binaire Hugo (> 0.25)](https://gohugo.io/getting-started/installing/) pour votre Système d'exploitation (Windows, Linux, Mac) : et c'est tout ! 10 | 11 | ![Magic](/basics/requirements/images/magic.gif?classes=shadow) 12 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/requirements/images/magic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/requirements/images/magic.gif -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/blue-variant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/blue-variant.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/green-variant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/green-variant.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/red-variant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/basics/style-customization/images/red-variant.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/_index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Content 3 | weight: 10 4 | chapter: true 5 | pre: "2. " 6 | --- 7 | 8 | ### Chapter 2 9 | 10 | # Content 11 | 12 | Find out how to create and organize your content quickly and intuitively. 13 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/_index.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Contenu 3 | weight: 10 4 | chapter: true 5 | pre: "2. " 6 | --- 7 | 8 | ### Chapitre 2 9 | 10 | # Contenu 11 | 12 | Découvrez comment créer et organiser votre contenu facilement et intuitivement. 13 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/archetypes.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Archetypes 3 | weight: 10 4 | --- 5 | 6 | Using the command: `hugo new [relative new content path]`, you can start a content file with the date and title automatically set. While this is a welcome feature, active writers need more : [archetypes](https://gohugo.io/content/archetypes/). 7 | 8 | It is pre-configured skeleton pages with default front matter. Please refer to the documentation for types of page to understand the differences. 9 | 10 | ## Chapter {#archetypes-chapter} 11 | 12 | To create a Chapter page, run the following commands 13 | 14 | ``` 15 | hugo new --kind chapter /_index.md 16 | ``` 17 | 18 | It will create a page with predefined Front-Matter: 19 | 20 | ```markdown 21 | +++ 22 | title = "{{ replace .TranslationBaseName "-" " " | title }}" 23 | date = {{ .Date }} 24 | weight = 5 25 | chapter = true 26 | pre = "X. " 27 | +++ 28 | 29 | ### Chapter X 30 | 31 | # Some Chapter title 32 | 33 | Lorem Ipsum. 34 | ``` 35 | 36 | ## Default 37 | 38 | To create a default page, run either one of the following commands 39 | 40 | ``` 41 | # Either 42 | hugo new //_index.md 43 | # Or 44 | hugo new /.md 45 | ``` 46 | 47 | It will create a page with predefined Front-Matter: 48 | 49 | ```markdown 50 | +++ 51 | title = "{{ replace .TranslationBaseName "-" " " | title }}" 52 | date = {{ .Date }} 53 | weight = 5 54 | +++ 55 | 56 | Lorem Ipsum. 57 | ``` -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/archetypes.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Archétypes 3 | weight: 10 4 | --- 5 | 6 | En utilisant la commande: `hugo new [chemin vers nouveau contenu]`, vous pouvez créer un nouveau fichier avec la date et le title automatiquement initialisé. Même si c'est une fonctionnalité intéressante, elle reste limitée pour les auteurs actifs qui ont besoin de mieux : les [archetypes](https://gohugo.io/content/archetypes/). 7 | 8 | Les archétypes sont des squelettes de pages préconfigurées avec un Front Matter par défaut. Merci de vous référer à la documentation pour connaitre les différents types de page. 9 | 10 | ## Chapitre {#archetypes-chapter} 11 | 12 | Pour créer un chapitre, lancez les commandes suivantes 13 | 14 | ``` 15 | hugo new --kind chapter /_index.md 16 | ``` 17 | 18 | Cela crééra une page avec le Front Matter suivant: 19 | 20 | ```markdown 21 | +++ 22 | title = "{{ replace .TranslationBaseName "-" " " | title }}" 23 | date = {{ .Date }} 24 | weight = 5 25 | chapter = true 26 | pre = "X. " 27 | +++ 28 | 29 | ### Chapter X 30 | 31 | # Some Chapter title 32 | 33 | Lorem Ipsum. 34 | ``` 35 | 36 | ## Défaut 37 | 38 | Pour créer une page classique, lancer l'une des deux commandes suivantes 39 | 40 | ``` 41 | # Soit 42 | hugo new //_index.md 43 | # Ou 44 | hugo new /.md 45 | ``` 46 | 47 | Cela crééra une page avec le Front Matter suivant: 48 | 49 | ```markdown 50 | +++ 51 | title = "{{ replace .TranslationBaseName "-" " " | title }}" 52 | date = {{ .Date }} 53 | weight = 5 54 | +++ 55 | 56 | Lorem Ipsum. 57 | ``` -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/i18n/_index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-04-09T16:50:16+02:00 3 | title: Multilingual and i18n 4 | weight: 30 5 | --- 6 | 7 | **Learn theme** is fully compatible with Hugo multilingual mode. 8 | 9 | It provides: 10 | 11 | - Translation strings for default values (English and French). Feel free to contribute ! 12 | - Automatic menu generation from multilingual content 13 | - In-browser language switching 14 | 15 | ![I18n menu](/cont/i18n/images/i18n-menu.gif) 16 | 17 | ## Basic configuration 18 | 19 | After learning [how Hugo handle multilingual websites](https://gohugo.io/content-management/multilingual), define your languages in your `config.toml` file. 20 | 21 | For example with current French and English website. 22 | 23 | ```toml 24 | # English is the default language 25 | defaultContentLanguage = "en" 26 | # Force to have /en/my-page and /fr/my-page routes, even for default language. 27 | defaultContentLanguageInSubdir= true 28 | 29 | [Languages] 30 | [Languages.en] 31 | title = "Documentation for Hugo Learn Theme" 32 | weight = 1 33 | languageName = "English" 34 | 35 | [Languages.fr] 36 | title = "Documentation du thème Hugo Learn" 37 | weight = 2 38 | languageName = "Français" 39 | ``` 40 | 41 | Then, for each new page, append the *id* of the language to the file. 42 | 43 | - Single file `my-page.md` is split in two files: 44 | - in English: `my-page.en.md` 45 | - in French: `my-page.fr.md` 46 | - Single file `_index.md` is split in two files: 47 | - in English: `_index.en.md` 48 | - in French: `_index.fr.md` 49 | 50 | {{% notice info %}} 51 | Be aware that only translated pages are displayed in menu. It's not replaced with default language content. 52 | {{% /notice %}} 53 | 54 | {{% notice tip %}} 55 | Use [slug](https://gohugo.io/content-management/multilingual/#translate-your-content) Front Matter parameter to translate urls too. 56 | {{% /notice %}} 57 | 58 | ## Overwrite translation strings 59 | 60 | Translations strings are used for common default values used in the theme (*Edit this page* button, *Search placeholder* and so on). Translations are available in french and english but you may use another language or want to override default values. 61 | 62 | To override these values, create a new file in your local i18n folder `i18n/.toml` and inspire yourself from the theme `themes/hugo-theme-learn/i18n/en.toml` 63 | 64 | By the way, as these translations could be used by other people, please take the time to propose a translation by [making a PR](https://github.com/matcornic/hugo-theme-learn/pulls) to the theme ! 65 | 66 | ## Disable language switching 67 | 68 | Switching the language in the browser is a great feature, but for some reasons you may want to disable it. 69 | 70 | Just set `disableLanguageSwitchingButton=true` in your `config.toml` 71 | 72 | ```toml 73 | [params] 74 | # When using mulitlingual website, disable the switch language button. 75 | disableLanguageSwitchingButton = true 76 | ``` 77 | 78 | ![I18n menu](/cont/i18n/images/i18n-menu.gif) -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/i18n/_index.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-04-09T16:50:16+02:00 3 | title: Multi-langue et i18n 4 | weight: 30 5 | --- 6 | 7 | **Learn** est complètement compatible avec le mode multi-langue d'Hugo. 8 | 9 | Il fournit : 10 | 11 | - Des *translation strings* pour les valeurs par défaut utilisées par le thème (Anglais et Français). N'hésitez pas à contribuer ! 12 | - Génération automatique du menu avec le contenu multi-langue 13 | - Modification de la langue dans le navigateur 14 | 15 | ![I18n menu](/cont/i18n/images/i18n-menu.gif) 16 | 17 | ## Configuration simple 18 | 19 | Après avoir appris [comment Hugo gère les sites multi-langue](https://gohugo.io/content-management/multilingual), définissez vos langues dans votre fichier `config.toml`. 20 | 21 | Par exemple, pour ce site, avec du contenu en français et en anglais. 22 | 23 | ```toml 24 | # Anglais est la langue par défaut 25 | defaultContentLanguage = "en" 26 | # Force d'avoir /en/ma-page et /fr/ma-page routes, même avec la langue par défaut. 27 | defaultContentLanguageInSubdir= true 28 | 29 | [Languages] 30 | [Languages.en] 31 | title = "Documentation for Hugo Learn Theme" 32 | weight = 1 33 | languageName = "English" 34 | 35 | [Languages.fr] 36 | title = "Documentation du thème Hugo Learn" 37 | weight = 2 38 | languageName = "Français" 39 | ``` 40 | 41 | Puis, pour chaque nouvelle page, ajoutez *l'id* de la langue du fichier. 42 | 43 | - Le fichier `my-page.md` est découpé en deux fichiers : 44 | - en anglais : `my-page.en.md` 45 | - en français : `my-page.fr.md` 46 | - Le fichier `_index.md` est découpé en deux fichiers : 47 | - en anglais: `_index.en.md` 48 | - en français: `_index.fr.md` 49 | 50 | {{% notice info %}} 51 | Attention, seulement les pages traduites sont affichées dans le menu. Le contenu n'est pas remplacé par les pages de la langue par défaut. 52 | {{% /notice %}} 53 | 54 | {{% notice tip %}} 55 | Utilisez le paramètre du Front Matter [slug](https://gohugo.io/content-management/multilingual/#translate-your-content) pour traduire également les URLs. 56 | {{% /notice %}} 57 | 58 | ## Surcharger les *translation strings* 59 | 60 | Les *Translations strings* sont utilisées comme valeurs par défaut dans le thème (Bouton *Modifier la page*, Element de subsitution *Recherche*, etc.). Les traductions sont disponibles en français et en anglais mais vous pouvez utiliser n'importe quelle autre langue et surcharger avec vos propres valeurs. 61 | 62 | Pour surcharger ces valeurs, créer un nouveau fichier dans votre dossier i18n local `i18n/.toml` et inspirez vous du thème `themes/hugo-theme-learn/i18n/en.toml` 63 | 64 | D'ailleurs, ces traductions pour servir à tout le monde, donc svp prenez le temps de [proposer une Pull Request](https://github.com/matcornic/hugo-theme-learn/pulls) ! 65 | 66 | ## Désactiver le changement de langue 67 | 68 | Vous pouvez changer de langue directement dans le navigateur. C'est une super fonctionnalité, mais vous avez peut-être besoin de la désactiver. 69 | 70 | Pour ce faire, ajouter le paramètre `disableLanguageSwitchingButton=true` dans votre `config.toml` 71 | 72 | ```toml 73 | [params] 74 | # Quand vous utilisez un site en multi-langue, désactive le bouton de changment de langue. 75 | disableLanguageSwitchingButton = true 76 | ``` 77 | 78 | ![I18n menu](/cont/i18n/images/i18n-menu.gif) -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/i18n/images/i18n-menu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/cont/i18n/images/i18n-menu.gif -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/pages/images/frontmatter-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/frontmatter-icon.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/pages/images/pages-chapter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/pages-chapter.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/cont/pages/images/pages-default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/cont/pages/images/pages-default.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/credits.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Credits 3 | disableToc: true 4 | --- 5 | 6 | ## Contributors 7 | 8 | Thanks to them for make Open Source Software a better place ! 9 | 10 | {{% ghcontributors "https://api.github.com/repos/matcornic/hugo-theme-learn/contributors?per_page=100" %}} 11 | 12 | And a special thanks to [@vjeantet](https://github.com/vjeantet) for his work on [docdock](https://github.com/vjeantet/hugo-theme-docdock), a fork of hugo-theme-learn. v2.0.0 of this theme is inspired by his work. 13 | 14 | ## Packages and libraries 15 | * [mermaid](https://knsv.github.io/mermaid) - generation of diagram and flowchart from text in a similar manner as markdown 16 | * [font awesome](http://fontawesome.io/) - the iconic font and CSS framework 17 | * [jQuery](https://jquery.com) - The Write Less, Do More, JavaScript Library 18 | * [lunr](https://lunrjs.com) - Lunr enables you to provide a great search experience without the need for external, server-side, search services... 19 | * [horsey](https://bevacqua.github.io/horsey/) - Progressive and customizable autocomplete component 20 | * [clipboard.js](https://zenorocha.github.io/clipboard.js) - copy text to clipboard 21 | * [highlight.js](https://highlightjs.org) - Javascript syntax highlighter 22 | * [modernizr](https://modernizr.com) - A JavaScript toolkit that allows web developers to use new CSS3 and HTML5 features while maintaining a fine level of control over browsers that don't support 23 | 24 | ## Tooling 25 | 26 | * [Netlify](https://www.netlify.com) - Continuous deployement and hosting of this documentation 27 | * [Hugo](https://gohugo.io/) 28 | 29 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/credits.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Crédits 3 | disableToc: true 4 | --- 5 | 6 | ## Contributeurs 7 | 8 | Merci à eux de rendre le monde Open Source meilleur ! 9 | 10 | {{% ghcontributors "https://api.github.com/repos/matcornic/hugo-theme-learn/contributors?per_page=100" %}} 11 | 12 | Et un grand merci à [@vjeantet](https://github.com/vjeantet) pour son travail sur [docdock](https://github.com/vjeantet/hugo-theme-docdock), un fork de _hugo-theme-learn_. La v2.0.0 du thème est en grande partie inspirée de son travail. 13 | 14 | ## Packages et librairies 15 | * [mermaid](https://knsv.github.io/mermaid) - géneration de diagrames et graphiques à partir de texte similaire à Markdown 16 | * [font awesome](http://fontawesome.io/) - Le framework de polices iconiques 17 | * [jQuery](https://jquery.com) - La plus connue des librairies Javascript 18 | * [lunr](https://lunrjs.com) - Lunr fournit des fonctions de recherche sans service externe 19 | * [horsey](https://bevacqua.github.io/horsey/) - Autocomplétion de composants (utiliser pour les suggestions de recherche) 20 | * [clipboard.js](https://zenorocha.github.io/clipboard.js) - Copier le texte dans le presse-papier 21 | * [highlight.js](https://highlightjs.org) - Mise en valeur de syntaxes 22 | * [modernizr](https://modernizr.com) - Une boite à outil Javascript qui permet aux développeurs d'utiliser les dernières fonctionnalités de CSS et HTML5, même sur de vieux navigateurs. 23 | 24 | ## Outils 25 | 26 | * [Netlify](https://www.netlify.com) - Déploiement continue et hébergement de cette documentation 27 | * [Hugo](https://gohugo.io/) 28 | 29 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/_index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-04-09T16:50:16+02:00 3 | title: Shortcodes 4 | pre: "3. " 5 | weight: 15 6 | --- 7 | 8 | Hugo uses Markdown for its simple content format. However, there are a lot of things that Markdown doesn’t support well. You could use pure HTML to expand possibilities. 9 | 10 | But this happens to be a bad idea. Everyone uses Markdown because it's pure and simple to read even non-rendered. You should avoid HTML to keep it as simple as possible. 11 | 12 | To avoid this limitations, Hugo created [shortcodes](https://gohugo.io/extras/shortcodes/). A shortcode is a simple snippet inside a page. 13 | 14 | **Hugo-theme-learn** provides multiple shortcodes on top of existing ones. 15 | 16 | {{%children style="h2" description="true" %}} 17 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/_index.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2016-04-09T16:50:16+02:00 3 | title: Shortcodes 4 | pre: "3. " 5 | weight: 15 6 | --- 7 | 8 | Hugo utilise Markdown pour son format simple. Cependant, il y a beaucoup de chose que Markdown ne supporte pas bien. On pourrait utiliser du HTML pur pour améliorer les capacité du Markdown. 9 | 10 | Mais c'est probablement une mauvaise idée. Tout le monde utilise le Markdown parce que c'est pur et simple à lire même lorsqu'il est affiché en texte brut. Vous devez éviter le HTML autant que possible pour garder le contenu simple. 11 | 12 | Cependant, pour éviter les limitations, Hugo a créé les [shortcodes](https://gohugo.io/extras/shortcodes/). Un shortcode est un bout de code (*snippet*) dans une page. 13 | 14 | **Hugo-theme-learn** fournit de multiple shortcodes en plus de ceux existant. 15 | 16 | {{%children style="h2" description="true" %}} 17 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/BachGavotteShort.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/BachGavotteShort.mp3 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/Carroll_AliceAuPaysDesMerveilles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/Carroll_AliceAuPaysDesMerveilles.pdf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/adivorciarsetoca00cape.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/adivorciarsetoca00cape.pdf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/hugo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/hugo.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/movieselectricsheep-flock-244-32500-2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.files/movieselectricsheep-flock-244-32500-2.mp4 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Attachments 3 | description : "The Attachments shortcode displays a list of files attached to a page." 4 | --- 5 | 6 | The Attachments shortcode displays a list of files attached to a page. 7 | 8 | {{% attachments /%}} 9 | 10 | ## Usage 11 | 12 | The shortcurt lists files found in a **specific folder**. 13 | Currently, it support two implementations for pages 14 | 15 | 1. If your page is a markdown file, attachements must be place in a **folder** named like your page and ending with **.files**. 16 | 17 | > * content 18 | > * _index.md 19 | > * page.files 20 | > * attachment.pdf 21 | > * page.md 22 | 23 | 2. If your page is a **folder**, attachements must be place in a nested **'files'** folder. 24 | 25 | > * content 26 | > * _index.md 27 | > * page 28 | > * index.md 29 | > * files 30 | > * attachment.pdf 31 | 32 | Be aware that if you use a multilingual website, you will need to have as many folders as languages. 33 | 34 | That's all ! 35 | 36 | ### Parameters 37 | 38 | | Parameter | Default | Description | 39 | |:--|:--|:--| 40 | | title | "Attachments" | List's title | 41 | | style | "" | Choose between "orange", "grey", "blue" and "green" for nice style | 42 | | pattern | ".*" | A regular expressions, used to filter the attachments by file name.

The **pattern** parameter value must be [regular expressions](https://en.wikipedia.org/wiki/Regular_expression). 43 | 44 | For example: 45 | 46 | * To match a file suffix of 'jpg', use **.*jpg** (not *.jpg). 47 | * To match file names ending in 'jpg' or 'png', use **.*(jpg|png)** 48 | 49 | ### Examples 50 | 51 | #### List of attachments ending in pdf or mp4 52 | 53 | 54 | {{%/*attachments title="Related files" pattern=".*(pdf|mp4)"/*/%}} 55 | 56 | renders as 57 | 58 | {{%attachments title="Related files" pattern=".*(pdf|mp4)"/%}} 59 | 60 | #### Colored styled box 61 | 62 | {{%/*attachments style="orange" /*/%}} 63 | 64 | renders as 65 | 66 | {{% attachments style="orange" /%}} 67 | 68 | 69 | {{%/*attachments style="grey" /*/%}} 70 | 71 | renders as 72 | 73 | {{% attachments style="grey" /%}} 74 | 75 | {{%/*attachments style="blue" /*/%}} 76 | 77 | renders as 78 | 79 | {{% attachments style="blue" /%}} 80 | 81 | {{%/*attachments style="green" /*/%}} 82 | 83 | renders as 84 | 85 | {{% attachments style="green" /%}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/BachGavotteShort.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/BachGavotteShort.mp3 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/Carroll_AliceAuPaysDesMerveilles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/Carroll_AliceAuPaysDesMerveilles.pdf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/adivorciarsetoca00cape.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/adivorciarsetoca00cape.pdf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/hugo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/hugo.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/movieselectricsheep-flock-244-32500-2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.files/movieselectricsheep-flock-244-32500-2.mp4 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/attachments.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Attachments (Pièces jointes) 3 | description : "The Attachments shortcode displays a list of files attached to a page." 4 | --- 5 | 6 | Le shortcode *Attachments* affiche une liste de pièces jointes d'une page. 7 | 8 | {{% attachments /%}} 9 | 10 | ## Utilisation 11 | 12 | Le shortcode affiche la liste de fichiers trouvés dans un **dossier spécifique** 13 | A l'heure actuelle, il supporte deux implémentations 14 | 15 | 1. Si votre page est un fichier Markdown, les pièces jointes doivent être placée dans un **dossier** nommé comme le nom de la page et suffixé par **.files**. 16 | 17 | > * content 18 | > * _index.md 19 | > * page.files 20 | > * attachment.pdf 21 | > * page.md 22 | 23 | 2. Si votre page est un **dossier**, les pièces jointes doivent être placées dans un dossier fils **'files'**. 24 | 25 | > * content 26 | > * _index.md 27 | > * page 28 | > * index.md 29 | > * files 30 | > * attachment.pdf 31 | 32 | Attention, si votre site est multi-langue, vous devrez avec autant de dossier qu'il y a de langues. 33 | 34 | C'est tout ! 35 | 36 | ### Paramètres 37 | 38 | | Paramètre | Défaut | Description | 39 | |:--|:--|:--| 40 | | title | "Pièces jointes" | Titre de la liste | 41 | | style | "" | Choisir entre "orange", "grey", "blue" et "green" pour un style plus sympa | 42 | | pattern | ".*" | Une expression régulière, utilisée pour filtrer les pièces jointes par leur nom de fichier.

Le paramètre **pattern** doit être une [expression régulière](https://en.wikipedia.org/wiki/Regular_expression). 43 | 44 | Par exemple: 45 | 46 | * Pour trouver les fichiers avec le suffixe 'jpg', utilisez **.*jpg** (pas *.jpg). 47 | * Pour trouver les fichiers avec les suffixe 'jpg' ou 'png', utilisez **.*(jpg|png)** 48 | 49 | ### Exemples 50 | 51 | #### Lister les pièces jointes de type pdf ou mp4 52 | 53 | 54 | {{%/*attachments title="Fichiers associés" pattern=".*(pdf|mp4)"/*/%}} 55 | 56 | s'affiche comme 57 | 58 | {{%attachments title="Fichiers associés" pattern=".*(pdf|mp4)"/%}} 59 | 60 | #### Modifier le style 61 | 62 | {{%/*attachments style="orange" /*/%}} 63 | 64 | s'affiche comme 65 | 66 | {{% attachments style="orange" /%}} 67 | 68 | 69 | {{%/*attachments style="grey" /*/%}} 70 | 71 | s'affiche comme 72 | 73 | {{% attachments style="grey" /%}} 74 | 75 | {{%/*attachments style="blue" /*/%}} 76 | 77 | s'affiche comme 78 | 79 | {{% attachments style="blue" /%}} 80 | 81 | {{%/*attachments style="green" /*/%}} 82 | 83 | s'affiche comme 84 | 85 | {{% attachments style="green" /%}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/button.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Button 3 | description : "Nice buttons on your page." 4 | --- 5 | 6 | A button is a just a clickable button with optional icon. 7 | 8 | ``` 9 | {{%/* button href="https://getgrav.org/" */%}}Get Grav{{%/* /button */%}} 10 | {{%/* button href="https://getgrav.org/" icon="fa fa-download" */%}}Get Grav with icon{{%/* /button */%}} 11 | {{%/* button href="https://getgrav.org/" icon="fa fa-download" icon-position="right" */%}}Get Grav with icon right{{%/* /button */%}} 12 | ``` 13 | 14 | {{% button href="https://getgrav.org/" %}}Get Grav{{% /button %}} 15 | {{% button href="https://getgrav.org/" icon="fa fa-download" %}}Get Grav with icon{{% /button %}} 16 | {{% button href="https://getgrav.org/" icon="fa fa-download" icon-position="right" %}}Get Grav with icon right{{% /button %}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/button.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Button (Bouton) 3 | description : "De beaux boutons sur votre page." 4 | --- 5 | 6 | Le shortcode *button* est simplement un bouton cliquable avec une icône optionnelle. 7 | 8 | ``` 9 | {{%/* button href="https://getgrav.org/" */%}}Téléchargez Grav{{%/* /button */%}} 10 | {{%/* button href="https://getgrav.org/" icon="fa fa-download" */%}}Téléchargez Grav avec icône{{%/* /button */%}} 11 | {{%/* button href="https://getgrav.org/" icon="fa fa-download" icon-position="right" */%}}Téléchargez Grav avec icône à droite{{%/* /button */%}} 12 | ``` 13 | 14 | {{% button href="https://getgrav.org/" %}}Téléchargez Grav{{% /button %}} 15 | {{% button href="https://getgrav.org/" icon="fa fa-download" %}}Téléchargez Grav avec icône{{% /button %}} 16 | {{% button href="https://getgrav.org/" icon="fa fa-download" icon-position="right" %}}Téléchargez Grav avec icône à droite{{% /button %}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/_index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title : Children 3 | description : List the child pages of a page 4 | --- 5 | 6 | Use the children shortcode to list the child pages of a page and the further descendants (children's children). By default, the shortcode displays links to the child pages. 7 | 8 | ## Usage 9 | 10 | | Parameter | Default | Description | 11 | |:--|:--|:--| 12 | | page | _current_ | Specify the page name (section name) to display children for | 13 | | style | "li" | Choose the style used to display descendants. It could be any HTML tag name | 14 | | showhidden | "false" | When true, child pages hidden from the menu will be displayed | 15 | | description | "false" | Allows you to include a short text under each page in the list.
when no description exists for the page, children shortcode takes the first 70 words of your content. [read more info about summaries on gohugo.io](https://gohugo.io/content/summaries/) | 16 | | depth | 1 | Enter a number to specify the depth of descendants to display. For example, if the value is 2, the shortcode will display 2 levels of child pages.
**Tips:** set 999 to get all descendants| 17 | | sort | none | Sort Children By

  • Weight - to sort on menu order
  • Name - to sort alphabetically on menu label
  • Identifier - to sort alphabetically on identifier set in frontmatter
  • URL - URL
  • | 18 | 19 | ## Demo 20 | 21 | {{%/* children */%}} 22 | 23 | {{% children %}} 24 | 25 | {{%/* children description="true" */%}} 26 | 27 | {{%children description="true" %}} 28 | 29 | {{%/* children depth="3" showhidden="true" */%}} 30 | 31 | {{% children depth="3" showhidden="true" %}} 32 | 33 | {{%/* children style="h2" depth="3" description="true" */%}} 34 | 35 | {{% children style="h2" depth="3" description="true" %}} 36 | 37 | {{%/* children style="div" depth="999" */%}} 38 | 39 | {{% children style="div" depth="999" %}} 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/_index.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title : Children (Pages filles) 3 | description : Liste les pages filles de la page 4 | --- 5 | 6 | Utilisez le shortcode *children* pour lister les pages filles de la page et tous ses déscendants (pages filles de pages filles). Par défaut, le shortcode affiche des liens vers les pages filles. 7 | 8 | ## Utilisation 9 | 10 | | Paramètre | Défaut | Description | 11 | |:--|:--|:--| 12 | | page | _current_ | Spécifie le nom de la page (nom de la section) à afficher | 13 | | style | "li" | Choisi le style à utiliser pour afficher les descendants. Cela peut être n'importe quel balise HTML | 14 | | showhidden | "false" | Quand *true*, pages filles cachées dans le menu seront affichées quand même | 15 | | description | "false" | Permet d'inclure le texte de la description de la page sous chaque entré de la liste.
    quand aucune description existe pour la page, le shortcode prend les 70 premiers mots du contenu. [plus d'infos sur gohugo.io](https://gohugo.io/content/summaries/) | 16 | | depth | 1 | Nombre de descendants à afficher. Par exemple, si la valeur est 2, le shortcode va afficher 2 niveaux de pages filels.
    **Astuce:** Utilisez 999 pour avoir tous les descendants| 17 | | sort | | Tri les pages filles par
  • Weight - Poids
  • Name - Nom
  • Identifier - Trier alphabétiquement par identifiant configuré dans le front matter
  • URL - URL
  • | 18 | 19 | ## Démo 20 | 21 | {{%/* children */%}} 22 | 23 | {{% children %}} 24 | 25 | {{%/* children description="true" */%}} 26 | 27 | {{%children description="true" %}} 28 | 29 | {{%/* children depth="3" showhidden="true" */%}} 30 | 31 | {{% children depth="3" showhidden="true" %}} 32 | 33 | {{%/* children style="h2" depth="3" description="true" */%}} 34 | 35 | {{% children style="h2" depth="3" description="true" %}} 36 | 37 | {{%/* children style="div" depth="999" */%}} 38 | 39 | {{% children style="div" depth="999" %}} 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/_index.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1" 3 | description = "This is a demo child page" 4 | +++ 5 | 6 | This is a demo child page -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/_index.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1" 3 | description = "Ceci est une page test" 4 | +++ 5 | 6 | Ceci est une page de demo -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/_index.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1-1" 3 | description = "This is a demo child page" 4 | +++ 5 | 6 | This is a demo child page -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/_index.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1-1" 3 | description = "Ceci est une page test" 4 | +++ 5 | 6 | Ceci est une page de demo -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/_index.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1-1-1" 3 | description = "This is a demo child page" 4 | +++ 5 | 6 | This is a demo child page -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/_index.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1-1-1" 3 | description = "Ceci est une page test" 4 | +++ 5 | 6 | Ceci est une page de demo -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/children-1-1-1-1/_index.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1-1-1-1" 3 | description = "This is a demo child page" 4 | +++ 5 | 6 | This is a demo child page -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/children-1-1-1-1/_index.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1-1-1-1" 3 | description = "Ceci est une page test" 4 | +++ 5 | 6 | Ceci est une page de demo -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/children-1-1-1-1/children-1-1-1-1-1/_index.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1-1-1-1-1" 3 | description = "This is a demo child page" 4 | +++ 5 | 6 | This is a demo child page -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-1/children-1-1/children-1-1-1/children-1-1-1-1/children-1-1-1-1-1/_index.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 1-1-1-1-1" 3 | description = "Ceci est une page test" 4 | +++ 5 | 6 | Ceci est une page de demo -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-2/_index.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 2" 3 | description = "" 4 | +++ 5 | 6 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 7 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 8 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 9 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 10 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 11 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-2/_index.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 2" 3 | description = "" 4 | +++ 5 | 6 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 7 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 8 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 9 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 10 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 11 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-2/test3.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page test 3" 3 | description = "This is a page test" 4 | +++ 5 | 6 | This is a test 3 demo child page -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-2/test3.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page test 3" 3 | description = "Ceci est une page test" 4 | +++ 5 | 6 | Ceci est une page de demo test 3 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-3/_index.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 3" 3 | description = "This is a demo child page" 4 | +++ 5 | 6 | This is a demo child page, not displayed in the menu -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-3/_index.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 3" 3 | description = "Ceci est une page test" 4 | +++ 5 | 6 | Ceci est une page de demo -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-4/_index.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 4" 3 | description = "This is a demo child page" 4 | hidden = true 5 | +++ 6 | 7 | This is a demo child page, not displayed in the menu -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/children-4/_index.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page 4" 3 | description = "Ceci est une page test" 4 | hidden = true 5 | +++ 6 | 7 | Ceci est une page de demo -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/test.en.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page test" 3 | description = "This is a page test" 4 | +++ 5 | 6 | This is a test demo child page -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/children/test.fr.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "page test" 3 | description = "Ceci est une page test" 4 | +++ 5 | 6 | Ceci est une page de demo -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/expand.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title : Expand 3 | description : "Displays an expandable/collapsible section of text on your page" 4 | --- 5 | 6 | The Expand shortcode displays an expandable/collapsible section of text on your page. 7 | Here is an example 8 | 9 | {{%expand%}} 10 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 11 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 12 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 13 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 14 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 15 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 16 | {{%/expand%}} 17 | 18 | 19 | ## Usage 20 | 21 | 22 | this shortcode takes exactly one optional parameter to define the text that appears next to the expand/collapse icon. (default is "Expand me...") 23 | 24 | {{%/*expand "Is this learn theme rocks ?" */%}}Yes !.{{%/* /expand*/%}} 25 | 26 | {{%expand "Is this learn theme rocks ?" %}}Yes !{{% /expand%}} 27 | 28 | # Demo 29 | 30 | {{%/*expand*/%}} 31 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 32 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 33 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 34 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 35 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 36 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 37 | {{%/* /expand*/%}} 38 | 39 | 40 | {{%expand%}}Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 41 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 42 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 43 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 44 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 45 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.{{% /expand%}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/expand.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title : Expand 3 | description : "Affiche une section de texte qui se plie et se déplie" 4 | --- 5 | 6 | Le shortcode *Expand* affiche une section de texte qui se plie et se déplie. 7 | Ci-dessous un exemple. 8 | 9 | {{%expand%}} 10 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 11 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 12 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 13 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 14 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 15 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 16 | {{%/expand%}} 17 | 18 | 19 | ## Utilisation 20 | 21 | 22 | Ce shortcode prends exactement un paramètre optionel pour définir le texte à côté de l'icone. (valeur par défaut est "Déroulez-moi...") 23 | 24 | {{%/*expand "Est-ce que ce thème envoie du pâté ?" */%}}Oui !.{{%/* /expand*/%}} 25 | 26 | {{%expand "Est-ce que ce thème envoie du pâté ?" %}}Oui !{{% /expand%}} 27 | 28 | # Demo 29 | 30 | {{%/*expand*/%}} 31 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 32 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 33 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 34 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 35 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 36 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 37 | {{%/* /expand*/%}} 38 | 39 | 40 | {{%expand%}}Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 41 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 42 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 43 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 44 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 45 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum.{{% /expand%}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/mermaid.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title : "Mermaid" 3 | description : "Generation of diagram and flowchart from text in a similar manner as markdown" 4 | --- 5 | 6 | [Mermaid](https://mermaidjs.github.io/) is a library helping you to generate diagram and flowcharts from text, in a similar manner as Markdown. 7 | 8 | Just insert your mermaid code in the `mermaid` shortcode and that's it. 9 | 10 | ## Flowchart example 11 | {{}} 12 | graph LR; 13 | A[Hard edge] -->|Link text| B(Round edge) 14 | B --> C{Decision} 15 | C -->|One| D[Result one] 16 | C -->|Two| E[Result two] 17 | {{}} 18 | 19 | renders as 20 | 21 | {{}} 22 | graph LR; 23 | A[Hard edge] -->|Link text| B(Round edge) 24 | B --> C{Decision} 25 | C -->|One| D[Result one] 26 | C -->|Two| E[Result two] 27 | {{< /mermaid >}} 28 | 29 | ## Sequence example 30 | 31 | {{}} 32 | sequenceDiagram 33 | participant Alice 34 | participant Bob 35 | Alice->>John: Hello John, how are you? 36 | loop Healthcheck 37 | John->John: Fight against hypochondria 38 | end 39 | Note right of John: Rational thoughts
    prevail... 40 | John-->Alice: Great! 41 | John->Bob: How about you? 42 | Bob-->John: Jolly good! 43 | {{}} 44 | 45 | renders as 46 | 47 | {{}} 48 | sequenceDiagram 49 | participant Alice 50 | participant Bob 51 | Alice->>John: Hello John, how are you? 52 | loop Healthcheck 53 | John->John: Fight against hypochondria 54 | end 55 | Note right of John: Rational thoughts
    prevail... 56 | John-->Alice: Great! 57 | John->Bob: How about you? 58 | Bob-->John: Jolly good! 59 | {{< /mermaid >}} 60 | 61 | ## GANTT Example 62 | 63 | {{}} 64 | gantt 65 | dateFormat YYYY-MM-DD 66 | title Adding GANTT diagram functionality to mermaid 67 | section A section 68 | Completed task :done, des1, 2014-01-06,2014-01-08 69 | Active task :active, des2, 2014-01-09, 3d 70 | Future task : des3, after des2, 5d 71 | Future task2 : des4, after des3, 5d 72 | section Critical tasks 73 | Completed task in the critical line :crit, done, 2014-01-06,24h 74 | Implement parser and jison :crit, done, after des1, 2d 75 | Create tests for parser :crit, active, 3d 76 | Future task in critical line :crit, 5d 77 | Create tests for renderer :2d 78 | Add to mermaid :1d 79 | {{}} 80 | 81 | 82 | render as 83 | 84 | {{}} 85 | gantt 86 | dateFormat YYYY-MM-DD 87 | title Adding GANTT diagram functionality to mermaid 88 | section A section 89 | Completed task :done, des1, 2014-01-06,2014-01-08 90 | Active task :active, des2, 2014-01-09, 3d 91 | Future task : des3, after des2, 5d 92 | Future task2 : des4, after des3, 5d 93 | section Critical tasks 94 | Completed task in the critical line :crit, done, 2014-01-06,24h 95 | Implement parser and jison :crit, done, after des1, 2d 96 | Create tests for parser :crit, active, 3d 97 | Future task in critical line :crit, 5d 98 | Create tests for renderer :2d 99 | Add to mermaid :1d 100 | {{}} 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/mermaid.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title : "Mermaid" 3 | description : "Génération de diagrammes à partir de texte, dans le même style que Markdown" 4 | --- 5 | 6 | [Mermaid](https://mermaidjs.github.io/) est une bibliothèque Javascript qui permet de générer des diagrammes (séquence, état, gantt, etc.) à partir de texte, dans le même style que Markdown. 7 | 8 | Insérer votre code Mermaid dans un shortcode `mermaid` et c'est tout. 9 | 10 | ## Flowchart example 11 | {{}} 12 | graph LR; 13 | A[Bords droits] -->|Lien texte| B(Bords arondis) 14 | B --> C{Décision} 15 | C -->|Un| D[Résultat un] 16 | C -->|Deux| E[Résultat deux] 17 | {{}} 18 | 19 | renders as 20 | 21 | {{}} 22 | graph LR; 23 | A[Bords droits] -->|Lien texte| B(Bords arondis) 24 | B --> C{Décision} 25 | C -->|Un| D[Résultat un] 26 | C -->|Deux| E[Résultat deux] 27 | {{< /mermaid >}} 28 | 29 | ## Sequence example 30 | 31 | {{}} 32 | sequenceDiagram 33 | participant Alice 34 | participant Bob 35 | Alice->>John: Salut John, comment vas-tu? 36 | loop Vérification 37 | John->John: Se bat contre l'hyponcodrie. 38 | end 39 | Note right of John: Les pensées rationnelles
    prédominent... 40 | John-->Alice: Super! 41 | John->Bob: Et toi? 42 | Bob-->John: Au top! 43 | {{}} 44 | 45 | renders as 46 | 47 | {{}} 48 | sequenceDiagram 49 | participant Alice 50 | participant Bob 51 | Alice->>John: Salut John, comment vas-tu? 52 | loop Vérification 53 | John->John: Se bat contre l'hyponcodrie. 54 | end 55 | Note right of John: Les pensées rationnelles
    prédominent... 56 | John-->Alice: Super! 57 | John->Bob: Et toi? 58 | Bob-->John: Au top! 59 | {{< /mermaid >}} 60 | 61 | ## GANTT Example 62 | 63 | {{}} 64 | gantt 65 | dateFormat YYYY-MM-DD 66 | title Ajout de la fonctionnalité de GANTT à Mermaid 67 | section Une section 68 | Tâche complétée :done, des1, 2014-01-06,2014-01-08 69 | Tâche en cours :active, des2, 2014-01-09, 3d 70 | Future tâche : des3, after des2, 5d 71 | Future tâche 2 : des4, after des3, 5d 72 | section Tâches critiques 73 | Tâche complétée dans le chemin critique :crit, done, 2014-01-06,24h 74 | Implémenter le parser et jison :crit, done, after des1, 2d 75 | Créer des tests pour le parser :crit, active, 3d 76 | Future tâche dans le chemin critique :crit, 5d 77 | Créer des tests pour le renderer :2d 78 | Ajout à Mermaid :1d 79 | {{}} 80 | 81 | 82 | render as 83 | 84 | {{}} 85 | gantt 86 | dateFormat YYYY-MM-DD 87 | title Ajout de la fonctionnalité de GANTT à Mermaid 88 | section Une section 89 | Tâche complétée :done, des1, 2014-01-06,2014-01-08 90 | Tâche en cours :active, des2, 2014-01-09, 3d 91 | Future tâche : des3, after des2, 5d 92 | Future tâche 2 : des4, after des3, 5d 93 | section Tâches critiques 94 | Tâche complétée dans le chemin critique :crit, done, 2014-01-06,24h 95 | Implémenter le parser et jison :crit, done, after des1, 2d 96 | Créer des tests pour le parser :crit, active, 3d 97 | Future tâche dans le chemin critique :crit, 5d 98 | Créer des tests pour le renderer :2d 99 | Ajout à Mermaid :1d 100 | {{}} 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/notice.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Notice 3 | description : "Disclaimers to help you structure your page" 4 | --- 5 | 6 | The notice shortcode shows 4 types of disclaimers to help you structure your page. 7 | 8 | ### Note 9 | 10 | ``` 11 | {{%/* notice note */%}} 12 | A notice disclaimer 13 | {{%/* /notice */%}} 14 | ``` 15 | 16 | renders as 17 | 18 | {{% notice note %}} 19 | A notice disclaimer 20 | {{% /notice %}} 21 | 22 | ### Info 23 | 24 | ``` 25 | {{%/* notice info */%}} 26 | An information disclaimer 27 | {{%/* /notice */%}} 28 | ``` 29 | 30 | renders as 31 | 32 | {{% notice info %}} 33 | An information disclaimer 34 | {{% /notice %}} 35 | 36 | ### Tip 37 | 38 | ``` 39 | {{%/* notice tip */%}} 40 | A tip disclaimer 41 | {{%/* /notice */%}} 42 | ``` 43 | 44 | renders as 45 | 46 | {{% notice tip %}} 47 | A tip disclaimer 48 | {{% /notice %}} 49 | 50 | ### Warning 51 | 52 | ``` 53 | {{%/* notice warning */%}} 54 | An warning disclaimer 55 | {{%/* /notice */%}} 56 | ``` 57 | 58 | renders as 59 | 60 | {{% notice warning %}} 61 | A warning disclaimer 62 | {{% /notice %}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/notice.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Notice 3 | description : "Message pour vous aider à structurer votre contenu" 4 | --- 5 | 6 | Le shortcode *Notice* permet d'afficher 4 types de message pour vous aider à structurer votre contenu. 7 | 8 | ### Note 9 | 10 | ``` 11 | {{%/* notice note */%}} 12 | Une notice de type *note* 13 | {{%/* /notice */%}} 14 | ``` 15 | 16 | s'affiche comme 17 | 18 | {{% notice note %}} 19 | Une notice de type *note* 20 | {{% /notice %}} 21 | 22 | ### Info 23 | 24 | ``` 25 | {{%/* notice info */%}} 26 | Une notice de type *info* 27 | {{%/* /notice */%}} 28 | ``` 29 | 30 | s'affiche comme 31 | 32 | {{% notice info %}} 33 | Une notice de type *info* 34 | {{% /notice %}} 35 | 36 | ### Tip 37 | 38 | ``` 39 | {{%/* notice tip */%}} 40 | Une notice de type *tip* 41 | {{%/* /notice */%}} 42 | ``` 43 | 44 | s'affiche comme 45 | 46 | {{% notice tip %}} 47 | Une notice de type *tip* 48 | {{% /notice %}} 49 | 50 | ### Warning 51 | 52 | ``` 53 | {{%/* notice warning */%}} 54 | Une notice de type *warning* 55 | {{%/* /notice */%}} 56 | ``` 57 | 58 | s'affiche comme 59 | 60 | {{% notice warning %}} 61 | Une notice de type *warning* 62 | {{% /notice %}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/siteparam.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Site param 3 | description : "Get value of site params variables in your page." 4 | --- 5 | 6 | `siteparam` shortcode is used to help you print values of site params. 7 | 8 | For instance, in this current site, the `editURL` variable is used in `config.toml` 9 | 10 | ```toml 11 | [params] 12 | editURL = "https://github.com/matcornic/hugo-theme-learn/edit/master/exampleSite/content/" 13 | ``` 14 | 15 | Use the `siteparam` shortcode to display its value. 16 | 17 | ``` 18 | `editURL` Value : {{%/* siteparam "editURL" */%}} 19 | ``` 20 | 21 | is displayed as 22 | 23 | `editURL` Value : {{% siteparam "editURL" %}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/shortcodes/siteparam.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Site param 3 | description : "Afficher la valeur d'un paramètre global du site dans votre page" 4 | --- 5 | 6 | Les shortcode `siteparam` est utilisé pour vous aider à afficher des valeurs provenant des paramètres globaux du site. 7 | 8 | Par exemple, dans ce site, le paramètre `editURL` est utilisé dans le fichier `config.toml` 9 | 10 | ```toml 11 | [params] 12 | editURL = "https://github.com/matcornic/hugo-theme-learn/edit/master/exampleSite/content/" 13 | ``` 14 | 15 | Utilisez le shortcode `siteparam` pour affichier sa valeur. 16 | 17 | ``` 18 | Valeur de `editURL` : {{%/* siteparam "editURL" */%}} 19 | ``` 20 | 21 | s'affiche comme 22 | 23 | Valeur de `editURL` : {{% siteparam "editURL" %}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/showcase.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Showcase 3 | disableToc: true 4 | --- 5 | 6 | #### [TAT](https://ovh.github.io/tat/overview/) by OVH 7 | ![TAT image](/images/showcase/tat.png?width=50pc) 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/content/showcase.fr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vitrine 3 | disableToc: true 4 | slug: vitrine 5 | --- 6 | 7 | #### [TAT](https://ovh.github.io/tat/overview/) par OVH 8 | ![TAT image](/images/showcase/tat.png?width=50pc) 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/layouts/partials/custom-footer.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/layouts/partials/logo.html: -------------------------------------------------------------------------------- 1 | 40 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/layouts/partials/menu-footer.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | Download 4 | 5 | 6 | Star 7 | 8 | 9 | Fork 10 | 11 |

    Built with from Grav and Hugo

    12 |
    13 | 14 | 15 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/layouts/shortcodes/ghcontributors.html: -------------------------------------------------------------------------------- 1 | 22 |
    23 | {{ $url := .Get 0 }} 24 | {{ range getJSON $url }} 25 |
    26 | 27 | 28 | {{.contributions}} commits 29 |
    30 | {{ end }} 31 |
    -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/static/fonts/monogramos-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/static/fonts/monogramos-webfont.eot -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/static/fonts/monogramos-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/static/fonts/monogramos-webfont.ttf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/static/fonts/monogramos-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/static/fonts/monogramos-webfont.woff -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/static/fonts/monogramos-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/static/fonts/monogramos-webfont.woff2 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/exampleSite/static/images/showcase/tat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/exampleSite/static/images/showcase/tat.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/i18n/en.toml: -------------------------------------------------------------------------------- 1 | [Search-placeholder] 2 | other = "Search..." 3 | 4 | [Clear-History] 5 | other = "Clear History" 6 | 7 | [Attachments-label] 8 | other = "Attachments" 9 | 10 | [title-404] 11 | other = "Error" 12 | 13 | [message-404] 14 | other = "Woops. Looks like this page doesn't exist ¯\\_(ツ)_/¯." 15 | 16 | [Go-to-homepage] 17 | other = "Go to homepage" 18 | 19 | [Edit-this-page] 20 | other = "Edit this page" 21 | 22 | [Shortcuts-Title] 23 | other = "More" 24 | 25 | [Expand-title] 26 | other = "Expand me..." -------------------------------------------------------------------------------- /themes/hugo-theme-learn/i18n/fr.toml: -------------------------------------------------------------------------------- 1 | [Search-placeholder] 2 | other = "Rechercher..." 3 | 4 | [Clear-History] 5 | other = "Supprimer l'historique" 6 | 7 | [Attachments-label] 8 | other = "Pièces jointes" 9 | 10 | [title-404] 11 | other = "Erreur" 12 | 13 | [message-404] 14 | other = "Oups. On dirait que cette page n'existe pas ¯\\_(ツ)_/¯" 15 | 16 | [Go-to-homepage] 17 | other = "Vers la page d'accueil" 18 | 19 | [Edit-this-page] 20 | other = "Modifier la page" 21 | 22 | [Shortcuts-Title] 23 | other = "Aller plus loin" 24 | 25 | [Expand-title] 26 | other = "Déroulez-moi..." -------------------------------------------------------------------------------- /themes/hugo-theme-learn/images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/images/screenshot.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/images/tn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/images/tn.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ partial "meta.html" . }} {{ partial "favicon.html" . }} {{ .Scratch.Add "title" "" }}{{ if eq .Site.Data.titles .Title }}{{ .Scratch.Set "title" (index .Site.Data.titles .Title).title }}{{ else }}{{ .Scratch.Set "title" .Title}}{{end}} 6 | {{ .Scratch.Get "title" }} 7 | 8 | {{ $assetBusting := not .Site.Params.disableAssetsBusting }} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {{with .Site.Params.themeVariant}} 18 | 19 | {{end}} 20 | 35 | {{ partial "custom-header.html" . }} 36 | 37 | 38 | 39 | 40 | 41 | 42 |
    43 |
    44 |
    45 |
    46 |

    {{T "title-404"}}

    47 |

    48 |

    49 |

    {{T "message-404"}}

    50 |

    51 |

    {{T "Go-to-homepage"}}

    52 |

    53 |
    54 |
    55 | 56 |
    57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/_default/list.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | {{ .Content }} 4 | 5 |
    6 | {{with .Params.LastModifierDisplayName}} 7 | {{ . }} {{with $.Date}} {{ .Format "02/01/2006" }}{{end}} 8 | 9 | {{end}} 10 |
    11 | 12 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/_default/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | {{ .Content }} 4 | 5 |
    6 | {{with .Params.LastModifierDisplayName}} 7 | {{ . }} {{with $.Date}} {{ .Format "02/01/2006" }}{{end}} 8 | 9 | {{end}} 10 |
    11 | 12 | 13 | {{ partial "footer.html" . }} 14 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/index.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | navigation 4 | 5 | 6 | {{if .Site.Home.Content }} 7 | {{.Site.Home.Content}} 8 | {{else}} 9 | {{if eq .Site.Language.Lang "fr"}} 10 |

    Personaliser la page d'accueil

    11 |

    12 | Le site fonctionne. Ne pas oublier de personaliser cette page avec votre propre contenu. 2 manières de faire : 13 |

    14 |
      15 |
    • 1. Créer un fichier _index.md dans le dossier content et le remplir de Markdown
    • 16 |
    • 2. Créer un fichier index.html dans le dossier static et le remplir de code HTML
    • 17 |
    • 2. Configurer le serveur http pour rediriger automatiquement la homepage vers la page de votre choix dans le site
    • 18 |
    19 | {{else}} 20 |

    Customize your own home page

    21 |

    22 | The site is working. Don't forget to customize this homepage with your own. You typically have 2 choices : 23 |

    24 |
      25 |
    • 1. Create an _index.md document in content folder and fill it with Markdown content
    • 26 |
    • 2. Create an index.html file in the static folder and fill the file with HTML content
    • 27 |
    • 3. Configure your server to automatically redirect home page to one your documentation page
    • 28 |
    29 | {{end}} 30 | {{ end }} 31 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/index.json: -------------------------------------------------------------------------------- 1 | [{{ range $index, $page := .Site.Pages }} 2 | {{- if ne $page.Type "json" -}} 3 | {{- if and $index (gt $index 0) -}},{{- end }} 4 | { 5 | "uri": "{{ $page.Permalink }}", 6 | "title": "{{ htmlEscape $page.Title}}", 7 | "tags": [{{ range $tindex, $tag := $page.Params.tags }}{{ if $tindex }}, {{ end }}"{{ $tag| htmlEscape }}"{{ end }}], 8 | "description": "{{ htmlEscape .Description}}", 9 | "content": {{$page.Plain | jsonify}} 10 | } 11 | {{- end -}} 12 | {{- end -}}] -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/partials/custom-footer.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/partials/custom-header.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/partials/favicon.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/partials/menu-footer.html: -------------------------------------------------------------------------------- 1 |

    Built with from Grav and Hugo

    2 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/partials/meta.html: -------------------------------------------------------------------------------- 1 | 2 | {{ with .Site.Params.author }}{{ end }} 3 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/partials/search.html: -------------------------------------------------------------------------------- 1 | 6 | {{ $assetBusting := not .Site.Params.disableAssetsBusting }} 7 | 8 | 9 | 16 | 17 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/partials/toc.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | {{ .TableOfContents }} 4 |
    5 |
    6 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/shortcodes/attachments.html: -------------------------------------------------------------------------------- 1 |
    2 | 6 | {{if eq .Page.File.BaseFileName "index"}} 7 | {{$.Scratch.Add "filesName" "files"}} 8 | {{else}} 9 | {{$.Scratch.Add "filesName" (printf "%s.files" .Page.File.BaseFileName)}} 10 | {{end}} 11 |
    12 | {{ range (readDir (printf "./content/%s%s" .Page.File.Dir ($.Scratch.Get "filesName")) ) }} 13 | {{ $fileDir := replace $.Page.File.Dir "\\" "/" }} 14 | {{if ($.Get "pattern")}} 15 | {{if (findRE ($.Get "pattern") .Name)}} 16 |
  • 17 | 18 | {{.Name}} 19 | 20 | ({{div .Size 1024 }} ko) 21 |
  • 22 | {{end}} 23 | {{else}} 24 |
  • 25 | 26 | {{.Name}} 27 | 28 | ({{div .Size 1024 }} ko) 29 |
  • 30 | {{end}} 31 | {{end}} 32 |
    33 | {{.Inner}} 34 |
    35 | 36 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/shortcodes/button.html: -------------------------------------------------------------------------------- 1 | 2 | {{ $icon := .Get "icon" }} 3 | {{ $iconposition := .Get "icon-position" }} 4 | {{ if ($icon) }} 5 | {{ if or (not ($iconposition)) (eq $iconposition "left") }} 6 | 7 | {{ end }} 8 | {{ end }} 9 | {{ .Inner }} 10 | {{ if and ($icon) (eq $iconposition "right")}} 11 | 12 | {{ end }} 13 | 14 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/shortcodes/expand.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 4 | 5 | {{$expandMessage := T "Expand-title"}} 6 | {{ if .IsNamedParams }} 7 | {{.Get "default" | default $expandMessage}} 8 | {{else}} 9 | {{.Get 0 | default $expandMessage}} 10 | {{end}} 11 | 12 |
    13 | 16 |
    -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/shortcodes/mermaid.html: -------------------------------------------------------------------------------- 1 |
    {{ safeHTML .Inner }}
    2 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/shortcodes/notice.html: -------------------------------------------------------------------------------- 1 |
    {{ .Inner }}
    2 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/shortcodes/ref.html: -------------------------------------------------------------------------------- 1 | {{- if in (.Get 0) "/_index.md" -}} 2 | {{- $paths := (split (.Get 0) "_index.md") -}} 3 | {{- $pagepath := index $paths 0 -}} 4 | {{- $anchor := index $paths 1 -}} 5 | {{- with .Site.GetPage "section" (trim $pagepath "/") -}} 6 | {{- ( printf "%s%s" $pagepath $anchor ) | relLangURL -}} 7 | {{- end -}} 8 | {{- else -}} 9 | {{- with .Site.GetPage "section" (.Get 0) }} 10 | {{- .URL -}} 11 | {{- else -}} 12 | {{- .Get 0 | relref .Page -}} 13 | {{- end -}} 14 | {{- end -}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/shortcodes/relref.html: -------------------------------------------------------------------------------- 1 | {{- if in (.Get 0) "/_index.md" -}} 2 | {{- $paths := (split (.Get 0) "_index.md") -}} 3 | {{- $pagepath := index $paths 0 -}} 4 | {{- $anchor := index $paths 1 -}} 5 | {{- with .Site.GetPage "section" (trim $pagepath "/") -}} 6 | {{- ( printf "%s%s" $pagepath $anchor ) | relLangURL -}} 7 | {{- end -}} 8 | {{- else -}} 9 | {{- with .Site.GetPage "section" (.Get 0) }} 10 | {{- .URL -}} 11 | {{- else -}} 12 | {{- .Get 0 | relref .Page -}} 13 | {{- end -}} 14 | {{- end -}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/layouts/shortcodes/siteparam.html: -------------------------------------------------------------------------------- 1 | {{- $paramName := (.Get 0) -}} 2 | {{- $siteParams := .Site.Params -}} 3 | {{- with $paramName -}} 4 | {{- with $siteParams -}} 5 | {{- index . (lower $paramName) -}} 6 | {{- end -}} 7 | {{- end -}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/css/auto-complete.css: -------------------------------------------------------------------------------- 1 | .autocomplete-suggestions { 2 | text-align: left; 3 | cursor: default; 4 | border: 1px solid #ccc; 5 | border-top: 0; 6 | background: #fff; 7 | box-shadow: -1px 1px 3px rgba(0,0,0,.1); 8 | 9 | /* core styles should not be changed */ 10 | position: absolute; 11 | display: none; 12 | z-index: 9999; 13 | max-height: 254px; 14 | overflow: hidden; 15 | overflow-y: auto; 16 | box-sizing: border-box; 17 | 18 | } 19 | .autocomplete-suggestion { 20 | position: relative; 21 | cursor: pointer; 22 | padding: 7px; 23 | line-height: 23px; 24 | white-space: nowrap; 25 | overflow: hidden; 26 | text-overflow: ellipsis; 27 | color: #333; 28 | } 29 | 30 | .autocomplete-suggestion b { 31 | font-weight: normal; 32 | color: #1f8dd6; 33 | } 34 | 35 | .autocomplete-suggestion.selected { 36 | background: #333; 37 | color: #fff; 38 | } 39 | 40 | .autocomplete-suggestion:hover { 41 | background: #444; 42 | color: #fff; 43 | } 44 | 45 | .autocomplete-suggestion > .context { 46 | font-size: 12px; 47 | } 48 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/css/featherlight.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Featherlight - ultra slim jQuery lightbox 3 | * Version 1.2.3 - http://noelboss.github.io/featherlight/ 4 | * 5 | * Copyright 2015, Noël Raoul Bossart (http://www.noelboss.com) 6 | * MIT Licensed. 7 | **/ 8 | @media all{.featherlight{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483647;text-align:center;white-space:nowrap;cursor:pointer;background:#333;background:rgba(0,0,0,0)}.featherlight:last-of-type{background:rgba(0,0,0,.8)}.featherlight:before{content:'';display:inline-block;height:100%;vertical-align:middle;margin-right:-.25em}.featherlight .featherlight-content{position:relative;text-align:left;vertical-align:middle;display:inline-block;overflow:auto;padding:25px 25px 0;border-bottom:25px solid transparent;min-width:30%;margin-left:5%;margin-right:5%;max-height:95%;background:#fff;cursor:auto;white-space:normal}.featherlight .featherlight-inner{display:block}.featherlight .featherlight-close-icon{position:absolute;z-index:9999;top:0;right:0;line-height:25px;width:25px;cursor:pointer;text-align:center;font:Arial,sans-serif;background:#fff;background:rgba(255,255,255,.3);color:#000}.featherlight .featherlight-image{width:100%}.featherlight-iframe .featherlight-content{border-bottom:0;padding:0}.featherlight iframe{border:0}}@media only screen and (max-width:1024px){.featherlight .featherlight-content{margin-left:10px;margin-right:10px;max-height:98%;padding:10px 10px 0;border-bottom:10px solid transparent}} -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/css/hybrid.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid) 4 | 5 | */ 6 | 7 | /*background color*/ 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #1d1f21; 13 | } 14 | 15 | /*selection color*/ 16 | .hljs::selection, 17 | .hljs span::selection { 18 | background: #373b41; 19 | } 20 | 21 | .hljs::-moz-selection, 22 | .hljs span::-moz-selection { 23 | background: #373b41; 24 | } 25 | 26 | /*foreground color*/ 27 | .hljs { 28 | color: #c5c8c6; 29 | } 30 | 31 | /*color: fg_yellow*/ 32 | .hljs-title, 33 | .hljs-name { 34 | color: #f0c674; 35 | } 36 | 37 | /*color: fg_comment*/ 38 | .hljs-comment, 39 | .hljs-meta, 40 | .hljs-meta .hljs-keyword { 41 | color: #707880; 42 | } 43 | 44 | /*color: fg_red*/ 45 | .hljs-number, 46 | .hljs-symbol, 47 | .hljs-literal, 48 | .hljs-deletion, 49 | .hljs-link { 50 | color: #cc6666 51 | } 52 | 53 | /*color: fg_green*/ 54 | .hljs-string, 55 | .hljs-doctag, 56 | .hljs-addition, 57 | .hljs-regexp, 58 | .hljs-selector-attr, 59 | .hljs-selector-pseudo { 60 | color: #b5bd68; 61 | } 62 | 63 | /*color: fg_purple*/ 64 | .hljs-attribute, 65 | .hljs-code, 66 | .hljs-selector-id { 67 | color: #b294bb; 68 | } 69 | 70 | /*color: fg_blue*/ 71 | .hljs-keyword, 72 | .hljs-selector-tag, 73 | .hljs-bullet, 74 | .hljs-tag { 75 | color: #81a2be; 76 | } 77 | 78 | /*color: fg_aqua*/ 79 | .hljs-subst, 80 | .hljs-variable, 81 | .hljs-template-tag, 82 | .hljs-template-variable { 83 | color: #8abeb7; 84 | } 85 | 86 | /*color: fg_orange*/ 87 | .hljs-type, 88 | .hljs-built_in, 89 | .hljs-builtin-name, 90 | .hljs-quote, 91 | .hljs-section, 92 | .hljs-selector-class { 93 | color: #de935f; 94 | } 95 | 96 | .hljs-emphasis { 97 | font-style: italic; 98 | } 99 | 100 | .hljs-strong { 101 | font-weight: bold; 102 | } 103 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Inconsolata.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Inconsolata.eot -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Inconsolata.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Inconsolata.ttf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Inconsolata.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Inconsolata.woff -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Novecentosanswide-Normal-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Novecentosanswide-Normal-webfont.eot -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Novecentosanswide-Normal-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Novecentosanswide-Normal-webfont.ttf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Novecentosanswide-Normal-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Novecentosanswide-Normal-webfont.woff -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Novecentosanswide-Normal-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Novecentosanswide-Normal-webfont.woff2 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Novecentosanswide-UltraLight-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Novecentosanswide-UltraLight-webfont.eot -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Novecentosanswide-UltraLight-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Novecentosanswide-UltraLight-webfont.ttf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Novecentosanswide-UltraLight-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Novecentosanswide-UltraLight-webfont.woff -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Novecentosanswide-UltraLight-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Novecentosanswide-UltraLight-webfont.woff2 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_200.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_200.eot -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_200.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_200.ttf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_200.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_200.woff -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_200.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_200.woff2 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_300.eot -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_300.ttf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_300.woff -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_300.woff2 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_500.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_500.eot -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_500.ttf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_500.woff -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/Work_Sans_500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/Work_Sans_500.woff2 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/images/clippy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/images/favicon.png -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/images/gopher-404.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hwayne/learntla/9416d7b62148db9fcc28720171684ffb14adf397/themes/hugo-theme-learn/static/images/gopher-404.jpg -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/js/hugo-learn.js: -------------------------------------------------------------------------------- 1 | // Get Parameters from some url 2 | var getUrlParameter = function getUrlParameter(sPageURL) { 3 | var url = sPageURL.split('?'); 4 | var obj = {}; 5 | if (url.length == 2) { 6 | var sURLVariables = url[1].split('&'), 7 | sParameterName, 8 | i; 9 | for (i = 0; i < sURLVariables.length; i++) { 10 | sParameterName = sURLVariables[i].split('='); 11 | obj[sParameterName[0]] = sParameterName[1]; 12 | } 13 | return obj; 14 | } else { 15 | return undefined; 16 | } 17 | }; 18 | 19 | // Execute actions on images generated from Markdown pages 20 | var images = $("div#body-inner img").not(".inline"); 21 | // Wrap image inside a featherlight (to get a full size view in a popup) 22 | images.wrap(function(){ 23 | var image =$(this); 24 | return ""; 25 | }); 26 | 27 | // Change styles, depending on parameters set to the image 28 | images.each(function(index){ 29 | var image = $(this) 30 | var o = getUrlParameter(image[0].src); 31 | if (typeof o !== "undefined") { 32 | var h = o["height"]; 33 | var w = o["width"]; 34 | var c = o["classes"]; 35 | image.css("width", function() { 36 | if (typeof w !== "undefined") { 37 | return w; 38 | } else { 39 | return "auto"; 40 | } 41 | }); 42 | image.css("height", function() { 43 | if (typeof h !== "undefined") { 44 | return h; 45 | } else { 46 | return "auto"; 47 | } 48 | }); 49 | if (typeof c !== "undefined") { 50 | var classes = c.split(','); 51 | for (i = 0; i < classes.length; i++) { 52 | image.addClass(classes[i]); 53 | } 54 | } 55 | } 56 | }); 57 | 58 | // Stick the top to the top of the screen when scrolling 59 | $("#top-bar").stick_in_parent( { 60 | parent: ".sticky-parent", 61 | spacer: ".sticky-spacer", 62 | }); 63 | 64 | 65 | jQuery(document).ready(function() { 66 | // Add link button for every 67 | var text, clip = new Clipboard('.anchor'); 68 | $("h1~h2,h1~h3,h1~h4,h1~h5,h1~h6").append(function(index, html){ 69 | var element = $(this); 70 | var url = document.location.origin + document.location.pathname; 71 | var link = url + "#"+element[0].id; 72 | return " " + 73 | "" + 74 | "" 75 | ; 76 | }); 77 | 78 | $(".anchor").on('mouseleave', function(e) { 79 | $(this).attr('aria-label', null).removeClass('tooltipped tooltipped-s tooltipped-w'); 80 | }); 81 | 82 | clip.on('success', function(e) { 83 | e.clearSelection(); 84 | $(e.trigger).attr('aria-label', 'Link copied to clipboard!').addClass('tooltipped tooltipped-s'); 85 | }); 86 | 87 | }); 88 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/static/js/jquery.sticky-kit.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 3 | */ 4 | (function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); 5 | if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
    "))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, 6 | u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), 8 | a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", 9 | y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n' + 80 | '» ' + item.title + 81 | '
    ' + 82 | (item.context || '') +'
    ' + 83 | '
    '; 84 | }, 85 | /* onSelect callback fires when a search suggestion is chosen */ 86 | onSelect: function(e, term, item) { 87 | location.href = item.getAttribute('data-uri'); 88 | } 89 | }); 90 | }); 91 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/theme.toml: -------------------------------------------------------------------------------- 1 | # theme.toml template for a Hugo theme 2 | # See https://github.com/spf13/hugoThemes#themetoml for an example 3 | 4 | name = "Learn" 5 | license = "MIT" 6 | licenselink = "https://github.com/matcornic/hugo-theme-learn/blob/master/LICENSE.md" 7 | description = "Documentation theme for Hugo, based on Grav Learn theme" 8 | homepage = "https://github.com/matcornic/hugo-theme-learn/" 9 | repo = "https://github.com/matcornic/hugo-theme-learn" 10 | tags = ["documentation", "grav", "learn", "doc", "search"] 11 | features = ["documentation", "menu", "nested sections", "search", "mermaid"] 12 | min_version = 0.25 13 | 14 | [author] 15 | name = "Mathieu Cornic" 16 | homepage = "http://matcornic.github.io/" 17 | 18 | [original] 19 | name = "Grav Learn" 20 | homepage = "http://learn.getgrav.org/" 21 | repo = "https://github.com/getgrav/grav-learn" 22 | -------------------------------------------------------------------------------- /themes/hugo-theme-learn/wercker.yml: -------------------------------------------------------------------------------- 1 | box: golang 2 | build: 3 | steps: 4 | # Sets the go workspace and places you package 5 | # at the right place in the workspace tree 6 | - setup-go-workspace 7 | 8 | # Gets the dependencies 9 | - script: 10 | name: get hugo 11 | code: | 12 | go get github.com/gohugoio/hugo 13 | 14 | # Build the project 15 | - script: 16 | name: build site 17 | code: | 18 | cd exampleSite && hugo --------------------------------------------------------------------------------