├── .nvmrc ├── .vscode └── settings.json ├── .npmrc ├── .gitignore ├── jsdoc-template ├── tmpl │ ├── example.tmpl │ ├── source.tmpl │ ├── mainpage.tmpl │ ├── type.tmpl │ ├── augments.tmpl │ ├── examples.tmpl │ ├── returns.tmpl │ ├── tutorial.tmpl │ ├── exceptions.tmpl │ ├── members.tmpl │ ├── layout.tmpl │ ├── method.tmpl │ ├── properties.tmpl │ ├── params.tmpl │ ├── details.tmpl │ └── container.tmpl ├── static │ ├── styles │ │ ├── arrow-down.svg │ │ ├── hljs.css │ │ └── jsdoc.css │ └── scripts │ │ └── hljs │ │ └── highlight.min.js └── publish.js ├── .github ├── CODEOWNERS ├── workflows │ ├── dependabot-approve-and-request-merge.yml │ ├── main.yaml │ ├── codeql.yml │ └── release.yaml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml └── PULL_REQUEST_TEMPLATE.md ├── README.md ├── .contentful └── vault-secrets.yaml ├── catalog-info.yaml ├── LICENSE ├── bin └── publish-docs.sh └── package.json /.nvmrc: -------------------------------------------------------------------------------- 1 | v18 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-scripts=true 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .lock-wscript 4 | out 5 | *.swp 6 | *.swp 7 | *.swo 8 | .idea 9 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/example.tmpl: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @contentful/team-developer-experience 2 | 3 | package.json 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # contentful-sdk-jsdoc 2 | 3 | 4 | Contentful [JSDoc](http://usejsdoc.org/) template for [contentful.js](https://contentful.github.io/contentful.js) and [contentful-management.js](contentful.github.io/contentful-management.js). 5 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/source.tmpl: -------------------------------------------------------------------------------- 1 | 4 |
5 |
6 |
7 |
8 |
-------------------------------------------------------------------------------- /jsdoc-template/tmpl/mainpage.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |
8 |
9 |
10 | 11 | -------------------------------------------------------------------------------- /.contentful/vault-secrets.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | services: 3 | github-action: 4 | policies: 5 | - dependabot 6 | - semantic-release 7 | - packages-read 8 | circleci: 9 | policies: 10 | - semantic-release-ecosystem 11 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/type.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | | 7 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/augments.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /jsdoc-template/static/styles/arrow-down.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/examples.tmpl: -------------------------------------------------------------------------------- 1 | 8 |

9 | 10 |
11 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/returns.tmpl: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 |
8 | 9 | 10 | 11 |
12 |
13 | Type 14 |
15 |
16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /jsdoc-template/static/styles/hljs.css: -------------------------------------------------------------------------------- 1 | // Syntax highlighting 2 | .hljs-attr { 3 | color: #8091a5; 4 | } 5 | 6 | .hljs-string { 7 | color: #16c98d; 8 | } 9 | 10 | .hljs-literal { 11 | color: #e0534e; 12 | } 13 | 14 | .hljs-number { 15 | color: #5b9fef; 16 | } 17 | 18 | .hljs-comment { 19 | color: #a9b9c0; 20 | } 21 | 22 | .hljs-keyword, 23 | .hljs-built_in { 24 | color: #4a90e2; 25 | font-weight: bold; 26 | } 27 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/tutorial.tmpl: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 0) { ?> 5 | 10 | 11 | 12 |

13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-approve-and-request-merge.yml: -------------------------------------------------------------------------------- 1 | name: "dependabot approve-and-request-merge" 2 | 3 | on: pull_request_target 4 | 5 | jobs: 6 | worker: 7 | permissions: 8 | contents: write 9 | id-token: write 10 | runs-on: ubuntu-latest 11 | if: github.actor == 'dependabot[bot]' 12 | steps: 13 | - uses: contentful/github-auto-merge@v1 14 | with: 15 | VAULT_URL: ${{ secrets.VAULT_URL }} 16 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | permissions: 3 | contents: read 4 | 5 | on: 6 | push: 7 | branches: ['**'] 8 | 9 | jobs: 10 | 11 | release: 12 | if: github.event_name == 'push' && contains(fromJSON('["refs/heads/master", "refs/heads/dev"]'), github.ref) 13 | permissions: 14 | contents: write 15 | id-token: write 16 | actions: read 17 | uses: ./.github/workflows/release.yaml 18 | secrets: 19 | VAULT_URL: ${{ secrets.VAULT_URL }} 20 | -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backstage.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: contentful-sdk-jsdoc 5 | description: Contentful JSDoc template for contentful.js and contentful-management.js 6 | annotations: 7 | github.com/project-slug: contentful/contentful-sdk-jsdoc 8 | contentful.com/ci-alert-slack: prd-ecosystem-dx-bots 9 | contentful.com/service-tier: "4" 10 | tags: 11 | - tier-4 12 | spec: 13 | type: library 14 | lifecycle: production 15 | owner: group:team-developer-experience 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Question or Discussion 4 | url: https://github.com/contentful/contentful-sdk-jsdoc/discussions 5 | about: Ask questions or discuss ideas with the community 6 | - name: Documentation 7 | url: https://contentful.com/docs 8 | about: Check out our documentation for help and guides 9 | - name: Security Vulnerability 10 | url: https://github.com/contentful/contentful-sdk-jsdoc/security/advisories/new 11 | about: Report a security vulnerability privately 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Enable version updates for npm 4 | - package-ecosystem: 'npm' 5 | directory: '/' 6 | schedule: 7 | interval: 'weekly' 8 | day: 'monday' 9 | open-pull-requests-limit: 10 10 | reviewers: 11 | - 'contentful/team-developer-experience' 12 | labels: 13 | - 'dependencies' 14 | commit-message: 15 | prefix: 'chore' 16 | include: 'scope' 17 | ignore: 18 | - dependency-name: husky 19 | versions: 20 | - ">=5.0.0" 21 | 22 | cooldown: 23 | default-days: 15 -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "CodeQL Scan for GitHub Actions Workflows" 3 | 4 | on: 5 | push: 6 | branches: [master] 7 | paths: [".github/workflows/**"] 8 | pull_request: 9 | branches: [master] 10 | paths: [".github/workflows/**"] 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze GitHub Actions workflows 15 | runs-on: ubuntu-latest 16 | permissions: 17 | actions: read 18 | contents: read 19 | security-events: write 20 | 21 | steps: 22 | - uses: actions/checkout@v5 23 | 24 | - name: Initialize CodeQL 25 | uses: github/codeql-action/init@v4 26 | with: 27 | languages: actions 28 | 29 | - name: Run CodeQL Analysis 30 | uses: github/codeql-action/analyze@v4 31 | with: 32 | category: actions 33 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | ## Summary 9 | 10 | 11 | 12 | ## Description 13 | 14 | 15 | 16 | ## Motivation and Context 17 | 18 | 22 | 23 | ## PR Checklist 24 | 25 | - [ ] I have read the `CONTRIBUTING.md` file 26 | - [ ] All commits follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) 27 | - [ ] Documentation is updated (if necessary) 28 | - [ ] PR doesn't contain any sensitive information 29 | - [ ] There are no breaking changes 30 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/exceptions.tmpl: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 |
8 | 9 |
10 |
11 |
12 |
13 |
14 |
15 | Type 16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 |
24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/members.tmpl: -------------------------------------------------------------------------------- 1 | 5 |

6 | 7 | 8 |

9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 | 20 |
Type:
21 | 26 | 27 | 28 | 29 |
Fires:
30 | 33 | 34 | 35 | 36 |
Example 1? 's':'' ?>
37 | 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Contentful 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a report to help us improve 4 | title: '[BUG] ' 5 | labels: bug 6 | assignees: '' 7 | --- 8 | 9 | ## Bug Description 10 | 11 | A clear and concise description of what the bug is. 12 | 13 | ## Steps to Reproduce 14 | 15 | 1. Go to '...' 16 | 2. Execute '...' 17 | 3. See error 18 | 19 | ## Expected Behavior 20 | 21 | A clear and concise description of what you expected to happen. 22 | 23 | ## Actual Behavior 24 | 25 | A clear and concise description of what actually happened. 26 | 27 | ## Code Sample 28 | 29 | ```javascript 30 | // Minimal code to reproduce the issue 31 | ``` 32 | 33 | ## Environment 34 | 35 | - OS: [e.g. macOS 13.0, Windows 11, Ubuntu 22.04] 36 | - Package Version: [e.g. 1.2.3] 37 | - Node Version: [e.g. 18.0.0] 38 | - Package Manager: [e.g. npm 9.0.0, yarn 1.22.0] 39 | 40 | ## Error Messages/Logs 41 | 42 | ``` 43 | Paste any error messages or relevant logs here 44 | ``` 45 | 46 | ## Screenshots 47 | 48 | If applicable, add screenshots to help explain your problem. 49 | 50 | ## Additional Context 51 | 52 | Add any other context about the problem here. 53 | 54 | ## Possible Solution 55 | 56 | If you have suggestions on how to fix the bug, please describe them here. 57 | -------------------------------------------------------------------------------- /bin/publish-docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | REPO_NAME=$1 5 | NAMESPACE=$2 6 | PAGES_DIR=./gh-pages 7 | DOCS_DIR=./out 8 | if [[ -n "${GITHUB_TOKEN}" ]]; then # If the GITHUB_TOKEN (which is an app token) is not empty we use an app token auth URL 9 | REPO="https://x-access-token:${GITHUB_TOKEN}@github.com/contentful/${REPO_NAME}.git" 10 | else # Legacy variant 11 | REPO="https://${GH_TOKEN}@github.com/contentful/${REPO_NAME}.git" 12 | fi 13 | 14 | 15 | VERSION=$(cat package.json | jq -r .version) 16 | 17 | echo "Publishing docs" 18 | 19 | if ! [ -d $DOCS_DIR ] ; then 20 | echo "Docs can't be found. Maybe you haven't generated them?" 21 | exit 1 22 | fi 23 | 24 | # get the gh-pages branch of the repo 25 | if [ ! -d $PAGES_DIR ] ; then 26 | git clone --single-branch --branch gh-pages $REPO $PAGES_DIR 27 | fi 28 | 29 | if ! [ -d $PAGES_DIR/$NAMESPACE/$VERSION ] ; then 30 | mkdir $PAGES_DIR/$NAMESPACE/$VERSION 31 | fi 32 | cp -r $DOCS_DIR/* $PAGES_DIR/$NAMESPACE/$VERSION 33 | 34 | rm -rf $PAGES_DIR/$NAMESPACE/latest 35 | 36 | cp -r $PAGES_DIR/$NAMESPACE/$VERSION $PAGES_DIR/$NAMESPACE/latest 37 | 38 | echo "" > $PAGES_DIR/index.html 39 | 40 | pushd $PAGES_DIR 41 | git add . 42 | git commit -a -m "Docs update for $VERSION [skip ci]" 43 | if [ $? -eq 1 ] ; then 44 | echo "Nothing to update" 45 | else 46 | git push origin gh-pages 47 | fi 48 | popd 49 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/layout.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <?js= title ?> - Documentation 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 26 | 27 |
28 | 29 |

30 | 31 | 32 | 33 |
34 | 35 |
36 | 37 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "contentful-sdk-jsdoc", 3 | "version": "2.2.0", 4 | "description": "JSDoc template and config for the Contentful JS SDKs", 5 | "homepage": "https://www.contentful.com/developers/docs/javascript/", 6 | "main": "index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/contentful/contentful-sdk-jsdoc.git" 10 | }, 11 | "author": "Contentful ", 12 | "license": "MIT", 13 | "scripts": { 14 | "test": "true", 15 | "semantic-release": "semantic-release" 16 | }, 17 | "files": [ 18 | "jsdoc*", 19 | "bin" 20 | ], 21 | "devDependencies": { 22 | "@semantic-release/changelog": "^6.0.0", 23 | "cz-conventional-changelog": "^3.3.0", 24 | "jsdoc": "^4.0.0", 25 | "json": "^11.0.0", 26 | "semantic-release": "^25.0.2" 27 | }, 28 | "config": { 29 | "commitizen": { 30 | "path": "./node_modules/cz-conventional-changelog" 31 | } 32 | }, 33 | "release": { 34 | "branches": [ 35 | "master", 36 | { 37 | "name": "dev", 38 | "channel": "dev", 39 | "prerelease": true 40 | } 41 | ], 42 | "plugins": [ 43 | [ 44 | "@semantic-release/commit-analyzer", 45 | { 46 | "releaseRules": [ 47 | { 48 | "type": "build", 49 | "scope": "deps", 50 | "release": "patch" 51 | } 52 | ] 53 | } 54 | ], 55 | "@semantic-release/release-notes-generator", 56 | "@semantic-release/npm", 57 | "@semantic-release/changelog", 58 | "@semantic-release/github" 59 | ] 60 | }, 61 | "dependencies": { 62 | "@jsdoc/salty": "^0.2.8" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for this project 4 | title: '[FEATURE] ' 5 | labels: enhancement 6 | assignees: '' 7 | --- 8 | 9 | ## Feature Description 10 | 11 | A clear and concise description of the feature you'd like to see. 12 | 13 | ## Problem Statement 14 | 15 | Is your feature request related to a problem? Please describe. 16 | Example: I'm always frustrated when [...] 17 | 18 | ## Proposed Solution 19 | 20 | A clear and concise description of what you want to happen. 21 | 22 | ## Use Case 23 | 24 | Describe the use case for this feature. How would you use it? 25 | 26 | ```javascript 27 | // Example of how the feature would be used 28 | const example = new Feature({ 29 | option: 'value', 30 | }); 31 | ``` 32 | 33 | ## Alternatives Considered 34 | 35 | A clear and concise description of any alternative solutions or features you've considered. 36 | 37 | ## Benefits 38 | 39 | What are the benefits of implementing this feature? 40 | 41 | - Benefit 1 42 | - Benefit 2 43 | - Benefit 3 44 | 45 | ## Potential Drawbacks 46 | 47 | Are there any potential drawbacks or challenges with this feature? 48 | 49 | ## Additional Context 50 | 51 | Add any other context, screenshots, or examples about the feature request here. 52 | 53 | ## Implementation Suggestions 54 | 55 | If you have ideas about how this could be implemented, please share them here. 56 | 57 | ## Priority 58 | 59 | How important is this feature to you? 60 | 61 | - [ ] Critical - Blocking my usage 62 | - [ ] High - Important for my use case 63 | - [ ] Medium - Would be nice to have 64 | - [ ] Low - Just a suggestion 65 | 66 | ## Willingness to Contribute 67 | 68 | - [ ] I'd be willing to submit a PR for this feature 69 | - [ ] I can help test this feature 70 | - [ ] I can help with documentation 71 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_call: 5 | secrets: 6 | VAULT_URL: 7 | required: true 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | 13 | permissions: 14 | contents: write 15 | id-token: write 16 | actions: read 17 | 18 | steps: 19 | - name: 'Retrieve Secrets from Vault' 20 | id: vault 21 | uses: hashicorp/vault-action@v3.4.0 22 | with: 23 | url: ${{ secrets.VAULT_URL }} 24 | role: ${{ github.event.repository.name }}-github-action 25 | method: jwt 26 | path: github-actions 27 | exportEnv: false 28 | secrets: | 29 | github/token/${{ github.event.repository.name }}-semantic-release token | GITHUB_TOKEN; 30 | 31 | - name: Get Automation Bot User ID 32 | id: get-user-id 33 | run: echo "user-id=$(gh api "/users/contentful-automation[bot]" --jq .id)" >> "$GITHUB_OUTPUT" 34 | env: 35 | GITHUB_TOKEN: ${{ steps.vault.outputs.GITHUB_TOKEN }} 36 | 37 | - name: Setting up Git User Credentials 38 | run: | 39 | git config --global user.name 'contentful-automation[bot]' 40 | git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+contentful-automation[bot]@users.noreply.github.com' 41 | 42 | - name: Checkout code 43 | uses: actions/checkout@v5 44 | with: 45 | fetch-depth: 0 46 | 47 | - name: Setup Node.js 48 | uses: actions/setup-node@v6 49 | with: 50 | node-version: '22' 51 | cache: 'npm' 52 | 53 | - name: Install latest npm 54 | run: npm install -g npm@latest 55 | 56 | - name: Install dependencies 57 | run: npm ci 58 | 59 | - name: Restore the build folders 60 | uses: actions/cache/restore@v4 61 | with: 62 | path: | 63 | dist 64 | key: build-cache-${{ github.run_id }}-${{ github.run_attempt }} 65 | 66 | - name: Run Release 67 | run: | 68 | echo "Starting Semantic Release Process" 69 | echo "npm version: $(npm -v)" 70 | npm run semantic-release 71 | env: 72 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 73 | 74 | - name: Get latest release tag 75 | id: get-tag 76 | run: | 77 | TAG=$(gh api repos/${{ github.repository }}/releases/latest --jq .tag_name) 78 | echo "tag=$TAG" >> $GITHUB_OUTPUT 79 | env: 80 | GITHUB_TOKEN: ${{ steps.vault.outputs.GITHUB_TOKEN }} 81 | 82 | - name: Summary 83 | run: | 84 | VERSION=$(echo "${{ steps.get-tag.outputs.tag }}" | sed 's/^v//') 85 | echo "## Release Summary" >> $GITHUB_STEP_SUMMARY 86 | echo "" >> $GITHUB_STEP_SUMMARY 87 | echo "- **Version**: ${{ steps.get-tag.outputs.tag }}" >> $GITHUB_STEP_SUMMARY 88 | echo "- **GitHub Release**: https://github.com/${{ github.repository }}/releases/tag/${{ steps.get-tag.outputs.tag }}" >> $GITHUB_STEP_SUMMARY -------------------------------------------------------------------------------- /jsdoc-template/tmpl/method.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |

Constructor

8 | 9 | 10 |

12 | 13 | 14 |

15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 | 27 |
Extends:
28 | 29 | 30 | 31 | 32 |
Type:
33 | 38 | 39 | 40 | 41 |
This:
42 | 43 | 44 | 45 | 46 |
Example 1? 's':'' ?>
47 | 48 | 49 | 50 | 51 |
Parameters:
52 | 53 | 54 | 55 | 56 |
Requires:
57 | 60 | 61 | 62 | 63 |
Fires:
64 | 67 | 68 | 69 | 70 |
Listens to Events:
71 | 74 | 75 | 76 | 77 |
Listeners of This Event:
78 | 81 | 82 | 83 | 84 |
Throws:
85 | 1) { ?> 91 | 92 | 94 | 95 | 96 |
Returns:
97 | 1) { ?> 103 | 104 | 106 | 107 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/properties.tmpl: -------------------------------------------------------------------------------- 1 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 91 | 92 | 93 | 94 | 99 | 100 | 101 | 104 | 105 | 106 | 107 | 108 |
NameTypeAttributesDefaultDescription
76 | 77 | 78 | 79 | 83 | 84 | <optional>
85 | 86 | 87 | 88 | <nullable>
89 | 90 |
95 | 96 | 97 | 98 | 102 |
Properties
103 |
109 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/params.tmpl: -------------------------------------------------------------------------------- 1 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 91 | 92 | 93 | 106 | 107 | 108 | 109 | 114 | 115 | 116 | 120 | 121 | 122 | 123 | 124 |
NameTypeAttributesDefaultDescription
87 | 88 | 89 | 90 | 94 | 95 | <optional>
96 | 97 | 98 | 99 | <nullable>
100 | 101 | 102 | 103 | <repeatable>
104 | 105 |
110 | 111 | 112 | 113 | 117 |
Properties
118 | 119 |
125 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/details.tmpl: -------------------------------------------------------------------------------- 1 | " + data.defaultvalue + ""; 13 | defaultObjectClass = ' class="object-value"'; 14 | } 15 | ?> 16 | 17 |
18 | 19 | 20 |
Source:
21 |
  • 22 | , 23 |
24 | 25 | 26 | 27 |
Version:
28 |
29 | 30 | 31 | 32 |
Since:
33 |
34 | 35 | 36 | 37 |
Inherited From:
38 |
  • 39 | 40 |
41 | 42 | 43 | 44 |
Overrides:
45 |
  • 46 | 47 |
48 | 49 | 50 | 51 |
Implementations:
52 |
    53 | 54 |
  • 55 | 56 |
57 | 58 | 59 | 60 |
Implements:
61 |
    62 | 63 |
  • 64 | 65 |
66 | 67 | 68 | 69 |
Mixes In:
70 | 71 |
    72 | 73 |
  • 74 | 75 |
76 | 77 | 78 | 79 |
Deprecated:
  • Yes
83 | 84 | 85 | 86 |
Author:
87 |
88 |
    89 |
  • 90 |
91 |
92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |
License:
101 |
102 | 103 | 104 | 105 |
Default Value:
106 |
    107 | > 108 |
109 | 110 | 111 | 112 |
Tutorials:
113 |
114 |
    115 |
  • 116 |
117 |
118 | 119 | 120 | 121 |
See:
122 |
123 |
    124 |
  • 125 |
126 |
127 | 128 | 129 | 130 |
To Do:
131 |
132 |
    133 |
  • 134 |
135 |
136 | 137 |
138 | 139 | 143 | 144 |
Properties:
145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /jsdoc-template/tmpl/container.tmpl: -------------------------------------------------------------------------------- 1 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 |
23 | 24 |

25 | 26 | 27 | 28 | 29 | 30 |

31 | 32 |
33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | 41 |
42 | 43 |
44 |
45 | 46 | 47 |
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
60 | 61 | 62 | 63 |

Example 1? 's':'' ?>

64 | 65 | 66 | 67 |
68 | 69 | 70 |

Extends

71 | 72 | 73 | 74 | 75 | 76 |

Requires

77 | 78 |
    79 |
  • 80 |
81 | 82 | 83 | 87 |

Classes

88 | 89 |
90 |
91 |
92 |
93 | 94 | 95 | 99 |

Mixins

100 | 101 |
102 |
103 |
104 |
105 | 106 | 107 | 111 |

Namespaces

112 | 113 |
114 |
115 |
116 |
117 | 118 | 119 | 130 |

Members

131 | 132 | 133 | 134 | 135 | 136 | 140 |

Type Definitions

141 | 142 | 145 | 146 | 150 | 151 | 154 | 155 | 156 | 160 |

Methods

161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 172 |

Events

173 | 174 | 175 | 176 | 177 | 178 |
179 | 180 |
181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /jsdoc-template/static/scripts/hljs/highlight.min.js: -------------------------------------------------------------------------------- 1 | /*! highlight.js v9.10.0 | BSD3 License | git.io/hljslicense */ 2 | !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return j[e]})}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){l+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substring(s,g[0].offset)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function s(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function l(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return s("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function s(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=s(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!L[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){y+=null!=E.sL?d():h(),k=""}function v(e){y+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(y+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');l(N);var R,E=i||N,x={},y="";for(R=E;R!==N;R=R.parent)R.cN&&(y=p(R.cN,"",!0)+y);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(y+=C);return{r:B,value:y,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(L);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?y[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,s,l=i(e);a(l)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,s=n.textContent,r=l?f(l,s,!0):g(s),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,l,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=L[n]=t(e);r.aliases&&r.aliases.forEach(function(e){y[e]=n})}function R(){return x(L)}function w(e){return e=(e||"").toLowerCase(),L[e]||L[y[e]]}var E=[],x=Object.keys,L={},y={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},j={"&":"&","<":"<",">":">"};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}}); -------------------------------------------------------------------------------- /jsdoc-template/static/styles/jsdoc.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Montserrat:400,700); 2 | 3 | * { 4 | box-sizing: border-box 5 | } 6 | 7 | html, body { 8 | height: 100%; 9 | width: 100%; 10 | } 11 | 12 | body { 13 | color: #4d4e53; 14 | background-color: #fff; 15 | margin: 0 auto; 16 | padding: 0 20px; 17 | font-family: 'Helvetica Neue', Helvetica, sans-serif; 18 | font-size: 16px; 19 | line-height: 160%; 20 | } 21 | 22 | img { 23 | max-width: 100%; 24 | } 25 | 26 | a, 27 | a:active { 28 | color: #1683d0; 29 | text-decoration: none; 30 | } 31 | 32 | a:hover { 33 | text-decoration: none; 34 | } 35 | 36 | article a { 37 | border-bottom: 1px solid #ddd; 38 | } 39 | 40 | article a:hover, article a:active { 41 | border-bottom-color: #222; 42 | } 43 | 44 | p, ul, ol, blockquote { 45 | margin-bottom: 1em; 46 | } 47 | 48 | h1, h2, h3, h4, h5, h6 { 49 | font-family: 'Montserrat', sans-serif; 50 | } 51 | 52 | h1, h2, h3, h4, h5, h6 { 53 | color: #000; 54 | font-weight: 400; 55 | margin: 0; 56 | } 57 | 58 | h1 { 59 | font-weight: 300; 60 | font-size: 48px; 61 | margin: 1em 0 .5em; 62 | } 63 | 64 | h1.page-title { 65 | font-size: 48px; 66 | margin: 1em 30px; 67 | } 68 | 69 | h2 { 70 | font-size: 24px; 71 | margin: 1.5em 0 .3em; 72 | } 73 | 74 | h3 { 75 | font-size: 24px; 76 | margin: 1.2em 0 .3em; 77 | } 78 | 79 | h4 { 80 | font-size: 18px; 81 | margin: 1em 0 .2em; 82 | color: #4d4e53; 83 | } 84 | 85 | h4.name { 86 | color: #000; 87 | background: #f7f9fa; 88 | box-shadow: 0 .25em .5em #d3d3d3; 89 | border-top: 1px solid #d3d3d3; 90 | border-bottom: 1px solid #d3d3d3; 91 | margin: 1.5em 0 0.5em; 92 | padding: .75em 0 .75em 10px; 93 | } 94 | 95 | h4.name a { 96 | color: #1683d0; 97 | } 98 | 99 | h4.name a:hover { 100 | border-bottom-color: #0c2c52; 101 | } 102 | 103 | h5, .container-overview .subsection-title { 104 | font-size: 120%; 105 | letter-spacing: -0.01em; 106 | margin: 8px 0 3px 0; 107 | } 108 | 109 | h6 { 110 | font-size: 100%; 111 | letter-spacing: -0.01em; 112 | margin: 6px 0 3px 0; 113 | font-style: italic; 114 | } 115 | 116 | tt, code, kbd, samp { 117 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 118 | background: #f4f4f4; 119 | padding: 1px 5px; 120 | } 121 | 122 | .class-description { 123 | font-size: 130%; 124 | line-height: 140%; 125 | margin-bottom: 1em; 126 | margin-top: 1em; 127 | } 128 | 129 | .class-description:empty { 130 | margin: 0 131 | } 132 | 133 | #main { 134 | float: right; 135 | min-width: 360px; 136 | width: calc(100% - 240px); 137 | } 138 | 139 | header { 140 | display: block 141 | } 142 | 143 | section { 144 | display: block; 145 | background-color: #fff; 146 | padding: 0 0 0 30px; 147 | } 148 | 149 | .variation { 150 | display: none 151 | } 152 | 153 | .signature-attributes { 154 | font-size: 60%; 155 | color: #bbb; 156 | font-style: italic; 157 | font-weight: lighter; 158 | } 159 | 160 | .cfnext-select-box { 161 | color: inherit; 162 | font-size: inherit; 163 | font-family: inherit; 164 | cursor: inherit; 165 | background: none; 166 | line-height: normal; 167 | border: 0; 168 | outline: 0; 169 | -webkit-appearance: none; 170 | -moz-appearance: none; 171 | appearance: none; 172 | font-size: inherit; 173 | height: 33px; 174 | line-height: normal; 175 | -webkit-box-sizing: border-box; 176 | -moz-box-sizing: border-box; 177 | box-sizing: border-box; 178 | padding-top: 6px; 179 | padding-bottom: 7px; 180 | border: 1px solid #d6dce4; 181 | border-color: #969fa6; 182 | -webkit-border-radius: 2px; 183 | border-radius: 2px; 184 | background-color: #f7f9fa; 185 | padding-left: 1ex; 186 | padding-right: 8ex; 187 | -o-text-overflow: ellipsis; 188 | text-overflow: ellipsis; 189 | overflow: hidden; 190 | white-space: nowrap; 191 | background-image: url(arrow-down.svg), none; 192 | background-position: center right 0.8em; 193 | background-repeat: no-repeat, repeat; 194 | -webkit-background-size: 0.7em, 100%; 195 | -moz-background-size: 0.7em, 100%; 196 | background-size: 0.7em, 100%; 197 | width:100%; 198 | } 199 | 200 | nav { 201 | float: left; 202 | display: block; 203 | width: 250px; 204 | background: #fff; 205 | overflow: auto; 206 | position: fixed; 207 | height: 100%; 208 | padding: 15px; 209 | -webkit-box-shadow: 0px 1px 2px 0px rgba(0,0,0,0.1); 210 | box-shadow: 0px 1px 2px 0px rgba(0,0,0,0.1); 211 | } 212 | 213 | nav h3 { 214 | margin-top: 12px; 215 | font-size: 13px; 216 | text-transform: uppercase; 217 | letter-spacing: 1px; 218 | font-weight: 700; 219 | line-height: 24px; 220 | margin: 15px 0 10px; 221 | padding: 0; 222 | color: #000; 223 | } 224 | 225 | nav ul { 226 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif; 227 | font-size: 100%; 228 | line-height: 17px; 229 | padding: 0; 230 | margin: 0; 231 | list-style-type: none; 232 | } 233 | 234 | nav ul a, 235 | nav ul a:active { 236 | font-family: 'Montserrat', sans-serif; 237 | line-height: 18px; 238 | padding: 0; 239 | display: block; 240 | font-size: 12px; 241 | } 242 | 243 | nav a:hover, 244 | nav a:active { 245 | color: #0c2c52; 246 | } 247 | 248 | nav > ul { 249 | padding: 0 10px; 250 | } 251 | 252 | nav > ul > li > a { 253 | color: #8091a5; 254 | } 255 | 256 | nav ul ul { 257 | margin-bottom: 10px 258 | } 259 | 260 | nav ul ul + ul { 261 | margin-top: -10px; 262 | } 263 | 264 | nav ul ul a { 265 | color: hsl(207, 1%, 60%); 266 | border-left: 1px solid hsl(207, 10%, 86%); 267 | } 268 | 269 | nav ul ul a, 270 | nav ul ul a:active { 271 | padding-left: 20px 272 | } 273 | 274 | nav h2 { 275 | font-size: 12px; 276 | margin: 0; 277 | padding: 0; 278 | } 279 | 280 | nav > h2 > a { 281 | display: block; 282 | margin: 10px 0 -10px; 283 | color: #1683d0 !important; 284 | } 285 | 286 | footer { 287 | color: hsl(0, 0%, 28%); 288 | margin-left: 250px; 289 | display: block; 290 | padding: 15px; 291 | font-style: italic; 292 | font-size: 90%; 293 | } 294 | 295 | .ancestors { 296 | color: #999 297 | } 298 | 299 | .ancestors a { 300 | color: #999 !important; 301 | } 302 | 303 | .clear { 304 | clear: both 305 | } 306 | 307 | .important { 308 | font-weight: bold; 309 | color: #950B02; 310 | } 311 | 312 | .yes-def { 313 | text-indent: -1000px 314 | } 315 | 316 | .type-signature { 317 | color: #1683d0; 318 | } 319 | 320 | .type-signature:last-child { 321 | color: #000; 322 | } 323 | 324 | .name, .signature { 325 | font-family: Consolas, Monaco, 'Andale Mono', monospace 326 | } 327 | 328 | .signature { 329 | color: #1683d0; 330 | } 331 | 332 | .details { 333 | margin-top: 6px; 334 | border-left: 2px solid #DDD; 335 | line-height: 20px; 336 | font-size: 14px; 337 | } 338 | 339 | .details dt { 340 | width: 120px; 341 | float: left; 342 | padding-left: 10px; 343 | } 344 | 345 | .details dd { 346 | margin-left: 70px; 347 | margin-top: 6px; 348 | margin-bottom: 6px; 349 | } 350 | 351 | .details ul { 352 | margin: 0 353 | } 354 | 355 | .details ul { 356 | list-style-type: none 357 | } 358 | 359 | .details pre.prettyprint { 360 | margin: 0 361 | } 362 | 363 | .details .object-value { 364 | padding-top: 0 365 | } 366 | 367 | .description { 368 | margin-bottom: 1em; 369 | margin-top: 1em; 370 | } 371 | 372 | .code-caption { 373 | font-style: italic; 374 | font-size: 107%; 375 | margin: 0; 376 | } 377 | 378 | .prettyprint { 379 | font-size: 14px; 380 | overflow: auto; 381 | } 382 | 383 | .prettyprint.source { 384 | width: inherit; 385 | line-height: 18px; 386 | display: block; 387 | background-color: #0d152a; 388 | color: ##536171; 389 | } 390 | 391 | .prettyprint code { 392 | line-height: 18px; 393 | display: block; 394 | background-color: #f7f9fa; 395 | } 396 | 397 | .prettyprint > code { 398 | padding: 15px; 399 | } 400 | 401 | .prettyprint .linenums code { 402 | padding: 0 15px 403 | } 404 | 405 | .prettyprint .linenums li:first-of-type code { 406 | padding-top: 15px 407 | } 408 | 409 | .prettyprint code span.line { 410 | display: inline-block 411 | } 412 | 413 | .prettyprint.linenums { 414 | padding-left: 70px; 415 | -webkit-user-select: none; 416 | -moz-user-select: none; 417 | -ms-user-select: none; 418 | user-select: none; 419 | } 420 | 421 | .prettyprint.linenums ol { 422 | padding-left: 0 423 | } 424 | 425 | .prettyprint.linenums li { 426 | border-left: 3px #34446B solid; 427 | } 428 | 429 | .prettyprint.linenums li.selected, .prettyprint.linenums li.selected * { 430 | background-color: #34446B; 431 | } 432 | 433 | .prettyprint.linenums li * { 434 | -webkit-user-select: text; 435 | -moz-user-select: text; 436 | -ms-user-select: text; 437 | user-select: text; 438 | } 439 | 440 | .params, .props { 441 | border-spacing: 0; 442 | border: 1px solid #ddd; 443 | border-collapse: collapse; 444 | border-radius: 3px; 445 | box-shadow: 0 1px 3px rgba(0,0,0,0.1); 446 | width: 100%; 447 | font-size: 14px; 448 | margin: 1em 0; 449 | } 450 | 451 | .params .type { 452 | white-space: nowrap; 453 | } 454 | 455 | .params code { 456 | white-space: pre; 457 | } 458 | 459 | .params td, .params .name, .props .name, .name code { 460 | color: #4D4E53; 461 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 462 | font-size: 100%; 463 | } 464 | 465 | .params td, .params th, .props td, .props th { 466 | margin: 0px; 467 | text-align: left; 468 | vertical-align: top; 469 | padding: 10px; 470 | display: table-cell; 471 | } 472 | 473 | .params td { 474 | border-top: 1px solid #eee 475 | } 476 | 477 | .params thead tr, .props thead tr { 478 | background-color: #fff; 479 | font-weight: bold; 480 | } 481 | 482 | .params .params thead tr, .props .props thead tr { 483 | background-color: #fff; 484 | font-weight: bold; 485 | } 486 | 487 | .params td.description > p:first-child, .props td.description > p:first-child { 488 | margin-top: 0; 489 | padding-top: 0; 490 | } 491 | 492 | .params td.description > p:last-child, .props td.description > p:last-child { 493 | margin-bottom: 0; 494 | padding-bottom: 0; 495 | } 496 | 497 | span.param-type, .params td .param-type, .param-type dd { 498 | color: #1683d0; 499 | font-family: Consolas, Monaco, 'Andale Mono', monospace 500 | } 501 | 502 | .param-type dt, .param-type dd { 503 | display: inline-block 504 | } 505 | 506 | .param-type { 507 | margin: 14px 0; 508 | } 509 | 510 | .disabled { 511 | color: #454545 512 | } 513 | 514 | /* navicon button */ 515 | .navicon-button { 516 | display: none; 517 | position: relative; 518 | padding: 2.0625rem 1.5rem; 519 | transition: 0.25s; 520 | cursor: pointer; 521 | -webkit-user-select: none; 522 | -moz-user-select: none; 523 | -ms-user-select: none; 524 | user-select: none; 525 | opacity: .8; 526 | } 527 | .navicon-button .navicon:before, .navicon-button .navicon:after { 528 | transition: 0.25s; 529 | } 530 | .navicon-button:hover { 531 | transition: 0.5s; 532 | opacity: 1; 533 | } 534 | .navicon-button:hover .navicon:before, .navicon-button:hover .navicon:after { 535 | transition: 0.25s; 536 | } 537 | .navicon-button:hover .navicon:before { 538 | top: .825rem; 539 | } 540 | .navicon-button:hover .navicon:after { 541 | top: -.825rem; 542 | } 543 | 544 | /* navicon */ 545 | .navicon { 546 | position: relative; 547 | width: 2.5em; 548 | height: .3125rem; 549 | background: #000; 550 | transition: 0.3s; 551 | border-radius: 2.5rem; 552 | } 553 | .navicon:before, .navicon:after { 554 | display: block; 555 | content: ""; 556 | height: .3125rem; 557 | width: 2.5rem; 558 | background: #000; 559 | position: absolute; 560 | z-index: -1; 561 | transition: 0.3s 0.25s; 562 | border-radius: 1rem; 563 | } 564 | .navicon:before { 565 | top: .625rem; 566 | } 567 | .navicon:after { 568 | top: -.625rem; 569 | } 570 | 571 | /* open */ 572 | .nav-trigger:checked + label:not(.steps) .navicon:before, 573 | .nav-trigger:checked + label:not(.steps) .navicon:after { 574 | top: 0 !important; 575 | } 576 | 577 | .nav-trigger:checked + label .navicon:before, 578 | .nav-trigger:checked + label .navicon:after { 579 | transition: 0.5s; 580 | } 581 | 582 | /* Minus */ 583 | .nav-trigger:checked + label { 584 | -webkit-transform: scale(0.75); 585 | transform: scale(0.75); 586 | } 587 | 588 | /* × and + */ 589 | .nav-trigger:checked + label.plus .navicon, 590 | .nav-trigger:checked + label.x .navicon { 591 | background: transparent; 592 | } 593 | 594 | .nav-trigger:checked + label.plus .navicon:before, 595 | .nav-trigger:checked + label.x .navicon:before { 596 | -webkit-transform: rotate(-45deg); 597 | transform: rotate(-45deg); 598 | background: #FFF; 599 | } 600 | 601 | .nav-trigger:checked + label.plus .navicon:after, 602 | .nav-trigger:checked + label.x .navicon:after { 603 | -webkit-transform: rotate(45deg); 604 | transform: rotate(45deg); 605 | background: #FFF; 606 | } 607 | 608 | .nav-trigger:checked + label.plus { 609 | -webkit-transform: scale(0.75) rotate(45deg); 610 | transform: scale(0.75) rotate(45deg); 611 | } 612 | 613 | .nav-trigger:checked ~ nav { 614 | left: 0 !important; 615 | } 616 | 617 | .nav-trigger:checked ~ .overlay { 618 | display: block; 619 | } 620 | 621 | .nav-trigger { 622 | position: fixed; 623 | top: 0; 624 | clip: rect(0, 0, 0, 0); 625 | } 626 | 627 | .overlay { 628 | display: none; 629 | position: fixed; 630 | top: 0; 631 | bottom: 0; 632 | left: 0; 633 | right: 0; 634 | width: 100%; 635 | height: 100%; 636 | background: hsla(0, 0%, 0%, 0.5); 637 | z-index: 1; 638 | } 639 | 640 | @media only screen and (min-width: 320px) and (max-width: 680px) { 641 | body { 642 | overflow-x: hidden; 643 | } 644 | 645 | nav { 646 | background: #FFF; 647 | width: 250px; 648 | height: 100%; 649 | position: fixed; 650 | top: 0; 651 | right: 0; 652 | bottom: 0; 653 | left: -250px; 654 | z-index: 3; 655 | padding: 0 10px; 656 | transition: left 0.2s; 657 | } 658 | 659 | .navicon-button { 660 | display: inline-block; 661 | position: fixed; 662 | top: 1.5em; 663 | right: 0; 664 | z-index: 2; 665 | } 666 | 667 | #main { 668 | width: 100%; 669 | min-width: 360px; 670 | } 671 | 672 | #main h1.page-title { 673 | margin: 1em 0; 674 | } 675 | 676 | #main section { 677 | padding: 0; 678 | } 679 | 680 | footer { 681 | margin-left: 0; 682 | } 683 | } 684 | 685 | /** Add a '#' to static members */ 686 | [data-type="member"] a::before { 687 | content: '#'; 688 | display: inline-block; 689 | margin-left: -14px; 690 | margin-right: 5px; 691 | } 692 | -------------------------------------------------------------------------------- /jsdoc-template/publish.js: -------------------------------------------------------------------------------- 1 | /*global env: true */ 2 | 'use strict'; 3 | 4 | var doop = require('jsdoc/util/doop'); 5 | var fs = require('jsdoc/fs'); 6 | var helper = require('jsdoc/util/templateHelper'); 7 | var logger = require('jsdoc/util/logger'); 8 | var path = require('jsdoc/path'); 9 | // https://github.com/jsdoc/jsdoc/tree/main/packages/jsdoc-salty#use-salty-in-a-jsdoc-template 10 | var taffy = require('@jsdoc/salty').taffy; 11 | var template = require('jsdoc/template'); 12 | var util = require('util'); 13 | 14 | var htmlsafe = helper.htmlsafe; 15 | var linkto = helper.linkto; 16 | var resolveAuthorLinks = helper.resolveAuthorLinks; 17 | var scopeToPunc = helper.scopeToPunc; 18 | var hasOwnProp = Object.prototype.hasOwnProperty; 19 | 20 | var data; 21 | var view; 22 | 23 | var outdir = path.normalize(env.opts.destination); 24 | 25 | function find(spec) { 26 | return helper.find(data, spec); 27 | } 28 | 29 | function tutoriallink(tutorial) { 30 | return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: 'Tutorial: ' }); 31 | } 32 | 33 | function getAncestorLinks(doclet) { 34 | return helper.getAncestorLinks(data, doclet); 35 | } 36 | 37 | function hashToLink(doclet, hash) { 38 | if ( !/^(#.+)/.test(hash) ) { return hash; } 39 | 40 | var url = helper.createLink(doclet); 41 | 42 | url = url.replace(/(#.+|$)/, hash); 43 | return '' + hash + ''; 44 | } 45 | 46 | function needsSignature(doclet) { 47 | var needsSig = false; 48 | 49 | // function and class definitions always get a signature 50 | if (doclet.kind === 'function' || doclet.kind === 'class') { 51 | needsSig = true; 52 | } 53 | // typedefs that contain functions get a signature, too 54 | else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names && 55 | doclet.type.names.length) { 56 | for (var i = 0, l = doclet.type.names.length; i < l; i++) { 57 | if (doclet.type.names[i].toLowerCase() === 'function') { 58 | needsSig = true; 59 | break; 60 | } 61 | } 62 | } 63 | 64 | return needsSig; 65 | } 66 | 67 | function getSignatureAttributes(item) { 68 | var attributes = []; 69 | 70 | if (item.optional) { 71 | attributes.push('opt'); 72 | } 73 | 74 | if (item.nullable === true) { 75 | attributes.push('nullable'); 76 | } 77 | else if (item.nullable === false) { 78 | attributes.push('non-null'); 79 | } 80 | 81 | return attributes; 82 | } 83 | 84 | function updateItemName(item) { 85 | var attributes = getSignatureAttributes(item); 86 | var itemName = item.name || ''; 87 | 88 | if (item.variable) { 89 | itemName = '…' + itemName; 90 | } 91 | 92 | if (attributes && attributes.length) { 93 | itemName = util.format( '%s%s', itemName, 94 | attributes.join(', ') ); 95 | } 96 | 97 | return itemName; 98 | } 99 | 100 | function addParamAttributes(params) { 101 | return params.filter(function(param) { 102 | return param.name && param.name.indexOf('.') === -1; 103 | }).map(updateItemName); 104 | } 105 | 106 | function buildItemTypeStrings(item) { 107 | var types = []; 108 | 109 | if (item && item.type && item.type.names) { 110 | item.type.names.forEach(function(name) { 111 | types.push( linkto(name, htmlsafe(name)) ); 112 | }); 113 | } 114 | 115 | return types; 116 | } 117 | 118 | function buildAttribsString(attribs) { 119 | var attribsString = ''; 120 | 121 | if (attribs && attribs.length) { 122 | attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) ); 123 | } 124 | 125 | return attribsString; 126 | } 127 | 128 | function addNonParamAttributes(items) { 129 | var types = []; 130 | 131 | items.forEach(function(item) { 132 | types = types.concat( buildItemTypeStrings(item) ); 133 | }); 134 | 135 | return types; 136 | } 137 | 138 | function addSignatureParams(f) { 139 | var params = f.params ? addParamAttributes(f.params) : []; 140 | f.signature = util.format( '%s(%s)', (f.signature || ''), params.join(', ') ); 141 | } 142 | 143 | function addSignatureReturns(f) { 144 | var attribs = []; 145 | var attribsString = ''; 146 | var returnTypes = []; 147 | var returnTypesString = ''; 148 | 149 | // jam all the return-type attributes into an array. this could create odd results (for example, 150 | // if there are both nullable and non-nullable return types), but let's assume that most people 151 | // who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa. 152 | if (f.returns) { 153 | f.returns.forEach(function(item) { 154 | helper.getAttribs(item).forEach(function(attrib) { 155 | if (attribs.indexOf(attrib) === -1) { 156 | attribs.push(attrib); 157 | } 158 | }); 159 | }); 160 | 161 | attribsString = buildAttribsString(attribs); 162 | } 163 | 164 | if (f.returns) { 165 | returnTypes = addNonParamAttributes(f.returns); 166 | } 167 | if (returnTypes.length) { 168 | returnTypesString = util.format( ' → %s{%s}', attribsString, returnTypes.join('|') ); 169 | } 170 | 171 | f.signature = '' + (f.signature || '') + '' + 172 | '' + returnTypesString + ''; 173 | } 174 | 175 | function addSignatureTypes(f) { 176 | var types = f.type ? buildItemTypeStrings(f) : []; 177 | 178 | f.signature = (f.signature || '') + '' + 179 | (types.length ? ' :' + types.join('|') : '') + ''; 180 | } 181 | 182 | function addAttribs(f) { 183 | var attribs = helper.getAttribs(f); 184 | var attribsString = buildAttribsString(attribs); 185 | 186 | f.attribs = util.format('%s', attribsString); 187 | } 188 | 189 | function shortenPaths(files, commonPrefix) { 190 | Object.keys(files).forEach(function(file) { 191 | files[file].shortened = files[file].resolved.replace(commonPrefix, '') 192 | // always use forward slashes 193 | .replace(/\\/g, '/'); 194 | }); 195 | 196 | return files; 197 | } 198 | 199 | function getPathFromDoclet(doclet) { 200 | if (!doclet.meta) { 201 | return null; 202 | } 203 | 204 | return doclet.meta.path && doclet.meta.path !== 'null' ? 205 | path.join(doclet.meta.path, doclet.meta.filename) : 206 | doclet.meta.filename; 207 | } 208 | 209 | function generate(type, title, docs, filename, resolveLinks) { 210 | resolveLinks = resolveLinks === false ? false : true; 211 | 212 | var docData = { 213 | type: type, 214 | title: title, 215 | docs: docs 216 | }; 217 | 218 | var outpath = path.join(outdir, filename), 219 | html = view.render('container.tmpl', docData); 220 | 221 | if (resolveLinks) { 222 | html = helper.resolveLinks(html); // turn {@link foo} into foo 223 | } 224 | 225 | fs.writeFileSync(outpath, html, 'utf8'); 226 | } 227 | 228 | function generateSourceFiles(sourceFiles, encoding) { 229 | encoding = encoding || 'utf8'; 230 | Object.keys(sourceFiles).forEach(function(file) { 231 | var source; 232 | // links are keyed to the shortened path in each doclet's `meta.shortpath` property 233 | var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); 234 | helper.registerLink(sourceFiles[file].shortened, sourceOutfile); 235 | 236 | try { 237 | source = { 238 | kind: 'source', 239 | code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) ) 240 | }; 241 | } 242 | catch(e) { 243 | logger.error('Error while generating source file %s: %s', file, e.message); 244 | } 245 | 246 | generate('Source', sourceFiles[file].shortened, [source], sourceOutfile, false); 247 | }); 248 | } 249 | 250 | /** 251 | * Look for classes or functions with the same name as modules (which indicates that the module 252 | * exports only that class or function), then attach the classes or functions to the `module` 253 | * property of the appropriate module doclets. The name of each class or function is also updated 254 | * for display purposes. This function mutates the original arrays. 255 | * 256 | * @private 257 | * @param {Array.} doclets - The array of classes and functions to 258 | * check. 259 | * @param {Array.} modules - The array of module doclets to search. 260 | */ 261 | function attachModuleSymbols(doclets, modules) { 262 | var symbols = {}; 263 | 264 | // build a lookup table 265 | doclets.forEach(function(symbol) { 266 | symbols[symbol.longname] = symbols[symbol.longname] || []; 267 | symbols[symbol.longname].push(symbol); 268 | }); 269 | 270 | return modules.map(function(module) { 271 | if (symbols[module.longname]) { 272 | module.modules = symbols[module.longname] 273 | // Only show symbols that have a description. Make an exception for classes, because 274 | // we want to show the constructor-signature heading no matter what. 275 | .filter(function(symbol) { 276 | return symbol.description || symbol.kind === 'class'; 277 | }) 278 | .map(function(symbol) { 279 | symbol = doop(symbol); 280 | 281 | if (symbol.kind === 'class' || symbol.kind === 'function') { 282 | symbol.name = symbol.name.replace('module:', '(require("') + '"))'; 283 | } 284 | 285 | return symbol; 286 | }); 287 | } 288 | }); 289 | } 290 | 291 | function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) { 292 | var nav = ''; 293 | 294 | if (items && items.length) { 295 | var itemsNav = ''; 296 | 297 | items.forEach(function(item) { 298 | var methods = find({kind:'function', memberof: item.longname}); 299 | var members = find({kind:'member', memberof: item.longname}); 300 | var docdash = env && env.conf && env.conf.docdash || {}; 301 | 302 | if ( !hasOwnProp.call(item, 'longname') ) { 303 | itemsNav += '
  • ' + linktoFn('', item.name); 304 | itemsNav += '
  • '; 305 | } else if ( !hasOwnProp.call(itemsSeen, item.longname) ) { 306 | itemsNav += '
  • ' + linktoFn(item.longname, item.name.replace(/^module:/, '')); 307 | 308 | if (docdash.static && members.find(function (m) { return m.scope === 'static'; } )) { 309 | itemsNav += "
      "; 310 | 311 | members.forEach(function (member) { 312 | if (!member.scope === 'static') return; 313 | itemsNav += "
    • "; 314 | itemsNav += linkto(member.longname, member.name); 315 | itemsNav += "
    • "; 316 | }); 317 | 318 | itemsNav += "
    "; 319 | } 320 | 321 | if (methods.length) { 322 | itemsNav += "
      "; 323 | 324 | methods.forEach(function (method) { 325 | itemsNav += "
    • "; 326 | itemsNav += linkto(method.longname, method.name); 327 | itemsNav += "
    • "; 328 | }); 329 | 330 | itemsNav += "
    "; 331 | } 332 | 333 | itemsNav += '
  • '; 334 | itemsSeen[item.longname] = true; 335 | } 336 | }); 337 | 338 | if (itemsNav !== '') { 339 | nav += '

    ' + itemHeading + '

      ' + itemsNav + '
    '; 340 | } 341 | } 342 | 343 | return nav; 344 | } 345 | 346 | function linktoTutorial(longName, name) { 347 | return tutoriallink(name); 348 | } 349 | 350 | function linktoExternal(longName, name) { 351 | return linkto(longName, name.replace(/(^"|"$)/g, '')); 352 | } 353 | 354 | /** 355 | * Create the navigation sidebar. 356 | * @param {object} members The members that will be used to create the sidebar. 357 | * @param {array} members.classes 358 | * @param {array} members.externals 359 | * @param {array} members.globals 360 | * @param {array} members.mixins 361 | * @param {array} members.modules 362 | * @param {array} members.namespaces 363 | * @param {array} members.tutorials 364 | * @param {array} members.events 365 | * @param {array} members.interfaces 366 | * @return {s 367 | ring} The HTML for the navigation sidebar. 368 | */ 369 | 370 | function buildNav(members) { 371 | var nav = '

    Home

    '; 372 | var seen = {}; 373 | var seenTutorials = {}; 374 | 375 | nav += buildMemberNav(members.classes, 'Classes', seen, linkto); 376 | nav += buildMemberNav(members.modules, 'Modules', {}, linkto); 377 | nav += buildMemberNav(members.externals, 'Externals', seen, linktoExternal); 378 | nav += buildMemberNav(members.events, 'Events', seen, linkto); 379 | nav += buildMemberNav(members.namespaces, 'Namespaces', seen, linkto); 380 | nav += buildMemberNav(members.mixins, 'Mixins', seen, linkto); 381 | nav += buildMemberNav(members.tutorials, 'Tutorials', seenTutorials, linktoTutorial); 382 | nav += buildMemberNav(members.interfaces, 'Interfaces', seen, linkto); 383 | 384 | if (members.globals.length) { 385 | var globalNav = ''; 386 | 387 | members.globals.forEach(function(g) { 388 | if ( g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname) ) { 389 | globalNav += '
  • ' + linkto(g.longname, g.name) + '
  • '; 390 | } 391 | seen[g.longname] = true; 392 | }); 393 | 394 | if (!globalNav) { 395 | // turn the heading into a link so you can actually get to the global page 396 | nav += '

    ' + linkto('global', 'Global') + '

    '; 397 | } 398 | else { 399 | nav += '

    Global

      ' + globalNav + '
    '; 400 | } 401 | } 402 | 403 | return nav; 404 | } 405 | 406 | /** 407 | @param {TAFFY} taffyData See . 408 | @param {object} opts 409 | @param {Tutorial} tutorials 410 | */ 411 | exports.publish = function(taffyData, opts, tutorials) { 412 | var docdash = env && env.conf && env.conf.docdash || {}; 413 | data = taffyData; 414 | 415 | var conf = env.conf.templates || {}; 416 | conf.default = conf.default || {}; 417 | 418 | var templatePath = path.normalize(opts.template); 419 | view = new template.Template( path.join(templatePath, 'tmpl') ); 420 | 421 | // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness 422 | // doesn't try to hand them out later 423 | var indexUrl = helper.getUniqueFilename('index'); 424 | // don't call registerLink() on this one! 'index' is also a valid longname 425 | 426 | var globalUrl = helper.getUniqueFilename('global'); 427 | helper.registerLink('global', globalUrl); 428 | 429 | // set up templating 430 | view.layout = conf.default.layoutFile ? 431 | path.getResourcePath(path.dirname(conf.default.layoutFile), 432 | path.basename(conf.default.layoutFile) ) : 433 | 'layout.tmpl'; 434 | 435 | // set up tutorials for helper 436 | helper.setTutorials(tutorials); 437 | 438 | data = helper.prune(data); 439 | 440 | docdash.sort !== false && data.sort('longname, version, since'); 441 | helper.addEventListeners(data); 442 | 443 | var sourceFiles = {}; 444 | var sourceFilePaths = []; 445 | data().each(function(doclet) { 446 | doclet.attribs = ''; 447 | 448 | if (doclet.examples) { 449 | doclet.examples = doclet.examples.map(function(example) { 450 | var caption, code; 451 | 452 | if (example.match(/^\s*([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) { 453 | caption = RegExp.$1; 454 | code = RegExp.$3; 455 | } 456 | 457 | return { 458 | caption: caption || '', 459 | code: code || example 460 | }; 461 | }); 462 | } 463 | if (doclet.see) { 464 | doclet.see.forEach(function(seeItem, i) { 465 | doclet.see[i] = hashToLink(doclet, seeItem); 466 | }); 467 | } 468 | 469 | // build a list of source files 470 | var sourcePath; 471 | if (doclet.meta) { 472 | sourcePath = getPathFromDoclet(doclet); 473 | sourceFiles[sourcePath] = { 474 | resolved: sourcePath, 475 | shortened: null 476 | }; 477 | if (sourceFilePaths.indexOf(sourcePath) === -1) { 478 | sourceFilePaths.push(sourcePath); 479 | } 480 | } 481 | }); 482 | 483 | // update outdir if necessary, then create outdir 484 | var packageInfo = ( find({kind: 'package'}) || [] ) [0]; 485 | if (packageInfo && packageInfo.name) { 486 | outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') ); 487 | } 488 | fs.mkPath(outdir); 489 | 490 | // copy the template's static files to outdir 491 | var fromDir = path.join(templatePath, 'static'); 492 | var staticFiles = fs.ls(fromDir, 3); 493 | 494 | staticFiles.forEach(function(fileName) { 495 | var toDir = fs.toDir( fileName.replace(fromDir, outdir) ); 496 | fs.mkPath(toDir); 497 | fs.copyFileSync(fileName, toDir); 498 | }); 499 | 500 | // copy user-specified static files to outdir 501 | var staticFilePaths; 502 | var staticFileFilter; 503 | var staticFileScanner; 504 | if (conf.default.staticFiles) { 505 | // The canonical property name is `include`. We accept `paths` for backwards compatibility 506 | // with a bug in JSDoc 3.2.x. 507 | staticFilePaths = conf.default.staticFiles.include || 508 | conf.default.staticFiles.paths || 509 | []; 510 | staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles); 511 | staticFileScanner = new (require('jsdoc/src/scanner')).Scanner(); 512 | 513 | staticFilePaths.forEach(function(filePath) { 514 | var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter); 515 | 516 | extraStaticFiles.forEach(function(fileName) { 517 | var sourcePath = fs.toDir(filePath); 518 | var toDir = fs.toDir( fileName.replace(sourcePath, outdir) ); 519 | fs.mkPath(toDir); 520 | fs.copyFileSync(fileName, toDir); 521 | }); 522 | }); 523 | } 524 | 525 | if (sourceFilePaths.length) { 526 | sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) ); 527 | } 528 | data().each(function(doclet) { 529 | var url = helper.createLink(doclet); 530 | helper.registerLink(doclet.longname, url); 531 | 532 | // add a shortened version of the full path 533 | var docletPath; 534 | if (doclet.meta) { 535 | docletPath = getPathFromDoclet(doclet); 536 | docletPath = sourceFiles[docletPath].shortened; 537 | if (docletPath) { 538 | doclet.meta.shortpath = docletPath; 539 | } 540 | } 541 | }); 542 | 543 | data().each(function(doclet) { 544 | var url = helper.longnameToUrl[doclet.longname]; 545 | 546 | if (url.indexOf('#') > -1) { 547 | doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop(); 548 | } 549 | else { 550 | doclet.id = doclet.name; 551 | } 552 | 553 | if ( needsSignature(doclet) ) { 554 | addSignatureParams(doclet); 555 | addSignatureReturns(doclet); 556 | addAttribs(doclet); 557 | } 558 | }); 559 | 560 | // do this after the urls have all been generated 561 | data().each(function(doclet) { 562 | doclet.ancestors = getAncestorLinks(doclet); 563 | 564 | if (doclet.kind === 'member') { 565 | addSignatureTypes(doclet); 566 | addAttribs(doclet); 567 | } 568 | 569 | if (doclet.kind === 'constant') { 570 | addSignatureTypes(doclet); 571 | addAttribs(doclet); 572 | doclet.kind = 'member'; 573 | } 574 | }); 575 | 576 | var members = helper.getMembers(data); 577 | members.tutorials = tutorials.children; 578 | 579 | // output pretty-printed source files by default 580 | var outputSourceFiles = conf.default && conf.default.outputSourceFiles !== false 581 | ? true 582 | : false; 583 | 584 | // add template helpers 585 | view.find = find; 586 | view.linkto = linkto; 587 | view.resolveAuthorLinks = resolveAuthorLinks; 588 | view.tutoriallink = tutoriallink; 589 | view.htmlsafe = htmlsafe; 590 | view.outputSourceFiles = outputSourceFiles; 591 | 592 | // once for all 593 | view.nav = buildNav(members); 594 | attachModuleSymbols( find({ longname: {left: 'module:'} }), members.modules ); 595 | 596 | // generate the pretty-printed source files first so other pages can link to them 597 | if (outputSourceFiles) { 598 | generateSourceFiles(sourceFiles, opts.encoding); 599 | } 600 | 601 | if (members.globals.length) { 602 | generate('', 'Global', [{kind: 'globalobj'}], globalUrl); 603 | } 604 | 605 | // index page displays information from package.json and lists files 606 | var files = find({kind: 'file'}); 607 | var packages = find({kind: 'package'}); 608 | 609 | generate('', 'Home', 610 | packages.concat( 611 | [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}] 612 | ).concat(files), 613 | indexUrl); 614 | 615 | // set up the lists that we'll use to generate pages 616 | var classes = taffy(members.classes); 617 | var modules = taffy(members.modules); 618 | var namespaces = taffy(members.namespaces); 619 | var mixins = taffy(members.mixins); 620 | var externals = taffy(members.externals); 621 | var interfaces = taffy(members.interfaces); 622 | 623 | Object.keys(helper.longnameToUrl).forEach(function(longname) { 624 | var myModules = helper.find(modules, {longname: longname}); 625 | if (myModules.length) { 626 | generate('Module', myModules[0].name, myModules, helper.longnameToUrl[longname]); 627 | } 628 | 629 | var myClasses = helper.find(classes, {longname: longname}); 630 | if (myClasses.length) { 631 | generate('Class', myClasses[0].name, myClasses, helper.longnameToUrl[longname]); 632 | } 633 | 634 | var myNamespaces = helper.find(namespaces, {longname: longname}); 635 | if (myNamespaces.length) { 636 | generate('Namespace', myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]); 637 | } 638 | 639 | var myMixins = helper.find(mixins, {longname: longname}); 640 | if (myMixins.length) { 641 | generate('Mixin', myMixins[0].name, myMixins, helper.longnameToUrl[longname]); 642 | } 643 | 644 | var myExternals = helper.find(externals, {longname: longname}); 645 | if (myExternals.length) { 646 | generate('External', myExternals[0].name, myExternals, helper.longnameToUrl[longname]); 647 | } 648 | 649 | var myInterfaces = helper.find(interfaces, {longname: longname}); 650 | if (myInterfaces.length) { 651 | generate('Interface', myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]); 652 | } 653 | }); 654 | 655 | // TODO: move the tutorial functions to templateHelper.js 656 | function generateTutorial(title, tutorial, filename) { 657 | var tutorialData = { 658 | title: title, 659 | header: tutorial.title, 660 | content: tutorial.parse(), 661 | children: tutorial.children 662 | }; 663 | 664 | var tutorialPath = path.join(outdir, filename); 665 | var html = view.render('tutorial.tmpl', tutorialData); 666 | 667 | // yes, you can use {@link} in tutorials too! 668 | html = helper.resolveLinks(html); // turn {@link foo} into foo 669 | fs.writeFileSync(tutorialPath, html, 'utf8'); 670 | } 671 | 672 | // tutorials can have only one parent so there is no risk for loops 673 | function saveChildren(node) { 674 | node.children.forEach(function(child) { 675 | generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name)); 676 | saveChildren(child); 677 | }); 678 | } 679 | 680 | saveChildren(tutorials); 681 | }; 682 | --------------------------------------------------------------------------------