├── .asf.yaml ├── .editorconfig ├── .github └── workflows │ ├── build.yml │ └── docs.sh ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── angular.json ├── commitlint.config.js ├── community ├── articles │ └── Apache Paimon V0.9最新进展.md ├── docs │ ├── downloads.md │ └── releases │ │ ├── release-0.4.md │ │ ├── release-0.5.md │ │ ├── release-0.6.md │ │ ├── release-0.7.md │ │ ├── release-0.8.1.md │ │ ├── release-0.8.2.md │ │ ├── release-0.8.md │ │ ├── release-0.9.md │ │ ├── release-1.0.md │ │ ├── release-1.1.md │ │ └── release-pypaimon-0.2.0.md └── profiles │ └── Jingsong Lee.yaml ├── eslint.config.js ├── library └── markdown-parser │ ├── config.ts │ ├── handlers │ ├── article.ts │ ├── document.ts │ ├── prerender.ts │ └── profile.ts │ ├── index.ts │ ├── models │ ├── article.ts │ ├── document.ts │ └── profile.ts │ ├── package.json │ ├── tsconfig.json │ └── utils │ ├── date.ts │ ├── directory.ts │ ├── markdown.ts │ ├── pick-random.ts │ └── uuid.ts ├── license-header.js ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── public ├── favicon.svg └── img │ ├── 1.1-postpone.png │ ├── 1.1-rest-api.png │ ├── changelog-lifecycle.png │ ├── deletion-vectors.png │ ├── v1-catalog.png │ ├── v1-commit.png │ ├── v1-iceberg.png │ └── v1-sort.png ├── server.ts ├── src ├── app │ ├── app.component.html │ ├── app.component.ts │ ├── app.config.server.ts │ ├── app.config.ts │ ├── app.i18n.ts │ ├── app.initializer.ts │ ├── app.routes.ts │ ├── components │ │ ├── blog-simple-card │ │ │ ├── blog-simple-card.component.html │ │ │ └── blog-simple-card.component.ts │ │ ├── click-outside │ │ │ └── click-outside.directive.ts │ │ ├── community-dropdown │ │ │ ├── community-dropdown.component.html │ │ │ └── community-dropdown.component.ts │ │ ├── footer │ │ │ ├── footer.component.html │ │ │ └── footer.component.ts │ │ ├── header │ │ │ ├── header.component.css │ │ │ ├── header.component.html │ │ │ └── header.component.ts │ │ ├── join-community │ │ │ ├── join-community.component.html │ │ │ └── join-community.component.ts │ │ ├── layout │ │ │ ├── layout.component.html │ │ │ └── layout.component.ts │ │ ├── markdown-render │ │ │ ├── markdown-render.component.css │ │ │ ├── markdown-render.component.html │ │ │ └── markdown-render.component.ts │ │ ├── page-container │ │ │ ├── page-container.component.html │ │ │ └── page-container.component.ts │ │ ├── pipes │ │ │ └── github-url.pipe.ts │ │ ├── search-bar │ │ │ ├── search-bar.component.html │ │ │ └── search-bar.component.ts │ │ └── ui-components │ │ │ ├── components │ │ │ ├── divider │ │ │ │ ├── divider.component.html │ │ │ │ └── divider.component.ts │ │ │ ├── dropdown-links │ │ │ │ ├── dropdown-links.component.html │ │ │ │ └── dropdown-links.component.ts │ │ │ ├── pagination │ │ │ │ ├── pagination.component.html │ │ │ │ └── pagination.component.ts │ │ │ └── switcher │ │ │ │ ├── switcher.component.html │ │ │ │ └── switcher.component.ts │ │ │ ├── index.ts │ │ │ └── public-api.ts │ ├── interfaces │ │ └── member.ts │ ├── routers │ │ ├── blog │ │ │ ├── blog.component.html │ │ │ ├── blog.component.ts │ │ │ ├── blog.routes.ts │ │ │ ├── components │ │ │ │ ├── anchor │ │ │ │ │ ├── anchor.component.html │ │ │ │ │ └── anchor.component.ts │ │ │ │ ├── blog-card │ │ │ │ │ ├── blog-card.component.html │ │ │ │ │ └── blog-card.component.ts │ │ │ │ └── blog-detail-footer │ │ │ │ │ ├── blog-detail-footer.component.html │ │ │ │ │ └── blog-detail-footer.component.ts │ │ │ ├── preload.guard.ts │ │ │ └── routers │ │ │ │ ├── blog-detail │ │ │ │ ├── blog-detail.component.html │ │ │ │ └── blog-detail.component.ts │ │ │ │ └── blog-list │ │ │ │ ├── blog-list.component.html │ │ │ │ └── blog-list.component.ts │ │ ├── downloads │ │ │ ├── downloads.component.html │ │ │ └── downloads.component.ts │ │ ├── home │ │ │ ├── components │ │ │ │ ├── about │ │ │ │ │ ├── about.component.html │ │ │ │ │ └── about.component.ts │ │ │ │ ├── key-features │ │ │ │ │ ├── key-features.component.html │ │ │ │ │ └── key-features.component.ts │ │ │ │ ├── overview │ │ │ │ │ ├── overview.component.css │ │ │ │ │ ├── overview.component.html │ │ │ │ │ └── overview.component.ts │ │ │ │ ├── team │ │ │ │ │ ├── team.component.html │ │ │ │ │ └── team.component.ts │ │ │ │ └── whosusing │ │ │ │ │ ├── whosusing.component.css │ │ │ │ │ ├── whosusing.component.html │ │ │ │ │ └── whosusing.component.ts │ │ │ ├── home.component.html │ │ │ └── home.component.ts │ │ ├── releases │ │ │ ├── releases.component.html │ │ │ ├── releases.component.ts │ │ │ ├── releases.guard.ts │ │ │ ├── releases.routes.ts │ │ │ └── routers │ │ │ │ └── release-detail │ │ │ │ ├── release-detail.component.html │ │ │ │ └── release-detail.component.ts │ │ ├── security │ │ │ ├── security.component.html │ │ │ └── security.component.ts │ │ ├── team │ │ │ ├── team.component.html │ │ │ └── team.component.ts │ │ └── users │ │ │ ├── users.component.html │ │ │ └── users.component.ts │ ├── services │ │ ├── article.service.ts │ │ ├── base-url.service.ts │ │ ├── document.service.ts │ │ ├── language.service.ts │ │ └── local-storage.service.ts │ └── tokens │ │ ├── member.ts │ │ └── users.ts ├── assets │ ├── i18n │ │ ├── en.json │ │ └── zh.json │ ├── icons │ │ ├── kf-1.svg │ │ ├── kf-2.svg │ │ ├── kf-3.svg │ │ ├── kf-4.svg │ │ ├── kf-5.svg │ │ ├── kf-6.svg │ │ ├── logo.png │ │ └── logo.svg │ ├── images │ │ ├── architecture.png │ │ ├── bg-header.png │ │ ├── bg.png │ │ ├── blog-bg.png │ │ └── key-features-bg.svg │ └── users │ │ ├── aliyun.png │ │ ├── amoro.png │ │ ├── antgroup.png │ │ ├── aodong.png │ │ ├── autohome.png │ │ ├── babeltime.png │ │ ├── bilibili.png │ │ ├── bytedance.png │ │ ├── celerdata.png │ │ ├── dinky.png │ │ ├── dustess.png │ │ ├── highlandhuanyu.png │ │ ├── kuayueexpress.png │ │ ├── mihoyo.png │ │ ├── netEase-media.png │ │ ├── selectdb.png │ │ ├── starrocks.png │ │ ├── tongchengtravel.png │ │ ├── unicom-digital.png │ │ ├── unicom.png │ │ ├── ververica.png │ │ ├── vivo.png │ │ ├── wanglong.png │ │ ├── xgimi.png │ │ ├── xiaopeng.png │ │ ├── ximalaya.png │ │ ├── yiou.png │ │ ├── zhihu.png │ │ ├── zhongyuanbank.png │ │ ├── ziroom.png │ │ └── zto.png ├── index.html ├── main.server.ts ├── main.ts ├── styles.css └── styles │ └── markdown.css ├── tailwind.config.js ├── tsconfig.app.json └── tsconfig.json /.asf.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | github: 19 | description: "Apache Paimon Website" 20 | homepage: https://paimon.apache.org/ 21 | features: 22 | issues: false 23 | projects: false 24 | wiki: false 25 | labels: 26 | - paimon 27 | enabled_merge_buttons: 28 | squash: true 29 | merge: false 30 | rebase: false 31 | 32 | publish: 33 | whoami: asf-site 34 | 35 | notifications: 36 | commits: commits@paimon.apache.org 37 | issues: issues@paimon.apache.org 38 | pullrequests: issues@paimon.apache.org 39 | jobs: builds@paimon.apache.org 40 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.github/workflows/docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ################################################################################ 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | ################################################################################ 19 | set -e 20 | 21 | mvn --version 22 | java -version 23 | javadoc -J-version 24 | 25 | # setup hugo 26 | HUGO_REPO=https://github.com/gohugoio/hugo/releases/download/v0.80.0/hugo_extended_0.80.0_Linux-64bit.tar.gz 27 | HUGO_ARTIFACT=hugo_extended_0.80.0_Linux-64bit.tar.gz 28 | if ! curl --fail -OL $HUGO_REPO ; then 29 | echo "Failed to download Hugo binary" 30 | exit 1 31 | fi 32 | tar -zxvf $HUGO_ARTIFACT 33 | git submodule update --init --recursive 34 | # generate docs into docs/target 35 | ./hugo -v --source docs --destination target 36 | if [ $? -ne 0 ]; then 37 | echo "Error building the docs" 38 | exit 1 39 | fi 40 | 41 | # build Paimon; required for Javadoc step 42 | mvn clean install -B -DskipTests 43 | 44 | # build java/scala docs 45 | mkdir -p docs/target/api 46 | mvn javadoc:aggregate -B \ 47 | -DadditionalJOption="-Xdoclint:none --allow-script-in-comments" \ 48 | -Dmaven.javadoc.failOnError=false \ 49 | -Dcheckstyle.skip=true \ 50 | -Dspotless.check.skip=true \ 51 | -Denforcer.skip=true \ 52 | -Dheader="

Back to Paimon Website

" 53 | mv target/site/apidocs docs/target/api/java 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. 2 | 3 | # Compiled output 4 | /src/assets/metadata/ 5 | /src/assets/docs/ 6 | /src/sitemap.xml 7 | /metadata 8 | /dist 9 | /tmp 10 | /out-tsc 11 | /bazel-out 12 | 13 | # Node 14 | /node_modules 15 | /library/markdown-parser/node_modules 16 | npm-debug.log 17 | yarn-error.log 18 | 19 | # IDEs and editors 20 | .idea/ 21 | .project 22 | .classpath 23 | .c9/ 24 | *.launch 25 | .settings/ 26 | *.sublime-workspace 27 | 28 | # Visual Studio Code 29 | .vscode/* 30 | !.vscode/settings.json 31 | !.vscode/tasks.json 32 | !.vscode/launch.json 33 | !.vscode/extensions.json 34 | .history/* 35 | 36 | # Miscellaneous 37 | /.angular/cache 38 | .sass-cache/ 39 | /connect.lock 40 | /coverage 41 | /libpeerconnection.log 42 | testem.log 43 | /typings 44 | .eslintcache 45 | 46 | # System files 47 | .DS_Store 48 | Thumbs.db 49 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | npx commitlint -e $1 -g commitlint.config.js 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | out-tsc/ 3 | dist/ 4 | coverage/ 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-tailwindcss"], 3 | "singleQuote": true, 4 | "useTabs": false, 5 | "printWidth": 120, 6 | "tabWidth": 2, 7 | "semi": true, 8 | "htmlWhitespaceSensitivity": "ignore", 9 | "arrowParens": "avoid", 10 | "bracketSpacing": true, 11 | "proseWrap": "preserve", 12 | "trailingComma": "none", 13 | "endOfLine": "auto", 14 | "overrides": [ 15 | { 16 | "files": ".prettierrc", 17 | "options": { 18 | "parser": "json" 19 | } 20 | }, 21 | { 22 | "files": "*.html", 23 | "options": { 24 | "printWidth": 100 25 | } 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const commitEditMsg = '.git/COMMIT_EDITMSG'; 3 | 4 | const types = [ 5 | 'feat', 6 | 'fix', 7 | 'build', 8 | 'ci', 9 | 'docs', 10 | 'perf', 11 | 'refactor', 12 | 'style', 13 | 'test', 14 | 'hotfix', 15 | 'release', 16 | 'chore', 17 | 'revert' 18 | ]; 19 | const typeDesc = { 20 | feat: ' new features, new functions', 21 | fix: ' fix normal no-emergency bug', 22 | build: ' changes that affect the build system, version release or external dependencies', 23 | ci: ' changes to CI configuration or scripts', 24 | docs: ' changes to the document', 25 | perf: ' optimize related, such as improving performance and experience', 26 | refactor: 'code refactoring', 27 | style: ' changes to the code format', 28 | test: ' add new function tests or changes to the origin test module', 29 | hotfix: ' urgent need to fix the online bug', 30 | release: ' version release', 31 | chore: ' changes in the build process or the auxiliary tools', 32 | revert: ' revert to the previous version' 33 | }; 34 | 35 | const exampleList = [ 36 | 'feat: add new features', 37 | 'feat(features): add new features' 38 | ]; 39 | 40 | function parseMessage(message) { 41 | const PATTERN = /(\w*)(?:\((.*)\))?: (.*)$/; 42 | const header = message.split('\n')[0]; 43 | const match = PATTERN.exec(header); 44 | if (match) { 45 | return { 46 | type: match[1] || null, 47 | scope: match[2] || null, 48 | subject: match[3] || null 49 | }; 50 | } 51 | return null; 52 | } 53 | 54 | function getTypeEnumRule() { 55 | const messages = fs.readFileSync(commitEditMsg, { encoding: 'utf-8' }); 56 | const myMessage = parseMessage(messages); 57 | if (myMessage) { 58 | const { type } = myMessage; 59 | if (type === 'hotfix' || type === 'release' || type === 'chore' || type === 'revert') { 60 | return [2, 'always', types]; 61 | } 62 | } 63 | console.log('Please strictly follow the following rules, such as:'); 64 | console.log(types.map(e => `${e}(optional): message ${typeDesc[e]}`)); 65 | console.log('Examples:'); 66 | exampleList.forEach(e => console.log(e)); 67 | return [2, 'always', types.map(e => `${e}`)]; 68 | } 69 | 70 | module.exports = { 71 | extends: ['@commitlint/config-angular'], 72 | rules: { 73 | 'body-leading-blank': [1, 'always'], 74 | 'footer-leading-blank': [1, 'always'], 75 | 'header-max-length': [2, 'always', 300], 76 | 'scope-case': [2, 'always', 'lower-case'], 77 | 'subject-empty': [2, 'never'], 78 | 'subject-full-stop': [2, 'never', '.'], 79 | 'type-empty': [2, 'never'], 80 | 'type-enum': getTypeEnumRule 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /community/docs/releases/release-0.4.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Release 0.4" 3 | type: release 4 | version: 0.4.0 5 | weight: 40 6 | --- 7 | 8 | # Apache Paimon 0.4 Available 9 | 10 | June 07, 2023 11 | 12 | We are happy to announce the availability of Paimon 0.4. This is the first release of the system inside the Apache Incubator and under the name Paimon. Releases up to 0.3 were under the name Flink Table Store, a sub-project of Flink where Paimon originates from. 13 | 14 | ## What is Paimon? 15 | 16 | Apache Paimon(incubating) is a streaming data lake platform that supports high-speed data ingestion, change data tracking and efficient real-time analytics. 17 | 18 | Paimon offers the following core capabilities: 19 | 20 | - **Unified Batch & Streaming**: Paimon supports batch write and batch read, as well as streaming write changes and streaming read table changelogs. 21 | - **Data Lake**: As a data lake storage, Paimon has the following advantages: low cost, high reliability, and scalable metadata. 22 | - **Merge Engines**: Paimon supports rich Merge Engines. By default, the last entry of the primary key is reserved. You can also use the "partial-update" or "aggregation" engine. 23 | - **Changelog producer**: Paimon supports rich Changelog producers, such as "lookup" and "full-compaction". The correct changelog can simplify the construction of a streaming pipeline. 24 | - **Append Only Tables**: Paimon supports Append Only tables, automatically compact small files, and provides orderly stream reading. You can use this to replace message queues. 25 | 26 | ## Release 0.4 27 | 28 | Paimon 0.4 includes many bug fixes and improvements that make the system more stable and robust. 29 | 30 | Download the release [here](https://paimon.apache.org/docs/0.4/project/download/). 31 | -------------------------------------------------------------------------------- /community/docs/releases/release-0.8.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Release 0.8.1" 3 | type: release 4 | version: 0.8.1 5 | weight: 81 6 | --- 7 | 8 | # Apache Paimon 0.8.1 Available 9 | 10 | June 11, 2024 - Jingsong Lee (jingsonglee0@gmail.com) 11 | 12 | Apache Paimon PMC has officially released Apache Paimon 0.8.1 version. This is the bug fix version of release 0.8. 13 | 14 | Thank you to all contributors for their support! 15 | 16 | ## Version Overview 17 | 18 | This release includes 58 commits. Including: 19 | 1. 30+ bugfix commits. 20 | 2. 20+ document improvements. 21 | 22 | The notable bugs include: 23 | 1. Paimon [#3476](https://github.com/apache/paimon/pull/3476): Make Flink Sink be compatible with Paimon 0.7. 24 | 2. Paimon [#3454](https://github.com/apache/paimon/pull/3454): Fix files system table performance issue by scanning all files during plan. 25 | 3. Paimon [#3484](https://github.com/apache/paimon/pull/3484): Fix infinite loops caused by nested types. 26 | 4. Paimon [#3467](https://github.com/apache/paimon/pull/3467): Fix that cannot read UPDATE_BEFORE of ignore-delete table. 27 | 5. Paimon [#3438](https://github.com/apache/paimon/pull/3438): Fix raw convert fail for old version storage read-optimized table. 28 | 6. Paimon [#3435](https://github.com/apache/paimon/pull/3435): Fix parquet conf cannot pass to parquet writer, for example, you cannot specify zstd level for parquet. 29 | 7. Paimon [#3338](https://github.com/apache/paimon/pull/3338): Incremental-between tags should deduplicate records, for a long time, its outcome has been more. 30 | 8. Paimon [#3314](https://github.com/apache/paimon/pull/3314): Paimon CDC: Fix when the order of the same field differs, it is considered a schema change, the bottleneck will be on the schema change. 31 | 9. Paimon [#3499](https://github.com/apache/paimon/pull/3499): Avoid commit conflicts caused by prolonged backpressure (Don't panic). 32 | 10. Paimon [#3452](https://github.com/apache/paimon/pull/3452): Fix FIRST_ROW merge engine for changelog-producer is none. 33 | 34 | ## Documentation 35 | 36 | https://paimon.apache.org/docs/0.8/ 37 | -------------------------------------------------------------------------------- /community/docs/releases/release-0.8.2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Release 0.8.2" 3 | type: release 4 | version: 0.8.2 5 | weight: 82 6 | --- 7 | 8 | # Apache Paimon 0.8.2 Available 9 | 10 | July 12, 2024 - Jingsong Lee (jingsonglee0@gmail.com) 11 | 12 | Apache Paimon PMC has officially released Apache Paimon 0.8.2 version. This is second bug fix version of release 0.8. 13 | 14 | Thank you to all contributors for their support! 15 | 16 | ## Version Overview 17 | 18 | This release includes 31 commits. 19 | 20 | See https://github.com/apache/paimon/commits/release-0.8.2 21 | 22 | ## Documentation 23 | 24 | https://paimon.apache.org/docs/0.8/ 25 | -------------------------------------------------------------------------------- /community/profiles/Jingsong Lee.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/community/profiles/Jingsong Lee.yaml -------------------------------------------------------------------------------- /library/markdown-parser/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | export const Configuration = { 20 | image: { 21 | profile: [] as string[], 22 | article: [] as string[] 23 | }, 24 | directory: { 25 | source: 'community', 26 | dist: 'metadata', 27 | article: 'articles', 28 | profile: 'profiles', 29 | release: 'releases' 30 | }, 31 | article: { 32 | abstract: { 33 | minLength: 150 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /library/markdown-parser/handlers/article.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { isAfter } from 'date-fns'; 20 | 21 | import * as fs from 'fs'; 22 | import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs'; 23 | import { parse as parseFileName } from 'path'; 24 | 25 | import { buildBriefArticleList, parseArticleFromBuffer, resolveArticle, ResolvedArticle } from '../models/article'; 26 | import { Profile } from '../models/profile'; 27 | import { getDirectoryPath } from '../utils/directory'; 28 | 29 | const { articleSource, articleDist } = getDirectoryPath(); 30 | 31 | export function processArticles(profiles: Profile[]): ResolvedArticle[] { 32 | if (fs.existsSync(articleDist)) { 33 | fs.rmSync(articleDist, { force: true, recursive: true }); 34 | } 35 | mkdirSync(articleDist, { recursive: true }); 36 | 37 | let articles: ResolvedArticle[] = []; 38 | let preArticle: Partial; 39 | 40 | if (!fs.existsSync(articleSource)) { 41 | mkdirSync(articleSource, { recursive: true }); 42 | } 43 | readdirSync(articleSource).forEach(file => { 44 | const { name } = parseFileName(file); 45 | const article = parseArticleFromBuffer(name, readFileSync(`${articleSource}/${name}.md`)); 46 | const resolvedArticle = resolveArticle(article, profiles); 47 | articles.push(resolvedArticle); 48 | }); 49 | 50 | articles = articles 51 | .sort((a, b) => { 52 | if (a.date && b.date) { 53 | return isAfter(a.date, b.date) ? -1 : 1; 54 | } else { 55 | return 0; 56 | } 57 | }) 58 | .reduce((pre, cur, index) => { 59 | const resolvedSimpleArticle = { id: cur.id, name: cur.name }; 60 | cur.pre = preArticle; 61 | 62 | preArticle = resolvedSimpleArticle; 63 | if (index > 0) { 64 | pre[index - 1].next = resolvedSimpleArticle; 65 | } 66 | 67 | pre.push(cur); 68 | return pre; 69 | }, []); 70 | 71 | articles.forEach(article => { 72 | writeFileSync(`${articleDist}/${article.id}.json`, JSON.stringify(article)); 73 | }); 74 | 75 | const briefArticleList = buildBriefArticleList(articles); 76 | writeFileSync(`${articleDist}/list.json`, JSON.stringify(briefArticleList)); 77 | return articles; 78 | } 79 | -------------------------------------------------------------------------------- /library/markdown-parser/handlers/document.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | import * as fs from 'fs'; 21 | import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs'; 22 | import { parse as parseFileName } from 'path'; 23 | 24 | import { BriefRelease, parseDocumentFromBuffer, ResolvedDocument, resolveDocument } from '../models/document'; 25 | import { getDirectoryPath } from '../utils/directory'; 26 | 27 | const { downloadsSource, releasesSource, docsDist } = getDirectoryPath(); 28 | 29 | export function processDocuments(): { releases: BriefRelease[] } { 30 | if (fs.existsSync(docsDist)) { 31 | fs.rmSync(docsDist, { force: true, recursive: true }); 32 | } 33 | mkdirSync(docsDist, { recursive: true }); 34 | 35 | if (!fs.existsSync(releasesSource)) { 36 | mkdirSync(releasesSource, { recursive: true }); 37 | } 38 | 39 | const releases: ResolvedDocument[] = []; 40 | const downloads = parseDocumentFromBuffer('downloads', readFileSync(`${downloadsSource}/downloads.md`)); 41 | const resolvedDownloads = resolveDocument(downloads); 42 | writeFileSync(`${docsDist}/downloads.json`, JSON.stringify(resolvedDownloads)); 43 | 44 | readdirSync(releasesSource).forEach(file => { 45 | const { name } = parseFileName(file); 46 | const release = parseDocumentFromBuffer(name, readFileSync(`${releasesSource}/${name}.md`)); 47 | const resolvedRelease = resolveDocument(release); 48 | releases.push(resolvedRelease); 49 | }); 50 | 51 | releases.forEach(release => writeFileSync(`${docsDist}/${release.version}.json`, JSON.stringify(release))); 52 | 53 | // sort by weight 54 | const briefReleases = releases 55 | .sort((a, b) => b.weight - a.weight) 56 | .map(release => new BriefRelease(release.title, release.version)); 57 | 58 | writeFileSync(`${docsDist}/releases.json`, JSON.stringify(briefReleases)); 59 | 60 | return { releases: briefReleases }; 61 | } 62 | -------------------------------------------------------------------------------- /library/markdown-parser/handlers/prerender.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { writeFileSync } from 'fs'; 20 | 21 | import { ResolvedArticle } from '../models/article'; 22 | import { BriefRelease } from '../models/document'; 23 | import { getDirectoryPath } from '../utils/directory'; 24 | 25 | const { dist } = getDirectoryPath(); 26 | 27 | export function processRoutes(articles: ResolvedArticle[], releases: BriefRelease[]): void { 28 | const articleUrls = articles.map(item => `/blog/${item.id}`); 29 | const releaseUrls = releases.map(item => `/releases/${item.version}`); 30 | const homeUrls = ['/', '/blog', '/downloads', '/releases']; 31 | const content = [...homeUrls, ...articleUrls, ...releaseUrls].join('\n'); 32 | writeFileSync(`${dist}/routes.txt`, content); 33 | } 34 | -------------------------------------------------------------------------------- /library/markdown-parser/handlers/profile.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import * as fs from 'fs'; 20 | import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs'; 21 | import { parse as parseFileName } from 'path'; 22 | 23 | import { parseProfileFromBuffer, Profile } from '../models/profile'; 24 | import { getDirectoryPath } from '../utils/directory'; 25 | 26 | const { profileSource, profileDist } = getDirectoryPath(); 27 | 28 | export function processProfiles(): Profile[] { 29 | if (fs.existsSync(profileDist)) { 30 | fs.rmSync(profileDist, { force: true, recursive: true }); 31 | } 32 | mkdirSync(profileDist, { recursive: true }); 33 | 34 | const profiles: Profile[] = []; 35 | 36 | readdirSync(profileSource).forEach(file => { 37 | const { name } = parseFileName(file); 38 | const profile = parseProfileFromBuffer(name, readFileSync(`${profileSource}/${name}.yaml`)); 39 | writeFileSync(`${profileDist}/${profile.id}.json`, JSON.stringify(profile)); 40 | profiles.push(profile); 41 | }); 42 | 43 | writeFileSync(`${profileDist}/list.json`, JSON.stringify(profiles)); 44 | return profiles; 45 | } 46 | -------------------------------------------------------------------------------- /library/markdown-parser/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { processArticles } from './handlers/article'; 20 | import { processDocuments } from './handlers/document'; 21 | import { processRoutes } from './handlers/prerender'; 22 | import { processProfiles } from './handlers/profile'; 23 | 24 | const profiles = processProfiles(); 25 | const documents = processDocuments(); 26 | 27 | const articles = processArticles(profiles); 28 | // init folder 29 | processRoutes(articles, documents.releases); 30 | -------------------------------------------------------------------------------- /library/markdown-parser/models/document.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import marked from 'marked'; 20 | 21 | import { ExtendTokensList, generateTOC, TOC } from './article'; 22 | import { parseMarkdownToHTML, parseMarkdownWithYAML } from '../utils/markdown'; 23 | 24 | /** 25 | * Raw data parsed from yaml & markdown 26 | */ 27 | export class Document { 28 | constructor( 29 | readonly title: string, 30 | readonly type: string, // 'release' | 'download' 31 | readonly content: string, 32 | readonly alias: string, 33 | readonly version?: string, 34 | readonly weight?: number 35 | ) {} 36 | } 37 | 38 | /** 39 | * Resolved document used to render in web 40 | */ 41 | export class ResolvedDocument { 42 | constructor( 43 | readonly title: string, 44 | readonly type: string, // 'release' | 'download' 45 | readonly content: string, 46 | readonly toc: TOC[], 47 | readonly alias: string, // for `Edit this page` button 48 | readonly version?: string, 49 | readonly weight?: number 50 | ) {} 51 | } 52 | 53 | export class BriefRelease { 54 | constructor( 55 | readonly title: string, 56 | readonly version: string 57 | ) {} 58 | } 59 | 60 | /** 61 | * parse document from buffer with yaml & markdown 62 | * @param name 63 | * @param buffer 64 | */ 65 | export function parseDocumentFromBuffer(name: string, buffer: Buffer): Document { 66 | try { 67 | const { title, type, version, weight, __content } = parseMarkdownWithYAML(buffer); 68 | return new Document(title, type, __content, name, version, weight); 69 | } catch (e) { 70 | console.log(e); 71 | throw new Error(name); 72 | } 73 | } 74 | 75 | /** 76 | * Correct and add more properties to document 77 | * @param doc 78 | */ 79 | export function resolveDocument(doc: Document): ResolvedDocument { 80 | const { title, type, content, alias, version, weight } = doc; 81 | const tokensList = new marked.Lexer().lex(doc.content) as unknown as ExtendTokensList; 82 | 83 | const contentString = parseMarkdownToHTML(content); 84 | const toc = generateTOC(tokensList); 85 | return new ResolvedDocument(title, type, contentString, toc, alias, version, weight); 86 | } 87 | -------------------------------------------------------------------------------- /library/markdown-parser/models/profile.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { parse } from 'yaml'; 20 | 21 | import { Configuration } from '../config'; 22 | import { pickRandom } from '../utils/pick-random'; 23 | import { generateUUID } from '../utils/uuid'; 24 | 25 | export class Profile { 26 | constructor( 27 | readonly id: string, 28 | readonly name: string, 29 | readonly title: string | null, 30 | readonly image: string | null, 31 | readonly blog: string | null, 32 | readonly github: string | null 33 | ) {} 34 | } 35 | 36 | /** 37 | * parse profile from yaml 38 | * @param name 39 | * @param buffer 40 | */ 41 | export function parseProfileFromBuffer(name: string, buffer: Buffer): Profile { 42 | const { title, image, blog, github } = parse(String(buffer)) || {}; 43 | const id = generateUUID(name); 44 | return new Profile(id, name, title, image || pickRandom(Configuration.image.profile), blog, github); 45 | } 46 | 47 | /** 48 | * create profile with name if not inside profileCollection 49 | * @param name 50 | * @param profileCollection 51 | * @returns 52 | */ 53 | export function resolveProfile(name: string, profileCollection: Profile[]): Profile { 54 | const targetProfile = profileCollection.find(p => p.name.includes(name)); 55 | if (targetProfile) { 56 | return targetProfile; 57 | } else { 58 | const id = generateUUID(name); 59 | return new Profile(id, name, null, null, null, null); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /library/markdown-parser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "markdown-parser", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "parse": "ts-node --files index.ts" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@types/github-slugger": "^1.3.0", 14 | "@types/md5": "^2.3.5", 15 | "@types/node": "^22.5.5", 16 | "@types/prismjs": "^1.26.4", 17 | "@types/semver": "^7.5.8", 18 | "@types/yaml-front-matter": "^4.1.3", 19 | "@typescript-eslint/eslint-plugin": "^8.6.0", 20 | "@typescript-eslint/parser": "^8.6.0", 21 | "eslint": "^9.11.0", 22 | "typescript": "^5.6.2" 23 | }, 24 | "dependencies": { 25 | "date-fns": "^4.1.0", 26 | "github-slugger": "^1.3.0", 27 | "html-entities": "^2.5.2", 28 | "marked": "^14.1.2", 29 | "md5": "^2.3.0", 30 | "prismjs": "^1.29.0", 31 | "semver": "^7.6.3", 32 | "sitemap": "^8.0.0", 33 | "ts-node": "^10.9.2", 34 | "yaml": "^2.5.1", 35 | "yaml-front-matter": "^4.1.1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /library/markdown-parser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "esModuleInterop": true, 5 | "allowSyntheticDefaultImports": true, 6 | "target": "es6", 7 | "noImplicitAny": true, 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "outDir": "../../dist", 11 | "baseUrl": "./", 12 | }, 13 | "include": [ 14 | "**/*.ts", 15 | "*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /library/markdown-parser/utils/date.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { isValid } from 'date-fns'; 20 | 21 | export function getValidDate(name: string, date: string): Date | null { 22 | if (date) { 23 | const parsedDate = new Date(date); 24 | if (isValid(parsedDate)) { 25 | return parsedDate; 26 | } else { 27 | console.warn(`Date ${date} parsed failed in ${name} file`); 28 | return null; 29 | } 30 | } else { 31 | return null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /library/markdown-parser/utils/directory.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { resolve } from 'path'; 20 | import * as process from 'process'; 21 | 22 | import { Configuration } from '../config'; 23 | 24 | export const getDirectoryPath = (): { 25 | source: string; 26 | dist: string; 27 | distRoot: string; 28 | articleDist: string; 29 | profileDist: string; 30 | articleSource: string; 31 | downloadsSource: string; 32 | releasesSource: string; 33 | docsDist: string; 34 | profileSource: string; 35 | } => { 36 | const processwd = process.cwd(); 37 | const source = resolve(processwd, `../../${Configuration.directory.source}`); 38 | const distRoot = resolve(processwd, `../../src`); 39 | const dist = resolve(distRoot, `./assets/${Configuration.directory.dist}`); 40 | return { 41 | source, 42 | dist, 43 | distRoot, 44 | articleDist: resolve(dist, Configuration.directory.article), 45 | profileDist: resolve(dist, Configuration.directory.profile), 46 | articleSource: resolve(source, Configuration.directory.article), 47 | downloadsSource: resolve(source, 'docs'), 48 | releasesSource: resolve(source, 'docs', Configuration.directory.release), 49 | docsDist: resolve(distRoot, `./assets/docs`), 50 | profileSource: resolve(source, Configuration.directory.profile) 51 | }; 52 | }; 53 | -------------------------------------------------------------------------------- /library/markdown-parser/utils/markdown.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import GithubSlugger from 'github-slugger'; 20 | import { Renderer, marked, Tokens } from 'marked'; 21 | import prism from 'prismjs'; 22 | import loadLanguages from 'prismjs/components/'; 23 | import { loadFront as parseMarkdownWithYAML } from 'yaml-front-matter'; 24 | 25 | loadLanguages(['java', 'sql']); 26 | 27 | const githubSlugger = new GithubSlugger(); 28 | 29 | class ArticleRender extends Renderer { 30 | override heading({ text, depth }: Tokens.Heading): string { 31 | const slugText = githubSlugger.slug(text); 32 | if (depth === 1) { 33 | return ``; 34 | } else { 35 | return `${text}`; 36 | } 37 | } 38 | 39 | override code({ text, lang }: Tokens.Code): string { 40 | const language = prism.languages[lang!] || prism.languages['java']; 41 | const highlight = prism.highlight(text, language, lang!); 42 | return `
${highlight}
`; 43 | } 44 | 45 | override image({ href, title }: Tokens.Image): string { 46 | return `${title}`; 47 | } 48 | 49 | override link({ href, title, text }: Tokens.Link): string { 50 | return `${text}`; 51 | } 52 | } 53 | 54 | const parseMarkdownToHTMLWithSlug = (content: string): string => { 55 | githubSlugger.reset(); 56 | return marked.parse(content, { renderer: new ArticleRender() }) as string; 57 | }; 58 | 59 | export { githubSlugger, parseMarkdownWithYAML, parseMarkdownToHTMLWithSlug as parseMarkdownToHTML }; 60 | -------------------------------------------------------------------------------- /library/markdown-parser/utils/pick-random.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | export function pickRandom(arr: T[]): T { 20 | return arr[Math.floor(Math.random() * arr.length)]; 21 | } 22 | -------------------------------------------------------------------------------- /library/markdown-parser/utils/uuid.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import md5 from 'md5'; 20 | 21 | export function generateUUID(source: string): string { 22 | return md5(source) as string; 23 | } 24 | -------------------------------------------------------------------------------- /license-header.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paimon-next-website", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "parse": "cd library/markdown-parser && npm run parse", 6 | "prestart": "npm run parse", 7 | "start": "ng serve --port 8801", 8 | "prebuild": "npm run parse", 9 | "build": "ng build", 10 | "serve:ssr": "node dist/server/server.mjs", 11 | "i18n:extract": "ngx-translate-extract --input ./src --output ./src/assets/i18n/{en,zh}.json -ss -k --clean --format json", 12 | "prepare": "husky", 13 | "lint": "ng lint --cache", 14 | "lint:fix": "ng lint --cache --fix" 15 | }, 16 | "private": true, 17 | "dependencies": { 18 | "@angular/animations": "^18.2.0", 19 | "@angular/common": "^18.2.0", 20 | "@angular/compiler": "^18.2.0", 21 | "@angular/core": "^18.2.0", 22 | "@angular/forms": "^18.2.0", 23 | "@angular/platform-browser": "^18.2.0", 24 | "@angular/platform-browser-dynamic": "^18.2.0", 25 | "@angular/platform-server": "^18.2.0", 26 | "@angular/router": "^18.2.0", 27 | "@angular/ssr": "^18.2.2", 28 | "@ngx-translate/core": "^15.0.0", 29 | "@ngx-translate/http-loader": "^8.0.0", 30 | "express": "^4.18.2", 31 | "github-slugger": "^1.3.0", 32 | "rxjs": "~7.8.0", 33 | "tslib": "^2.3.0", 34 | "zone.js": "~0.14.10" 35 | }, 36 | "devDependencies": { 37 | "@angular-devkit/build-angular": "^18.2.2", 38 | "@angular/cli": "^18.2.2", 39 | "@angular/compiler-cli": "^18.2.0", 40 | "@commitlint/cli": "^19.5.0", 41 | "@commitlint/config-angular": "^19.5.0", 42 | "@eslint/compat": "^1.1.1", 43 | "@eslint/eslintrc": "^3.1.0", 44 | "@types/express": "^4.17.17", 45 | "@types/github-slugger": "^1.3.0", 46 | "@types/node": "^22.7.0", 47 | "@vendure/ngx-translate-extract": "^9.2.1", 48 | "angular-eslint": "18.3.1", 49 | "autoprefixer": "^10.4.20", 50 | "eslint": "^9.11.1", 51 | "eslint-plugin-header": "^3.1.1", 52 | "eslint-plugin-import": "^2.30.0", 53 | "eslint-plugin-jsdoc": "^50.3.0", 54 | "eslint-plugin-prettier": "^5.2.1", 55 | "eslint-plugin-unused-imports": "^4.1.4", 56 | "husky": "^9.1.6", 57 | "lint-staged": "^15.2.10", 58 | "postcss": "^8.4.44", 59 | "prettier": "^3.3.3", 60 | "prettier-plugin-tailwindcss": "^0.6.6", 61 | "tailwindcss": "^3.4.10", 62 | "tailwindcss-animation-delay": "^2.0.1", 63 | "typescript": "~5.5.2", 64 | "typescript-eslint": "8.2.0" 65 | }, 66 | "lint-staged": { 67 | "*.{ts,html}": [ 68 | "eslint --fix" 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'library/*' 3 | -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /public/img/1.1-postpone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/public/img/1.1-postpone.png -------------------------------------------------------------------------------- /public/img/1.1-rest-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/public/img/1.1-rest-api.png -------------------------------------------------------------------------------- /public/img/changelog-lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/public/img/changelog-lifecycle.png -------------------------------------------------------------------------------- /public/img/deletion-vectors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/public/img/deletion-vectors.png -------------------------------------------------------------------------------- /public/img/v1-catalog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/public/img/v1-catalog.png -------------------------------------------------------------------------------- /public/img/v1-commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/public/img/v1-commit.png -------------------------------------------------------------------------------- /public/img/v1-iceberg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/public/img/v1-iceberg.png -------------------------------------------------------------------------------- /public/img/v1-sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/public/img/v1-sort.png -------------------------------------------------------------------------------- /server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { APP_BASE_HREF } from '@angular/common'; 20 | import { CommonEngine } from '@angular/ssr'; 21 | 22 | import express from 'express'; 23 | 24 | import { dirname, join, resolve } from 'node:path'; 25 | import { fileURLToPath } from 'node:url'; 26 | 27 | import bootstrap from './src/main.server'; 28 | 29 | // The Express app is exported so that it can be used by serverless Functions. 30 | export function app(): express.Express { 31 | const server = express(); 32 | const serverDistFolder = dirname(fileURLToPath(import.meta.url)); 33 | const browserDistFolder = resolve(serverDistFolder, '../browser'); 34 | const indexHtml = join(serverDistFolder, 'index.server.html'); 35 | 36 | const commonEngine = new CommonEngine(); 37 | 38 | server.set('view engine', 'html'); 39 | server.set('views', browserDistFolder); 40 | 41 | // Example Express Rest API endpoints 42 | // server.get('/api/**', (req, res) => { }); 43 | // Serve static files from /browser 44 | server.get( 45 | '**', 46 | express.static(browserDistFolder, { 47 | maxAge: '1y', 48 | index: 'index.html' 49 | }) 50 | ); 51 | 52 | // All regular routes use the Angular engine 53 | server.get('**', (req, res, next) => { 54 | const { protocol, originalUrl, baseUrl, headers } = req; 55 | 56 | commonEngine 57 | .render({ 58 | bootstrap, 59 | documentFilePath: indexHtml, 60 | url: `${protocol}://${headers.host}${originalUrl}`, 61 | publicPath: browserDistFolder, 62 | providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }] 63 | }) 64 | .then(html => res.send(html)) 65 | .catch(err => next(err)); 66 | }); 67 | 68 | return server; 69 | } 70 | 71 | function run(): void { 72 | const port = process.env['PORT'] || 4000; 73 | 74 | // Start up the Node server 75 | const server = app(); 76 | server.listen(port, () => { 77 | console.log(`Node Express server listening on http://localhost:${port}`); 78 | }); 79 | } 80 | 81 | run(); 82 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | @defer { 2 | 3 | 4 | 5 | } @placeholder (minimum 200ms) { 6 |
9 | Apache Paimon 16 |
17 | 20 | 23 | 26 | 29 | 32 | 35 |
36 |
37 | } 38 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgOptimizedImage } from '@angular/common'; 20 | import { Component } from '@angular/core'; 21 | import { RouterOutlet } from '@angular/router'; 22 | 23 | import { LayoutComponent } from '@paimon/app/components/layout/layout.component'; 24 | 25 | @Component({ 26 | selector: 'paimon-root', 27 | standalone: true, 28 | imports: [RouterOutlet, LayoutComponent, NgOptimizedImage], 29 | templateUrl: './app.component.html' 30 | }) 31 | export class AppComponent {} 32 | -------------------------------------------------------------------------------- /src/app/app.config.server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { mergeApplicationConfig, ApplicationConfig } from '@angular/core'; 20 | import { provideServerRendering } from '@angular/platform-server'; 21 | 22 | import { appConfig } from './app.config'; 23 | 24 | const serverConfig: ApplicationConfig = { 25 | providers: [provideServerRendering()] 26 | }; 27 | 28 | export const config = mergeApplicationConfig(appConfig, serverConfig); 29 | -------------------------------------------------------------------------------- /src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { provideHttpClient, withFetch, withInterceptorsFromDi } from '@angular/common/http'; 20 | import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; 21 | import { provideClientHydration } from '@angular/platform-browser'; 22 | import { 23 | PreloadAllModules, 24 | provideRouter, 25 | withEnabledBlockingInitialNavigation, 26 | withPreloading, 27 | withRouterConfig 28 | } from '@angular/router'; 29 | // eslint-disable-next-line import/no-unassigned-import 30 | import '@angular/common/locales/global/zh'; 31 | 32 | import { provideApplicationInitializer } from './app.initializer'; 33 | import { routes } from './app.routes'; 34 | 35 | export const appConfig: ApplicationConfig = { 36 | providers: [ 37 | provideZoneChangeDetection({ eventCoalescing: true }), 38 | provideRouter( 39 | routes, 40 | withPreloading(PreloadAllModules), 41 | withEnabledBlockingInitialNavigation(), 42 | withRouterConfig({ 43 | onSameUrlNavigation: 'reload' 44 | }) 45 | ), 46 | provideClientHydration(), 47 | provideHttpClient(withFetch(), withInterceptorsFromDi()), 48 | provideApplicationInitializer({ defaultLanguage: 'en' }) 49 | ] 50 | }; 51 | -------------------------------------------------------------------------------- /src/app/app.i18n.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { HttpClient } from '@angular/common/http'; 20 | import { EnvironmentProviders, importProvidersFrom, makeEnvironmentProviders } from '@angular/core'; 21 | 22 | import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; 23 | import { TranslateHttpLoader } from '@ngx-translate/http-loader'; 24 | 25 | export const provideTranslate = (defaultLanguage: string): EnvironmentProviders => 26 | makeEnvironmentProviders([ 27 | importProvidersFrom( 28 | TranslateModule.forRoot({ 29 | defaultLanguage, 30 | loader: { 31 | provide: TranslateLoader, 32 | useFactory: (http: HttpClient) => new TranslateHttpLoader(http, 'assets/i18n/', '.json'), 33 | deps: [HttpClient] 34 | } 35 | }) 36 | ) 37 | ]); 38 | -------------------------------------------------------------------------------- /src/app/app.initializer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { APP_INITIALIZER, LOCALE_ID, Provider } from '@angular/core'; 20 | 21 | import { Language, LanguageService } from '@paimon/app/services/language.service'; 22 | import { LocalStorageService } from '@paimon/app/services/local-storage.service'; 23 | 24 | import { provideTranslate } from './app.i18n'; 25 | 26 | export const provideApplicationInitializer = (options: { defaultLanguage: Language }): Provider => { 27 | return [ 28 | provideTranslate(options.defaultLanguage), 29 | { 30 | provide: LOCALE_ID, 31 | useFactory: (localStorageService: LocalStorageService) => { 32 | return localStorageService.getLanguage(options.defaultLanguage); 33 | }, 34 | deps: [LocalStorageService] 35 | }, 36 | { 37 | provide: APP_INITIALIZER, 38 | useFactory: (languageService: LanguageService, language: Language) => () => { 39 | languageService.setLanguage(language); 40 | }, 41 | deps: [LanguageService, LOCALE_ID], 42 | multi: true 43 | } 44 | ]; 45 | }; 46 | -------------------------------------------------------------------------------- /src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { Routes } from '@angular/router'; 20 | 21 | import { DownloadsComponent, downloadsResolver } from '@paimon/app/routers/downloads/downloads.component'; 22 | import { HomeComponent } from '@paimon/app/routers/home/home.component'; 23 | import { SecurityComponent } from '@paimon/app/routers/security/security.component'; 24 | import { TeamComponent } from '@paimon/app/routers/team/team.component'; 25 | import { UsersComponent } from '@paimon/app/routers/users/users.component'; 26 | 27 | export const routes: Routes = [ 28 | { 29 | path: '', 30 | component: HomeComponent 31 | }, 32 | { 33 | path: 'blog', 34 | loadChildren: () => import('@paimon/app/routers/blog/blog.routes').then(m => m.blogRoutes) 35 | }, 36 | { 37 | path: 'team', 38 | component: TeamComponent 39 | }, 40 | { 41 | path: 'security', 42 | component: SecurityComponent 43 | }, 44 | { 45 | path: 'downloads', 46 | component: DownloadsComponent, 47 | resolve: { 48 | downloads: downloadsResolver 49 | } 50 | }, 51 | { 52 | path: 'users', 53 | component: UsersComponent 54 | }, 55 | { 56 | path: 'releases', 57 | loadChildren: () => import('@paimon/app/routers/releases/releases.routes').then(m => m.releasesRoutes) 58 | } 59 | ]; 60 | -------------------------------------------------------------------------------- /src/app/components/blog-simple-card/blog-simple-card.component.html: -------------------------------------------------------------------------------- 1 |
2 | 9 |
10 | {{ article.name }} 11 |
12 | 17 | Read More 18 | 19 |
20 | -------------------------------------------------------------------------------- /src/app/components/blog-simple-card/blog-simple-card.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgOptimizedImage } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; 21 | import { RouterLink } from '@angular/router'; 22 | 23 | import { TranslateModule } from '@ngx-translate/core'; 24 | import { BriefArticle } from '@paimon-markdown-parser/article'; 25 | 26 | @Component({ 27 | selector: 'paimon-blog-simple-card', 28 | standalone: true, 29 | imports: [NgOptimizedImage, TranslateModule, RouterLink], 30 | templateUrl: './blog-simple-card.component.html', 31 | changeDetection: ChangeDetectionStrategy.OnPush 32 | }) 33 | export class BlogSimpleCardComponent { 34 | @Input() article: BriefArticle; 35 | } 36 | -------------------------------------------------------------------------------- /src/app/components/click-outside/click-outside.directive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from '@angular/core'; 20 | 21 | @Directive({ 22 | selector: '[paimonClickOutside]', 23 | standalone: true 24 | }) 25 | export class ClickOutsideDirective { 26 | // id or className 27 | @Input() skipSelectors: string[] = []; 28 | @Output() clickOutsideChange = new EventEmitter(); 29 | 30 | constructor(private _elementRef: ElementRef) {} 31 | 32 | @HostListener('document:click', ['$event', '$event.target']) 33 | public onClick($event: MouseEvent, targetElement: HTMLDivElement): void { 34 | const isClickedInside = this._elementRef.nativeElement.contains(targetElement); 35 | // if need to skip elements with specific selectors 36 | const isSkipped = this.skipSelectors.some( 37 | selector => targetElement.classList.contains(selector) || targetElement.id === selector 38 | ); 39 | if (!isClickedInside && !isSkipped) { 40 | this.clickOutsideChange.emit(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/components/community-dropdown/community-dropdown.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; 20 | import { RouterLink } from '@angular/router'; 21 | 22 | import { TranslateModule } from '@ngx-translate/core'; 23 | import { BriefArticle } from '@paimon-markdown-parser/article'; 24 | 25 | import { BlogSimpleCardComponent } from '@paimon/app/components/blog-simple-card/blog-simple-card.component'; 26 | import { ArticleService } from '@paimon/app/services/article.service'; 27 | 28 | @Component({ 29 | selector: 'paimon-community-dropdown', 30 | standalone: true, 31 | imports: [TranslateModule, RouterLink, BlogSimpleCardComponent], 32 | templateUrl: './community-dropdown.component.html', 33 | changeDetection: ChangeDetectionStrategy.OnPush 34 | }) 35 | export class CommunityDropdownComponent implements OnInit { 36 | listOfArticle: BriefArticle[] = []; 37 | constructor( 38 | private articleService: ArticleService, 39 | private cdr: ChangeDetectorRef 40 | ) {} 41 | 42 | ngOnInit(): void { 43 | this.articleService.list().subscribe(data => { 44 | this.listOfArticle = (data || []).slice(0, 2); 45 | this.cdr.markForCheck(); 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/app/components/footer/footer.component.html: -------------------------------------------------------------------------------- 1 |
4 | Copyright © 2023 The Apache Software Foundation. Apache Paimon, Paimon, and its feather logo 5 | are trademarks of The Apache Software Foundation. 6 |
7 | -------------------------------------------------------------------------------- /src/app/components/footer/footer.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 20 | 21 | @Component({ 22 | selector: 'paimon-footer', 23 | standalone: true, 24 | templateUrl: './footer.component.html', 25 | changeDetection: ChangeDetectionStrategy.OnPush 26 | }) 27 | export class FooterComponent {} 28 | -------------------------------------------------------------------------------- /src/app/components/header/header.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | &.menu-open { 3 | .dropdown-menu { 4 | display: block; 5 | } 6 | } 7 | 8 | header { 9 | transition: background-color 0.3s ease; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/app/components/join-community/join-community.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgOptimizedImage } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 21 | 22 | import { TranslateModule } from '@ngx-translate/core'; 23 | 24 | @Component({ 25 | selector: 'paimon-join-community', 26 | standalone: true, 27 | imports: [NgOptimizedImage, TranslateModule], 28 | templateUrl: './join-community.component.html', 29 | changeDetection: ChangeDetectionStrategy.OnPush 30 | }) 31 | export class JoinCommunityComponent {} 32 | -------------------------------------------------------------------------------- /src/app/components/layout/layout.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /src/app/components/layout/layout.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 20 | 21 | import { HeaderComponent } from '@paimon/app/components/header/header.component'; 22 | 23 | @Component({ 24 | selector: 'paimon-layout', 25 | standalone: true, 26 | imports: [HeaderComponent], 27 | templateUrl: './layout.component.html', 28 | changeDetection: ChangeDetectionStrategy.OnPush 29 | }) 30 | export class LayoutComponent {} 31 | -------------------------------------------------------------------------------- /src/app/components/markdown-render/markdown-render.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | .markdown { 3 | img { 4 | max-width: 100%; 5 | max-height: 100%; 6 | margin: 0; 7 | } 8 | 9 | .code { 10 | width: 100%; 11 | overflow-x: auto; 12 | overflow-y: hidden; 13 | 14 | &::-webkit-scrollbar { 15 | width: 0; 16 | height: 0; 17 | } 18 | 19 | -ms-overflow-style: none; 20 | scrollbar-width: none; 21 | 22 | code { 23 | width: 100%; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/components/markdown-render/markdown-render.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | 6 |
7 | 13 |
14 | -------------------------------------------------------------------------------- /src/app/components/markdown-render/markdown-render.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { isPlatformBrowser } from '@angular/common'; 20 | import { 21 | ChangeDetectionStrategy, 22 | ChangeDetectorRef, 23 | Component, 24 | DestroyRef, 25 | inject, 26 | Input, 27 | OnInit, 28 | PLATFORM_ID 29 | } from '@angular/core'; 30 | import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; 31 | import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; 32 | import { fromEvent, startWith } from 'rxjs'; 33 | 34 | import { TOC } from '@paimon-markdown-parser/article'; 35 | 36 | import { AnchorComponent } from '@paimon/app/routers/blog/components/anchor/anchor.component'; 37 | 38 | @Component({ 39 | selector: 'paimon-markdown-render', 40 | standalone: true, 41 | imports: [AnchorComponent], 42 | templateUrl: './markdown-render.component.html', 43 | styleUrl: './markdown-render.component.css', 44 | changeDetection: ChangeDetectionStrategy.OnPush 45 | }) 46 | export class MarkdownRenderComponent implements OnInit { 47 | @Input() set html(content: string) { 48 | this.safeContent = this.sanitized.bypassSecurityTrustHtml(content); 49 | this.cdr.markForCheck(); 50 | } 51 | @Input() set toc(anchors: TOC[]) { 52 | this.anchors = this.getFlattenTreeFromTOC(anchors); 53 | this.cdr.markForCheck(); 54 | } 55 | safeContent: SafeHtml | null = null; 56 | anchors: TOC[] = []; 57 | showAnchor = false; 58 | 59 | private readonly destroyRef = inject(DestroyRef); 60 | private readonly platformId = inject(PLATFORM_ID); 61 | 62 | constructor( 63 | private sanitized: DomSanitizer, 64 | private cdr: ChangeDetectorRef 65 | ) {} 66 | 67 | ngOnInit(): void { 68 | if (isPlatformBrowser(this.platformId)) { 69 | fromEvent(window, 'scroll') 70 | .pipe(startWith(true), takeUntilDestroyed(this.destroyRef)) 71 | .subscribe(() => { 72 | const offsetY = window.scrollY || document.documentElement.scrollTop; 73 | this.showAnchor = offsetY > 280; 74 | this.cdr.markForCheck(); 75 | }); 76 | } 77 | } 78 | 79 | private getFlattenTreeFromTOC = (toc: TOC[]): TOC[] => { 80 | if (!toc.length) { 81 | return []; 82 | } else { 83 | const firstDepth = toc[0].depth; 84 | return toc.map(e => ({ 85 | ...e, 86 | depth: e.depth - firstDepth 87 | })); 88 | } 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /src/app/components/page-container/page-container.component.html: -------------------------------------------------------------------------------- 1 |
2 | 7 |
8 | 9 |
10 | 11 |
12 | -------------------------------------------------------------------------------- /src/app/components/page-container/page-container.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 20 | 21 | import { FooterComponent } from '@paimon/app/components/footer/footer.component'; 22 | 23 | @Component({ 24 | selector: 'paimon-page-container', 25 | standalone: true, 26 | imports: [FooterComponent], 27 | templateUrl: './page-container.component.html', 28 | changeDetection: ChangeDetectionStrategy.OnPush 29 | }) 30 | export class PageContainerComponent {} 31 | -------------------------------------------------------------------------------- /src/app/components/pipes/github-url.pipe.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { Pipe, PipeTransform } from '@angular/core'; 20 | 21 | @Pipe({ 22 | name: 'githubUrl', 23 | standalone: true 24 | }) 25 | export class GithubUrlPipe implements PipeTransform { 26 | readonly githubUrl = 'https://github.com/apache/paimon-website'; 27 | transform(segments: string[]): string { 28 | return `${this.githubUrl}/blob/master/main/${segments.join('/')}`; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/components/search-bar/search-bar.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgIf } from '@angular/common'; 20 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core'; 21 | import { FormsModule } from '@angular/forms'; 22 | import { RouterLink } from '@angular/router'; 23 | import { map } from 'rxjs'; 24 | 25 | import { TranslateModule } from '@ngx-translate/core'; 26 | import { BriefArticle } from '@paimon-markdown-parser/article'; 27 | 28 | import { ClickOutsideDirective } from '@paimon/app/components/click-outside/click-outside.directive'; 29 | import { DividerComponent } from '@paimon/app/components/ui-components'; 30 | import { ArticleService } from '@paimon/app/services/article.service'; 31 | 32 | @Component({ 33 | selector: 'paimon-search-bar', 34 | standalone: true, 35 | imports: [ClickOutsideDirective, DividerComponent, FormsModule, NgIf, RouterLink, TranslateModule], 36 | templateUrl: './search-bar.component.html', 37 | changeDetection: ChangeDetectionStrategy.OnPush 38 | }) 39 | export class SearchBarComponent { 40 | searchValue = ''; 41 | showSearchInput = false; 42 | listOfResult: BriefArticle[] = []; 43 | 44 | constructor( 45 | private cdr: ChangeDetectorRef, 46 | private articleService: ArticleService 47 | ) {} 48 | 49 | toggleSearchInput(visible: boolean): void { 50 | this.showSearchInput = visible; 51 | this.cdr.markForCheck(); 52 | } 53 | 54 | search(): void { 55 | this.articleService 56 | .list() 57 | .pipe( 58 | map(data => { 59 | return data.filter( 60 | item => 61 | item.name.toLowerCase().includes((this.searchValue || '').toLowerCase()) || 62 | item.authors.find(author => author.name?.toLowerCase()?.includes((this.searchValue || '').toLowerCase())) 63 | ); 64 | }) 65 | ) 66 | .subscribe(result => { 67 | this.listOfResult = result || []; 68 | this.cdr.markForCheck(); 69 | }); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/app/components/ui-components/components/divider/divider.component.html: -------------------------------------------------------------------------------- 1 |
2 | @if (direction === 'vertical') { 3 |
4 | } @else { 5 |
9 | } 10 |
11 | -------------------------------------------------------------------------------- /src/app/components/ui-components/components/divider/divider.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgClass } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; 21 | 22 | type DividerDirection = 'horizontal' | 'vertical'; 23 | 24 | @Component({ 25 | selector: 'paimon-divider', 26 | standalone: true, 27 | imports: [NgClass], 28 | templateUrl: './divider.component.html', 29 | changeDetection: ChangeDetectionStrategy.OnPush 30 | }) 31 | export class DividerComponent { 32 | @Input() direction: DividerDirection = 'vertical'; 33 | @Input() classNames = ''; 34 | } 35 | -------------------------------------------------------------------------------- /src/app/components/ui-components/components/dropdown-links/dropdown-links.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /src/app/components/ui-components/components/dropdown-links/dropdown-links.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgClass } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; 21 | import { RouterLink } from '@angular/router'; 22 | 23 | export interface DropdownOption { 24 | label: string; 25 | value: string | string[]; 26 | target?: string; 27 | } 28 | 29 | @Component({ 30 | selector: 'paimon-dropdown-links', 31 | standalone: true, 32 | imports: [NgClass, RouterLink], 33 | templateUrl: './dropdown-links.component.html', 34 | changeDetection: ChangeDetectionStrategy.OnPush, 35 | host: { 36 | ngSkipHydration: 'true' 37 | } 38 | }) 39 | export class DropdownLinksComponent { 40 | @Input() options: DropdownOption[] = []; 41 | 42 | protected isRouterLink(value: string | string[]): boolean { 43 | return Array.isArray(value); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/app/components/ui-components/components/pagination/pagination.component.html: -------------------------------------------------------------------------------- 1 |
2 | 9 | 18 | 19 | 20 | 26 | 27 | 28 | 34 | 35 | 36 | 37 | 38 | 39 | 65 | 72 | 81 | 82 | 83 | 89 | 90 | 91 | 97 | 98 | 99 | 100 | 101 |
102 | -------------------------------------------------------------------------------- /src/app/components/ui-components/components/switcher/switcher.component.html: -------------------------------------------------------------------------------- 1 |
2 | @for (item of options; track $index) { 3 | 7 | } 8 |
13 |
14 | -------------------------------------------------------------------------------- /src/app/components/ui-components/components/switcher/switcher.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; 20 | import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms'; 21 | import { Subject, takeUntil } from 'rxjs'; 22 | 23 | export interface SwitcherOption { 24 | label: string; 25 | value: string; 26 | } 27 | 28 | @Component({ 29 | selector: 'paimon-switcher', 30 | standalone: true, 31 | imports: [ReactiveFormsModule], 32 | templateUrl: './switcher.component.html', 33 | changeDetection: ChangeDetectionStrategy.OnPush, 34 | providers: [ 35 | { 36 | provide: NG_VALUE_ACCESSOR, 37 | multi: true, 38 | useExisting: SwitcherComponent 39 | } 40 | ] 41 | }) 42 | export class SwitcherComponent implements OnInit, OnDestroy, ControlValueAccessor { 43 | @Input() options: SwitcherOption[] = []; 44 | constructor(private cdr: ChangeDetectorRef) {} 45 | 46 | formControl = new FormControl(''); 47 | private destroy$ = new Subject(); 48 | 49 | get isLast(): boolean { 50 | return this.options.findIndex(v => v.value === this.formControl.value) === this.options.length - 1; 51 | } 52 | 53 | ngOnInit(): void { 54 | this.formControl.valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => { 55 | this.fnChange(value || ''); 56 | }); 57 | } 58 | 59 | ngOnDestroy(): void { 60 | this.destroy$.next(); 61 | this.destroy$.complete(); 62 | } 63 | 64 | // NG_VALUE_ACCESSOR 65 | writeValue(value: string): void { 66 | this.formControl.setValue(value, { emitEvent: false }); 67 | } 68 | fnChange: (v: string) => void = () => void 0; 69 | fnTouched: () => void = () => void 0; 70 | registerOnChange(fn: (v: string) => void): void { 71 | this.fnChange = fn; 72 | } 73 | registerOnTouched(fn: () => void): void { 74 | this.fnTouched = fn; 75 | } 76 | setDisabledState(disabled: boolean): void { 77 | if (disabled) { 78 | this.formControl.disable({ emitEvent: false }); 79 | } else { 80 | this.formControl.enable({ emitEvent: false }); 81 | } 82 | this.cdr.markForCheck(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/app/components/ui-components/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | export * from './public-api'; 20 | -------------------------------------------------------------------------------- /src/app/components/ui-components/public-api.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | export * from './components/divider/divider.component'; 20 | export * from './components/dropdown-links/dropdown-links.component'; 21 | export * from './components/switcher/switcher.component'; 22 | export * from './components/pagination/pagination.component'; 23 | -------------------------------------------------------------------------------- /src/app/interfaces/member.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | export interface Member { 20 | avatarId: string; 21 | name: string; 22 | github: string; 23 | } 24 | -------------------------------------------------------------------------------- /src/app/routers/blog/blog.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | @if (!!article) { 4 |
5 |
6 | {{ article.name }} 7 |
8 | 17 |
18 | } @else { 19 |
Learn about Paimon
20 | } 21 |
22 |
23 | 24 |
25 |
26 | -------------------------------------------------------------------------------- /src/app/routers/blog/blog.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component, DestroyRef, inject, OnInit } from '@angular/core'; 20 | import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; 21 | import { ActivatedRoute, NavigationEnd, Router, RouterOutlet } from '@angular/router'; 22 | import { filter, map, startWith } from 'rxjs'; 23 | 24 | import { TranslateModule } from '@ngx-translate/core'; 25 | import { ResolvedArticle } from '@paimon-markdown-parser/article'; 26 | 27 | import { PageContainerComponent } from '@paimon/app/components/page-container/page-container.component'; 28 | import { ArticleService } from '@paimon/app/services/article.service'; 29 | 30 | @Component({ 31 | selector: 'paimon-blog', 32 | standalone: true, 33 | imports: [PageContainerComponent, RouterOutlet, TranslateModule], 34 | templateUrl: './blog.component.html', 35 | changeDetection: ChangeDetectionStrategy.OnPush 36 | }) 37 | export class BlogComponent implements OnInit { 38 | article: ResolvedArticle | null = null; 39 | private readonly destroyRef = inject(DestroyRef); 40 | 41 | constructor( 42 | private activatedRoute: ActivatedRoute, 43 | private router: Router, 44 | private articleService: ArticleService 45 | ) {} 46 | 47 | ngOnInit(): void { 48 | this.router.events 49 | .pipe( 50 | filter(item => item instanceof NavigationEnd), 51 | startWith(true), 52 | map(() => true), 53 | takeUntilDestroyed(this.destroyRef) 54 | ) 55 | .subscribe(() => { 56 | const id = this.activatedRoute?.snapshot?.firstChild?.params?.['id']; 57 | if (id) { 58 | this.loadArticle(id); 59 | } else { 60 | this.article = null; 61 | } 62 | }); 63 | } 64 | 65 | private loadArticle(id: string): void { 66 | this.articleService.get(id).subscribe(article => { 67 | this.article = article; 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/app/routers/blog/blog.routes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { Routes } from '@angular/router'; 20 | 21 | import { BlogComponent } from '@paimon/app/routers/blog/blog.component'; 22 | import { PreloadGuard } from '@paimon/app/routers/blog/preload.guard'; 23 | import { BlogDetailComponent } from '@paimon/app/routers/blog/routers/blog-detail/blog-detail.component'; 24 | import { BlogListComponent } from '@paimon/app/routers/blog/routers/blog-list/blog-list.component'; 25 | 26 | export const blogRoutes: Routes = [ 27 | { 28 | path: '', 29 | component: BlogComponent, 30 | children: [ 31 | { 32 | path: '', 33 | component: BlogListComponent 34 | }, 35 | { 36 | path: ':id', 37 | canActivate: [PreloadGuard], 38 | component: BlogDetailComponent 39 | }, 40 | { 41 | path: '**', 42 | pathMatch: 'full', 43 | redirectTo: '' 44 | } 45 | ] 46 | } 47 | ]; 48 | -------------------------------------------------------------------------------- /src/app/routers/blog/components/anchor/anchor.component.html: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /src/app/routers/blog/components/anchor/anchor.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { isPlatformBrowser, NgClass, ViewportScroller } from '@angular/common'; 20 | import { 21 | ChangeDetectionStrategy, 22 | ChangeDetectorRef, 23 | Component, 24 | inject, 25 | Input, 26 | OnChanges, 27 | PLATFORM_ID 28 | } from '@angular/core'; 29 | 30 | import { TOC } from '@paimon-markdown-parser/article'; 31 | import GithubSlugger from 'github-slugger'; 32 | 33 | const githubSlugger = new GithubSlugger(); 34 | 35 | type DomObj = Record; 36 | 37 | @Component({ 38 | selector: 'paimon-anchor', 39 | standalone: true, 40 | imports: [NgClass], 41 | templateUrl: './anchor.component.html', 42 | changeDetection: ChangeDetectionStrategy.OnPush 43 | }) 44 | export class AnchorComponent implements OnChanges { 45 | @Input() links: TOC[] = []; 46 | @Input() classNames = 'top-6'; 47 | 48 | highLightId?: string | null; 49 | intersectionObserver?: IntersectionObserver; 50 | domShow: DomObj = {}; 51 | 52 | private readonly platformId = inject(PLATFORM_ID); 53 | 54 | constructor( 55 | private viewportScroller: ViewportScroller, 56 | private cdr: ChangeDetectorRef 57 | ) {} 58 | 59 | scrollTo(id: string | null, title: string): void { 60 | const convertId = id || githubSlugger.slug(title); 61 | this.viewportScroller.setOffset([0, 84]); 62 | this.viewportScroller.scrollToAnchor(convertId); 63 | } 64 | 65 | observe(): void { 66 | if (isPlatformBrowser(this.platformId)) { 67 | this.intersectionObserver?.disconnect(); 68 | this.intersectionObserver = new IntersectionObserver( 69 | entries => { 70 | for (const entry of entries) { 71 | this.domShow[entry.target.id] = entry.intersectionRatio; 72 | } 73 | const highlightItem = this.links.find(item => item.id && this.domShow[item.id] > 0); 74 | if (highlightItem) { 75 | this.highLightId = highlightItem.id; 76 | } 77 | this.cdr.markForCheck(); 78 | }, 79 | { 80 | threshold: [0, 0.5, 1], 81 | rootMargin: '-60px 0px' 82 | } 83 | ); 84 | this.links.forEach(item => { 85 | if (isPlatformBrowser(this.platformId) && window?.document) { 86 | const element = document.getElementById(item.id!); 87 | if (element) { 88 | this.intersectionObserver?.observe(element); 89 | } 90 | } 91 | }); 92 | } 93 | } 94 | 95 | ngOnChanges(): void { 96 | this.observe(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/app/routers/blog/components/blog-card/blog-card.component.html: -------------------------------------------------------------------------------- 1 |
2 |
{{ article.date | date: 'longDate' }}
3 | 4 | {{ article.name }} 5 | 6 |
{{ article.abstract }}
7 | 12 | Read More 13 | 14 |
15 | -------------------------------------------------------------------------------- /src/app/routers/blog/components/blog-card/blog-card.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { DatePipe } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; 21 | import { RouterLink } from '@angular/router'; 22 | 23 | import { TranslateModule } from '@ngx-translate/core'; 24 | import { BriefArticle } from '@paimon-markdown-parser/article'; 25 | 26 | @Component({ 27 | selector: 'paimon-blog-card', 28 | standalone: true, 29 | imports: [DatePipe, RouterLink, TranslateModule], 30 | templateUrl: './blog-card.component.html', 31 | changeDetection: ChangeDetectionStrategy.OnPush 32 | }) 33 | export class BlogCardComponent { 34 | @Input() article: BriefArticle; 35 | } 36 | -------------------------------------------------------------------------------- /src/app/routers/blog/components/blog-detail-footer/blog-detail-footer.component.html: -------------------------------------------------------------------------------- 1 | 37 | -------------------------------------------------------------------------------- /src/app/routers/blog/components/blog-detail-footer/blog-detail-footer.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; 20 | import { RouterLink } from '@angular/router'; 21 | 22 | @Component({ 23 | selector: 'paimon-blog-detail-footer', 24 | standalone: true, 25 | imports: [RouterLink], 26 | templateUrl: './blog-detail-footer.component.html', 27 | changeDetection: ChangeDetectionStrategy.OnPush 28 | }) 29 | export class BlogDetailFooterComponent { 30 | @Input() preName: undefined | string; 31 | @Input() preUrl: Array = []; 32 | @Input() nextName: undefined | string; 33 | @Input() nextUrl: Array = []; 34 | } 35 | -------------------------------------------------------------------------------- /src/app/routers/blog/preload.guard.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { Injectable } from '@angular/core'; 20 | import { ActivatedRouteSnapshot, CanActivate, GuardResult, MaybeAsync } from '@angular/router'; 21 | import { map, Observable, of } from 'rxjs'; 22 | import { catchError } from 'rxjs/operators'; 23 | 24 | import { ArticleService } from '@paimon/app/services/article.service'; 25 | 26 | @Injectable({ 27 | providedIn: 'root' 28 | }) 29 | export class PreloadGuard implements CanActivate { 30 | constructor(private articleService: ArticleService) {} 31 | 32 | preload(id: string): Observable { 33 | return this.articleService.get(id).pipe( 34 | map(() => true), 35 | catchError(() => of(false)) 36 | ); 37 | } 38 | 39 | canActivate(route: ActivatedRouteSnapshot): MaybeAsync { 40 | return this.preload(route.params?.['id']); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/app/routers/blog/routers/blog-detail/blog-detail.component.html: -------------------------------------------------------------------------------- 1 | @if (article) { 2 | 3 |
4 |
    5 |
  1. 6 | 14 | 19 | 20 | 21 | 26 | Learn about Paimon 27 | 28 | 40 | 41 | 42 |
  2. 43 |
  3. 44 | {{ article.name }} 45 |
  4. 46 |
47 |
48 |
49 | 55 |
56 |
57 | } 58 | -------------------------------------------------------------------------------- /src/app/routers/blog/routers/blog-detail/blog-detail.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { isPlatformBrowser } from '@angular/common'; 20 | import { 21 | ChangeDetectionStrategy, 22 | ChangeDetectorRef, 23 | Component, 24 | DestroyRef, 25 | inject, 26 | OnInit, 27 | PLATFORM_ID 28 | } from '@angular/core'; 29 | import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; 30 | import { ActivatedRoute, RouterLink } from '@angular/router'; 31 | 32 | import { TranslateModule } from '@ngx-translate/core'; 33 | import { ResolvedArticle } from '@paimon-markdown-parser/article'; 34 | 35 | import { MarkdownRenderComponent } from '@paimon/app/components/markdown-render/markdown-render.component'; 36 | import { AnchorComponent } from '@paimon/app/routers/blog/components/anchor/anchor.component'; 37 | import { BlogDetailFooterComponent } from '@paimon/app/routers/blog/components/blog-detail-footer/blog-detail-footer.component'; 38 | import { ArticleService } from '@paimon/app/services/article.service'; 39 | 40 | @Component({ 41 | selector: 'paimon-blog-detail', 42 | standalone: true, 43 | imports: [RouterLink, AnchorComponent, BlogDetailFooterComponent, MarkdownRenderComponent, TranslateModule], 44 | templateUrl: './blog-detail.component.html', 45 | changeDetection: ChangeDetectionStrategy.OnPush 46 | }) 47 | export class BlogDetailComponent implements OnInit { 48 | article: ResolvedArticle | null = null; 49 | 50 | private readonly destroyRef = inject(DestroyRef); 51 | private readonly platformId = inject(PLATFORM_ID); 52 | 53 | constructor( 54 | private articleService: ArticleService, 55 | private activatedRoute: ActivatedRoute, 56 | private cdr: ChangeDetectorRef 57 | ) {} 58 | 59 | ngOnInit(): void { 60 | this.activatedRoute.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(({ id }) => { 61 | if (isPlatformBrowser(this.platformId)) { 62 | window.scrollTo({ 63 | top: 0, 64 | left: 0, 65 | behavior: 'auto' 66 | }); 67 | } 68 | this.articleService.get(id).subscribe(article => { 69 | this.article = article; 70 | this.cdr.markForCheck(); 71 | }); 72 | }); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/app/routers/blog/routers/blog-list/blog-list.component.html: -------------------------------------------------------------------------------- 1 | @if (listOfCategories.length > 0) { 2 |
3 |
11 | All 12 |
13 | @for (item of listOfCategories; track $index) { 14 |
21 | {{ item }} 22 |
23 | } 24 |
25 | } 26 | @if (listOfShownArticles.length) { 27 |
28 | 38 |
39 |
40 | @for (item of listOfShownArticles; track $index) { 41 | 42 | } 43 |
44 |
45 | 52 |
53 |
54 |
55 | } @else { 56 |
No Post found
57 | } 58 | -------------------------------------------------------------------------------- /src/app/routers/blog/routers/blog-list/blog-list.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; 20 | import { RouterLink } from '@angular/router'; 21 | 22 | import { TranslateModule } from '@ngx-translate/core'; 23 | import { BriefArticle } from '@paimon-markdown-parser/article'; 24 | 25 | import { PageContainerComponent } from '@paimon/app/components/page-container/page-container.component'; 26 | import { PaginationComponent } from '@paimon/app/components/ui-components'; 27 | import { BlogCardComponent } from '@paimon/app/routers/blog/components/blog-card/blog-card.component'; 28 | import { ArticleService } from '@paimon/app/services/article.service'; 29 | 30 | @Component({ 31 | selector: 'paimon-blog-list', 32 | standalone: true, 33 | imports: [PageContainerComponent, PaginationComponent, BlogCardComponent, RouterLink, TranslateModule], 34 | templateUrl: './blog-list.component.html', 35 | changeDetection: ChangeDetectionStrategy.OnPush 36 | }) 37 | export class BlogListComponent implements OnInit { 38 | total = 0; 39 | pageIndex = 1; 40 | pageSize = 5; 41 | latestPostsPageSize = 10; 42 | selectedCategory = ''; 43 | 44 | listOfArticles: BriefArticle[] = []; 45 | listOfShownArticles: BriefArticle[] = []; 46 | listOfLatestArticles: BriefArticle[] = []; 47 | listOfCategories: string[] = []; 48 | 49 | constructor( 50 | private articleService: ArticleService, 51 | private cdr: ChangeDetectorRef 52 | ) {} 53 | 54 | ngOnInit(): void { 55 | this.articleService.list().subscribe(data => { 56 | this.total = data.length; 57 | this.listOfLatestArticles = data.slice(0, this.latestPostsPageSize); 58 | this.listOfShownArticles = data.slice(0, this.pageSize); 59 | this.listOfArticles = data; 60 | this.listOfCategories = this.articleService.getCategories(data); 61 | this.cdr.markForCheck(); 62 | }); 63 | } 64 | 65 | updateShown(): void { 66 | const filteredArticles = this.listOfArticles.filter( 67 | a => !this.selectedCategory || a.categories.includes(this.selectedCategory) 68 | ); 69 | const startIndex = (this.pageIndex - 1) * this.pageSize; 70 | this.listOfLatestArticles = filteredArticles.slice(0, this.latestPostsPageSize); 71 | this.listOfShownArticles = filteredArticles.slice(startIndex, startIndex + this.pageSize); 72 | this.total = filteredArticles.length; 73 | } 74 | 75 | categoryChange(value: string): void { 76 | this.pageIndex = 1; 77 | this.selectedCategory = value; 78 | this.updateShown(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/app/routers/downloads/downloads.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
Downloads
4 |
5 |
6 | @if (downloads) { 7 | 8 | 30 | 31 | } 32 |
33 |
34 | -------------------------------------------------------------------------------- /src/app/routers/downloads/downloads.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit } from '@angular/core'; 20 | import { ActivatedRoute, ResolveFn } from '@angular/router'; 21 | 22 | import { ResolvedDocument } from '@paimon-markdown-parser/document'; 23 | 24 | import { MarkdownRenderComponent } from '@paimon/app/components/markdown-render/markdown-render.component'; 25 | import { PageContainerComponent } from '@paimon/app/components/page-container/page-container.component'; 26 | import { GithubUrlPipe } from '@paimon/app/components/pipes/github-url.pipe'; 27 | import { DocumentService } from '@paimon/app/services/document.service'; 28 | 29 | export const downloadsResolver: ResolveFn = () => { 30 | const documentService = inject(DocumentService); 31 | return documentService.getDownloads(); 32 | }; 33 | 34 | @Component({ 35 | selector: 'paimon-downloads', 36 | standalone: true, 37 | imports: [PageContainerComponent, MarkdownRenderComponent, GithubUrlPipe], 38 | templateUrl: './downloads.component.html', 39 | changeDetection: ChangeDetectionStrategy.OnPush 40 | }) 41 | export class DownloadsComponent implements OnInit { 42 | downloads: ResolvedDocument | null = null; 43 | constructor( 44 | private activatedRoute: ActivatedRoute, 45 | private cdr: ChangeDetectorRef 46 | ) {} 47 | 48 | ngOnInit(): void { 49 | this.activatedRoute.data.subscribe(({ downloads }) => { 50 | this.downloads = downloads; 51 | this.cdr.markForCheck(); 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/routers/home/components/about/about.component.html: -------------------------------------------------------------------------------- 1 |
2 | ABOUT US 3 |
4 | One Storage for All Your Data 5 |
6 | Architecture 7 |
8 | -------------------------------------------------------------------------------- /src/app/routers/home/components/about/about.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 20 | 21 | import { TranslateModule } from '@ngx-translate/core'; 22 | 23 | @Component({ 24 | selector: 'paimon-about', 25 | standalone: true, 26 | imports: [TranslateModule], 27 | templateUrl: './about.component.html', 28 | changeDetection: ChangeDetectionStrategy.OnPush 29 | }) 30 | export class AboutComponent {} 31 | -------------------------------------------------------------------------------- /src/app/routers/home/components/key-features/key-features.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgOptimizedImage } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 21 | 22 | import { TranslateModule } from '@ngx-translate/core'; 23 | 24 | @Component({ 25 | selector: 'paimon-key-features', 26 | standalone: true, 27 | imports: [NgOptimizedImage, TranslateModule], 28 | templateUrl: './key-features.component.html', 29 | changeDetection: ChangeDetectionStrategy.OnPush 30 | }) 31 | export class KeyFeaturesComponent {} 32 | -------------------------------------------------------------------------------- /src/app/routers/home/components/overview/overview.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | .bg-container { 3 | margin: -64px -32px 0 -32px; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/app/routers/home/components/overview/overview.component.html: -------------------------------------------------------------------------------- 1 |
4 |
Apache Paimon™
5 |
6 | 61 |
62 | -------------------------------------------------------------------------------- /src/app/routers/home/components/overview/overview.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 20 | 21 | import { TranslateModule } from '@ngx-translate/core'; 22 | 23 | import { DropdownLinksComponent } from '@paimon/app/components/ui-components/components/dropdown-links/dropdown-links.component'; 24 | 25 | @Component({ 26 | selector: 'paimon-overview', 27 | standalone: true, 28 | imports: [DropdownLinksComponent, TranslateModule], 29 | templateUrl: './overview.component.html', 30 | styleUrl: './overview.component.css', 31 | changeDetection: ChangeDetectionStrategy.OnPush 32 | }) 33 | export class OverviewComponent {} 34 | -------------------------------------------------------------------------------- /src/app/routers/home/components/team/team.component.html: -------------------------------------------------------------------------------- 1 |
2 |
5 |
6 | TEAM 7 |
8 |
Our Members
9 |
10 | 15 | LEARN MORE 16 | 17 |
18 |
21 |
24 | @for (item of listOfTeam; track $index) { 25 | 31 |
32 | 39 |
40 |
41 | } 42 |
43 |
44 |
45 |
46 | -------------------------------------------------------------------------------- /src/app/routers/home/components/team/team.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgOptimizedImage } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 21 | 22 | import { TranslateModule } from '@ngx-translate/core'; 23 | 24 | import { listOfCommitters, listOfPMCs } from '@paimon/app/tokens/member'; 25 | 26 | @Component({ 27 | selector: 'paimon-team', 28 | standalone: true, 29 | imports: [NgOptimizedImage, TranslateModule], 30 | templateUrl: './team.component.html', 31 | changeDetection: ChangeDetectionStrategy.OnPush 32 | }) 33 | export class TeamComponent { 34 | readonly listOfTeam = [...listOfPMCs, ...listOfCommitters]; 35 | } 36 | -------------------------------------------------------------------------------- /src/app/routers/home/components/whosusing/whosusing.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | img { 3 | max-width: 100%; 4 | } 5 | 6 | .gradient-shadow { 7 | -webkit-mask-image: linear-gradient(90deg, transparent, #F4F4F6 20%, #F4F4F6 80%, transparent); 8 | mask-image: linear-gradient(90deg, transparent, #F4F4F6 20%, #F4F4F6 80%, transparent); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/app/routers/home/components/whosusing/whosusing.component.html: -------------------------------------------------------------------------------- 1 |
2 | TRUSTED BY ENTERPRISES 3 |
Who's Using
4 |
5 |
6 | Various companies and organizations are using Paimon for production and commercial products. 7 |
8 |
9 | Are you using this project? 10 | 15 | Add your company 16 | 17 |
18 |
19 | 20 | 21 | 52 | 53 | 54 |
55 |
58 | @for (item of listOfUsers; track $index) { 59 |
60 | 67 |
68 | } 69 |
70 |
71 |
72 | -------------------------------------------------------------------------------- /src/app/routers/home/components/whosusing/whosusing.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgOptimizedImage } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; 21 | 22 | import { TranslateModule } from '@ngx-translate/core'; 23 | 24 | import { WHO_IS_USING } from '@paimon/app/tokens/users'; 25 | 26 | @Component({ 27 | selector: 'paimon-whosusing', 28 | standalone: true, 29 | imports: [NgOptimizedImage, TranslateModule], 30 | templateUrl: './whosusing.component.html', 31 | styleUrl: './whosusing.component.css', 32 | preserveWhitespaces: true, 33 | changeDetection: ChangeDetectionStrategy.OnPush 34 | }) 35 | export class WhosusingComponent { 36 | readonly listOfUsers = inject(WHO_IS_USING); 37 | } 38 | -------------------------------------------------------------------------------- /src/app/routers/home/home.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 |
10 | 11 |
12 | -------------------------------------------------------------------------------- /src/app/routers/home/home.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 20 | 21 | import { FooterComponent } from '@paimon/app/components/footer/footer.component'; 22 | import { JoinCommunityComponent } from '@paimon/app/components/join-community/join-community.component'; 23 | import { AboutComponent } from '@paimon/app/routers/home/components/about/about.component'; 24 | import { KeyFeaturesComponent } from '@paimon/app/routers/home/components/key-features/key-features.component'; 25 | import { OverviewComponent } from '@paimon/app/routers/home/components/overview/overview.component'; 26 | import { TeamComponent } from '@paimon/app/routers/home/components/team/team.component'; 27 | import { WhosusingComponent } from '@paimon/app/routers/home/components/whosusing/whosusing.component'; 28 | 29 | @Component({ 30 | selector: 'paimon-home', 31 | standalone: true, 32 | imports: [ 33 | OverviewComponent, 34 | AboutComponent, 35 | KeyFeaturesComponent, 36 | WhosusingComponent, 37 | TeamComponent, 38 | JoinCommunityComponent, 39 | FooterComponent 40 | ], 41 | templateUrl: './home.component.html', 42 | changeDetection: ChangeDetectionStrategy.OnPush 43 | }) 44 | export class HomeComponent {} 45 | -------------------------------------------------------------------------------- /src/app/routers/releases/releases.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
Releases
4 |
5 |
6 | 7 |
8 |
9 | -------------------------------------------------------------------------------- /src/app/routers/releases/releases.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 20 | import { RouterOutlet } from '@angular/router'; 21 | 22 | import { PageContainerComponent } from '@paimon/app/components/page-container/page-container.component'; 23 | 24 | @Component({ 25 | selector: 'paimon-releases', 26 | standalone: true, 27 | imports: [RouterOutlet, PageContainerComponent], 28 | templateUrl: './releases.component.html', 29 | changeDetection: ChangeDetectionStrategy.OnPush 30 | }) 31 | export class ReleasesComponent {} 32 | -------------------------------------------------------------------------------- /src/app/routers/releases/releases.guard.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { inject } from '@angular/core'; 20 | import { CanActivateFn, Router } from '@angular/router'; 21 | import { map } from 'rxjs'; 22 | 23 | import { DocumentService } from '@paimon/app/services/document.service'; 24 | 25 | export const canActivateReleases: CanActivateFn = (route, state) => { 26 | const router = inject(Router); 27 | const documentService = inject(DocumentService); 28 | const urlTree = router.parseUrl(state.url); 29 | 30 | return documentService.listRelease().pipe( 31 | map(() => { 32 | const segments = urlTree.root.children['primary'].segments; 33 | if (segments.length === 2 && documentService.releases.has(segments[1].path)) { 34 | return true; 35 | } 36 | 37 | // if the version is not found, redirect to the latest version 38 | return router.createUrlTree(['/releases', documentService.latestVersion]); 39 | }) 40 | ); 41 | }; 42 | -------------------------------------------------------------------------------- /src/app/routers/releases/releases.routes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { Routes } from '@angular/router'; 20 | 21 | import { ReleasesComponent } from '@paimon/app/routers/releases/releases.component'; 22 | import { canActivateReleases } from '@paimon/app/routers/releases/releases.guard'; 23 | import { ReleaseDetailComponent } from '@paimon/app/routers/releases/routers/release-detail/release-detail.component'; 24 | 25 | export const releasesRoutes: Routes = [ 26 | { 27 | path: '', 28 | component: ReleasesComponent, 29 | canActivate: [canActivateReleases], 30 | children: [ 31 | { 32 | path: ':version', 33 | component: ReleaseDetailComponent 34 | } 35 | ] 36 | } 37 | ]; 38 | -------------------------------------------------------------------------------- /src/app/routers/releases/routers/release-detail/release-detail.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { isPlatformBrowser } from '@angular/common'; 20 | import { 21 | ChangeDetectionStrategy, 22 | ChangeDetectorRef, 23 | Component, 24 | DestroyRef, 25 | inject, 26 | OnInit, 27 | PLATFORM_ID 28 | } from '@angular/core'; 29 | import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; 30 | import { ActivatedRoute, RouterLink } from '@angular/router'; 31 | 32 | import { ResolvedDocument } from '@paimon-markdown-parser/document'; 33 | 34 | import { MarkdownRenderComponent } from '@paimon/app/components/markdown-render/markdown-render.component'; 35 | import { GithubUrlPipe } from '@paimon/app/components/pipes/github-url.pipe'; 36 | import { DropdownLinksComponent, DropdownOption } from '@paimon/app/components/ui-components'; 37 | import { DocumentService } from '@paimon/app/services/document.service'; 38 | 39 | @Component({ 40 | selector: 'paimon-release-detail', 41 | standalone: true, 42 | imports: [RouterLink, DropdownLinksComponent, MarkdownRenderComponent, GithubUrlPipe], 43 | templateUrl: './release-detail.component.html', 44 | changeDetection: ChangeDetectionStrategy.OnPush 45 | }) 46 | export class ReleaseDetailComponent implements OnInit { 47 | release: ResolvedDocument | null; 48 | links: DropdownOption[] = []; 49 | 50 | private readonly destroyRef = inject(DestroyRef); 51 | private readonly platformId = inject(PLATFORM_ID); 52 | 53 | get latestVersion(): string { 54 | return this.documentService.latestVersion; 55 | } 56 | 57 | constructor( 58 | private documentService: DocumentService, 59 | private activatedRoute: ActivatedRoute, 60 | private cdr: ChangeDetectorRef 61 | ) {} 62 | 63 | ngOnInit(): void { 64 | this.documentService.listRelease().subscribe(releases => { 65 | this.links = releases.map(release => ({ 66 | label: release.version, 67 | value: ['/', 'releases', release.version] 68 | })); 69 | this.cdr.markForCheck(); 70 | }); 71 | 72 | this.activatedRoute.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(({ version }) => { 73 | if (isPlatformBrowser(this.platformId)) { 74 | window.scrollTo({ 75 | top: 0, 76 | left: 0, 77 | behavior: 'auto' 78 | }); 79 | } 80 | this.documentService.getRelease(version).subscribe(release => { 81 | this.release = release; 82 | this.cdr.markForCheck(); 83 | }); 84 | this.documentService.activeVersion$.next(version); 85 | }); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/app/routers/security/security.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
Apache Paimon™ Security
4 |
5 |
6 |
7 |

8 | If you have apprehensions regarding Paimon's security or you discover vulnerability or 9 | potential threat, don't hesitate to get in touch with the Apache Security Team by dropping a 10 | mail at security@apache.org. In the mail, specify the project name Paimon with the 11 | description of the issue or potential threat. You are also urged to recommend the way to 12 | reproduce and replicate the issue. The security team and the Paimon community will get back 13 | to you after assessing and analysing the findings. 14 |

15 |

16 | PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it 17 | on public domain. 18 |

19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /src/app/routers/security/security.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 20 | 21 | import { PageContainerComponent } from '@paimon/app/components/page-container/page-container.component'; 22 | 23 | @Component({ 24 | selector: 'paimon-security', 25 | standalone: true, 26 | imports: [PageContainerComponent], 27 | templateUrl: './security.component.html', 28 | changeDetection: ChangeDetectionStrategy.OnPush 29 | }) 30 | export class SecurityComponent {} 31 | -------------------------------------------------------------------------------- /src/app/routers/team/team.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
Our Team
4 |
5 |
6 |
7 |
PMC Members
8 |
9 |
10 |
11 | @for (item of listOfPMCs; track $index) { 12 | 30 | } 31 |
32 |
33 |
34 |
35 |
36 |
37 |
Committers
38 |
39 | (Apart from PMC members) 40 |
41 |
42 |
43 |
44 |
45 | @for (item of listOfCommitters; track $index) { 46 | 64 | } 65 |
66 |
67 |
68 |
69 |
70 | 71 |
72 |
73 |
74 | -------------------------------------------------------------------------------- /src/app/routers/team/team.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgOptimizedImage } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 21 | 22 | import { TranslateModule } from '@ngx-translate/core'; 23 | 24 | import { JoinCommunityComponent } from '@paimon/app/components/join-community/join-community.component'; 25 | import { PageContainerComponent } from '@paimon/app/components/page-container/page-container.component'; 26 | import { listOfCommitters, listOfPMCs } from '@paimon/app/tokens/member'; 27 | 28 | @Component({ 29 | selector: 'paimon-team', 30 | standalone: true, 31 | imports: [PageContainerComponent, NgOptimizedImage, JoinCommunityComponent, TranslateModule], 32 | templateUrl: './team.component.html', 33 | changeDetection: ChangeDetectionStrategy.OnPush 34 | }) 35 | export class TeamComponent { 36 | protected readonly listOfPMCs = listOfPMCs; 37 | protected readonly listOfCommitters = listOfCommitters; 38 | } 39 | -------------------------------------------------------------------------------- /src/app/routers/users/users.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
Who's Using
4 |
5 | 6 | Various companies and organizations are using Paimon for production and commercial products. 7 | 8 | Are you using this project? 9 | 14 | Add your company 15 | 16 |
17 |
18 |
19 |
20 |
23 | @for (item of listOfUsers; track $index) { 24 |
25 | 32 |
33 | } 34 |
35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /src/app/routers/users/users.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { NgOptimizedImage } from '@angular/common'; 20 | import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; 21 | 22 | import { TranslateModule } from '@ngx-translate/core'; 23 | 24 | import { PageContainerComponent } from '@paimon/app/components/page-container/page-container.component'; 25 | import { WHO_IS_USING } from '@paimon/app/tokens/users'; 26 | 27 | @Component({ 28 | selector: 'paimon-users', 29 | standalone: true, 30 | imports: [PageContainerComponent, TranslateModule, NgOptimizedImage], 31 | templateUrl: './users.component.html', 32 | changeDetection: ChangeDetectionStrategy.OnPush 33 | }) 34 | export class UsersComponent { 35 | readonly listOfUsers = inject(WHO_IS_USING); 36 | } 37 | -------------------------------------------------------------------------------- /src/app/services/article.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { HttpClient } from '@angular/common/http'; 20 | import { Injectable } from '@angular/core'; 21 | import { combineLatest, map, Observable, of } from 'rxjs'; 22 | import { shareReplay, tap } from 'rxjs/operators'; 23 | 24 | import { BriefArticle, ResolvedArticle } from '@paimon-markdown-parser/article'; 25 | 26 | import { BaseUrlService } from '@paimon/app/services/base-url.service'; 27 | import { LanguageService } from '@paimon/app/services/language.service'; 28 | 29 | @Injectable({ 30 | providedIn: 'root' 31 | }) 32 | export class ArticleService { 33 | briefArticles$: Observable | null = null; 34 | articles = new Map(); 35 | 36 | get baseUrl(): string { 37 | return `${this.baseUrlService.getBaseUrl()}/metadata`; 38 | } 39 | 40 | constructor( 41 | private httpClient: HttpClient, 42 | private baseUrlService: BaseUrlService, 43 | private languageService: LanguageService 44 | ) {} 45 | 46 | getCategories(articles: BriefArticle[], maxCount = 0): string[] { 47 | const categoryMap = new Map(); 48 | articles.forEach(item => { 49 | item.categories.forEach(key => { 50 | const value = categoryMap.get(key); 51 | if (!value) { 52 | categoryMap.set(key, 1); 53 | } else { 54 | categoryMap.set(key, value + 1); 55 | } 56 | }); 57 | }); 58 | return Array.from(categoryMap) 59 | .sort(([, pc], [, nc]) => nc - pc) 60 | .filter(([, c]) => c > maxCount) 61 | .map(([v]) => v); 62 | } 63 | 64 | list(): Observable { 65 | if (this.briefArticles$) { 66 | return this.briefArticles$; 67 | } else { 68 | const query$ = this.httpClient.get(`${this.baseUrl}/articles/list.json`); 69 | this.briefArticles$ = combineLatest([query$, this.languageService.languageChanged()]).pipe( 70 | map(([data, language]) => data.filter(v => !v.languages || v.languages.includes(language))), 71 | shareReplay(1) 72 | ); 73 | return this.briefArticles$; 74 | } 75 | } 76 | 77 | get(id: string): Observable { 78 | const cacheArticle = this.articles.get(id); 79 | if (cacheArticle) { 80 | return of(cacheArticle); 81 | } else { 82 | return this.httpClient.get(`${this.baseUrl}/articles/${id}.json`).pipe( 83 | tap(article => { 84 | this.articles.set(id, article); 85 | }) 86 | ); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/app/services/base-url.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { isPlatformBrowser } from '@angular/common'; 20 | import { inject, Injectable, PLATFORM_ID } from '@angular/core'; 21 | 22 | @Injectable({ 23 | providedIn: 'root' 24 | }) 25 | export class BaseUrlService { 26 | private readonly platformId = inject(PLATFORM_ID); 27 | 28 | getBaseUrl(): string { 29 | if (isPlatformBrowser(this.platformId)) { 30 | return './assets'; 31 | } else { 32 | return 'http://localhost:8801/assets'; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/services/document.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { HttpClient } from '@angular/common/http'; 20 | import { Injectable } from '@angular/core'; 21 | import { Observable, of, Subject } from 'rxjs'; 22 | import { shareReplay, tap } from 'rxjs/operators'; 23 | 24 | import { BriefRelease, ResolvedDocument } from '@paimon-markdown-parser/document'; 25 | 26 | import { BaseUrlService } from '@paimon/app/services/base-url.service'; 27 | 28 | @Injectable({ 29 | providedIn: 'root' 30 | }) 31 | export class DocumentService { 32 | briefReleases$: Observable | null = null; 33 | releases = new Map(); 34 | latestVersion: string; 35 | activeVersion$ = new Subject(); 36 | 37 | get baseUrl(): string { 38 | return `${this.baseUrlService.getBaseUrl()}/docs`; 39 | } 40 | 41 | constructor( 42 | private httpClient: HttpClient, 43 | private baseUrlService: BaseUrlService 44 | ) {} 45 | 46 | getDownloads(): Observable { 47 | return this.httpClient.get(`${this.baseUrl}/downloads.json`); 48 | } 49 | 50 | listRelease(): Observable { 51 | if (this.briefReleases$) { 52 | return this.briefReleases$; 53 | } else { 54 | const query$ = this.httpClient.get(`${this.baseUrl}/releases.json`).pipe( 55 | tap(releases => { 56 | this.latestVersion = releases[0]?.version; 57 | // initialize the cache with available versions 58 | releases.forEach(release => { 59 | this.releases.set(release.version, null); 60 | }); 61 | }) 62 | ); 63 | this.briefReleases$ = query$.pipe(shareReplay(1)); 64 | return this.briefReleases$; 65 | } 66 | } 67 | 68 | getRelease(version: string): Observable { 69 | const cacheRelease = this.releases.get(version); 70 | if (cacheRelease) { 71 | return of(cacheRelease); 72 | } else { 73 | return this.httpClient.get(`${this.baseUrl}/${version}.json`).pipe( 74 | tap(release => { 75 | this.releases.set(version, release); 76 | }) 77 | ); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/app/services/language.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { Injectable } from '@angular/core'; 20 | import { map, Observable, startWith } from 'rxjs'; 21 | 22 | import { TranslateService } from '@ngx-translate/core'; 23 | 24 | import { LocalStorageService } from '@paimon/app/services/local-storage.service'; 25 | 26 | export type Language = 'zh' | 'en'; 27 | 28 | @Injectable({ 29 | providedIn: 'root' 30 | }) 31 | export class LanguageService { 32 | constructor( 33 | private translateService: TranslateService, 34 | private localStorageService: LocalStorageService 35 | ) {} 36 | 37 | get language(): Language { 38 | return this.translateService.currentLang as Language; 39 | } 40 | 41 | languageChanged(): Observable { 42 | return this.translateService.onLangChange.asObservable().pipe( 43 | map(event => event.lang as Language), 44 | startWith(this.language) 45 | ); 46 | } 47 | 48 | setLanguage(language: Language): void { 49 | this.translateService.use(language); 50 | this.localStorageService.setLanguage(language); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/app/services/local-storage.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { isPlatformBrowser } from '@angular/common'; 20 | import { inject, Injectable, PLATFORM_ID } from '@angular/core'; 21 | 22 | @Injectable({ 23 | providedIn: 'root' 24 | }) 25 | export class LocalStorageService { 26 | private readonly currentLangKey = 'paimon-website-language'; 27 | private readonly platformId = inject(PLATFORM_ID); 28 | 29 | setLanguage(lang: string): void { 30 | if (isPlatformBrowser(this.platformId) && window?.localStorage) { 31 | localStorage.setItem(this.currentLangKey, lang); 32 | } 33 | } 34 | 35 | getLanguage(fallback: string): string { 36 | if (isPlatformBrowser(this.platformId) && window?.localStorage) { 37 | return localStorage.getItem(this.currentLangKey) || fallback; 38 | } 39 | return fallback; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/app/tokens/member.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | import { Member } from '@paimon/app/interfaces/member'; 21 | 22 | export const listOfPMCs: Member[] = [ 23 | { 24 | avatarId: '9601882', 25 | name: 'Jingsong Lee (Chair)', 26 | github: 'JingsongLi' 27 | }, 28 | { 29 | avatarId: '5778611', 30 | name: 'Becket Qin', 31 | github: 'becketqin' 32 | }, 33 | { 34 | avatarId: '89049', 35 | name: 'Robert Metzger', 36 | github: 'rmetzger' 37 | }, 38 | { 39 | avatarId: '1727146', 40 | name: 'Stephan Ewen', 41 | github: 'StephanEwen' 42 | }, 43 | { 44 | avatarId: '6239804', 45 | name: 'Yu Li', 46 | github: 'carp84' 47 | }, 48 | { 49 | avatarId: '19909549', 50 | name: 'Caizhi Weng', 51 | github: 'tsreaper' 52 | }, 53 | { 54 | avatarId: '99001603', 55 | name: 'Feng Wang', 56 | github: 'wangfengpro' 57 | }, 58 | { 59 | avatarId: '10048174', 60 | name: 'Nicholas Jiang', 61 | github: 'SteNicholas' 62 | }, 63 | { 64 | avatarId: '5746567', 65 | name: 'Timo Walther', 66 | github: 'twalthr' 67 | }, 68 | { 69 | avatarId: '28703471', 70 | name: 'Fang Yong', 71 | github: 'FangYongs' 72 | }, 73 | { 74 | avatarId: '33053040', 75 | name: 'Zelin Yu', 76 | github: 'yuzelin' 77 | }, 78 | { 79 | avatarId: '10036681', 80 | name: 'Bi Yan', 81 | github: 'YannByron' 82 | } 83 | ]; 84 | 85 | export const listOfCommitters: Member[] = [ 86 | { 87 | avatarId: '37063904', 88 | name: 'Chong Zhuang', 89 | github: 'zhuangchong' 90 | }, 91 | { 92 | avatarId: '69444450', 93 | name: 'Ming Li', 94 | github: 'liming30' 95 | }, 96 | { 97 | avatarId: '41894543', 98 | name: 'Junhao Ye', 99 | github: 'leaves12138' 100 | }, 101 | { 102 | avatarId: '26704332', 103 | name: 'Guojun Li', 104 | github: 'schnappi17' 105 | }, 106 | { 107 | avatarId: '9486140', 108 | name: 'WenJun Min', 109 | github: 'Aitozi' 110 | }, 111 | { 112 | avatarId: '37108074', 113 | name: 'Xinyu Zou', 114 | github: 'Zouxxyy' 115 | } 116 | ]; 117 | -------------------------------------------------------------------------------- /src/app/tokens/users.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { InjectionToken } from '@angular/core'; 20 | 21 | export const WHO_IS_USING = new InjectionToken('WHO_IS_USING', { 22 | providedIn: 'root', 23 | factory: () => { 24 | return [ 25 | 'aliyun.png', 26 | 'bytedance.png', 27 | 'ximalaya.png', 28 | 'antgroup.png', 29 | 'zhongyuanbank.png', 30 | 'autohome.png', 31 | 'dustess.png', 32 | 'babeltime.png', 33 | 'tongchengtravel.png', 34 | 'xiaopeng.png', 35 | 'mihoyo.png', 36 | 'highlandhuanyu.png', 37 | 'ziroom.png', 38 | 'starrocks.png', 39 | 'kuayueexpress.png', 40 | 'selectdb.png', 41 | 'dinky.png', 42 | 'ververica.png', 43 | 'amoro.png', 44 | 'netEase-media.png', 45 | 'celerdata.png', 46 | 'aodong.png', 47 | 'unicom.png', 48 | 'wanglong.png', 49 | 'unicom-digital.png', 50 | 'zhihu.png', 51 | 'vivo.png', 52 | 'xgimi.png', 53 | 'yiou.png', 54 | 'bilibili.png', 55 | 'zto.png' 56 | ].map(img => { 57 | const largeHeight = ['highlandhuanyu.png', 'ziroom.png', 'dinky.png'].includes(img); 58 | const mediumHeight = ['aodong.png', 'yiou.png'].includes(img); 59 | return { 60 | label: img, 61 | src: `assets/users/${img}`, 62 | width: largeHeight ? 64 : mediumHeight ? 128 : 192, 63 | height: largeHeight ? 72 : mediumHeight ? 96 : 133 64 | }; 65 | }); 66 | } 67 | }); 68 | -------------------------------------------------------------------------------- /src/assets/i18n/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "(Apart from PMC members)": "(更多社区贡献者)", 3 | "@paimon.overview.description": "一种 Lake 格式,支持使用 Flink 和 Spark 构建实时 Lakehouse 架构,用于流式和批处理操作。创新地结合了 Lake 格式和 LSM 结构,将实时流式更新引入 Lake 架构。", 4 | "ABOUT US": "关于我们", 5 | "Add your company": "添加您的公司", 6 | "All": "全部", 7 | "Apache Paimon is developed by an open and friendly community. Everybody is cordially welcome to join the community and contribute to Apache Paimon.": "Apache Paimon 由一个开放而友好的社区开发,欢迎大家加入社区,为 Apache Paimon 做出贡献。", 8 | "Append Data Processing": "追加数据处理", 9 | "Append table (no primary-key) provides large scale batch and streaming processing capability. Supports compaction with z-order sorting.": "附加表(无主键)提供大规模批量和流式处理能力。支持使用 z 顺序排序的压缩", 10 | "Are you using this project?": "您正在使用这个项目吗?", 11 | "BLOG": "博客", 12 | "Based on indexes such as minmax, filter irrelevant files and provide high-performance queries, more indexes are being supported.": "基于 minmax 等索引,过滤不相关的文件并提供高性能查询,正在支持更多的索引", 13 | "Blog": "博客", 14 | "COMMUNITY": "社区", 15 | "Change-tracking Updates": "变更跟踪更新", 16 | "Committers": "提交者", 17 | "Community": "社区", 18 | "DOCUMENT": "文档", 19 | "DOCUMENTATION": "文档", 20 | "DOWNLOADS": "下载", 21 | "Data Lake Capabilities": "数据湖功能", 22 | "Defining Merge Engines, update records however you like. Deduplicate to keep last row, or partial-update, or aggregate records, or first-row, you decide.": "定义合并引擎,按你喜欢的方式更新记录。删除重复项以保留最后一行,或部分更新,或聚合记录,或第一行,由你决定", 23 | "Defining changelog-producer, produce correct and complete changelog in updates for merge engines, simplifying your streaming analytics.": "定义 changelog-producer,为合并引擎的更新生成正确且完整的变更日志,简化您的流分析", 24 | "Developer guide": "开发者指南", 25 | "Flexible Updates": "灵活更新", 26 | "Get Started": "快速开始", 27 | "How to Contribute": "如何贡献", 28 | "Issue Tracking": "问题跟踪", 29 | "Join the Community": "加入社区", 30 | "Key Features": "主要特点", 31 | "LEARN MORE": "了解更多", 32 | "Latest Posts": "文章", 33 | "Learn about Paimon": "了解 Paimon", 34 | "Low cost, High reliability, Scalable metadata, Time Travel and Full Schema Evolution. All advantage as a data lake storage.": "低成本、高可靠性、可扩展元数据、时间旅行和完整模式演进。作为数据湖存储,所有优势均具备", 35 | "Mailing List": "邮件列表", 36 | "No Post found": "No Post found", 37 | "One Storage for All Your Data": "实时数据湖存储系统,存你想存,查你所需", 38 | "Open Menu": "展开菜单", 39 | "Our Members": "社区成员", 40 | "Our Team": "社区团队", 41 | "Overview": "概览", 42 | "PMC Members": "PMC 成员", 43 | "Primary-key table supports real-time streaming updates of large amounts of data. Real-time query within 1 minute.": "主键表支持海量数据实时流式更新,1分钟内实时查询", 44 | "Query Data Skipping": "查询数据跳过", 45 | "Quick Start": "快速开始", 46 | "RELEASES": "发行", 47 | "RESOURCES": "资源", 48 | "Read More": "阅读文章", 49 | "Real-time Updates": "实时更新", 50 | "Search within blog posts by title or author...": "搜索文章名称或作者查询博客...", 51 | "Slack Channel": "Slack 频道", 52 | "Source Code": "源代码", 53 | "TEAM": "团队", 54 | "TRUSTED BY ENTERPRISES": "深受企业信赖", 55 | "Various companies and organizations are using Paimon for production and commercial products.": "各种公司和组织都在使用 Paimon 进行生产和商业产品。", 56 | "WHY PAIMON": "为什么选择 PAIMON", 57 | "Who's Using": "谁在使用" 58 | } 59 | -------------------------------------------------------------------------------- /src/assets/icons/kf-3.svg: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/assets/icons/kf-6.svg: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/assets/icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/icons/logo.png -------------------------------------------------------------------------------- /src/assets/images/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/images/architecture.png -------------------------------------------------------------------------------- /src/assets/images/bg-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/images/bg-header.png -------------------------------------------------------------------------------- /src/assets/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/images/bg.png -------------------------------------------------------------------------------- /src/assets/images/blog-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/images/blog-bg.png -------------------------------------------------------------------------------- /src/assets/images/key-features-bg.svg: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/users/aliyun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/aliyun.png -------------------------------------------------------------------------------- /src/assets/users/amoro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/amoro.png -------------------------------------------------------------------------------- /src/assets/users/antgroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/antgroup.png -------------------------------------------------------------------------------- /src/assets/users/aodong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/aodong.png -------------------------------------------------------------------------------- /src/assets/users/autohome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/autohome.png -------------------------------------------------------------------------------- /src/assets/users/babeltime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/babeltime.png -------------------------------------------------------------------------------- /src/assets/users/bilibili.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/bilibili.png -------------------------------------------------------------------------------- /src/assets/users/bytedance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/bytedance.png -------------------------------------------------------------------------------- /src/assets/users/celerdata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/celerdata.png -------------------------------------------------------------------------------- /src/assets/users/dinky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/dinky.png -------------------------------------------------------------------------------- /src/assets/users/dustess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/dustess.png -------------------------------------------------------------------------------- /src/assets/users/highlandhuanyu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/highlandhuanyu.png -------------------------------------------------------------------------------- /src/assets/users/kuayueexpress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/kuayueexpress.png -------------------------------------------------------------------------------- /src/assets/users/mihoyo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/mihoyo.png -------------------------------------------------------------------------------- /src/assets/users/netEase-media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/netEase-media.png -------------------------------------------------------------------------------- /src/assets/users/selectdb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/selectdb.png -------------------------------------------------------------------------------- /src/assets/users/starrocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/starrocks.png -------------------------------------------------------------------------------- /src/assets/users/tongchengtravel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/tongchengtravel.png -------------------------------------------------------------------------------- /src/assets/users/unicom-digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/unicom-digital.png -------------------------------------------------------------------------------- /src/assets/users/unicom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/unicom.png -------------------------------------------------------------------------------- /src/assets/users/ververica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/ververica.png -------------------------------------------------------------------------------- /src/assets/users/vivo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/vivo.png -------------------------------------------------------------------------------- /src/assets/users/wanglong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/wanglong.png -------------------------------------------------------------------------------- /src/assets/users/xgimi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/xgimi.png -------------------------------------------------------------------------------- /src/assets/users/xiaopeng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/xiaopeng.png -------------------------------------------------------------------------------- /src/assets/users/ximalaya.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/ximalaya.png -------------------------------------------------------------------------------- /src/assets/users/yiou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/yiou.png -------------------------------------------------------------------------------- /src/assets/users/zhihu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/zhihu.png -------------------------------------------------------------------------------- /src/assets/users/zhongyuanbank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/zhongyuanbank.png -------------------------------------------------------------------------------- /src/assets/users/ziroom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/ziroom.png -------------------------------------------------------------------------------- /src/assets/users/zto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/paimon-website/788c70e685dcbe3b29e2ff34a0ba40a6440ec33d/src/assets/users/zto.png -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Apache Paimon™ 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main.server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ApplicationRef } from '@angular/core'; 20 | import { bootstrapApplication } from '@angular/platform-browser'; 21 | 22 | import { AppComponent } from '@paimon/app/app.component'; 23 | import { config } from '@paimon/app/app.config.server'; 24 | 25 | const bootstrap = (): Promise => bootstrapApplication(AppComponent, config); 26 | 27 | export default bootstrap; 28 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | import { bootstrapApplication } from '@angular/platform-browser'; 21 | 22 | import { AppComponent } from './app/app.component'; 23 | import { appConfig } from './app/app.config'; 24 | 25 | bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); 26 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | @import './styles/markdown.css'; 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | @layer base { 8 | :root { 9 | --paimon-blue-1: #edf2fc; 10 | --paimon-blue-2: #e0e9fb; 11 | --paimon-blue-3: #ceddfc; 12 | --paimon-blue-4: #afc9ff; 13 | --paimon-blue-5: #90b2fa; 14 | --paimon-blue-6: #6694f6; 15 | --paimon-blue-7: #4077eb; 16 | --paimon-blue-8: #2861d8; 17 | --paimon-blue-9: #174fc5; 18 | --paimon-blue-10: #083ba7; 19 | --paimon-blue-11: #072d7e; 20 | --paimon-blue-12: #062464; 21 | --paimon-blue-13: #01143e; 22 | --paimon-blue-14: #070b22; 23 | --paimon-blue-15: #030611; 24 | /*gray*/ 25 | --paimon-gray-1: #f4f4f6; 26 | --paimon-gray-2: #ebecef; 27 | --paimon-gray-3: #dddee4; 28 | --paimon-gray-4: #c7c9d1; 29 | --paimon-gray-5: #b3b6c1; 30 | --paimon-gray-6: #a3a6b3; 31 | --paimon-gray-7: #9295a5; 32 | --paimon-gray-8: #818598; 33 | --paimon-gray-9: #6e7587; 34 | --paimon-gray-10: #5c6170; 35 | --paimon-gray-11: #4c505d; 36 | --paimon-gray-12: #2e3038; 37 | --paimon-gray-13: #1e1f24; 38 | --paimon-gray-14: #121316; 39 | --paimon-gray-15: #0a0a0a; 40 | } 41 | 42 | @font-face { 43 | font-family: 'Roboto'; 44 | font-style: normal; 45 | font-weight: 400; 46 | font-display: swap; 47 | src: url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap'); 48 | } 49 | } 50 | 51 | @layer utilities { 52 | .paused { 53 | animation-play-state: paused; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: 'class', 4 | content: ['./src/**/*.{html,ts}'], 5 | theme: { 6 | fontFamily: { 7 | roboto: 8 | 'system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"' 9 | }, 10 | extend: { 11 | colors: { 12 | 'paimon-blue': { 13 | primary: 'var(--paimon-blue-8)', 14 | hover: 'var(--paimon-blue-9)', 15 | active: 'var(--paimon-blue-10)', 16 | 1: 'var(--paimon-blue-1)', 17 | 2: 'var(--paimon-blue-2)', 18 | 3: 'var(--paimon-blue-3)', 19 | 4: 'var(--paimon-blue-4)', 20 | 5: 'var(--paimon-blue-5)', 21 | 6: 'var(--paimon-blue-6)', 22 | 7: 'var(--paimon-blue-7)', 23 | 11: 'var(--paimon-blue-11)', 24 | 12: 'var(--paimon-blue-12)', 25 | 13: 'var(--paimon-blue-13)', 26 | 14: 'var(--paimon-blue-14)', 27 | 15: 'var(--paimon-blue-15)' 28 | }, 29 | 'paimon-gray': { 30 | 1: 'var(--paimon-gray-1)', 31 | 2: 'var(--paimon-gray-2)', 32 | 3: 'var(--paimon-gray-3)', 33 | 4: 'var(--paimon-gray-4)', 34 | 5: 'var(--paimon-gray-5)', 35 | 6: 'var(--paimon-gray-6)', 36 | 7: 'var(--paimon-gray-7)', 37 | 8: 'var(--paimon-gray-8)', 38 | 9: 'var(--paimon-gray-9)', 39 | 10: 'var(--paimon-gray-10)', 40 | 11: 'var(--paimon-gray-11)', 41 | 12: 'var(--paimon-gray-12)', 42 | 13: 'var(--paimon-gray-13)', 43 | 14: 'var(--paimon-gray-14)', 44 | 15: 'var(--paimon-gray-15)' 45 | }, 46 | 'paimon-text': { 47 | base: 'var(--paimon-gray-1)', 48 | hover: 'var(--paimon-gray-4)' 49 | } 50 | }, 51 | keyframes: { 52 | 'fade-in': { 53 | '0%': { opacity: '0' }, 54 | '100%': { opacity: '1' } 55 | }, 56 | slide: { 57 | '0%': { transform: 'translateX(0%)' }, 58 | '100%': { transform: 'translateX(-100%)' } 59 | } 60 | }, 61 | animation: { 62 | 'paimon-loading': 'fade-in 0.5s infinite alternate', 63 | 'paimon-slide': 'slide 60s linear infinite' 64 | } 65 | } 66 | }, 67 | plugins: [ 68 | require('tailwindcss-animation-delay'), 69 | { 70 | tailwindcss: {}, 71 | autoprefixer: {} 72 | } 73 | ] 74 | }; 75 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "extends": "./tsconfig.json", 5 | "compilerOptions": { 6 | "outDir": "./out-tsc/app", 7 | "types": [ 8 | "node" 9 | ] 10 | }, 11 | "files": [ 12 | "src/main.ts", 13 | "src/main.server.ts", 14 | "server.ts" 15 | ], 16 | "include": [ 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "compileOnSave": false, 5 | "compilerOptions": { 6 | "rootDir": ".", 7 | "baseUrl": "./", 8 | "outDir": "./dist/out-tsc", 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "skipLibCheck": true, 15 | "isolatedModules": true, 16 | "esModuleInterop": true, 17 | "sourceMap": true, 18 | "strictPropertyInitialization": false, 19 | "declaration": false, 20 | "experimentalDecorators": true, 21 | "moduleResolution": "node", 22 | "importHelpers": true, 23 | "target": "ES2022", 24 | "module": "ES2022", 25 | "resolveJsonModule": true, 26 | "useDefineForClassFields": false, 27 | "lib": ["ES2022", "es2018", "es2019", "es2020", "es2021", "dom"], 28 | "types": ["node"], 29 | "paths": { 30 | "@paimon/*": ["src/*"], 31 | "@paimon-markdown-parser/*": ["./library/markdown-parser/models/*"] 32 | } 33 | }, 34 | "angularCompilerOptions": { 35 | "noPropertyAccessFromIndexSignature": false, 36 | "enableI18nLegacyMessageIdFormat": false, 37 | "strictInjectionParameters": true, 38 | "strictInputAccessModifiers": true, 39 | "strictTemplates": true, 40 | } 41 | } 42 | --------------------------------------------------------------------------------