Compare commits
2 Commits
d4baa970d6
...
63ef3c0b5e
Author | SHA1 | Date | |
---|---|---|---|
63ef3c0b5e | |||
4c4be43cb0 |
@ -12,9 +12,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.5.10",
|
||||
"@astrojs/mdx": "^2.3.0",
|
||||
"@astrojs/mdx": "^2.3.1",
|
||||
"@astrojs/tailwind": "^5.1.0",
|
||||
"astro": "^4.6.1",
|
||||
"astro": "^4.6.3",
|
||||
"codejar": "^4.2.0",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.4.5",
|
||||
|
@ -12,13 +12,13 @@ importers:
|
||||
specifier: ^0.5.10
|
||||
version: 0.5.10(typescript@5.4.5)
|
||||
'@astrojs/mdx':
|
||||
specifier: ^2.3.0
|
||||
specifier: ^2.3.1
|
||||
version: 2.3.1(astro@4.6.3(@types/node@20.11.30)(typescript@5.4.5))
|
||||
'@astrojs/tailwind':
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0(astro@4.6.3(@types/node@20.11.30)(typescript@5.4.5))(tailwindcss@3.4.3)
|
||||
astro:
|
||||
specifier: ^4.6.1
|
||||
specifier: ^4.6.3
|
||||
version: 4.6.3(@types/node@20.11.30)(typescript@5.4.5)
|
||||
codejar:
|
||||
specifier: ^4.2.0
|
||||
@ -870,8 +870,8 @@ packages:
|
||||
resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
caniuse-lite@1.0.30001612:
|
||||
resolution: {integrity: sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==}
|
||||
caniuse-lite@1.0.30001683:
|
||||
resolution: {integrity: sha512-iqmNnThZ0n70mNwvxpEC2nBJ037ZHZUoBI5Gorh1Mw6IlEAZujEoU1tXA628iZfzm7R9FvFzxbfdgml82a3k8Q==}
|
||||
|
||||
ccount@2.0.1:
|
||||
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
|
||||
@ -3394,7 +3394,7 @@ snapshots:
|
||||
autoprefixer@10.4.19(postcss@8.4.38):
|
||||
dependencies:
|
||||
browserslist: 4.23.0
|
||||
caniuse-lite: 1.0.30001612
|
||||
caniuse-lite: 1.0.30001683
|
||||
fraction.js: 4.3.7
|
||||
normalize-range: 0.1.2
|
||||
picocolors: 1.0.0
|
||||
@ -3470,7 +3470,7 @@ snapshots:
|
||||
|
||||
browserslist@4.23.0:
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001612
|
||||
caniuse-lite: 1.0.30001683
|
||||
electron-to-chromium: 1.4.746
|
||||
node-releases: 2.0.14
|
||||
update-browserslist-db: 1.0.13(browserslist@4.23.0)
|
||||
@ -3492,7 +3492,7 @@ snapshots:
|
||||
|
||||
camelcase@7.0.1: {}
|
||||
|
||||
caniuse-lite@1.0.30001612: {}
|
||||
caniuse-lite@1.0.30001683: {}
|
||||
|
||||
ccount@2.0.1: {}
|
||||
|
||||
|
@ -3,6 +3,14 @@ import type { PageEntry } from "../layouts/PagesLayout.astro";
|
||||
|
||||
const entry: PageEntry = Astro.props.entry;
|
||||
const post_url = entry.url + (entry.url.endsWith("/") ? "" : "/");
|
||||
|
||||
// this may deal with folders.
|
||||
// if so, it will turn any `-` into whitespace,
|
||||
// and remove any leading number
|
||||
const entry_title = entry.title
|
||||
.replaceAll("-", " ")
|
||||
.replaceAll(/\d+_/g, "");
|
||||
|
||||
---
|
||||
|
||||
{
|
||||
@ -21,7 +29,7 @@ const post_url = entry.url + (entry.url.endsWith("/") ? "" : "/");
|
||||
entry.children && (
|
||||
<>
|
||||
<div class="mt-6 px-3 py-1 uppercase font-display text-c-text-2 font-medium">
|
||||
{entry.title.replaceAll("-", " ")}
|
||||
{entry_title}
|
||||
</div>
|
||||
|
||||
<ul class="my-1">
|
||||
|
@ -17,7 +17,7 @@ export function leftTrimDedent(input: string): Array<string> {
|
||||
// Get indentation level of the first line
|
||||
let indentationLevel = 0;
|
||||
for (const char of lines[0]!) {
|
||||
if (char === " ") {
|
||||
if (char === " " || char === "\n") {
|
||||
indentationLevel += 1;
|
||||
} else {
|
||||
break;
|
||||
@ -33,7 +33,7 @@ export function leftTrimDedent(input: string): Array<string> {
|
||||
output.push(trimWhitespace(line, indentationLevel));
|
||||
}
|
||||
|
||||
if (output.length > 1 && output[output.length - 1] === "") {
|
||||
if (output.length > 1 && output[output.length - 1] === "") {
|
||||
output = output.slice(0, -1);
|
||||
}
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
import PagesLayout from "./PagesLayout.astro";
|
||||
|
||||
const { frontmatter, headings } = Astro.props;
|
||||
|
||||
const posts = await Astro.glob("@/pages/learn/**/*.{md,mdx}");
|
||||
const indexSubpath = `/learn/index.mdx`;
|
||||
---
|
||||
|
||||
<PagesLayout
|
||||
frontmatter={frontmatter}
|
||||
headings={headings}
|
||||
posts={posts}
|
||||
indexSubpath={indexSubpath}
|
||||
basePath="/learn/"
|
||||
disable_container={!!frontmatter.disable_container}
|
||||
>
|
||||
<slot />
|
||||
</PagesLayout>
|
@ -42,16 +42,14 @@ const {
|
||||
const base_len = base_url.length;
|
||||
|
||||
const posts_2 = posts
|
||||
.map(post => {
|
||||
return {
|
||||
.map(post => ({
|
||||
...post,
|
||||
title: post.frontmatter.title,
|
||||
// this should be a path relative to the base url.
|
||||
// e.g if base_url is `/spec`, then this instead of
|
||||
// being `/spec/ast/tokens` would be `/ast/tokens`
|
||||
path: post.url.substring(base_len),
|
||||
}
|
||||
})
|
||||
}))
|
||||
.sort((p1, p2) => p1.frontmatter.order > p2.frontmatter.order? 1 : -1);
|
||||
|
||||
// build a hierarchy of the files
|
||||
@ -75,39 +73,42 @@ for (const post of posts_2) {
|
||||
}
|
||||
}
|
||||
|
||||
// transform to the layout that the sidebar expects
|
||||
// build a folder hierarchy (only 2 levels)
|
||||
|
||||
const entries: Array<any> = [];
|
||||
for (const levels_key in second_level) {
|
||||
const levels_keys = Object.keys(second_level).toSorted();
|
||||
|
||||
// The key `_` contains the top level links. Always insert those
|
||||
const top_level_posts = second_level["_"]!;
|
||||
// sort
|
||||
const sorted_posts = top_level_posts.toSorted(sort_posts);
|
||||
entries.push(...sorted_posts);
|
||||
|
||||
for (const levels_key of levels_keys) {
|
||||
if (levels_key === "_") {
|
||||
// top level
|
||||
const posts = second_level[levels_key]!;
|
||||
entries.push(...posts)
|
||||
// top level, already inserted
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
const posts = second_level[levels_key]!;
|
||||
const sorted_posts = posts.toSorted(sort_posts);
|
||||
const parentEntry = {
|
||||
path: "",
|
||||
title: levels_key,
|
||||
children: posts,
|
||||
children: sorted_posts,
|
||||
url: "",
|
||||
};
|
||||
entries.push(parentEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
const index_page = posts_2.find(post => post.relative_file === "/index.md" || post.relative_file === "/index.mdx");
|
||||
if (index_page === undefined) {
|
||||
console.error("\n\nBuilding without an index page");
|
||||
console.error(import.meta.dirname);
|
||||
console.error("base_path", base_dir);
|
||||
console.error("entries len", entries.length);
|
||||
entries.forEach(e => console.log("\t"+e.url));
|
||||
throw new Error("No entries");
|
||||
function sort_posts(p1, p2) {
|
||||
if (!!p1.frontmatter.order && !!p2.frontmatter.order) {
|
||||
return p1.frontmatter.order > p2.frontmatter.order ? 1 : -1;
|
||||
} else {
|
||||
return p1.title > p2.title? 1 : -1;
|
||||
}
|
||||
}
|
||||
const basePath = index_page?.url ?? "/";
|
||||
*/
|
||||
---
|
||||
|
||||
<BaseLayout title={frontmatter.title}>
|
||||
|
@ -1,126 +0,0 @@
|
||||
---
|
||||
import Navbar from "../components/Navbar.astro";
|
||||
import BaseLayout from "./BaseLayout.astro";
|
||||
import TOC from "../components/TOC.astro";
|
||||
import Sidebar from "../components/Sidebar.astro";
|
||||
|
||||
const {
|
||||
frontmatter,
|
||||
headings,
|
||||
posts: _posts,
|
||||
indexSubpath,
|
||||
basePath,
|
||||
disable_container,
|
||||
} = Astro.props;
|
||||
const posts: Record<string, any>[] = _posts;
|
||||
|
||||
const indexPage = posts.find((post) => post.file.endsWith(indexSubpath));
|
||||
|
||||
if (indexPage === undefined) {
|
||||
throw new Error(`No index page found at ${indexSubpath}`);
|
||||
}
|
||||
|
||||
export type PageEntry = {
|
||||
path: string;
|
||||
title?: string;
|
||||
children?: Array<PageEntry>;
|
||||
};
|
||||
|
||||
const pagesIndex: Array<PageEntry> | undefined =
|
||||
indexPage.frontmatter.pagesLayout;
|
||||
|
||||
if (pagesIndex === undefined) {
|
||||
console.error(indexPage.frontmatter);
|
||||
throw new Error(`No pagesLayout frontmatter found in ${indexSubpath}`);
|
||||
}
|
||||
|
||||
function validateEntry(entry: PageEntry, basePath: string) {
|
||||
if (!entry.children) {
|
||||
// Attempt to get the page title from frontmatter
|
||||
const pageData = posts.find(
|
||||
(post) =>
|
||||
post.file.endsWith(entry.path + ".md") ||
|
||||
post.file.endsWith(entry.path + ".mdx"),
|
||||
);
|
||||
|
||||
if (pageData === undefined) {
|
||||
console.error(entry);
|
||||
console.error(entry.path + ".md");
|
||||
throw new Error(`No page found at ${entry.path}`);
|
||||
}
|
||||
|
||||
// set the title
|
||||
entry.title = pageData.frontmatter.title ?? "Title not set";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Recursively search for children
|
||||
if (!entry.title) {
|
||||
console.log(entry);
|
||||
throw new Error(
|
||||
`No title found in ${basePath + entry.path}, which is a folder and requires it.`,
|
||||
);
|
||||
}
|
||||
|
||||
const folderName = entry.title;
|
||||
|
||||
entry.children.forEach((child) =>
|
||||
validateEntry(child, basePath + "/" + folderName),
|
||||
);
|
||||
}
|
||||
|
||||
for (const entry of pagesIndex) {
|
||||
validateEntry(entry, basePath);
|
||||
}
|
||||
---
|
||||
|
||||
<BaseLayout title={frontmatter.title}>
|
||||
<Navbar />
|
||||
|
||||
<div
|
||||
class={`lg:grid lg:grid-cols-[14rem_auto_12rem] ${disable_container? "": "lg:container"} mx-auto font-display`}
|
||||
>
|
||||
<div
|
||||
id="sidebar"
|
||||
class="pt-12 h-screen lg:sticky top-0 fixed z-10 bg-c-bg w-60 lg:w-auto border-r-2 lg:border-0
|
||||
border-c-border-1 -translate-x-64 lg:translate-x-0 transition-transform"
|
||||
>
|
||||
<nav class="py-4 pr-2 overflow-x-scroll h-[calc(100vh-3rem)]">
|
||||
{
|
||||
pagesIndex.map((entry) => (
|
||||
<Sidebar entry={entry} basePath={basePath} />
|
||||
))
|
||||
}
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<main
|
||||
class="pt-[3.5rem] pb-[10rem] lg:pl-12 lg:pr-4 markdown min-w-0 small-container mx-auto"
|
||||
>
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<div
|
||||
class="lg:pt-12 hidden lg:block pt-4 max-h-screen overflow-x-scroll sticky top-0"
|
||||
>
|
||||
<nav class="rounded-md lg:mt-10">
|
||||
<h2 class="font-display font-medium pb-2 text-c-text-2">
|
||||
On this page
|
||||
</h2>
|
||||
|
||||
<TOC headings={headings} />
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { highlightOnDom } from "./thpHighlighter";
|
||||
document.addEventListener("DOMContentLoaded", highlightOnDom);
|
||||
</script>
|
||||
<script>
|
||||
import { sidebarHighlight } from "./utils";
|
||||
// Highlight the current url of the sidebar
|
||||
document.addEventListener("DOMContentLoaded", sidebarHighlight);
|
||||
</script>
|
||||
</BaseLayout>
|
@ -1,18 +0,0 @@
|
||||
---
|
||||
import PagesLayout from "./PagesLayout.astro";
|
||||
|
||||
const { frontmatter, headings } = Astro.props;
|
||||
|
||||
const posts = await Astro.glob("../pages/spec/**/*.{md,mdx}");
|
||||
const indexSubpath = `/spec/index.mdx`;
|
||||
---
|
||||
|
||||
<PagesLayout
|
||||
frontmatter={frontmatter}
|
||||
headings={headings}
|
||||
posts={posts}
|
||||
indexSubpath={indexSubpath}
|
||||
basePath="/spec/"
|
||||
>
|
||||
<slot />
|
||||
</PagesLayout>
|
@ -12,7 +12,7 @@ const error_classes = "underline underline-offset-4 decoration-wavy decoration-r
|
||||
* - The tokens as a list of <span /> elements
|
||||
* - An error message, if any
|
||||
*/
|
||||
export async function native_highlighter(code: string, level = HighlightLevel.Syntactic): Promise<[string, string | null]> {
|
||||
export async function native_highlighter(code: string, level = HighlightLevel.Lexic): Promise<[string, string | null]> {
|
||||
let formatted_code = leftTrimDedent(code).join("\n");
|
||||
|
||||
try {
|
||||
|
@ -42,5 +42,16 @@ case 1, 2, 3 {
|
||||
else {
|
||||
print("hello dear")
|
||||
}
|
||||
|
||||
match customer_id
|
||||
| 1 | 2 | 3 {
|
||||
print("ehhhh")
|
||||
}
|
||||
| 4 | 5 {
|
||||
print("ohhh")
|
||||
}
|
||||
| _ {
|
||||
print("???")
|
||||
}
|
||||
`} />
|
||||
|
52
src/pages/en/latest/learn/03_flow-control/pipes.mdx
Normal file
52
src/pages/en/latest/learn/03_flow-control/pipes.mdx
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
layout: "../_wrapper.astro"
|
||||
title: Pipes
|
||||
---
|
||||
import Code from "@/components/Code.astro"
|
||||
|
||||
# Pipes
|
||||
|
||||
You can use pipes `|>` & `<|` to redirect output from an
|
||||
expression as input to another.
|
||||
|
||||
For example, instead of writing:
|
||||
|
||||
<Code thpcode={`
|
||||
val result = third_function(second_function(first_function(my_value)))
|
||||
`} />
|
||||
|
||||
You can use pipes:
|
||||
|
||||
<Code thpcode={`
|
||||
val result = my_value
|
||||
|> first_function
|
||||
|> second_function
|
||||
|> third_function
|
||||
`} />
|
||||
|
||||
Or use it to group expressions:
|
||||
|
||||
<Code thpcode={`
|
||||
print <| (2 + 3 * 4) / 7
|
||||
`} />
|
||||
|
||||
TBD: How to handle piping to functions with more than 1 param
|
||||
|
||||
## Function composition
|
||||
|
||||
<Code thpcode={`
|
||||
fun add_one(x: Int) -> Int {
|
||||
x + 1
|
||||
}
|
||||
|
||||
fun times_two(x: Int) -> Int {
|
||||
x * 2
|
||||
}
|
||||
|
||||
// (Int) -> (Int)
|
||||
val plus_one_times_2 = add_one >> times_two
|
||||
|
||||
print(plus_one_times_2(5)) // 12
|
||||
`} />
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user