├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── labeler.yml
└── workflows
│ ├── codeql-analysis.yml
│ ├── greetings.yml
│ ├── label.yml
│ └── quisque.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── example
├── config.json
├── example.gif
├── ghes-2.20.yml
└── openapi.yml
├── package.json
├── src-engine
├── cli.js
└── index.js
├── src
├── .babelrc
├── .browserslistrc
├── assets
│ ├── highlighter-theme-dark.less
│ ├── highlighter-theme-light.less
│ ├── theme.less
│ └── utils.less
├── components
│ ├── ContactTeam.vue
│ ├── DocEntry.vue
│ ├── DocEntryTitle.vue
│ ├── DocFooter.vue
│ ├── DocHeader.vue
│ ├── DocLayout.vue
│ ├── DocSidebar.vue
│ ├── DocSidebarEntry.vue
│ ├── DocSidebarTag.vue
│ ├── DocTag.vue
│ ├── DocToolbox.vue
│ ├── DocToolboxDropdown.vue
│ ├── DocToolboxIcon.vue
│ ├── Endpoint.vue
│ ├── Example.vue
│ ├── Highlight.vue
│ ├── Markdown.vue
│ ├── ReqBody.vue
│ ├── ReqResponse.vue
│ ├── Shield.vue
│ ├── SplitSection.vue
│ └── StatusCode.vue
├── environment.json
├── index.html
├── index.js
├── index.vue
├── plugins
│ ├── codegen.js
│ └── envInject.js
├── store.js
└── vue.config.js
└── yarn.lock
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # Description
2 |
3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
4 |
5 | Fixes # (issue)
6 |
7 | ### Type of change
8 |
9 | Please delete options that are not relevant.
10 |
11 | - [ ] Bug fix (non-breaking change which fixes an issue)
12 | - [ ] New feature (non-breaking change which adds functionality)
13 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
14 | - [ ] This change requires a documentation update
15 |
16 | ### Checklist:
17 |
18 | - [ ] My code follows the style guidelines of this project
19 | - [ ] I have performed a self-review of my own code
20 | - [ ] I have commented my code in hard-to-understand areas
21 | - [ ] I have made corresponding changes to the documentation
22 | - [ ] My changes generate no new warnings
23 | - [ ] Any dependent changes have been merged and published in downstream modules
24 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "npm"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 | assignees:
8 | - "r4wizard"
9 | pull-request-branch-name:
10 | separator: "-"
11 |
--------------------------------------------------------------------------------
/.github/labeler.yml:
--------------------------------------------------------------------------------
1 | documentation:
2 | - "**/*.md"
3 |
4 | engine:
5 | - "src/**/*"
6 |
7 | template:
8 | - "src-nuxt/**/*"
9 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | pull_request:
7 | # The branches below must be a subset of the branches above
8 | branches: [master]
9 | schedule:
10 | - cron: '0 19 * * 2'
11 |
12 | jobs:
13 | analyze:
14 | name: Analyze
15 | runs-on: ubuntu-latest
16 |
17 | strategy:
18 | fail-fast: false
19 | matrix:
20 | # Override automatic language detection by changing the below list
21 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
22 | language: ['javascript']
23 | # Learn more...
24 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
25 |
26 | steps:
27 | - name: Checkout repository
28 | uses: actions/checkout@v2
29 | with:
30 | # We must fetch at least the immediate parents so that if this is
31 | # a pull request then we can checkout the head.
32 | fetch-depth: 2
33 |
34 | # If this run was triggered by a pull request event, then checkout
35 | # the head of the pull request instead of the merge commit.
36 | - run: git checkout HEAD^2
37 | if: ${{ github.event_name == 'pull_request' }}
38 |
39 | # Initializes the CodeQL tools for scanning.
40 | - name: Initialize CodeQL
41 | uses: github/codeql-action/init@v1
42 | with:
43 | languages: ${{ matrix.language }}
44 |
45 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
46 | # If this step fails, then you should remove it and run the build manually (see below)
47 | - name: Autobuild
48 | uses: github/codeql-action/autobuild@v1
49 |
50 | # ℹ️ Command-line programs to run using the OS shell.
51 | # 📚 https://git.io/JvXDl
52 |
53 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
54 | # and modify them (or add more) to build your code if your project
55 | # uses a compiled language
56 |
57 | #- run: |
58 | # make bootstrap
59 | # make release
60 |
61 | - name: Perform CodeQL Analysis
62 | uses: github/codeql-action/analyze@v1
63 |
--------------------------------------------------------------------------------
/.github/workflows/greetings.yml:
--------------------------------------------------------------------------------
1 | name: Greetings
2 |
3 | on: [pull_request, issues]
4 |
5 | jobs:
6 | greeting:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/first-interaction@v1
10 | with:
11 | repo-token: ${{ secrets.GITHUB_TOKEN }}
12 | issue-message: 'Thank you for opening your first issue! Please ensure you''ve read the [CONTRIBUTING.md](https://github.com/ouropencode/OpenDocumenter/blob/master/CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](https://github.com/ouropencode/OpenDocumenter/blob/master/CODE_OF_CONDUCT.md) files.'
13 | pr-message: 'Thank you for opening your first pull request! Please ensure you''ve read the [CONTRIBUTING.md](https://github.com/ouropencode/OpenDocumenter/blob/master/CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](https://github.com/ouropencode/OpenDocumenter/blob/master/CODE_OF_CONDUCT.md) files.'
14 |
--------------------------------------------------------------------------------
/.github/workflows/label.yml:
--------------------------------------------------------------------------------
1 | name: Labeler
2 |
3 | on: [pull_request]
4 |
5 | jobs:
6 | label:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/labeler@v2
10 | with:
11 | repo-token: "${{ secrets.GITHUB_TOKEN }}"
12 |
--------------------------------------------------------------------------------
/.github/workflows/quisque.yml:
--------------------------------------------------------------------------------
1 | name: Quisque API Build
2 |
3 | on:
4 | push:
5 | branches: ["master"]
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Setup Node.js Environment
12 | uses: actions/setup-node@v2.1.1
13 | with:
14 | node-version: '>=14.6'
15 | - name: Checkout Git Repository
16 | uses: actions/checkout@master
17 | - name: Install Dependencies (with caching)
18 | uses: bahmutov/npm-install@v1
19 | - name: Generate Documentation
20 | run: npm run dev-generate
21 | - name: Upload Build Artifact
22 | uses: actions/upload-artifact@v2
23 | with:
24 | name: documentation
25 | path: example/docs/
26 | if-no-files-found: error
27 | - name: Deploy to GitHub Pages
28 | uses: crazy-max/ghaction-github-pages@v2.1.1
29 | with:
30 | target_branch: gh-pages
31 | build_dir: example/docs/
32 | env:
33 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .nuxt/
3 | dist/
4 | docs/
5 | tmp/
6 | *.log
7 | package-lock.json
8 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at ouropencode@shadowacre.ltd. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | We love pull requests from everyone.
4 |
5 | When contributing to this repository, please first discuss the change you wish to make by opening an issue. Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
6 |
7 | ## Development Setup
8 |
9 | ### Fork the repository
10 | ```bash
11 | > git clone git@github.com:ouropencode/opendocumenter.git
12 | ```
13 |
14 | ### Set up your machine
15 | ```bash
16 | > yarn install
17 | ```
18 |
19 | ### Execute
20 | ```bash
21 | > yarn start # run the example 'openapi.yml' in ./example
22 | > yarn dev # watch the filesystem for changes and exec `yarn start`
23 | ```
24 |
25 | ## Pull Request Process
26 | When your feature is ready to show to others, you should follow the below process to allow for an easy contribution flow.
27 |
28 | 1. Make your changes.
29 | 2. If applicable, Update the [README.md](README.md).
30 | 3. If applicable, Update the `./example/config.json` file.
31 | 4. If applicable, Update the `./example/openapi.yml` file.
32 | 5. Push to a new branch.
33 | 6. Create a [draft pull request](https://github.blog/2019-02-14-introducing-draft-pull-requests/).
34 | 7. When ready to merge, update pull request to 'Ready for Review'.
35 | 8. Wait for us, we try to comment on pull requests within a reasonable timeframe. We may suggest changes before accepting the pull request.
36 |
37 | ## Internationalization
38 | Any contributions should consider the existing i18n support available through the `$i18n()` method. Any new strings added to the project should use this method for string internationalization. When adding a new string you will need to edit the `./src/index.js` file, and the `./example/config.json` file.
39 |
40 | ## Configuration
41 | All configuration is handled through a `.json` file provided by the end-user. Provided throughout the project via the `$config.*` variable. When adding a new parameter you will need to edit the `./src/index.js` file, the `./src/environment.json` file, and the `./example/config.json` file.
42 |
43 | Care should be taken when altering the `environment.json` file - the intention if to provide enough structure for the documentation to display even if no env is available to inject (this happens when running `yarn dev-nuxt`). Ideally, this means purely structural elements such as `{}` and `[]` although this isn't a hard requirement.
44 |
45 | ## Versions
46 | For versioning we use the [Semantic Versioning](https://semver.org) versioning scheme. Versioning will be managed by the $ourOpenCode team and contributors should leave all versions at the version forked.
47 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2020+ OurOpenCode
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
OpenDocumenter
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | OpenDocumenter is a automatic documentation generator for [OpenAPI v3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md) schemas. Simply provide your schema file in JSON or YAML, then sit back and enjoy the documentation.
20 |
21 | Powered by [nuxt.js](https://nuxtjs.org/https://nuxtjs.org/) and [swagger-parser](https://github.com/swagger-api/swagger-parser).
22 |
23 | ## Example
24 | For a live preview of documentation generated with OpenDocumenter you can view our demo documentation "**[Quisque API](https://ouropencode.github.io/OpenDocumenter/)**". This example uses lorem-ipsum for all content to provide placeholder text used to demonstrate the form of a document without relying on meaningful content.
25 |
26 | ## Installation
27 |
28 | ```bash
29 | > npm install -g opendocumenter
30 | ```
31 | or
32 | ```bash
33 | > yarn global add opendocumenter
34 | ```
35 |
36 | ## Usage
37 | ```
38 | > opendocumenter --help
39 |
40 | _____ ____ _
41 | | |___ ___ ___| \ ___ ___ _ _ _____ ___ ___| |_ ___ ___
42 | | | | . | -_| | | | . | _| | | | -_| | _| -_| _|
43 | |_____| _|___|_|_|____/|___|___|___|_|_|_|___|_|_|_| |___|_|
44 | |_|
45 |
46 | OpenDocumenter is a automatic documentation generator for OpenAPI v3 schemas.
47 | Simply provide your schema file in JSON or YAML, then sit back and enjoy the documentation.
48 |
49 | Powered by nuxt.js and swagger-parser.
50 |
51 | Usage:
52 |
53 | opendocumenter --schema= --output=
54 |
55 | Arguments:
56 |
57 | --schema= (required) The OpenAPI 3 format file to generate documentation from.
58 | --output= (required) The output destination directory.
59 | --config= A configuration file to load advanced options from.
60 | ```
61 |
62 | ## Configuration
63 | OpenDocumenter can be configured using a `.json` file stored alongside your schema file.
64 |
65 | ### Merge From Directory
66 | The `mergeFromDirectory` parameter allows you to specify a directory that will be copied over the base template before building. This allows customization of any part of OpenDocumenter to suit your needs.
67 |
68 | ```json
69 | {
70 | "mergeFromDirectory": "./overrides"
71 | }
72 | ```
73 |
74 | Any part of the OpenDocumenter vue source (see: [./src](./src)) can be overridden, just ensure to follow the same directory structure!
75 | ```
76 | overrides
77 | |- assets
78 | | '- theme.less
79 | '- components
80 | |- DocHeader.vue
81 | '- DocEntry.vue
82 | ```
83 |
84 | ### 'Generated Using' Footer
85 | By default, a small 'Generated Using' message is included on the footer of the generated documentation. Although we'd love you to keep it, you can disable this by setting the `disableGeneratedUsingFooter` parameter to true.
86 |
87 | ```json
88 | {
89 | "disableGeneratedUsingFooter": true
90 | }
91 | ```
92 |
93 | ### Aborting on Invalid Schema
94 | OpenDocumenter is capable of generating documentation for OpenAPI schemas that don't match the OpenAPI Specification entirely. When generating we attempt to validate your schema, display any validation warnings, and then continue to generate. If you would like the generation to abort when a schema is invalid you can set the `abortOnInvalidSchema` parameter to true.
95 |
96 | ```json
97 | {
98 | "abortOnInvalidSchema": true
99 | }
100 | ```
101 |
102 | ### Shields / Badges
103 | Various shields are included in the generated documentation header, such as the API version. Additional shields can be added using the `shields` parameter. Each shield is an object containing either the `url` key, or a combination of `left`, `right` and `color`. The `translate` parameter can be used (`left`, `right`, `both`) to run the text through the internationalization handler. An optional link can provided with the `href` parameter. All shields are generated using [shields.io](https://shields.io) unless a URL is provided.
104 |
105 | ```json
106 | {
107 | "shields": [
108 | { "url": "https://img.shields.io/badge/test-1.2.3--test-blue" },
109 | { "left": "test", "right": "1.2.3-test", "color": "blue" },
110 | {
111 | "left": "test",
112 | "right": "1.2.3-test",
113 | "color": "blue",
114 | "href": "https://www.example.com"
115 | }
116 | ]
117 | }
118 | ```
119 |
120 | ### Build: Modern Mode
121 | By default, the build-chain produces "Modern Mode" output, shipping native ES2015 code to modern browsers that support it, with auto fallback to a legacy bundle. This can be turned off by setting `vueModernMode` parameter, afterwards the build-chain produces "Legacy" output for older browser compatibility.
122 |
123 | ```json
124 | {
125 | "vueModernMode": false
126 | }
127 | ```
128 |
129 | ### Build: Reporting
130 | You can control the reporting output from the build-chain with the `vueReport` parameter. This defaults to `none` and can be set to `json`, `html` or `both`. With this enabled the build-chain will output a report file describing the webpack bundle.
131 |
132 | ```json
133 | {
134 | "vueReport": "html"
135 | }
136 | ```
137 |
138 | ### Internationalization
139 | Most of the documentation text is taken directly from the OpenAPI schema file, however, there are various strings throughout the project that cannot be stored within the schema file. All of these strings are customizable by editing the `i18n` parameter.
140 | ```json
141 | {
142 | "i18n": {
143 | "API_SDK_DOCUMENTATION": "API and SDK Documentation",
144 | "VERSION": "version",
145 | "NO_INDEPTH_DOCS_AVAILABLE_ENDPOINT": "No in-depth API documentation is available for this endpoint.",
146 | "NO_INDEPTH_DOCS_AVAILABLE_TAG": "No in-depth API documentation is available for this section.",
147 | "CLICK_TO_COPY": "click to copy",
148 | "COPIED": "copied",
149 | "REQUEST_BODY": "Request Body",
150 | "REQUEST_RESPONSES": "Request Responses",
151 | "DEFINITION": "Definition",
152 | "DEFINITIONS": "Definitions",
153 | "SERVER": "Server",
154 | "LANGUAGE": "Language",
155 | "GENERATED_USING": "Generated using OpenDocumenter by $ourOpenCode",
156 | "HAVE_ANY_QUESTIONS_CONTACT": "Have any questions? Please contact",
157 | "US": "us",
158 | "OR": "or",
159 | "VIA_EMAIL": "via email",
160 | "VIA_OUR_WEBSITE": "via our website",
161 | "TERMS_OF_SERVICE": "Terms of Service",
162 | "SEND_US_AN_EMAIL": "Send us an email",
163 | "VISIT_OUR_WEBSITE": "Visit our website",
164 | "EXTERNAL_DOCUMENTATION": "External Documentation",
165 | "DOCUMENTATION": "Documentation"
166 | }
167 | }
168 | ```
169 |
170 | > There is a single end-user visible string that isn't configurable in this config. The "Loading Documentation..." text in the page title, briefly shown during page load, is only configurable using the "Merge From Directory" parameter.
171 |
172 | ## License
173 | Licensed under the MIT license. Please see [LICENSE](LICENSE) for more details.
174 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 | Only the latest version is supported and actively maintained while the project is pre-v1.
5 |
6 | | Version | Supported |
7 | | ------- | ------------------ |
8 | | 0.5.x | :white_check_mark: |
9 | | < 0.5 | :x: |
10 |
11 | ## Reporting a vulnerability
12 | To report any vulnerabilities please create an issue, you can expect to get an update on a reported vulnerability
13 | within a reasonable timeframe. If you have the time you can additionally create a patch for the vulnerability and
14 | create a pull request - this may speed up the process.
15 |
--------------------------------------------------------------------------------
/example/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "mergeFromDirectory": null,
3 | "disableGeneratedUsingFooter": false,
4 | "abortOnInvalidSchema": false,
5 | "vueModernMode": true,
6 | "vueReport": "none",
7 | "shields": [],
8 | "i18n": {
9 | "API_SDK_DOCUMENTATION": "API and SDK Documentation",
10 | "VERSION": "version",
11 | "NO_INDEPTH_DOCS_AVAILABLE_ENDPOINT": "No in-depth API documentation is available for this endpoint.",
12 | "NO_INDEPTH_DOCS_AVAILABLE_TAG": "No in-depth API documentation is available for this section.",
13 | "CLICK_TO_COPY": "click to copy",
14 | "COPIED": "copied",
15 | "REQUEST_BODY": "Request Body",
16 | "REQUEST_RESPONSES": "Request Responses",
17 | "DEFINITION": "Definition",
18 | "DEFINITIONS": "Definitions",
19 | "SERVER": "Server",
20 | "LANGUAGE": "Language",
21 | "GENERATED_USING": "Generated using OpenDocumenter by $ourOpenCode",
22 | "HAVE_ANY_QUESTIONS_CONTACT": "Have any questions? Please contact",
23 | "US": "us",
24 | "OR": "or",
25 | "VIA_EMAIL": "via email",
26 | "VIA_OUR_WEBSITE": "via our website",
27 | "TERMS_OF_SERVICE": "Terms of Service",
28 | "SEND_US_AN_EMAIL": "Send us an email",
29 | "VISIT_OUR_WEBSITE": "Visit our website",
30 | "EXTERNAL_DOCUMENTATION": "External Documentation",
31 | "DOCUMENTATION": "Documentation"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/example/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouropencode/OpenDocumenter/8389fdab1341f5f12d37ed61b730de4ca656234f/example/example.gif
--------------------------------------------------------------------------------
/example/openapi.yml:
--------------------------------------------------------------------------------
1 | openapi: "3.0.0"
2 |
3 | info:
4 | version: 1.0.0
5 | title: Quisque API
6 | description: |
7 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc nec dui nec nisl dapibus ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut tincidunt vestibulum venenatis. Phasellus semper vehicula consectetur. Fusce convallis nulla id auctor interdum. Curabitur ut aliquam metus. Ut ac euismod elit.
8 |
9 | Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer auctor eu diam a convallis. Phasellus at maximus dui. Quisque imperdiet elementum volutpat. Integer molestie nisi hendrerit sem semper volutpat. Morbi nec porta eros. Morbi porttitor risus id massa convallis, at pharetra diam dictum.
10 |
11 | Nulla a nisl ullamcorper, scelerisque augue eu, suscipit massa. Vivamus consequat, nibh id porttitor rutrum, magna erat egestas ipsum, ac posuere neque lectus eu nibh. Etiam nunc tellus, lacinia eget luctus sit amet, rutrum et erat. Donec massa magna, finibus id vehicula vel, maximus sit amet mauris. Mauris pellentesque est a ex malesuada, a ultricies neque vulputate. Vivamus hendrerit felis a gravida tempor. Sed congue efficitur tellus, sed scelerisque lorem ultricies ac. Nullam aliquet facilisis tincidunt. Ut aliquam ipsum ac sem rutrum, ut vulputate elit porttitor.
12 | contact:
13 | name: Quisque support
14 | email: support@example.com
15 | url: https://example.com
16 | termsOfService: https://example.com/terms
17 | license:
18 | name: MIT
19 | url: https://github.com/ouropencode/OpenDocumenter/blob/master/LICENSE
20 | identifier: MIT
21 |
22 | servers:
23 | - url: https://fermentum.example.com
24 | description: Fermentum API
25 | - url: https://vestibulum.example.com
26 | description: Vestibulum API
27 |
28 | externalDocs:
29 | url: https://doc.example.com
30 | description: Curabitur eget porta
31 |
32 | tags:
33 | - name: Consectetur
34 | description: |
35 | Pellentesque sit amet metus lacinia, venenatis erat quis, gravida massa. Suspendisse facilisis porttitor nunc, in consequat augue. Vestibulum tincidunt quam vel mi dapibus, non convallis lacus porttitor. Etiam id purus nec diam vehicula feugiat ut sit amet metus. Nunc mattis dolor nec tristique ullamcorper. Integer malesuada in nisl eu consequat. Donec eu quam pellentesque, sodales neque ut, mattis ipsum. Nullam sit amet varius est. Duis et commodo leo, non suscipit eros. Nam tempor ultricies libero in bibendum. Curabitur eu bibendum erat. Morbi odio ipsum, imperdiet quis luctus at, venenatis sit amet nibh.
36 | - name: Posuere
37 | description: |
38 | Cras condimentum pulvinar venenatis. Nam sed mi in odio ornare imperdiet et eget dolor. Curabitur eros lorem, eleifend id finibus et, euismod a felis. Aliquam lobortis consectetur nisl in faucibus. In euismod consequat justo, eu auctor nunc semper in. Cras non tristique sem. Duis nec luctus augue. Etiam leo leo, malesuada in pellentesque rutrum, tempus ut sem. Duis neque velit, aliquet at malesuada congue, ultricies vehicula lacus.
39 | - name: Egestas
40 | description: |
41 | Phasellus eu felis hendrerit, volutpat odio sit amet, luctus augue. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean quis tempor lectus. Nam eu enim malesuada ex tristique congue id id orci. Duis pretium nisi a arcu efficitur, quis faucibus justo suscipit. Mauris consequat, eros eget cursus scelerisque, sapien nibh sodales elit, ut porttitor nisi lacus nec ante. Suspendisse libero leo, pharetra vel porta nec, gravida eu magna. Vivamus sit amet nisl elementum, euismod justo quis, volutpat nunc.
42 | - name: Convallis
43 | description: |
44 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar felis eget leo porta ultricies. Integer fermentum diam at ex commodo molestie. Nulla facilisi. Donec egestas metus sodales ante vulputate dignissim. Etiam ut sollicitudin ligula. Ut molestie leo nec nisl elementum mattis. Vestibulum sollicitudin tellus ut felis aliquam, a pulvinar ipsum tempus. Etiam ac faucibus arcu. Donec non lectus faucibus odio pulvinar tempus. Duis convallis dictum eros ut varius.
45 |
46 | paths:
47 | /consectetur/venenatis:
48 | get:
49 | summary: Nullam vehicula enim
50 | description: |
51 | Nullam convallis leo tortor, at vestibulum libero hendrerit at. Vivamus posuere, velit eu consectetur commodo, lectus lorem dictum felis, at commodo sem nulla sed eros. Etiam in ligula non ligula condimentum rhoncus. Phasellus aliquam lacus nisl, non hendrerit magna accumsan et. Phasellus lacinia est quis faucibus fermentum. Nulla ac sem at massa vehicula porta ac laoreet ligula. Suspendisse lobortis molestie tincidunt. Sed faucibus neque at ex feugiat, ac consequat augue aliquam.
52 | tags:
53 | - Consectetur
54 | requestBody:
55 | required: true
56 | content:
57 | application/json:
58 | example:
59 | lorem: loremipsum
60 | ipsum: ipsumlorem
61 | schema:
62 | $ref: '#/components/schemas/LoremIpsum'
63 | responses:
64 | '200':
65 | description: Vestibulum vitae tempor lorem
66 | content:
67 | application/json:
68 | example:
69 | lorem: loremipsum
70 | ipsum: ipsumlorem
71 | schema:
72 | $ref: '#/components/schemas/LoremIpsum'
73 | '404':
74 | description: Nullam blandit faucibus vehicula
75 | content:
76 | application/json:
77 | example:
78 | error: iaculis arcu vitae urna accumsan
79 | schema:
80 | $ref: '#/components/schemas/Error'
81 | '409':
82 | description: Praesent vulputate vehicula urna
83 | content:
84 | application/json:
85 | example:
86 | error: scelerisque condimentum eleifend sed
87 | schema:
88 | $ref: '#/components/schemas/Error'
89 | '418':
90 | description: Nunc enim arcu mattis at rutrum
91 | content:
92 | application/json:
93 | example:
94 | error: arcu diam laoreet nulla in vestibulum
95 | schema:
96 | $ref: '#/components/schemas/Error'
97 |
98 | /consectetur/vitae:
99 | post:
100 | summary: Phasellus nec vestibulum
101 | description: |
102 | Etiam aliquam quam ac porta venenatis. Nulla facilisi. Curabitur mollis finibus mi, et congue nisi tincidunt non. Sed eleifend justo et turpis mollis sodales. In et tortor in augue mattis congue. Vestibulum imperdiet imperdiet auctor. Quisque sit amet consequat justo, in imperdiet sapien. Integer hendrerit vehicula lacus, eget vestibulum nisi consequat eget. Morbi dapibus neque aliquam mauris lacinia venenatis. Sed facilisis libero lacus, in egestas massa scelerisque molestie. Nunc tincidunt gravida sem in gravida. Duis facilisis ultrices massa, a malesuada purus ultrices nec. Cras ac urna at nulla interdum efficitur. Sed eu arcu at ante consectetur imperdiet ut vel sem.
103 | tags:
104 | - Consectetur
105 | requestBody:
106 | required: true
107 | content:
108 | application/json:
109 | example:
110 | lorem: loremipsum
111 | ipsum: ipsumlorem
112 | schema:
113 | $ref: '#/components/schemas/LoremIpsum'
114 | responses:
115 | '200':
116 | description: Vestibulum vitae tempor lorem
117 | content:
118 | application/json:
119 | example:
120 | lorem: loremipsum
121 | ipsum: ipsumlorem
122 | schema:
123 | $ref: '#/components/schemas/LoremIpsum'
124 | '409':
125 | description: Nullam blandit faucibus vehicula
126 | content:
127 | application/json:
128 | example:
129 | error: curabitur sed lectus ac felis
130 | schema:
131 | $ref: '#/components/schemas/Error'
132 |
133 | /consectetur/pulvinar:
134 | put:
135 | summary: In tincidunt nec nisl sed ornare
136 | description: |
137 | Nullam blandit faucibus vehicula. Cras ut lectus ornare sapien euismod mollis id pharetra nulla. Aliquam a libero faucibus, posuere mi ac, blandit eros. Maecenas aliquet ultricies urna, nec laoreet lacus fermentum ut. Sed ac magna sed risus facilisis accumsan. Fusce scelerisque erat quis vestibulum varius. Quisque pretium interdum leo, a tristique turpis maximus eu.
138 | tags:
139 | - Consectetur
140 | requestBody:
141 | required: true
142 | content:
143 | application/json:
144 | example:
145 | lorem: loremipsum
146 | ipsum: ipsumlorem
147 | schema:
148 | $ref: '#/components/schemas/LoremIpsum'
149 | responses:
150 | '200':
151 | description: Nunc malesuada scelerisque sem
152 | content:
153 | application/json:
154 | example:
155 | lorem: loremipsum
156 | ipsum: ipsumlorem
157 | schema:
158 | $ref: '#/components/schemas/LoremIpsum'
159 | '409':
160 | description: Integer suscipit lacus lorem
161 | content:
162 | application/json:
163 | example:
164 | error: curabitur sed lectus ac felis
165 | schema:
166 | $ref: '#/components/schemas/Error'
167 |
168 | /consectetur/condimentum/dolor:
169 | delete:
170 | summary: Cras sed augue varius
171 | description: |
172 | Fringilla elit eget, tincidunt odio. Curabitur ultrices eget purus ut rutrum. Ut vulputate pulvinar finibus. Quisque sollicitudin velit non dui suscipit dapibus. Duis non porta nisi. Mauris et magna vitae felis imperdiet finibus. Fusce accumsan sed urna vitae vehicula. Nulla id fermentum orci. Aenean egestas ac libero at sodales. Nam in aliquam orci. Cras volutpat placerat arcu, in gravida magna pharetra at.
173 | tags:
174 | - Consectetur
175 | responses:
176 | '200':
177 | description: In ut facilisis nulla
178 | content:
179 | application/json:
180 | example:
181 | lorem: loremipsum
182 | ipsum: ipsumlorem
183 | schema:
184 | $ref: '#/components/schemas/LoremIpsum'
185 | '404':
186 | description: Aenean imperdiet nisi ac mauris
187 | content:
188 | application/json:
189 | example:
190 | error: integer leo massa
191 | schema:
192 | $ref: '#/components/schemas/Error'
193 |
194 | /posuere/mollis:
195 | get:
196 | summary: Praesent consectetur pharetra
197 | description: |
198 | Aenean a justo vel erat condimentum sollicitudin at ut velit. Mauris volutpat lectus lorem, sed rutrum felis cursus nec. Praesent dapibus, augue vitae varius viverra, ante orci gravida risus, eu aliquet ex est non metus. In ultricies sem ac dictum feugiat. Sed accumsan pretium justo vitae rutrum. Nunc in efficitur lacus. Proin sodales condimentum blandit. Maecenas consectetur accumsan vestibulum.
199 | tags:
200 | - Posuere
201 | responses:
202 | '200':
203 | description: Sed a porttitor risus id dapibus purus
204 | content:
205 | application/json:
206 | example:
207 | lorem: loremipsum
208 | ipsum: ipsumlorem
209 | schema:
210 | $ref: '#/components/schemas/LoremIpsum'
211 |
212 | /posuere/imperdiet:
213 | get:
214 | summary: Mauris volutpat lectus
215 | description: |
216 | This endpoint provides a list of all the teams the logged in user has access to.Praesent dapibus, augue vitae varius viverra, ante orci gravida risus, eu aliquet ex est non metus. In ultricies sem ac dictum feugiat. Sed accumsan pretium justo vitae rutrum. Nunc in efficitur lacus. Proin sodales condimentum blandit. Maecenas consectetur accumsan vestibulum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean facilisis lectus et rutrum sagittis.
217 | tags:
218 | - Posuere
219 | responses:
220 | '200':
221 | description: Sed a porttitor risus id dapibus purus
222 | content:
223 | application/json:
224 | example:
225 | lorem: loremipsum
226 | ipsum: ipsumlorem
227 | schema:
228 | $ref: '#/components/schemas/LoremIpsum'
229 |
230 | /egestas/{{lorem}}/aliquam:
231 | get:
232 | summary: Duis ac egestas augue
233 | description: |
234 | Pellentesque aliquet pulvinar tellus eu varius. Quisque ultrices sit amet augue tristique lobortis. Mauris id libero a nulla dignissim sodales. Vestibulum bibendum, nunc eu finibus imperdiet, magna libero ultrices dolor, eu ullamcorper urna ipsum fringilla libero. In venenatis odio a velit vestibulum fringilla. Phasellus vulputate bibendum porta. Duis mattis quis tellus nec posuere. Nunc rutrum pharetra vulputate. Praesent et metus ultrices, tristique mauris id, consectetur erat.
235 | tags:
236 | - Egestas
237 | responses:
238 | '200':
239 | description: Sed a porttitor risus id dapibus purus
240 | content:
241 | application/json:
242 | example:
243 | lorem: loremipsum
244 | ipsum: ipsumlorem
245 | schema:
246 | $ref: '#/components/schemas/LoremIpsum'
247 | '403':
248 | description: Nulla tincidunt dapibus nisi
249 | content:
250 | application/json:
251 | example:
252 | error: sit amet semper nibh
253 | schema:
254 | $ref: '#/components/schemas/Error'
255 |
256 | /convallis:
257 | post:
258 | summary: Vivamus eget leo eget
259 | description: |
260 | Etiam pellentesque ligula urna, quis feugiat ante rhoncus nec. Praesent egestas, mi a venenatis rutrum, nisl eros lacinia libero, eget consectetur lectus enim ac risus. Vivamus at eleifend justo. Mauris cursus orci lacinia vehicula vestibulum. Integer accumsan accumsan felis vel ultricies. Phasellus gravida imperdiet urna, et varius mi pharetra eu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Morbi ut nunc lacinia, euismod elit non, fermentum est. Aliquam sollicitudin sodales velit quis ultricies. Nulla sollicitudin posuere magna, eu interdum ipsum aliquet in. Vestibulum cursus at lorem non faucibus. Aliquam erat volutpat. Proin sit amet arcu ullamcorper, elementum magna a, dictum leo. Nunc lobortis cursus lacus a condimentum.
261 | tags:
262 | - Convallis
263 | responses:
264 | '200':
265 | description: Quisque ultrices sit amet
266 | content:
267 | application/json:
268 | example:
269 | lorem: loremipsum
270 | ipsum: ipsumlorem
271 | schema:
272 | $ref: '#/components/schemas/LoremIpsum'
273 |
274 | components:
275 | schemas:
276 | Error:
277 | type: object
278 | required:
279 | - error
280 | properties:
281 | error:
282 | type: string
283 |
284 | LoremIpsum:
285 | type: object
286 | required:
287 | - lorem
288 | - ipsum
289 | properties:
290 | lorem:
291 | type: string
292 | ipsum:
293 | type: string
294 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "opendocumenter",
3 | "version": "0.5.0",
4 | "author": "$ourOpenCode",
5 | "scripts": {
6 | "start": "npm-run-all dev-generate dev-serve",
7 | "dev": "nodemon -e js,vue,less,sass,css,html,json,yml --ignore tmp/ --ignore example/docs/ --exec npm start",
8 | "dev-generate": "node ./src-engine/cli.js --schema=./example/openapi.yml --output=./example/docs --config=./example/config.json",
9 | "dev-serve": "serve ./example/docs",
10 | "vue": "vue-cli-service build"
11 | },
12 | "main": "./src-engine/index.js",
13 | "dependencies": {
14 | "@apidevtools/swagger-parser": "^10.0.1",
15 | "@fortawesome/fontawesome-svg-core": "^1.2.30",
16 | "@fortawesome/free-solid-svg-icons": "^5.14.0",
17 | "@fortawesome/vue-fontawesome": "^0.1.10",
18 | "@vue/cli-plugin-babel": "~4.5.3",
19 | "@vue/cli-plugin-vuex": "~4.5.3",
20 | "@vue/cli-service": "~4.5.2",
21 | "babel-plugin-root-import": "^6.5.0",
22 | "babel-runtime": "^6.26.0",
23 | "colors": "^1.4.0",
24 | "core-js": "^3.6.5",
25 | "exec-sh": "^0.3.4",
26 | "highlight.js": "9.18.3",
27 | "less": "^3.0.4",
28 | "less-loader": "^6.2.0",
29 | "markdown-it-vue": "^1.1.3",
30 | "minimist": "^1.2.5",
31 | "npm-run-all": "^4.1.5",
32 | "recursive-copy": "^2.0.10",
33 | "uuid": "^8.3.0",
34 | "vue": "^2.6.11",
35 | "vue-cli-plugin-webfontloader": "~0.1.1",
36 | "vue-head": "^2.2.0",
37 | "vue-highlight.js": "^3.1.0",
38 | "vue-template-compiler": "^2.6.11",
39 | "vuex": "^3.4.0",
40 | "webfontloader": "^1.6.28"
41 | },
42 | "devDependencies": {
43 | "nodemon": "^2.0.4",
44 | "serve": "^11.3.2"
45 | },
46 | "bin": {
47 | "opendocumenter": "src/cli.js"
48 | },
49 | "engines": {
50 | "node": ">=14.6"
51 | },
52 | "license": "MIT"
53 | }
54 |
--------------------------------------------------------------------------------
/src-engine/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const Core = require('./index.js')
4 | const minimist = require("minimist")
5 | const colors = require("colors")
6 | const pkg = require('../package.json')
7 |
8 | const argv = minimist(process.argv.slice(2))
9 |
10 | const start = async () => {
11 | const docgen = new Core(argv.schema, argv.output, argv.config)
12 | try {
13 | await docgen.prepare()
14 | await docgen.generate()
15 | await docgen.finish()
16 | } catch(e) {
17 | let message = e.message
18 | .toString()
19 | .replace(/Swagger/gi, "OpenAPI")
20 | .split('\n')[0]
21 |
22 | docgen._displayBanner("Aborting due to error: " + message, "err")
23 | } finally {
24 | await docgen.finalize()
25 | }
26 | }
27 |
28 | console.log(`
29 | _____ ____ _
30 | | |___ ___ ___| \\ ___ ___ _ _ _____ ___ ___| |_ ___ ___
31 | | | | . | -_| | | | . | _| | | | -_| | _| -_| _|
32 | |_____| _|___|_|_|____/|___|___|___|_|_|_|___|_|_|_| |___|_|
33 | |_| ${pkg.version}
34 | `.green)
35 |
36 | if(!argv.schema || !argv.output) {
37 | console.log(`
38 | OpenDocumenter is a automatic documentation generator for OpenAPI v3 schemas.
39 | Simply provide your schema file in JSON or YAML, then sit back and enjoy the documentation.
40 |
41 | Powered by nuxt.js and swagger-parser.
42 |
43 | Usage:
44 |
45 | opendocumenter --schema= --output=
46 |
47 | Arguments:
48 |
49 | --schema= (required) The OpenAPI v3 format file to generate documentation from.
50 | --output= (required) The output destination directory.
51 | --config= A configuration file to load advanced options from.`)
52 | } else {
53 | start()
54 | }
55 |
--------------------------------------------------------------------------------
/src-engine/index.js:
--------------------------------------------------------------------------------
1 | const SwaggerParser = require("@apidevtools/swagger-parser")
2 | const copy = require("recursive-copy")
3 | const path = require("path")
4 | const fs = require("fs")
5 | const uuid = require("uuid")
6 | const colors = require("colors")
7 | const execShPromise = require("exec-sh").promise;
8 |
9 | module.exports = class Core {
10 |
11 | constructor(schema, outputDir, configFile) {
12 | this._schema = path.resolve(schema)
13 | this._outputDir = path.resolve(outputDir)
14 | this._configFile = configFile ? path.resolve(configFile) : undefined
15 |
16 | let config = {}
17 | if(this._configFile)
18 | config = JSON.parse(fs.readFileSync(this._configFile))
19 |
20 | this._config = {
21 | "mergeFromDirectory": null,
22 | "disableGeneratedUsingFooter": false,
23 | "abortOnInvalidSchema": false,
24 | "vueModernMode": true,
25 | "vueReport": "none",
26 | "shields": [],
27 | "i18n": {},
28 | ...config
29 | }
30 |
31 | this._config.i18n = {
32 | "API_SDK_DOCUMENTATION": "API and SDK Documentation",
33 | "VERSION": "version",
34 | "NO_INDEPTH_DOCS_AVAILABLE_ENDPOINT": "No in-depth API documentation is available for this endpoint.",
35 | "NO_INDEPTH_DOCS_AVAILABLE_TAG": "No in-depth API documentation is available for this section.",
36 | "CLICK_TO_COPY": "click to copy",
37 | "COPIED": "copied",
38 | "REQUEST_BODY": "Request Body",
39 | "REQUEST_RESPONSES": "Request Responses",
40 | "DEFINITION": "Definition",
41 | "DEFINITIONS": "Definitions",
42 | "SERVER": "Server",
43 | "LANGUAGE": "Language",
44 | "GENERATED_USING": "Generated using OpenDocumenter by $ourOpenCode",
45 | "HAVE_ANY_QUESTIONS_CONTACT": "Have any questions? Please contact",
46 | "US": "us",
47 | "OR": "or",
48 | "VIA_EMAIL": "via email",
49 | "VIA_OUR_WEBSITE": "via our website",
50 | "EXTERNAL_DOCUMENTATION": "External Documentation",
51 | "DOCUMENTATION": "Documentation",
52 | ...config.i18n
53 | }
54 |
55 | if(this._config.mergeFromDirectory != null)
56 | this._mrgPath = path.resolve(this._config.mergeFromDirectory)
57 |
58 | this._srcPath = path.join(__dirname, '..', 'src')
59 | this._tmpPath = path.join(__dirname, '..', 'tmp', uuid.v4(), 'src')
60 | this._cwd = process.cwd()
61 | }
62 |
63 | async prepare() {
64 | this._api = await this.loadAPI(this._schema)
65 |
66 | this._displayInfo()
67 |
68 | await copy(this._srcPath, this._tmpPath, { dot: true })
69 |
70 | await copy(
71 | path.join(this._srcPath, "vue.config.js"),
72 | path.join(this._tmpPath, "..", "vue.config.js")
73 | )
74 |
75 | await copy(
76 | "package.json",
77 | path.join(this._tmpPath, "..", "package.json")
78 | )
79 |
80 | if(this._config.mergeFromDirectory != null)
81 | await copy(this._mrgPath, this._tmpPath, { overwrite: true, dot: true })
82 |
83 | fs.writeFileSync(path.join(this._tmpPath, "environment.json"), JSON.stringify({
84 | ...this._config,
85 | api: this._api,
86 | }))
87 | }
88 |
89 | async finish() {
90 | fs.rmdirSync(this._outputDir, { recursive: true });
91 |
92 | const results = await copy(path.join(this._tmpPath, "..", "dist"), this._outputDir)
93 |
94 | this._displayBanner(`OpenDocumenter finished! ${results.length} files created.`)
95 | }
96 |
97 | async finalize() {
98 | process.chdir(this._cwd)
99 | fs.rmdirSync(this._tmpPath, { recursive: true })
100 | }
101 |
102 | async generate(file) {
103 | process.chdir(path.resolve(this._tmpPath, '..'))
104 |
105 | let flags = []
106 |
107 | if(this._config.vueModernMode == true)
108 | flags.push("--modern")
109 |
110 | if(this._config.vueReport == "html" || this._config.vueReport == "both")
111 | flags.push("--report")
112 |
113 | if(this._config.vueReport == "json" || this._config.vueReport == "both")
114 | flags.push("--report-json")
115 |
116 | flags = flags.join(' ')
117 |
118 | let flagStr = flags.length > 0 ? `with flags: ${flags}` : ''
119 | this._displayBanner(`Starting build ${flagStr}`)
120 | await execShPromise(`vue-cli-service build ${flags}`)
121 | }
122 |
123 | async loadAPI(file) {
124 | let api = await SwaggerParser.parse(file)
125 |
126 | try {
127 | api = await SwaggerParser.validate(file)
128 | } catch(e) {
129 | if(e.name != "SyntaxError") throw e
130 | this._displaySchemaSyntaxError(e.details)
131 | if(this._config.abortOnInvalidSchema == true)
132 | throw e
133 | }
134 |
135 | return api
136 | }
137 |
138 | async _displayBanner(text, type = "default") {
139 | let prefix = "---";
140 | let color = "green"
141 |
142 | if(type == "warn" || type == "warning") {
143 | prefix = "???"
144 | color = "yellow"
145 | }
146 |
147 | if(type == "err" || type == "error") {
148 | prefix = "!!!"
149 | color = "red"
150 | }
151 |
152 | console.log()
153 | console.log(` ${prefix} ${text}`.bold[color])
154 | console.log()
155 | }
156 |
157 | async _displayInfo() {
158 | this._displayBanner("API Details")
159 | console.log(` Name: ${this._api.info.title}`)
160 | console.log(` Version: ${this._api.info.version}`)
161 | console.log(` Schema: ${this._schema}`)
162 | console.log(` Output: ${this._outputDir}`)
163 | if(this._configFile)
164 | console.log(` Config: ${this._configFile}`)
165 | }
166 |
167 | async _displaySchemaSyntaxError(details) {
168 | this._displayBanner("OpenAPI schema validation failed", "warn")
169 | details.forEach((issue, idx) => {
170 | console.log(" - #/" + issue.path.join('/'))
171 | console.log(" " + issue.message)
172 | if(idx != details.length - 1)
173 | console.log()
174 | })
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@vue/cli-plugin-babel/preset"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/src/assets/highlighter-theme-dark.less:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull
4 |
5 | */
6 |
7 | .hljs {
8 | display: block;
9 | overflow-x: auto;
10 | padding: 0.5em;
11 | background: #002b36;
12 | color: #839496;
13 | }
14 |
15 | .hljs-comment,
16 | .hljs-quote {
17 | color: #586e75;
18 | }
19 |
20 | /* Solarized Green */
21 | .hljs-keyword,
22 | .hljs-selector-tag,
23 | .hljs-addition {
24 | color: #859900;
25 | }
26 |
27 | /* Solarized Cyan */
28 | .hljs-number,
29 | .hljs-string,
30 | .hljs-meta .hljs-meta-string,
31 | .hljs-literal,
32 | .hljs-doctag,
33 | .hljs-regexp {
34 | color: #2aa198;
35 | }
36 |
37 | /* Solarized Blue */
38 | .hljs-title,
39 | .hljs-section,
40 | .hljs-name,
41 | .hljs-selector-id,
42 | .hljs-selector-class {
43 | color: #268bd2;
44 | }
45 |
46 | /* Solarized Yellow */
47 | .hljs-attribute,
48 | .hljs-attr,
49 | .hljs-variable,
50 | .hljs-template-variable,
51 | .hljs-class .hljs-title,
52 | .hljs-type {
53 | color: #b58900;
54 | }
55 |
56 | /* Solarized Orange */
57 | .hljs-symbol,
58 | .hljs-bullet,
59 | .hljs-subst,
60 | .hljs-meta,
61 | .hljs-meta .hljs-keyword,
62 | .hljs-selector-attr,
63 | .hljs-selector-pseudo,
64 | .hljs-link {
65 | color: #cb4b16;
66 | }
67 |
68 | /* Solarized Red */
69 | .hljs-built_in,
70 | .hljs-deletion {
71 | color: #dc322f;
72 | }
73 |
74 | .hljs-formula {
75 | background: #073642;
76 | }
77 |
78 | .hljs-emphasis {
79 | font-style: italic;
80 | }
81 |
82 | .hljs-strong {
83 | font-weight: bold;
84 | }
85 |
--------------------------------------------------------------------------------
/src/assets/highlighter-theme-light.less:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull
4 |
5 | */
6 |
7 | .hljs {
8 | display: block;
9 | overflow-x: auto;
10 | padding: 0.5em;
11 | background: #fdf6e3;
12 | color: #657b83;
13 | }
14 |
15 | .hljs-comment,
16 | .hljs-quote {
17 | color: #93a1a1;
18 | }
19 |
20 | /* Solarized Green */
21 | .hljs-keyword,
22 | .hljs-selector-tag,
23 | .hljs-addition {
24 | color: #859900;
25 | }
26 |
27 | /* Solarized Cyan */
28 | .hljs-number,
29 | .hljs-string,
30 | .hljs-meta .hljs-meta-string,
31 | .hljs-literal,
32 | .hljs-doctag,
33 | .hljs-regexp {
34 | color: #2aa198;
35 | }
36 |
37 | /* Solarized Blue */
38 | .hljs-title,
39 | .hljs-section,
40 | .hljs-name,
41 | .hljs-selector-id,
42 | .hljs-selector-class {
43 | color: #268bd2;
44 | }
45 |
46 | /* Solarized Yellow */
47 | .hljs-attribute,
48 | .hljs-attr,
49 | .hljs-variable,
50 | .hljs-template-variable,
51 | .hljs-class .hljs-title,
52 | .hljs-type {
53 | color: #b58900;
54 | }
55 |
56 | /* Solarized Orange */
57 | .hljs-symbol,
58 | .hljs-bullet,
59 | .hljs-subst,
60 | .hljs-meta,
61 | .hljs-meta .hljs-keyword,
62 | .hljs-selector-attr,
63 | .hljs-selector-pseudo,
64 | .hljs-link {
65 | color: #cb4b16;
66 | }
67 |
68 | /* Solarized Red */
69 | .hljs-built_in,
70 | .hljs-deletion {
71 | color: #dc322f;
72 | }
73 |
74 | .hljs-formula {
75 | background: #eee8d5;
76 | }
77 |
78 | .hljs-emphasis {
79 | font-style: italic;
80 | }
81 |
82 | .hljs-strong {
83 | font-weight: bold;
84 | }
85 |
--------------------------------------------------------------------------------
/src/assets/theme.less:
--------------------------------------------------------------------------------
1 | /**
2 | * Colors
3 | */
4 |
5 | @color-body-background: white;
6 | @color-body-text: black;
7 |
8 | @color-body-link: #292b36;
9 | @color-body-link-hover: #8b8fa7;
10 |
11 | @color-sidebar-background: #f5f5f5;
12 | @color-sidebar-link: #16171d;
13 | @color-sidebar-link-hover: #8b8fa7;
14 |
15 | @color-split-background: #16171d;
16 | @color-split-text: white;
17 |
18 | @color-code-background: white;
19 | @color-code-text: black;
20 | @color-code-dark-background: #292b36;
21 | @color-code-dark-text: white;
22 |
23 | @color-toolbox-text: white;
24 | @color-toolbox-background: #292b36;
25 | @color-toolbox-active-background: #292b36;
26 | @color-toolbox-dropdown-background: white;
27 | @color-toolbox-link: #16171d;
28 | @color-toolbox-link-hover: #8b8fa7;
29 |
30 | @color-header-version: #808080;
31 | @color-header-intro: #808080;
32 |
33 | @color-help-text: #292b36;
34 |
35 | @color-endpoint-text: white;
36 | @color-endpoint-unk: #3387CC;
37 | @color-endpoint-get: green;
38 | @color-endpoint-put: #e5c500;
39 | @color-endpoint-post: #4070ec;
40 | @color-endpoint-delete: #ff4e3f;
41 |
42 | /**
43 | * Fonts
44 | */
45 |
46 | @primary-font: Montserrat, sans-serif;
47 | @secondary-font: Roboto, sans-serif;
48 | @monospace-font: "Source Code Pro", monospace;
49 |
50 | .theme-font-title() {
51 | font-family: @primary-font;
52 | font-weight: 400;
53 | font-size: 2.5em;
54 | }
55 |
56 | .theme-font-subtitle() {
57 | font-family: @primary-font;
58 | font-weight: 400;
59 | font-size: 1.8em;
60 | }
61 |
62 | .theme-font-summary() {
63 | font-family: @primary-font;
64 | font-weight: 400;
65 | font-size: 1.2em;
66 | }
67 |
68 | .theme-font-tag-title() {
69 | font-family: @primary-font;
70 | font-weight: 400;
71 | font-size: 1.6em;
72 | }
73 |
74 | .theme-font-entry-title() {
75 | font-family: @primary-font;
76 | font-weight: 400;
77 | font-size: 1.2em;
78 | }
79 |
80 | .theme-font-entry-subtitle() {
81 | font-family: @primary-font;
82 | font-weight: 400;
83 | font-size: 1em;
84 | }
85 |
86 | .theme-font-body() {
87 | font-family: @secondary-font;
88 | font-weight: 400;
89 | font-size: 1em;
90 | }
91 |
92 | .theme-font-code() {
93 | font-family: @monospace-font;
94 | font-weight: 400;
95 | font-size: 1em;
96 | }
97 |
--------------------------------------------------------------------------------
/src/assets/utils.less:
--------------------------------------------------------------------------------
1 | .truncated() {
2 | white-space: nowrap;
3 | overflow: hidden;
4 | text-overflow: ellipsis;
5 | }
6 |
--------------------------------------------------------------------------------
/src/components/ContactTeam.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
30 |
31 |
40 |
--------------------------------------------------------------------------------
/src/components/DocEntry.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ $i18n('NO_INDEPTH_DOCS_AVAILABLE_ENDPOINT') }}
7 |
8 |
9 |
{{ $i18n('REQUEST_BODY') }}
10 |
11 |
12 |
13 |
14 |
{{ $i18n('REQUEST_RESPONSES') }}
15 |
16 |
17 |
18 |
19 |
20 |
21 | "
22 |
23 |
24 |
25 |
26 |
27 |
28 |
59 |
60 |
78 |
--------------------------------------------------------------------------------
/src/components/DocEntryTitle.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
20 |
21 |
46 |
--------------------------------------------------------------------------------
/src/components/DocFooter.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
21 |
22 |
58 |
--------------------------------------------------------------------------------
/src/components/DocHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
30 |
63 |
64 |
95 |
--------------------------------------------------------------------------------
/src/components/DocLayout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
34 |
35 |
64 |
--------------------------------------------------------------------------------
/src/components/DocSidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
26 |
27 |
28 |
35 |
36 |
43 |
--------------------------------------------------------------------------------
/src/components/DocSidebarEntry.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
24 |
25 |
59 |
--------------------------------------------------------------------------------
/src/components/DocSidebarTag.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
18 |
19 |
20 |
41 |
42 |
64 |
--------------------------------------------------------------------------------
/src/components/DocTag.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ tag.name }}
5 |
6 |
7 |
8 |
{{ $i18n('NO_INDEPTH_DOCS_AVAILABLE_TAG') }}
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
30 |
31 |
43 |
--------------------------------------------------------------------------------
/src/components/DocToolbox.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
76 |
77 |
91 |
--------------------------------------------------------------------------------
/src/components/DocToolboxDropdown.vue:
--------------------------------------------------------------------------------
1 |
2 |
29 |
30 |
31 |
53 |
54 |
116 |
--------------------------------------------------------------------------------
/src/components/DocToolboxIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
27 |
--------------------------------------------------------------------------------
/src/components/Endpoint.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ path }}
5 |
6 |
7 |
8 | {{ method }}
9 |
10 |
11 |
12 | {{ $i18n('COPIED') }}
13 | {{ $i18n('CLICK_TO_COPY') }}
14 |
15 |
16 |
17 |
18 |
50 |
51 |
113 |
--------------------------------------------------------------------------------
/src/components/Example.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
16 |
17 |
37 |
--------------------------------------------------------------------------------
/src/components/Highlight.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ content }}
4 |
5 |
6 |
7 |
34 |
35 |
65 |
--------------------------------------------------------------------------------
/src/components/Markdown.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
36 |
--------------------------------------------------------------------------------
/src/components/ReqBody.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
23 |
--------------------------------------------------------------------------------
/src/components/ReqResponse.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ response.description }}
8 |
9 |
10 |
11 |
12 |
13 |
22 |
23 |
45 |
--------------------------------------------------------------------------------
/src/components/Shield.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
31 |
32 |
38 |
--------------------------------------------------------------------------------
/src/components/SplitSection.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
41 |
--------------------------------------------------------------------------------
/src/components/StatusCode.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ code }}
4 |
{{ friendlyCode(code) }}
5 |
6 |
7 |
8 |
62 |
63 |
74 |
--------------------------------------------------------------------------------
/src/environment.json:
--------------------------------------------------------------------------------
1 | {
2 | "api": {
3 | "openapi": "0.0.0",
4 | "info": {},
5 | "servers": [],
6 | "paths": {},
7 | "components": {},
8 | "security": [],
9 | "tags": [],
10 | "externalDocs": []
11 | },
12 | "i18n": {}
13 | }
14 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Loading Documentation...
8 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | import './plugins/codegen'
4 | import envInject from './plugins/envInject'
5 |
6 | Vue.config.productionTip = false
7 |
8 | // Setup webfonts
9 | import WebFont from 'webfontloader'
10 | WebFont.load({
11 | google: {
12 | families: ["Montserrat:200,400", "Roboto:400,700", "Source Code Pro:400"]
13 | }
14 | })
15 |
16 | // Setup vue-head
17 | import VueHead from 'vue-head'
18 | Vue.use(VueHead)
19 |
20 | // Setup vue-highlight.js
21 | import VueHighlightJS from 'vue-highlight.js'
22 | import 'vue-highlight.js/lib/allLanguages'
23 | import 'highlight.js/styles/default.css'
24 | Vue.use(VueHighlightJS)
25 |
26 | // Setup fontawesome
27 | import { library } from '@fortawesome/fontawesome-svg-core'
28 | import { faChevronDown, faCog, faHeart, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'
29 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
30 | library.add(faChevronDown)
31 | library.add(faCog)
32 | library.add(faHeart)
33 | library.add(faQuestionCircle)
34 | Vue.component('font-awesome-icon', FontAwesomeIcon)
35 |
36 | // Smooth scrolling helper function
37 | Vue.prototype.$smoothScroll = id => {
38 | history.pushState({}, '', "#" + id)
39 | if(id == "") id = "top"
40 | let ele = document.getElementById(id)
41 | if(!ele)
42 | return console.log("cannot scroll to missing ele", id)
43 | document.getElementById(id).scrollIntoView({
44 | behavior: "smooth"
45 | })
46 | }
47 |
48 | // Path hashing function
49 | Vue.prototype.$hashPath = (path, method) => {
50 | path = path.replace(/[^a-zA-Z0-9_-]+/g, "-")
51 | let hash = `${method}-${path}`
52 | return hash.replace(/-+$/g, "").toLowerCase()
53 | }
54 |
55 | // Initialise Vue
56 | import store from './store'
57 | import index from './index.vue'
58 | ;(async () => {
59 | await envInject()
60 | new Vue({
61 | store: store,
62 | render: h => h(index)
63 | }).$mount('#app')
64 | })()
65 |
--------------------------------------------------------------------------------
/src/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
34 |
35 |
61 |
--------------------------------------------------------------------------------
/src/plugins/codegen.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import store from '@/store'
3 |
4 | const generators = {
5 |
6 | curl(server, def) {
7 | let cmd = `curl -X ${def.method.toUpperCase()} "${server}${def.path}"`
8 |
9 | if (def.requestBody) {
10 | if(def.requestBody.content['application/json']) {
11 | let example = JSON.stringify(def.requestBody.content['application/json'].example || {});
12 | cmd += ` -H "Content-Type: application/json" --data ${example}`
13 | }
14 | }
15 |
16 | return cmd
17 | },
18 |
19 | }
20 |
21 | const codegen = (lang, def) => {
22 | const server = store.getters.currentServer
23 | if(!generators[lang])
24 | return ""
25 | return generators[lang](server, def)
26 | }
27 |
28 | Vue.prototype.$codegen = codegen
29 |
--------------------------------------------------------------------------------
/src/plugins/envInject.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import SwaggerParser from '@apidevtools/swagger-parser'
3 | import Environment from '../environment.json'
4 |
5 | const addSaneDefaults = api => {
6 | api.info = {
7 | title: "Untitled",
8 | version: "0.0.0",
9 | description: "",
10 | ...api.info
11 | }
12 | }
13 |
14 | const addPathMethodAndDefaultTags = api => {
15 | for(let path in api.paths) {
16 | for(let method in api.paths[path]) {
17 | const def = api.paths[path][method]
18 | def.path = path
19 | def.method = method
20 | if(!Array.isArray(def.tags) || def.tags.length == 0) {
21 | def.tags = ['default']
22 | if(api.tags.filter(t => t.name == 'default').length == 0)
23 | api.tags.push({ name: "default" })
24 | }
25 | }
26 | }
27 | }
28 |
29 | const addPathsToTags = api => {
30 | api.tags.forEach(tag => {
31 | tag.paths = {}
32 | for(let path in api.paths) {
33 | for(let method in api.paths[path]) {
34 | const def = api.paths[path][method]
35 | if(def.tags.indexOf(tag.name) !== -1) {
36 | if(tag.paths[path] == undefined)
37 | tag.paths[path] = {}
38 | tag.paths[path][method] = def
39 | }
40 | }
41 | }
42 | })
43 | }
44 |
45 | export default async () => {
46 | let api = Environment.api
47 | addSaneDefaults(api)
48 | addPathMethodAndDefaultTags(api)
49 | addPathsToTags(api)
50 | api = await SwaggerParser.bundle(api)
51 |
52 | Vue.prototype.$api = api
53 | Vue.prototype.$config = Environment
54 | Vue.prototype.$i18n = key => Environment.i18n[key] || key
55 |
56 | console.log(`API name: ${api.info.title}, Version: ${api.info.version}`)
57 | }
58 |
--------------------------------------------------------------------------------
/src/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | Vue.use(Vuex)
4 |
5 | const state = () => ({
6 | currentServer: '',
7 | currentLang: '',
8 | showDefinition: false,
9 | })
10 |
11 | const mutations = {
12 | setServer(state, server) {
13 | state.currentServer = server
14 | },
15 | setLang(state, lang) {
16 | state.currentLang = lang
17 | },
18 | setShowDefinition(state, show) {
19 | state.showDefinition = show
20 | },
21 | }
22 |
23 | const getters = {
24 | currentServer: state => state.currentServer,
25 | currentLang: state => state.currentLang,
26 | showDefinition: state => state.showDefinition,
27 | }
28 |
29 | export default new Vuex.Store({
30 | state,
31 | mutations,
32 | getters,
33 | })
34 |
--------------------------------------------------------------------------------
/src/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "publicPath": "./",
3 | pages: {
4 | index: {
5 | entry: 'src/index.js',
6 | template: 'src/index.html',
7 | filename: 'index.html',
8 | title: 'Loading Documentation...',
9 | },
10 | },
11 | }
12 |
--------------------------------------------------------------------------------