├── .devcontainer └── devcontainer.json ├── .github └── workflows │ ├── build.yml │ ├── post-build.yml │ └── release.yml ├── .gitignore ├── .tours └── diplodoc-project-tutorial.tour ├── .vscode └── launch.json ├── README.md ├── docs ├── .yfm ├── en │ ├── about.md │ ├── anotherpage.md │ ├── index.yaml │ ├── page.md │ ├── sub-section │ │ ├── content.md │ │ ├── index.yaml │ │ └── toc.yaml │ └── toc.yaml └── ru │ ├── about.md │ ├── anotherpage.md │ ├── index.yaml │ ├── page.md │ ├── sub-section │ ├── content.md │ ├── index.yaml │ └── toc.yaml │ └── toc.yaml ├── images ├── codespaces-project.jpeg └── open-in-a-codespace.jpeg ├── index.html ├── package-lock.json ├── package.json └── scripts └── serve.js /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "mcr.microsoft.com/devcontainers/universal:2", 3 | "hostRequirements": { 4 | "cpus": 4 5 | }, 6 | "waitFor": "onCreateCommand", 7 | "updateContentCommand": "npm install", 8 | "postCreateCommand": "", 9 | "postAttachCommand": { 10 | "server": "npm start" 11 | }, 12 | "customizations": { 13 | "codespaces": { 14 | "openFiles": [ 15 | "docs/index.yaml", 16 | "docs/toc.yaml" 17 | ] 18 | }, 19 | "vscode": { 20 | "extensions": [ 21 | "vsls-contrib.codetour" 22 | ] 23 | } 24 | }, 25 | "portsAttributes": { 26 | "8000": { 27 | "label": "Diplodoc Playground", 28 | "onAutoForward": "openPreview" 29 | } 30 | }, 31 | "forwardPorts": [8000] 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize] 6 | 7 | jobs: 8 | build-docs: 9 | runs-on: ubuntu-latest 10 | if: ${{ github.repository != 'diplodoc-platform/documentation-template' }} 11 | permissions: write-all 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | 16 | - name: Build 17 | uses: diplodoc-platform/docs-build-action@v3 18 | with: 19 | revision: "pr-${{ github.event.pull_request.number }}" 20 | src-root: "./docs" 21 | -------------------------------------------------------------------------------- /.github/workflows/post-build.yml: -------------------------------------------------------------------------------- 1 | name: Upload & Message 2 | 3 | on: 4 | workflow_run: 5 | workflows: [Build] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | post-build: 11 | permissions: write-all 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Upload 15 | uses: diplodoc-platform/docs-upload-action@v1 16 | if: github.event.workflow_run.conclusion == 'success' 17 | with: 18 | github-token: ${{ secrets.GITHUB_TOKEN }} 19 | storage-endpoint: ${{ vars.DIPLODOC_STORAGE_ENDPOINT }} 20 | storage-region: ${{ vars.DIPLODOC_STORAGE_REGION }} 21 | storage-bucket: ${{ vars.DIPLODOC_STORAGE_BUCKET }} 22 | storage-access-key-id: ${{ secrets.DIPLODOC_ACCESS_KEY_ID }} 23 | storage-secret-access-key: ${{ secrets.DIPLODOC_SECRET_ACCESS_KEY }} 24 | 25 | - name: Comment message 26 | uses: diplodoc-platform/docs-message-action@v1 27 | with: 28 | github-token: ${{ secrets.GITHUB_TOKEN }} 29 | project-link: ${{ vars.DIPLODOC_PROJECT_LINK }} 30 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | types: [closed] 7 | branches: 8 | - main 9 | 10 | jobs: 11 | check-env: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: "Check is DIPLODOC_STORAGE_BUCKET secret exists" 15 | env: 16 | storage-bucket: ${{ vars.DIPLODOC_STORAGE_BUCKET }} 17 | if: ${{ env.storage-bucket == '' }} 18 | run: 'echo "::error:: The variable \"DIPLODOC_STORAGE_BUCKET\" has not been made; please check that all necessary secrets and variables are installed or follow the link https://diplodoc.com/quickstart" && exit 1' 19 | build: 20 | needs: check-env 21 | if: ${{ github.repository != 'diplodoc-platform/documentation-template' }} 22 | runs-on: ubuntu-latest 23 | permissions: write-all 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v3 27 | - name: Build 28 | uses: diplodoc-platform/docs-build-action@v3 29 | with: 30 | revision: "${{ github.sha }}" 31 | src-root: "./docs" 32 | upload: 33 | needs: build 34 | runs-on: ubuntu-latest 35 | permissions: write-all 36 | steps: 37 | - name: Upload 38 | uses: diplodoc-platform/docs-upload-action@v1 39 | with: 40 | github-token: ${{ secrets.GITHUB_TOKEN }} 41 | storage-endpoint: ${{ vars.DIPLODOC_STORAGE_ENDPOINT }} 42 | storage-region: ${{ vars.DIPLODOC_STORAGE_REGION }} 43 | storage-bucket: ${{ vars.DIPLODOC_STORAGE_BUCKET }} 44 | storage-access-key-id: ${{ secrets.DIPLODOC_ACCESS_KEY_ID }} 45 | storage-secret-access-key: ${{ secrets.DIPLODOC_SECRET_ACCESS_KEY }} 46 | release: 47 | needs: upload 48 | runs-on: ubuntu-latest 49 | steps: 50 | - name: Release 51 | uses: diplodoc-platform/docs-release-action@v2 52 | with: 53 | revision: "${{ github.sha }}" 54 | storage-bucket: ${{ vars.DIPLODOC_STORAGE_BUCKET }} 55 | storage-access-key-id: ${{ secrets.DIPLODOC_ACCESS_KEY_ID }} 56 | storage-secret-access-key: ${{ secrets.DIPLODOC_SECRET_ACCESS_KEY }} 57 | project-link: ${{ vars.DIPLODOC_PROJECT_LINK }} 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | docs-html/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.tours/diplodoc-project-tutorial.tour: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://aka.ms/codetour-schema", 3 | "title": "Diplodoc Project Tutorial", 4 | "steps": [ 5 | { 6 | "title": "Introduction", 7 | "description" : "This tutorial will take you through basic diplodoc documentation project" 8 | }, 9 | { 10 | "title": "Playground", 11 | "description": "You are right now in the diplodoc playground\n\nPlayground starts development server that rebuilds documentation on file changes\nand serves it\nGiving you ability to see live changes inside the Simple Browser window\n\nyou can start development server with `npm start` command(it is done automatically inside github codespaces)\ndocumentation served on `0.0.0.0:8000`" 12 | }, 13 | { 14 | "title": "Project structure", 15 | "description": "Let's go through documentation project structure" 16 | }, 17 | { 18 | "title": "Documentation sources", 19 | "description": "Documentation sources are located inside the `docs/` folder", 20 | "directory": "docs" 21 | }, 22 | { 23 | "title": "Documentation build result", 24 | "description": "Documentation build result can be found in the `docs-html` folder as the `static html`", 25 | "directory": "docs-html" 26 | }, 27 | { 28 | "title": "Table Of Contents | toc.yaml", 29 | "description": "TOC - Table Of Contents is written in the yaml format\n\nIt helps you describe content\nLinks to files listed in the `toc.yaml` will appear in the aside menu in the html\n\n[Read more about TOC](https://ydocs.tech/en/project/toc)", 30 | "file": "docs/toc.yaml" 31 | }, 32 | { 33 | "title": "Leading Page | index.yaml", 34 | "description": "Leading page is written in the yaml format\n\nIt helps you generate index leading page with links to your content\nFiles linked in the `index.yaml` will appear on the leading page as links\n\n[Read more about Leading Page](https://ydocs.tech/en/project/leading-page)", 35 | "file": "docs/index.yaml" 36 | }, 37 | { 38 | "title": "Adding new file", 39 | "description": "Let's create new markdown content file\n\nCreate new file named `new.md` inside the `docs` folder\n\nAfter creating it, editor will open `new.md` file in the new tab.\nPut following content inside of it and switch back to the CodeTour tab.\n\n```\n# new title\n\nnew content\n```", 40 | "directory": "docs" 41 | }, 42 | { 43 | "title": "Add new item to TOC", 44 | "description": "Let's add our new file to the `toc.yaml`\n\nAdd two lines to the `toc.yaml`\nfirst: `- name: new content`\nsecond: `href: new.md`\nindent them to align with previous items(indentation is important inside the YAML files)\n\n`name` will describe how item will be named in the aside menu\n`href` specifies location of the file", 45 | "file": "docs/toc.yaml", 46 | "line": 12 47 | }, 48 | { 49 | "title": "Add new item to Leading Page", 50 | "description": "Let's add our new file to the `index.yaml` leading page as well\n\nAdd two lines to the `index.yaml`\nfirst: `- title: new content`\nsecond: `href:new.md`\nindent them to align with previous items(indentation is important inside the YAML files)\n\n`title` will describe text of the link on the leading page\n`href` specifies location of the file to link to", 51 | "file": "docs/index.yaml", 52 | "line": 9 53 | }, 54 | { 55 | "title": "Check out the results", 56 | "description": "Now refresh page inside the Simple Browser to able to see changes\n\n**Note: outside of the codetour changes will be hot reloaded(you wouldn't need to refresh your browser to see changes)\n\nGo ahead close the Code Tour and try adding new files to your documentation or edit existing ones!", 57 | "directory": "docs-html" 58 | } 59 | ], 60 | "isPrimary": true 61 | } 62 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configuration": [ 4 | { 5 | "name": "Run Diplodoc Playground", 6 | "type": "node", 7 | "request": "launch", 8 | "cwd": "${workspaceFolder}", 9 | "console": "integratedTerminal", 10 | "runtimeExecutable": "npm", 11 | "runtimeArgs": [ 12 | "start" 13 | ], 14 | "skipFiles": [ 15 | "/**" 16 | ] 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Documentation Template created by Diplodoc 2 | 3 | Features: 4 | 5 | - initial project structure 6 | - dev server with hot reload 7 | - codespaces support 8 | - vscode tutorial via code tours 9 | 10 | ## Initial project structure 11 | 12 | Initiatl project structure with basic content can be found within your public github repo "diplodoc-example/docs" 13 | 14 | ## Usage 15 | 16 | ### Run locally by cloning repo: 17 | 18 | ``` 19 | > git clone git@github.com:diplodoc-platform/documentation-template.git 20 | 21 | > cd documentation-template 22 | 23 | > npm start 24 | 25 | > listening on 0.0.0.0:8000 26 | 27 | ``` 28 | now you have development server with hot reload runing and serving built documentation on `0.0.0.0:8000` 29 | 30 | ### github codespaces 31 | 32 | press Use this template -> Open in a codespace 33 | 34 | ![open in a codespace](images/open-in-a-codespace.jpeg) 35 | 36 | wait for the development server startup 37 | 38 | enjoy developing documentation with html result preview in split view 39 | 40 | ![codespaces project](images/codespaces-project.jpeg) 41 | -------------------------------------------------------------------------------- /docs/.yfm: -------------------------------------------------------------------------------- 1 | langs: ['ru', 'en'] 2 | 3 | docs-viewer: 4 | langs: ['en','ru'] -------------------------------------------------------------------------------- /docs/en/about.md: -------------------------------------------------------------------------------- 1 | # Basic "About page" 2 | 3 | This is an example for basic documenation project. 4 | It contains simple structure with couple of pages (this page, another page) and nested sub-section. 5 | 6 | Diplodoc provides you with unique name how this project can be reached on https://diplodoc.com like 7 | "https://common---gh-aje0e4eg9hffg001r5e5.viewer.diplodoc.com/en/" 8 | 9 | If you would like to extend your project - please refer to [YFM Project Organization guide](https://diplodoc.com/docs/en/project/) 10 | 11 | All changes for this project can be done within you public github repository called "diplodoc-example/docs". 12 | To make changes and apply them: 13 | 14 | - go to your repo under "diplodoc-example/docs" 15 | - make changes for project structure or content 16 | - commit & push into your repository 17 | - go to "Actions" tab for docs repository 18 | - run "Release" action and wait till completion 19 | - done, updates should be available for everyone. 20 | 21 | 22 | In case if you would like to make proxy from your own domain to this Documentation - please [Contact Us](https://diplodoc.com/#contact) - we will support you accordingly till appropriate documentation creation. 23 | 24 | -------------------------------------------------------------------------------- /docs/en/anotherpage.md: -------------------------------------------------------------------------------- 1 | # Simple documentation project with YFM 2 | 3 | 4 | ## Project Structure 5 | Basic project contains few config files and pages with actual content. Both config files and markdown linked into the following structure: 6 | 7 | 8 | ``` 9 | input-folder 10 | |-- .yfm (config file for whole project) 11 | |-- toc.yaml (table of content) 12 | |-- presets.yaml (presets for vairables) 13 | |-- index.yaml (index page) 14 | |-- pages (Content pages) 15 | |-- faq.md 16 | |-- how-to.md 17 | |-- _assets (directory with pictures) 18 | |-- image1.png 19 | |-- image2.png 20 | |-- _includes (directory for reusable content) 21 | |-- faq_shared_block.md 22 | ``` 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/en/index.yaml: -------------------------------------------------------------------------------- 1 | title: Documentation Template 2 | links: 3 | - title: About 4 | href: about.md 5 | - title: Diplodoc page on index page 6 | href: page.md 7 | - title: YFM Structure on index page 8 | href: anotherpage.md 9 | - title: Sub-section on index page 10 | href: sub-section/ -------------------------------------------------------------------------------- /docs/en/page.md: -------------------------------------------------------------------------------- 1 | # Diplodoc 2 | 3 | Diplodoc is an open-source platform for working with your documentation in the "Documentation as a Code" paradigm. 4 | Simple and comfortable solution for everyone. 5 | 6 | ## Advantages of the platform 7 | ### Easy to use 8 | - Work with documents in the same way as with code 9 | - Minimal efforts for deployment and integration 10 | 11 | ### Speed 12 | - Fast validation, build and deploy for your projects 13 | - Easy integration with your developement pipelines 14 | 15 | ### Full support of Markdown 16 | - Simple syntax 17 | - Easy learning 18 | - Concentration on content creation, not deployment 19 | - Rich functionality 20 | 21 | ### Support for complex Documentation projects 22 | - Customization and localization 23 | - “One Source” support 24 | - Add more functionality with plugins even 25 | 26 | ### Supports for autogenerated documentation 27 | - OpenAPI support out of the box 28 | - Custom includer’s interface for any kind of autogenerated docs (JavaDoc, etc..) -------------------------------------------------------------------------------- /docs/en/sub-section/content.md: -------------------------------------------------------------------------------- 1 | # Sub-Section with content 2 | 3 | This is an example page for demonstation how sub-sections can be organized. 4 | More details about subsections inclusion can be found [here](https://diplodoc.com/docs/en/project/toc) 5 | -------------------------------------------------------------------------------- /docs/en/sub-section/index.yaml: -------------------------------------------------------------------------------- 1 | title: Sub-section Example on index page 2 | links: 3 | - title: Content on a page under Sub-section 4 | href: content.md 5 | -------------------------------------------------------------------------------- /docs/en/sub-section/toc.yaml: -------------------------------------------------------------------------------- 1 | title: Sub-section Example TOC 2 | href: index.yaml 3 | items: 4 | - name: Content page under sub-section 5 | href: content.md 6 | -------------------------------------------------------------------------------- /docs/en/toc.yaml: -------------------------------------------------------------------------------- 1 | title: Documentation Project Template 2 | href: index.yaml 3 | items: 4 | - name: About 5 | href: about.md 6 | - name: Additional page 7 | href: page.md 8 | - name: Another page 9 | href: anotherpage.md 10 | - name: Sub-Section 11 | include: 12 | path: sub-section/toc.yaml 13 | mode: link -------------------------------------------------------------------------------- /docs/ru/about.md: -------------------------------------------------------------------------------- 1 | # Основная страница "О проекте" 2 | 3 | Это пример простого проекта документации. 4 | Он содержит простую структуру с несколькими страницами и вложенным подразделом. 5 | 6 | Диплодок предоставляет вам уникальный адрес, по которому можно осуществить доступ к этому проекту на https://diplodoc.com, например, "https://common---gh-aje0e4eg9hffg001r5e5.viewer.diplodoc.com/ru/" 7 | 8 | Если вы хотите расширить свой проект, пожалуйста, обратитесь к [Руководству по организации проекта YFM](https://diplodoc.com/docs/ru/project/). 9 | 10 | Все изменения для этого проекта могут быть выполнены в вашем общедоступном репозитории GitHub под названием "diplodoc-example/docs". 11 | Чтобы внести изменения и применить их: 12 | 13 | - перейдите в ваш репозиторий по адресу "diplodoc-example/docs" 14 | - внесите изменения в структуру проекта или контент 15 | - закоммитьте и отправьте изменения в ваш репозиторий 16 | - перейдите на вкладку "Actions" (Действия) для репозитория документации 17 | - запустите действие "Release" (Выпуск) и дождитесь его завершения 18 | - готово, обновления должны быть доступны для всех 19 | 20 | Если вы хотите сделать прокси с вашего собственного домена на эту документацию, пожалуйста, [воспользуйтесь гайдом из документации](https://diplodoc.com/docs/ru/personal-domain-ya-cloud). 21 | -------------------------------------------------------------------------------- /docs/ru/anotherpage.md: -------------------------------------------------------------------------------- 1 | # Простой проект документации с YFM 2 | 3 | ## Структура проекта 4 | Основной проект содержит несколько конфигурационных файлов и страницы с фактическим содержанием. Оба конфигурационных файла и markdown организованы в следующую структуру: 5 | 6 | ``` 7 | input-folder 8 | |-- .yfm (конфигурационный файл для всего проекта) 9 | |-- toc.yaml (оглавление) 10 | |-- presets.yaml (предустановки для переменных) 11 | |-- index.yaml (индексная страница) 12 | |-- pages (страницы с контентом) 13 | |-- faq.md 14 | |-- how-to.md 15 | |-- _assets (директория с изображениями) 16 | |-- image1.png 17 | |-- image2.png 18 | |-- _includes (директория для многократно используемого контента) 19 | |-- faq_shared_block.md 20 | ``` 21 | 22 | Эта структура позволяет организовать документацию в формате YFM для более удобного редактирования и согласования. -------------------------------------------------------------------------------- /docs/ru/index.yaml: -------------------------------------------------------------------------------- 1 | title: Шаблон документации 2 | links: 3 | - title: О проекте 4 | href: about.md 5 | - title: Страница Diplodoc на главной странице 6 | href: page.md 7 | - title: Структура YFM на главной странице 8 | href: anotherpage.md 9 | - title: Подраздел на главной странице 10 | href: sub-section/ 11 | -------------------------------------------------------------------------------- /docs/ru/page.md: -------------------------------------------------------------------------------- 1 | # Диплодок 2 | 3 | Диплодок — это открытая платформа для работы с документацией в парадигме "Документация как Код". Простое и удобное решение для всех. 4 | 5 | ## Преимущества платформы 6 | ### Простота использования 7 | - Работа с документами аналогична работе с кодом 8 | - Минимальные усилия для развертывания и интеграции 9 | 10 | ### Скорость 11 | - Быстрая проверка, сборка и развертывание ваших проектов 12 | - Простая интеграция с вашими процессами разработки 13 | 14 | ### Полная поддержка Markdown 15 | - Простой синтаксис 16 | - Легкость обучения 17 | - Концентрация на создании контента, а не на развертывании 18 | - Богатый функционал 19 | 20 | ### Поддержка сложных документационных проектов 21 | - Настройка и локализация 22 | - Поддержка концепции "Единого источника" 23 | - Расширение функционала с помощью плагинов 24 | 25 | ### Поддержка авто-сгенерированной документации 26 | - Поддержка OpenAPI из коробки 27 | - Индивидуальный интерфейс для включения любых видов авто-сгенерированной документации (JavaDoc и др.) -------------------------------------------------------------------------------- /docs/ru/sub-section/content.md: -------------------------------------------------------------------------------- 1 | # Подраздел с контентом 2 | 3 | Это пример страницы, демонстрирующий, как можно организовывать подразделы. 4 | Дополнительные сведения о включении подразделов можно найти [здесь](https://diplodoc.com/docs/ru/project/toc). -------------------------------------------------------------------------------- /docs/ru/sub-section/index.yaml: -------------------------------------------------------------------------------- 1 | title: Пример раздела на главной странице 2 | links: 3 | - title: Контент на странице в подразделе 4 | href: content.md 5 | -------------------------------------------------------------------------------- /docs/ru/sub-section/toc.yaml: -------------------------------------------------------------------------------- 1 | title: Пример содержания подраздела 2 | href: index.yaml 3 | items: 4 | - name: Страница контента в подразделе 5 | href: content.md 6 | -------------------------------------------------------------------------------- /docs/ru/toc.yaml: -------------------------------------------------------------------------------- 1 | title: Шаблон проекта документации 2 | href: index.yaml 3 | items: 4 | - name: О проекте 5 | href: about.md 6 | - name: Дополнительная страница 7 | href: page.md 8 | - name: Другая страница 9 | href: anotherpage.md 10 | - name: Подраздел 11 | include: 12 | path: sub-section/toc.yaml 13 | mode: link 14 | -------------------------------------------------------------------------------- /images/codespaces-project.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diplodoc-platform/documentation-template/c2edfcdb9abd1809aeb62a4e6812160e1c9f7917/images/codespaces-project.jpeg -------------------------------------------------------------------------------- /images/open-in-a-codespace.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diplodoc-platform/documentation-template/c2edfcdb9abd1809aeb62a4e6812160e1c9f7917/images/open-in-a-codespace.jpeg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | Diplodoc Playground Redirect 10 | 11 | 12 | 13 | If you are not redirected automatically, follow this to go to the diplodoc playground. 14 | 15 | 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@diplodoc/documentation-template", 3 | "version": "0.0.0", 4 | "description": "template for your diplodoc documentation with hot reload development server", 5 | "homepage": "https://github.com/diplodoc-platform/documentation-template", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:diplodoc-platform/documentation-template.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/diplodoc-platform/documentation-template/issues", 12 | "email": "morozov.kirill.moki@gmail.com" 13 | }, 14 | "author": { 15 | "name": "moki", 16 | "email": "morozov.kirill.moki@gmail.com", 17 | "url": "github.com/moki" 18 | }, 19 | "keywords": [ 20 | "diplodoc", 21 | "markdown-it", 22 | "markdown", 23 | "playground", 24 | "sandbox", 25 | "documentation", 26 | "development", 27 | "hot-reload", 28 | "codespaces", 29 | "template" 30 | ], 31 | "license": "MIT", 32 | "main": "scripts/serve.js", 33 | "scripts": { 34 | "start": "npm run build:docs && node scripts/serve.js", 35 | "build:docs": "yfm --input docs --output docs-html" 36 | }, 37 | "dependencies": { 38 | "@diplodoc/cli": "^4.55.1", 39 | "chokidar": "^3.5.3", 40 | "express": "^4.18.2", 41 | "glob": "^10.3.4", 42 | "lodash": "^4.17.21", 43 | "open": "^8.4.2", 44 | "parse5": "^7.1.2", 45 | "parse5-utils": "^2.0.0", 46 | "serve-static": "^1.15.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /scripts/serve.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const {execSync} = require('child_process'); 4 | 5 | const chokidar = require('chokidar'); 6 | const express = require('express'); 7 | const serveStatic = require('serve-static'); 8 | 9 | const {parse, serialize} = require('parse5'); 10 | const utils = require('parse5-utils'); 11 | 12 | const watcher = new chokidar.FSWatcher({ignored: '*.swp'}); 13 | const glob = require('glob'); 14 | 15 | const {debounce} = require('lodash'); 16 | const open = require('open'); 17 | 18 | class Server { 19 | // read configuration 20 | constructor(parameters = {}) { 21 | const { 22 | autoOpen = false, 23 | 24 | watchPattern = 'docs/**/*', 25 | 26 | port = 8000, 27 | 28 | serveIndexes = ['index.html'], 29 | serveDir = 'docs-html', 30 | cacheControl = false, 31 | 32 | ssePath = '/events', 33 | sseEventName = 'reload', 34 | sseEventMessage = 'rebuilt' 35 | } = parameters; 36 | 37 | this.configs = { 38 | autoOpen, 39 | 40 | watchPattern, 41 | 42 | port, 43 | 44 | serveIndexes, 45 | serveDir, 46 | cacheControl, 47 | 48 | ssePath, 49 | sseEventName, 50 | sseEventMessage, 51 | }; 52 | 53 | this.configs.sseScript = ` 54 | const events = new EventSource("${this.configs.ssePath}"); 55 | 56 | events.addEventListener("${this.configs.sseEventName}", function(e) { 57 | window.location.reload(); 58 | }); 59 | `; 60 | 61 | this.configure(); 62 | } 63 | 64 | // configure server 65 | configure() { 66 | this.app = express(); 67 | this.app.use(serveStatic(this.configs.serveDir, { 68 | index: this.configs.serveIndexes, 69 | cacheControl: this.configs.cacheControl, 70 | })); 71 | this.app.get(this.configs.ssePath, this.sseRequestHandler.bind(this)); 72 | this.app.get('/', (req, res) => { 73 | res.redirect('/ru/index.html'); 74 | }); 75 | this.sseResponseMessage = `event: ${this.configs.sseEventName}\ndata: ${this.configs.sseEventMessage}\n\n`; 76 | 77 | this.buildDocumentation(); 78 | this.injectSSE(); 79 | 80 | watcher.add(this.configs.watchPattern); 81 | } 82 | 83 | // handle sse request 84 | sseRequestHandler(req, res, next) { 85 | res.writeHead(200, { 86 | 'Content-Type': 'text/event-stream', 87 | 'Cache-Control': 'no-cache', 88 | 'Connection': 'keep-alive' 89 | }); 90 | res.flushHeaders(); 91 | 92 | // when sources change: 93 | // - rebuild documentation 94 | // - inject sse into documentation 95 | // - notify client with reload event 96 | watcher.on('all', debounce((event, path) => { 97 | console.info(`event: ${event}, path: ${path}`); 98 | 99 | try { 100 | this.buildDocumentation.call(this); 101 | } catch (err) { 102 | console.error('failed building documentation:', err); 103 | } 104 | 105 | this.injectSSE.call(this); 106 | this.sendSSEReloadResponse.call(this, res); 107 | }, 500)); 108 | } 109 | 110 | // build documentation 111 | buildDocumentation() { 112 | console.info('building documentation'); 113 | 114 | execSync('npm run build:docs'); 115 | } 116 | 117 | injectSSE() { 118 | console.info('injecting sse into html'); 119 | 120 | const pattern = path.join(this.configs.serveDir, '**', '*.html'); 121 | const paths = glob.globSync(pattern, {ignore: 'node_modules/**'}).map(p => path.join(process.cwd(), p)); 122 | 123 | for (const path of paths) { 124 | try { 125 | const html = fs.readFileSync(path, 'utf8'); 126 | const transformed = this.injectSSEIntoHTML(html, this.configs.sseScript); 127 | fs.writeFileSync(path, transformed, {encoding: 'utf8'}); 128 | } catch (err) { 129 | process.exit(1); 130 | } 131 | } 132 | } 133 | 134 | // send sse reload message 135 | sendSSEReloadResponse(res) { 136 | console.info('sending sse event'); 137 | 138 | res.write(this.sseResponseMessage); 139 | } 140 | 141 | injectSSEIntoHTML(html, sse) { 142 | const parsed = parse(html); 143 | 144 | traverse(parsed, (node) => { 145 | if (node.nodeName === 'head') { 146 | const sseScript = utils.createNode('script'); 147 | const sseScriptBody = utils.createTextNode(sse); 148 | 149 | utils.append(sseScript, sseScriptBody); 150 | utils.append(node, sseScript); 151 | } 152 | }); 153 | 154 | return serialize(parsed); 155 | } 156 | 157 | // start up server 158 | listen() { 159 | this.app.listen(this.configs.port); 160 | 161 | console.info(`serving on: http://0.0.0.0:${this.configs.port}/ru/index.html`); 162 | 163 | if (this.configs.autoOpen) { 164 | open(`http://0.0.0.0:${this.configs.port}/ru/index.html`); 165 | } 166 | } 167 | } 168 | 169 | function traverse(node, cb) { 170 | cb(node); 171 | 172 | const childNodes = node['childNodes']; 173 | if (!childNodes) { 174 | return ; 175 | } 176 | 177 | for (const childNode in childNodes) { 178 | traverse(childNodes[childNode], cb); 179 | } 180 | } 181 | 182 | const server = new Server(); 183 | server.listen(); 184 | --------------------------------------------------------------------------------