diff --git a/scripts/page.ts b/scripts/page.ts index 4e29ee8a..8f5a1a61 100644 --- a/scripts/page.ts +++ b/scripts/page.ts @@ -56,7 +56,7 @@ function isSectionItem(item: SectionItem | Section): item is SectionItem { function enrichTableOfContents(sections: Section[]): EnrichedSection[] { return sections.map((section) => { return { - id: section.title.toLowerCase().replace(" ", "_"), + id: section.title.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/(^_|_$)/g, ""), title: section.title, items: section.items.map((item) => { if (isSectionItem(item)) { @@ -101,11 +101,7 @@ function renderSection(section: EnrichedSection | EnrichedSectionItem): string { } else { return `
/.*/.
Values of type `string` may be compared against regular
-expressions using either the [apply operator](apply.malloynb), `name ? r'c.*'` or the like operator, `name ~ r'c.*'`.
+expressions using either the [apply operator](expressions.malloynb), `name ? r'c.*'` or the like operator, `name ~ r'c.*'`.
### Ranges
There are three types of ranges today: `number` ranges, `date` ranges, and `timestamp` ranges. The most basic ranges
are of the form `start to end` and represent the range from `start` up to, but not including, `end`, e.g. `10 to 20` or `@2004-01 to @2005-05`.
-Ranges may be used in conjunction with the [apply operator](apply.malloynb) to test whether a value falls within a given range.
+Ranges may be used in conjunction with the [apply operator](expressions.malloynb) to test whether a value falls within a given range.
### Alternations and Partials
@@ -249,7 +249,7 @@ inclusion respectively.
For example, `'CA' | r'N.*'` represents the condition of being equal to 'CA' or starting with 'N', and `10 to 20 | 20 to 30` represents the condition of being _either_ between 10 and 20 _or_ 20 and 30.
-Alternations and partials may be used in conjunction with the [apply operator](apply.malloynb) to test whether a value meets the given condition.
+Alternations and partials may be used in conjunction with the [apply operator](expressions.malloynb) to test whether a value meets the given condition.
## Nullability
diff --git a/src/documentation/language/time-ranges.malloynb b/src/documentation/language/time-ranges.malloynb
index b023c08f..d474bbff 100644
--- a/src/documentation/language/time-ranges.malloynb
+++ b/src/documentation/language/time-ranges.malloynb
@@ -10,7 +10,7 @@ There are two forms of range expressions
A timestamp can be compared to a range. If the time stamp is within
the range it will be `=`. Before the range it will be `<` and after
-the range it will be `>`. If you [apply](apply.malloynb) a range, (for example, `eventDate: @2003 to @2004`) that will also check if the value is within the range.
+the range it will be `>`. If you [apply](expressions.malloynb) a range, (for example, `eventDate: @2003 to @2004`) that will also check if the value is within the range.
## Range shortcuts
@@ -38,7 +38,7 @@ at the moment of truncation and the duration is the timeframe unit
used to specify the truncation, so for example `eventDate.year`
would be a range covering the entire year which contains `eventDate`
-This is extremely useful with the [Apply operator](apply.malloynb), `?`. To see if two events happen in the same calendar year, for example, the boolean expression in Malloy could be `oneEvent ? otherEvent.year`
+This is extremely useful with the [Apply operator](expressions.malloynb), `?`. To see if two events happen in the same calendar year, for example, the boolean expression in Malloy could be `oneEvent ? otherEvent.year`
## Interval Measurement
diff --git a/src/js/sidebar_state.js b/src/js/sidebar_state.js
index 2df09983..772d0817 100644
--- a/src/js/sidebar_state.js
+++ b/src/js/sidebar_state.js
@@ -34,14 +34,14 @@ function toggleTab(tabElement) {
function getCollapseState() {
try {
- return JSON.parse(localStorage.getItem("collapse_state")) || {};
+ return JSON.parse(sessionStorage.getItem("collapse_state")) || {};
} catch (_error) {
return {};
}
}
function setCollapseState(collapseState) {
- localStorage.setItem("collapse_state", JSON.stringify(collapseState));
+ sessionStorage.setItem("collapse_state", JSON.stringify(collapseState));
}
function setCollapsed(id, isCollapsed) {
@@ -58,6 +58,7 @@ function getCollapsed(id) {
Array.from(document.getElementsByClassName("sidebar-section-title")).forEach(
(element) => {
+ // Restore session state
if (!getCollapsed(element.id)) {
element.classList.remove("collapsed");
}
@@ -65,8 +66,24 @@ Array.from(document.getElementsByClassName("sidebar-section-title")).forEach(
}
);
+// Expand all ancestor sections of the active page (after restoring session state)
+var activeItem = document.querySelector(".sidebar-item.active");
+if (activeItem) {
+ var parent = activeItem.parentElement;
+ while (parent) {
+ if (parent.classList && parent.classList.contains("sidebar-section")) {
+ var title = parent.querySelector(":scope > .sidebar-section-title");
+ if (title && title.classList.contains("collapsed")) {
+ title.classList.remove("collapsed");
+ setCollapsed(title.id, false);
+ }
+ }
+ parent = parent.parentElement;
+ }
+}
+
const sidebarElement = document.getElementById("sidebar");
sidebarElement.addEventListener("scroll", () => {
- localStorage.setItem("sidebar_scroll_position", sidebarElement.scrollTop);
+ sessionStorage.setItem("sidebar_scroll_position", sidebarElement.scrollTop);
});
-sidebarElement.scrollTop = localStorage.getItem("sidebar_scroll_position") || 0;
+sidebarElement.scrollTop = sessionStorage.getItem("sidebar_scroll_position") || 0;
diff --git a/src/table_of_contents.json b/src/table_of_contents.json
index 95e5775d..7772cf6b 100644
--- a/src/table_of_contents.json
+++ b/src/table_of_contents.json
@@ -132,84 +132,137 @@
"title": "Language Reference",
"items": [
{
- "title": "Models",
- "link": "/language/statement.malloynb"
- },
- {
- "title": "Sources",
- "link": "/language/source.malloynb"
- },
- {
- "title": "Queries",
- "link": "/language/query.malloynb"
- },
- {
- "title": "Views",
- "link": "/language/views.malloynb"
- },
- {
- "title": "Data Types",
- "link": "/language/datatypes.malloynb"
- },
- {
- "title": "Fields",
- "link": "/language/fields.malloynb"
- },
- {
- "title": "Aggregates",
- "link": "/language/aggregates.malloynb"
- },
- {
- "title": "Expressions",
- "link": "/language/expressions.malloynb"
- },
- {
- "title": "Functions",
- "link": "/language/functions.malloynb"
- },
- {
- "title": "Filters",
- "link": "/language/filters.malloynb"
- },
- {
- "title": "Calculations (window functions)",
- "link": "/language/calculations_windows.malloynb"
- },
- {
- "title": "Ordering and Limiting",
- "link": "/language/order_by.malloynb"
- },
- {
- "title": "Joins",
- "link": "/language/join.malloynb"
- },
- {
- "title": "Nested Views",
- "link": "/language/nesting.malloynb"
- },
- {
- "title": "SQL Sources",
- "link": "/language/sql_sources.malloynb"
+ "title": "Quick Reference",
+ "link": "/language/quick_reference.html"
},
{
- "title": "Imports",
- "link": "/language/imports.malloynb"
+ "title": "Core Concepts",
+ "items": [
+ {
+ "title": "Models",
+ "link": "/language/statement.malloynb"
+ },
+ {
+ "title": "Sources",
+ "link": "/language/source.malloynb"
+ },
+ {
+ "title": "Queries",
+ "link": "/language/query.malloynb"
+ },
+ {
+ "title": "Views",
+ "link": "/language/views.malloynb"
+ },
+ {
+ "title": "Fields",
+ "link": "/language/fields.malloynb"
+ }
+ ]
},
{
- "title": "Connections",
- "link": "/language/connections.malloynb"
+ "title": "Data & Types",
+ "items": [
+ {
+ "title": "Data Types",
+ "link": "/language/datatypes.malloynb"
+ },
+ {
+ "title": "Time Ranges",
+ "link": "/language/time-ranges.malloynb"
+ },
+ {
+ "title": "Timestamp Operations",
+ "link": "/language/timestamp-operations.malloynb"
+ },
+ {
+ "title": "Timezones",
+ "link": "/language/timezones.malloynb"
+ },
+ {
+ "title": "Null Handling",
+ "link": "/language/null-handling.malloynb"
+ }
+ ]
},
{
- "title": "Tags",
- "link": "/language/tags.malloynb"
+ "title": "Expressions & Functions",
+ "items": [
+ {
+ "title": "Expressions",
+ "link": "/language/expressions.malloynb"
+ },
+ {
+ "title": "Functions",
+ "link": "/language/functions.malloynb"
+ },
+ {
+ "title": "Filters",
+ "link": "/language/filters.malloynb"
+ },
+ {
+ "title": "Filter Expressions",
+ "link": "/language/filter-expressions.malloynb"
+ }
+ ]
},
{
- "title": "Quick Reference",
- "link": "/language/quick_reference.html"
+ "title": "Aggregation & Analysis",
+ "items": [
+ {
+ "title": "Aggregates",
+ "link": "/language/aggregates.malloynb"
+ },
+ {
+ "title": "Ungrouped Aggregates",
+ "link": "/language/ungrouped-aggregates.malloynb"
+ },
+ {
+ "title": "Calculations (window functions)",
+ "link": "/language/calculations_windows.malloynb"
+ },
+ {
+ "title": "Evaluation Spaces",
+ "link": "/language/eval_space.malloynb"
+ },
+ {
+ "title": "Ordering and Limiting",
+ "link": "/language/order_by.malloynb"
+ }
+ ]
},
{
- "title": "Change Log",
- "link": "/language/changelog.malloynb"
+ "title": "Composition",
+ "items": [
+ {
+ "title": "Joins",
+ "link": "/language/join.malloynb"
+ },
+ {
+ "title": "Nested Views",
+ "link": "/language/nesting.malloynb"
+ },
+ {
+ "title": "SQL Sources",
+ "link": "/language/sql_sources.malloynb"
+ },
+ {
+ "title": "Imports",
+ "link": "/language/imports.malloynb"
+ },
+ {
+ "title": "Connections",
+ "link": "/language/connections.malloynb"
+ },
+ {
+ "title": "Tags",
+ "link": "/language/tags.malloynb"
+ },
+ {
+ "title": "HyperLogLog",
+ "link": "/language/hyperloglog.malloynb"
+ }
+ ]
},
{
"title": "Dialects",
@@ -241,6 +294,10 @@
"link": "/language/dialect/mssql-via-duckdb.malloynb"
}
]
+ },
+ {
+ "title": "Change Log",
+ "link": "/language/changelog.malloynb"
}
]
},
@@ -408,10 +465,6 @@
"title": "SQL Expressions",
"link": "/experiments/sql_expressions.malloynb"
},
- {
- "title": "Window Partitions",
- "link": "/experiments/window.malloynb"
- },
{
"title": "Parameters",
"link": "/experiments/parameters.malloynb"