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) => ( + + {highlightLine(line)} + {i < arr.length - 1 ? '\n' : null} + + )); +} + const LandingpageText: React.FC = () => { return (
-
-

Why choose TreePPL?

-

- TreePPL expresses models as computer programs that generate simulations based on input data. Specialized inference machinery then estimate posterior probability distributions for the program. -

-

- This approach lets users focus on model description while getting inference automatically. -

-

- The modeling language is designed to feel familiar to R and Python users and employs a functional programming style that works well with generic inference algorithms. Users can conveniently compile and run model programs from Python or R environments, which handle pre-processing, data input, inference control, and output processing. -

+
+
+
+

Why TreePPL?

+
+

Flexible modeling

+

Express any model of interest using a powerful programming language

+
+
+

Easy-to-use interfaces

+

Import data and analyze results using R or Python interfaces with Jupyter support

+
+
+

Powerful inference

+

Select from a range of built-in strategies or develop your own

+
+
+

Extensive libraries

+

Develop models faster using the code and model libraries

+
+
+
+
+
+            {highlightCode(treepplCode)}
+          
+
); }; - - export default LandingpageText; - diff --git a/src/css/custom.css b/src/css/custom.css index 2ac7664..fa6a6bd 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -43,9 +43,13 @@ font-family: DIN, sans-serif; + --ifm-navbar-background-color: #7a7455; + --ifm-navbar-link-color: #ffffff; + --ifm-navbar-link-hover-color: rgba(255, 255, 255, 0.75); } [data-theme='dark'] { + --ifm-navbar-background-color: #000000; --ifm-color-primary: #25c2a0; --ifm-color-primary-dark: #21af90; --ifm-color-primary-darker: #1fa588; diff --git a/src/pages/index.module.css b/src/pages/index.module.css index 3f1c9e1..64b5cc1 100644 --- a/src/pages/index.module.css +++ b/src/pages/index.module.css @@ -4,22 +4,29 @@ */ .heroBanner { - padding: 7.5rem 0; + padding: 6rem 0; text-align: center; position: relative; overflow: hidden; - background-image: url("/img/treebk4_green_light.png"); + background-image: url("/img/forrest.jpg"); background-repeat: no-repeat; background-position: center; + background-size: cover; background-color: transparent; - color: rgb(8, 8, 8); + color: white; font-weight: normal; - /* text-shadow: 1px 1px 4px black, -1px -1px 4px black, 1px -1px 4px black, -1px 1px 4px black; */ +} + +.heroBanner :global(.container) { + background: rgba(0, 0, 0, 0.45); + border-radius: 8px; + padding: 2rem 3rem; + display: inline-block; } @media screen and (max-width: 966px) { .heroBanner { - padding: 2rem; + padding: 1.6rem; } } diff --git a/static/img/forrest.jpg b/static/img/forrest.jpg new file mode 100644 index 0000000..397658f Binary files /dev/null and b/static/img/forrest.jpg differ