diff --git a/docusaurus.config.js b/docusaurus.config.js
index 328dc61..f6a1502 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -10,7 +10,7 @@ import rehypeKatex from 'rehype-katex';
const config = {
title: 'TreePPL',
- tagline: 'A Universal Probabilistic Programming Language for Phylogenetics and Evolutionary Biology',
+ tagline: 'Universal Probabilistic Programming for Phylogenetics',
url: 'http://treeppl.org/',
baseUrl: '/',
projectName: 'treeppl.github.io',
diff --git a/package-lock.json b/package-lock.json
index 8be9991..f02ceb5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -257,7 +257,6 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "^7.28.6",
"@babel/generator": "^7.28.6",
@@ -2046,7 +2045,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18"
},
@@ -2069,7 +2067,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18"
}
@@ -2179,7 +2176,6 @@
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
"integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -2601,7 +2597,6 @@
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
"integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -3399,7 +3394,6 @@
"resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz",
"integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@docusaurus/babel": "3.9.2",
"@docusaurus/bundler": "3.9.2",
@@ -3581,7 +3575,6 @@
"resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz",
"integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@docusaurus/core": "3.9.2",
"@docusaurus/logger": "3.9.2",
@@ -4611,7 +4604,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz",
"integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==",
- "peer": true,
"dependencies": {
"@types/mdx": "^2.0.0"
},
@@ -5080,7 +5072,6 @@
"resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz",
"integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/core": "^7.21.3",
"@svgr/babel-preset": "8.1.0",
@@ -5443,7 +5434,6 @@
"version": "18.3.14",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.14.tgz",
"integrity": "sha512-NzahNKvjNhVjuPBQ+2G7WlxstQ+47kXZNHlUvFakDViuIEfGY926GqhMueQFZ7woG+sPiQKlF36XfrIUVSUfFg==",
- "peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
@@ -5780,7 +5770,6 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -5846,7 +5835,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -5892,7 +5880,6 @@
"resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.47.0.tgz",
"integrity": "sha512-AGtz2U7zOV4DlsuYV84tLp2tBbA7RPtLA44jbVH4TTpDcc1dIWmULjHSsunlhscbzDydnjuFlNhflR3nV4VJaQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@algolia/abtesting": "1.13.0",
"@algolia/client-abtesting": "5.47.0",
@@ -6378,7 +6365,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -7322,7 +7308,6 @@
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
"integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -8704,7 +8689,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -13407,7 +13391,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -13968,7 +13951,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -14872,7 +14854,6 @@
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
"integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -15692,7 +15673,6 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
- "peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -15704,7 +15684,6 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
- "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -15756,7 +15735,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz",
"integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==",
- "peer": true,
"dependencies": {
"@types/react": "*"
},
@@ -15783,7 +15761,6 @@
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz",
"integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==",
- "peer": true,
"dependencies": {
"@babel/runtime": "^7.12.13",
"history": "^4.9.0",
@@ -17616,8 +17593,7 @@
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "peer": true
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/tsyringe": {
"version": "4.10.0",
@@ -17695,7 +17671,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"devOptional": true,
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -18058,7 +18033,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -18255,7 +18229,6 @@
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.2.tgz",
"integrity": "sha512-dRXm0a2qcHPUBEzVk8uph0xWSjV/xZxenQQbLwnwP7caQCYpqG1qddwlyEkIDkYn0K8tvmcrZ+bOrzoQ3HxCDw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8",
diff --git a/src/components/LandingpageText.module.css b/src/components/LandingpageText.module.css
index 478c22a..554ce33 100644
--- a/src/components/LandingpageText.module.css
+++ b/src/components/LandingpageText.module.css
@@ -1,40 +1,110 @@
.Tagline {
font-size: var(--ifm-font-size-28);
- color: var(--ifm-color-text-dark);
+ color: #3d5c45;
font-weight: bold;
+ margin-top: 0;
}
-.Description {
- font-size: var(--ifm-font-size-20);
- color: var(--ifm-color-text-light);
- padding: 1rem 0;
- font-weight: normal;
+:global([data-theme='dark']) .Tagline {
+ color: #ffffff;
+}
+
+:global([data-theme='dark']) .FeatureTitle {
+ color: #ffffff;
+}
+
+:global([data-theme='dark']) .FeatureDesc {
+ color: #ffffff;
+}
+
+.FeatureBox {
+ border-radius: 10px;
+ padding: 0 1.5rem 1.2rem 1.5rem;
+}
+
+.FeatureItem {
+ margin-bottom: 1.4rem;
}
-.DescriptionBold {
+.FeatureItem:last-child {
+ margin-bottom: 0;
+}
+
+.FeatureTitle {
font-size: var(--ifm-font-size-20);
- color: var(--ifm-color-text-light);
- padding: 1rem 0;
+ color: #3d5c45;
font-weight: bold;
+ margin-bottom: 0.2rem;
+}
+
+.FeatureDesc {
+ font-size: var(--ifm-font-size-16);
+ color: var(--ifm-color-text-light);
+ margin: 0;
}
.Content {
display: flex;
flex-direction: column;
align-items: center;
- width: 95%;
+ width: 98%;
max-width: var(--ifm-container-width);
margin: 0 auto;
- padding: 8rem 0;
+ padding: 2.4rem 0 1.6rem 0;
}
-.HeaderContainer {
+.TwoColumnLayout {
display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ gap: 1.5rem;
+ width: 100%;
+ max-width: 1200px;
+}
+
+.TextColumn {
flex: 1;
+ display: flex;
flex-direction: column;
justify-content: center;
- text-align: center;
- align-items: left;
- max-width: 1200px;
}
+.CodeColumn {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.CodeBlock {
+ background: #1e1e2e;
+ border-radius: 8px;
+ padding: 1.5rem 2rem;
+ font-size: 0.9rem;
+ line-height: 1.7;
+ color: #cdd6f4;
+ overflow-x: auto;
+ width: 100%;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
+}
+
+.keyword {
+ color: #89b4fa;
+ font-weight: bold;
+}
+
+.type {
+ color: #a6e3a1;
+ font-weight: bold;
+}
+
+.distribution {
+ color: #f9e2af;
+ font-weight: bold;
+}
+
+@media screen and (max-width: 966px) {
+ .TwoColumnLayout {
+ flex-direction: column;
+ }
+}
diff --git a/src/components/LandingpageText.tsx b/src/components/LandingpageText.tsx
index e64dade..fc278f2 100644
--- a/src/components/LandingpageText.tsx
+++ b/src/components/LandingpageText.tsx
@@ -4,26 +4,91 @@ import clsx from 'clsx';
import styles from './LandingpageText.module.css';
import Link from '@docusaurus/Link';
+const treepplCode = `function walk(node: Tree, time:Real, lambda: Real) {
+ observe 0 ~ Poisson(lambda * (time - node.age));
+ if node is Node {
+ observe 0.0 ~ Exponential(lambda);
+ walk(node.left, node.age, lambda);
+ walk(node.right, node.age, lambda);
+ }
+}
+
+model function crb(tree: Tree) => Real {
+ assume lambda ~ Gamma(1.0, 1.0);
+ walk(tree.left, tree.age, lambda);
+ walk(tree.right, tree.age, lambda);
+ return lambda;
+}`;
+
+function highlightLine(line: string): React.ReactNode[] {
+ const pattern = /\b(function|observe|model|assume|if|is|return)\b|\b(Real|Tree)\b|\b(Poisson|Exponential|Gamma)\b/g;
+ const parts: React.ReactNode[] = [];
+ let lastIndex = 0;
+ let match: RegExpExecArray | null;
+ let key = 0;
+
+ while ((match = pattern.exec(line)) !== null) {
+ if (match.index > lastIndex) {
+ parts.push({line.slice(lastIndex, match.index)});
+ }
+ const className = match[1] ? styles.keyword : match[2] ? styles.type : styles.distribution;
+ parts.push(
+
+ {match[0]}
+
+ );
+ lastIndex = match.index + match[0].length;
+ }
+
+ if (lastIndex < line.length) {
+ parts.push({line.slice(lastIndex)});
+ }
+
+ return parts;
+}
+
+function highlightCode(code: string): React.ReactNode[] {
+ return code.split('\n').map((line, i, arr) => (
+
Express any model of interest using a powerful programming language
+Import data and analyze results using R or Python interfaces with Jupyter support
+Select from a range of built-in strategies or develop your own
+Develop models faster using the code and model libraries
+
+ {highlightCode(treepplCode)}
+
+