adapt-authoring-docs 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,55 @@
1
+ name: Bug Report
2
+ description: File a bug report
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to fill out this bug report!
9
+ - type: textarea
10
+ id: description
11
+ attributes:
12
+ label: What happened?
13
+ description: Please describe the issue
14
+ validations:
15
+ required: true
16
+ - type: textarea
17
+ id: expected
18
+ attributes:
19
+ label: Expected behaviour
20
+ description: Tell us what should have happened
21
+ - type: textarea
22
+ id: repro-steps
23
+ attributes:
24
+ label: Steps to reproduce
25
+ description: Tell us how to reproduce the issue
26
+ validations:
27
+ required: true
28
+ - type: input
29
+ id: aat-version
30
+ attributes:
31
+ label: Authoring tool version
32
+ description: What version of the Adapt authoring tool are you running?
33
+ validations:
34
+ required: true
35
+ - type: input
36
+ id: fw-version
37
+ attributes:
38
+ label: Framework version
39
+ description: What version of the Adapt framework are you running?
40
+ - type: dropdown
41
+ id: browsers
42
+ attributes:
43
+ label: What browsers are you seeing the problem on?
44
+ multiple: true
45
+ options:
46
+ - Firefox
47
+ - Chrome
48
+ - Safari
49
+ - Microsoft Edge
50
+ - type: textarea
51
+ id: logs
52
+ attributes:
53
+ label: Relevant log output
54
+ description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
55
+ render: sh
@@ -0,0 +1 @@
1
+ blank_issues_enabled: false
@@ -0,0 +1,22 @@
1
+ name: Feature request
2
+ description: Request a new feature
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to request a new feature in the Adapt authoring tool! The Adapt team will consider all new feature requests, but unfortunately cannot commit to every one.
9
+ - type: textarea
10
+ id: description
11
+ attributes:
12
+ label: Feature description
13
+ description: Please describe your feature request
14
+ validations:
15
+ required: true
16
+ - type: checkboxes
17
+ id: contribute
18
+ attributes:
19
+ label: Can you work on this feature?
20
+ description: If you are able to commit your own time to work on this feature, it will greatly increase the liklihood of it being implemented by the core dev team. Otherwise, it will be triaged and prioritised alongside the core team's current priorities.
21
+ options:
22
+ - label: I can contribute
@@ -0,0 +1,11 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "npm" # See documentation for possible values
9
+ directory: "/" # Location of package manifests
10
+ schedule:
11
+ interval: "weekly"
@@ -0,0 +1,25 @@
1
+ [//]: # (Please title your PR according to eslint commit conventions)
2
+ [//]: # (See https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-eslint#eslint-convention for details)
3
+
4
+ [//]: # (Add a link to the original issue)
5
+
6
+ [//]: # (Delete as appropriate)
7
+ ### Fix
8
+ * A sentence describing each fix
9
+
10
+ ### Update
11
+ * A sentence describing each udpate
12
+
13
+ ### New
14
+ * A sentence describing each new feature
15
+
16
+ ### Breaking
17
+ * A sentence describing each breaking change
18
+
19
+ [//]: # (List appropriate steps for testing if needed)
20
+ ### Testing
21
+ 1. Steps for testing
22
+
23
+ [//]: # (Mention any other dependencies)
24
+
25
+
@@ -0,0 +1,16 @@
1
+ name: Add labelled PRs to project
2
+
3
+ on:
4
+ pull_request:
5
+ types: [ labeled ]
6
+
7
+ jobs:
8
+ add-to-project:
9
+ if: ${{ github.event.label.name == 'dependencies' }}
10
+ name: Add to main project
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/add-to-project@v0.1.0
14
+ with:
15
+ project-url: https://github.com/orgs/adapt-security/projects/5
16
+ github-token: ${{ secrets.PROJECTS_SECRET }}
@@ -0,0 +1,19 @@
1
+ name: Add to main project
2
+
3
+ on:
4
+ issues:
5
+ types:
6
+ - opened
7
+ pull_request:
8
+ types:
9
+ - opened
10
+
11
+ jobs:
12
+ add-to-project:
13
+ name: Add to main project
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/add-to-project@v0.1.0
17
+ with:
18
+ project-url: https://github.com/orgs/adapt-security/projects/5
19
+ github-token: ${{ secrets.PROJECTS_SECRET }}
@@ -0,0 +1,32 @@
1
+ name: Release
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+
7
+ jobs:
8
+ release:
9
+ name: Release
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write # to be able to publish a GitHub release
13
+ issues: write # to be able to comment on released issues
14
+ pull-requests: write # to be able to comment on released pull requests
15
+ id-token: write # to enable use of OIDC for trusted publishing and npm provenance
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@v3
19
+ with:
20
+ fetch-depth: 0
21
+ - name: Setup Node.js
22
+ uses: actions/setup-node@v3
23
+ with:
24
+ node-version: 'lts/*'
25
+ - name: Update npm
26
+ run: npm install -g npm@latest
27
+ - name: Install dependencies
28
+ run: npm ci
29
+ - name: Release
30
+ env:
31
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32
+ run: npx semantic-release
@@ -0,0 +1,13 @@
1
+ name: Standard.js formatting check
2
+ on: push
3
+ jobs:
4
+ default:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@master
8
+ - uses: actions/setup-node@master
9
+ with:
10
+ node-version: 'lts/*'
11
+ cache: 'npm'
12
+ - run: npm ci
13
+ - run: npx standard
@@ -0,0 +1,11 @@
1
+ {
2
+ "module": false,
3
+ "documentation": {
4
+ "enable": true,
5
+ "manualPages": {
6
+ "building-docs.md": "basics",
7
+ "custom-documentation-plugins.md": "advanced",
8
+ "writing-documentation.md": "contributing"
9
+ }
10
+ }
11
+ }
package/assets/bg.png ADDED
Binary file
Binary file
Binary file
Binary file
Binary file
package/bin/docgen.js ADDED
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generates documentation for the installed modules.
4
+ */
5
+ import { App } from 'adapt-authoring-core'
6
+ import docsify from '../docsify/docsify.js'
7
+ import fs from 'fs/promises'
8
+ import jsdoc3 from '../jsdoc3/jsdoc3.js'
9
+ import path from 'path'
10
+ import swagger from '../swagger/swagger.js'
11
+
12
+ process.env.NODE_ENV ??= 'production'
13
+ process.env.ADAPT_AUTHORING_LOGGER__mute = true
14
+
15
+ const app = App.instance
16
+ let outputdir
17
+
18
+ let manualIndex // populated in cacheConfigs
19
+ let sourceIndex // populated in cacheConfigs
20
+ /**
21
+ * Caches loaded JSON so we don't load multiple times.
22
+ * Documentation for a module can be enabled in:
23
+ * package.json > adapt_authoring.documentation.enable
24
+ */
25
+ function cacheConfigs () {
26
+ const cache = []
27
+ const excludes = app.pkg.documentation.excludes ?? []
28
+ Object.values(app.dependencies).forEach(dep => {
29
+ const c = dep.documentation
30
+
31
+ let omitMsg
32
+ if (!c) omitMsg = 'no documentation config defined'
33
+ else if (!c.enable) omitMsg = 'documentation.enable is set to false'
34
+ else if (excludes.includes(dep.name)) omitMsg = 'module has been excluded in documentation config'
35
+ if (omitMsg) return console.log(`Omitting ${dep.name}, ${omitMsg}`)
36
+
37
+ if (c.manualIndex) {
38
+ if (manualIndex) return console.log(`${dep.name}: manualIndex has been specified by another module as ${manualIndex}`)
39
+ manualIndex = path.join(dep.rootDir, c.manualIndex).split(path.sep).join(path.posix.sep)
40
+ }
41
+ if (c.sourceIndex) {
42
+ if (sourceIndex) return console.log(`${dep.name}: sourceIndex has been specified by another module as ${sourceIndex}`)
43
+ sourceIndex = path.join(dep.rootDir, c.sourceIndex).split(path.sep).join(path.posix.sep)
44
+ }
45
+ cache.push({
46
+ ...c,
47
+ name: dep.name,
48
+ version: dep.version,
49
+ module: !!app.dependencyloader.instances[dep.name],
50
+ rootDir: dep.rootDir,
51
+ includes: c.includes || {}
52
+ })
53
+ })
54
+ cache.push({
55
+ ...app.pkg.documentation,
56
+ enable: true,
57
+ name: 'adapt-authoring',
58
+ rootDir: app.rootDir,
59
+ includes: {}
60
+ })
61
+ return cache
62
+ }
63
+
64
+ async function copyRootFiles () {
65
+ const resolve = p => new URL(`../${p}`, import.meta.url)
66
+ await fs.cp(resolve('/root'), outputdir, { recursive: true })
67
+ await fs.cp(resolve('assets'), path.resolve(outputdir, 'assets'), { recursive: true })
68
+ }
69
+
70
+ async function docs () {
71
+ console.log(`Generating documentation for ${app.pkg.name}@${app.pkg.version}`)
72
+
73
+ try {
74
+ await app.onReady()
75
+ } catch (e) {
76
+ console.log(`App failed to start, cannot continue.\n${e}`)
77
+ process.exit(1)
78
+ }
79
+ const config = await app.waitForModule('config')
80
+ const { name } = JSON.parse(await fs.readFile(new URL('../package.json', import.meta.url)))
81
+ outputdir = path.resolve(process.cwd(), config.get(`${name}.outputDir`))
82
+
83
+ const cachedConfigs = cacheConfigs()
84
+
85
+ console.log('\nThis might take a minute or two...\n')
86
+
87
+ try {
88
+ await fs.rm(outputdir, { recursive: true, force: true })
89
+ await fs.mkdir(outputdir)
90
+ await copyRootFiles()
91
+ await jsdoc3(app, cachedConfigs, outputdir, sourceIndex)
92
+ await docsify(app, cachedConfigs, outputdir, manualIndex, sourceIndex)
93
+ await swagger(app, cachedConfigs, outputdir)
94
+ } catch (e) {
95
+ console.log(e)
96
+ process.exit(1)
97
+ }
98
+ console.log('Documentation build complete.')
99
+ process.exit()
100
+ }
101
+
102
+ export default docs()
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generates an HTTP server for viewing the local copy of the documentation (note these must be build first with `at-docgen`)
4
+ */
5
+ import { App } from 'adapt-authoring-core'
6
+ import { spawn } from 'child_process'
7
+ import http from 'http-server'
8
+ import path from 'path'
9
+ /*
10
+ function getMime (filePath) {
11
+ const ext = path.parse(filePath).ext
12
+ return {
13
+ '.ico': 'image/x-icon',
14
+ '.html': 'text/html',
15
+ '.js': 'text/javascript',
16
+ '.json': 'application/json',
17
+ '.css': 'text/css',
18
+ '.png': 'image/png',
19
+ '.jpg': 'image/jpeg',
20
+ '.svg': 'image/svg+xml',
21
+ '.pdf': 'application/pdf',
22
+ '.doc': 'application/msword'
23
+ }[ext] || 'text/plain'
24
+ }
25
+ */
26
+ process.env.NODE_ENV ??= 'production'
27
+ process.env.ADAPT_AUTHORING_LOGGER__mute = true
28
+
29
+ console.log('Starting app, please wait\n')
30
+ // TODO remove need to start app
31
+ App.instance.onReady().then(async app => {
32
+ console.log('App started\n');
33
+ (await app.waitForModule('server')).close() // close connections so we can still run the app separately
34
+
35
+ const ROOT = path.resolve(app.config.get('adapt-authoring-docs.outputDir'))
36
+ const PORT = 9000
37
+ const OPEN = process.argv.some(a => a === '--open')
38
+
39
+ const server = http.createServer({ root: ROOT, port: PORT })
40
+
41
+ server.listen(PORT, () => {
42
+ const url = `http://localhost:${PORT}`
43
+ console.log(`Docs hosted at ${url}`)
44
+
45
+ if (OPEN) {
46
+ const command = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open'
47
+ spawn(`${command} ${url}`, { shell: true })
48
+ .on('error', e => console.log('spawn error', e))
49
+ }
50
+ })
51
+ })
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "outputDir": {
6
+ "description": "Path to store documentation build files",
7
+ "type": "string",
8
+ "isDirectory": true,
9
+ "default": "$TEMP/docs-build"
10
+ },
11
+ "manualSections": {
12
+ "description": "Sections for categorising documentation manual pages",
13
+ "type": "object",
14
+ "default": {
15
+ "getting-started": {
16
+ "title": "Getting started"
17
+ },
18
+ "basics": {
19
+ "title": "The basics"
20
+ },
21
+ "advanced": {
22
+ "title": "Advanced topics"
23
+ },
24
+ "ui": {
25
+ "title": "Front-end app"
26
+ },
27
+ "other-guides": {
28
+ "title": "Other guides",
29
+ "default": true
30
+ },
31
+ "contributing": {
32
+ "title": "Contributing"
33
+ },
34
+ "reference": {
35
+ "title": "Reference"
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,21 @@
1
+ # Building the docs
2
+ If you want to build your own local copy of the documentation, you'll need to run the bin script bundled with the documentation module.
3
+
4
+ > If you ran the automated intaller, chances are you didn't install the optional developer dependencies (and therefore don't have the documentation module). You can fix this by running:
5
+ `npm i --only=dev`
6
+
7
+ Run the documentation generator using:
8
+
9
+ ```bash
10
+ npx at-docgen
11
+ ```
12
+
13
+ Once the documentation has been built, it'll be stored in the temp directory. Where this is will vary depending on your config file, but you can find the default [location here](configuration?id=adapt-authoring-docs).
14
+
15
+ To correctly view the docs, you'll need to run a local web server. You can do this using another automated bin script bundled with the documentation module:
16
+
17
+ ```bash
18
+ npx at-docserve
19
+ ```
20
+
21
+ See the [bin script docs](binscripts) for full usage details.
@@ -0,0 +1,41 @@
1
+ # Writing custom documentation plugins
2
+
3
+ In addition to the standard static markdown files, you can also generate dynamic content by writing your own documentation plugin.
4
+
5
+ To do this, you need to do the following:
6
+
7
+ ## 1. Write your plugin
8
+ The first step involves writing the Javascript to do what you need. Here are a few tips on writing your own documentation plugin:
9
+ - Write any new `.md` files to the `outputDir` directory (any files not in this folder will not be included in the final output!)
10
+ - Include any new files in the `customFiles` array (forgetting this step will mean your files aren't included in the documentation side nav bar)
11
+ - You can access any App properties using the instance passed to your plugin's constructor
12
+ - To keep things neat, we recommend putting all plugin files in a separate `plugins/` folder in the `docs/` folder of your module (e.g. `mymodule/docs/plugins/MyDocPlugin.js`)
13
+
14
+ You can use the following code as a starting-point:
15
+ ```js
16
+ class MyDocPlugin {
17
+ /**
18
+ * @param {App} app Reference to the main App instance
19
+ * @param {Object} config Parsed adapt-authoring.json file for this module
20
+ * @param {String} outputDir The docs output path (write any custom .md files here)
21
+ */
22
+ constructor(app, config, outputDir) {
23
+ // include the FULL paths to any new .md files in this array.
24
+ this.customFiles = [];
25
+ }
26
+ }
27
+ module.exports = MyDocPlugin;
28
+ ```
29
+
30
+ ## 2. Add your plugin to adapt-authoring.json
31
+ In order for your plugin to be executed by the documentation generator, you must add it to the list of `manualPlugins` in the `adapt-authoring.json` for your module (this path should be relative to the root folder of your plugin).
32
+
33
+ ```json
34
+ {
35
+ "documentation": {
36
+ // ...other options
37
+ "manualPlugins": ["docs/plugins/MyDocPlugin.js"]
38
+ }
39
+ }
40
+
41
+ ```
@@ -0,0 +1,55 @@
1
+ # Writing documentation
2
+ The Adapt authoring tool makes use of automatically generated documentation (powered by [JSDoc](https://jsdoc.app/)).
3
+
4
+ **Source code reference** *mandatory* <br>
5
+ Requires annotated code (see below), but otherwise completely automated.
6
+
7
+ **Developer manual** *optional*<br>
8
+ Requires handwritten markdown. Provides extra advice on using your code in practical scenarios.
9
+
10
+ ## Documenting code
11
+ The source code reference is completely automated, and shouldn't need much input from you as a developer (provided your code has been correctly annotated).
12
+
13
+ If you're not familiar with the JSDoc notation, you can find a list of accepted tags as well as examples of usage in the [JSDoc docs](https://jsdoc.app/) (you can also of course check the source code for any of the [core-supported Adapt authoring modules](coreplugins.html) which are fully documented).
14
+
15
+ ### Useful tips
16
+ Below are some useful tips/gotchas for any budding documentation writers.
17
+
18
+ #### Instance variables must be initialised
19
+ Any declared instance variables must be initialised in order to be picked up by the documentation generator, even if they don't need a value (in which case `this.var = undefined` is fine).
20
+
21
+ ## Writing developer guides
22
+ Developer guides go a step further than the source code reference, and provide more user-friendly "how-to" guides on how to actually *use* your code in a practical scenario.
23
+
24
+ Whether or not you include these in your modules is completely up to you, but it will greatly help the community if you do!
25
+
26
+ What to include in developer guides:
27
+ - Any required configuration options
28
+ - Common usage examples
29
+ - Any known issues/workarounds
30
+
31
+ > If you have need to generate a dynamic documentation file, check out our guide on [writing custom doc plugins](custom-documentation-plugins).
32
+
33
+ ## Configuration
34
+ In addition to writing the manual files, you'll also need to add some configuration to the `adapt-authoring.json` file for your module to ensure that your files are included when the documentation is built.
35
+
36
+ All documentation-related options are contained in a `documentation` object at the root level:
37
+ ```json
38
+ {
39
+ "documentation": {
40
+ "enable": true,
41
+ "manualPlugins": [],
42
+ "manualPages": {}
43
+ }
44
+ }
45
+ ```
46
+
47
+ The below table gives a brief explanation of each option:
48
+
49
+ | Attribute | Type | Default | Description |
50
+ | --------- | ---- | :-----: | ----------- |
51
+ | `enable` | Boolean | `true` | Whether documentation should be generated for this module. |
52
+ | `manualPlugins` | Array | `[]` | A list of paths to any custom manual plugins. See [this page](custom-documentation-plugins) for more info. |
53
+ | `manualPages` | Object | `{}` | A key/value store mapping file names to a section (e.g. `"manual-page.md": "advanced"`). The key must be the filename only, and not a path. The section ID must match one of those defined in the config (see the [configuration reference](configuration?id=adapt-authoring-docs) for the defaults, or set your own in your config file). |
54
+
55
+ > You can also store manual files in the root repository of the application; just make sure to add your doc files to a `/docs` directory.
@@ -0,0 +1,67 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import { pathToFileURL } from 'url'
4
+ /**
5
+ * Utility functions to be used by Docsify plugins
6
+ */
7
+ export default class DocsifyPluginWrapper {
8
+ get customFiles () {
9
+ return this.plugin.customFiles ?? []
10
+ }
11
+
12
+ constructor (config) {
13
+ this.config = config
14
+ this.config.srcDir = path.dirname(config.pluginEntry)
15
+ }
16
+
17
+ async init () {
18
+ const PluginClass = (await import(pathToFileURL(this.config.pluginEntry))).default
19
+ this.plugin = new PluginClass()
20
+ this.plugin.app = this.config.app
21
+ this.plugin.config = this.config
22
+
23
+ if (!this.plugin.run || typeof this.plugin.run !== 'function') throw new Error('Documentation plugin must define a \'run\' function')
24
+
25
+ await this.plugin.run()
26
+ // set some default values
27
+ this.plugin.contents ??= []
28
+ this.plugin.customFiles ??= []
29
+ this.plugin.replace ??= {}
30
+
31
+ if (this.plugin.manualFile) await this.writeFile()
32
+ }
33
+
34
+ generateTOC (items) {
35
+ const pageName = this.plugin?.manualFile?.replace(path.extname(this.plugin.manualFile), '') ?? ''
36
+ let output = '### Quick navigation\n\n<ul class="toc">\n'
37
+ items.forEach(i => {
38
+ let text = i; let link = i
39
+ if (Array.isArray(i)) {
40
+ text = i[0]
41
+ link = i[1]
42
+ }
43
+ output += `<li><a href="#/${pageName}?id=${link}">${text}</a></li>\n`
44
+ })
45
+ output += '</ul>\n'
46
+ return output
47
+ }
48
+
49
+ async writeFile () {
50
+ if (this.plugin.contents.length) {
51
+ this.plugin.replace.TABLE_OF_CONTENTS = this.generateTOC(this.plugin.contents)
52
+ }
53
+ const filePath = path.resolve(this.config.srcDir, this.plugin.manualFile)
54
+ let file
55
+ try {
56
+ file = fs.readFileSync(filePath).toString()
57
+ } catch (e) {
58
+ throw new Error(`Failed to load manual file at ${filePath}`)
59
+ }
60
+ // do any specified string replacements
61
+ file = Object.entries(this.plugin.replace).reduce((f, [key, value]) => f.replaceAll(`{{{${key}}}}`, value), file)
62
+
63
+ const outputPath = path.join(this.config.outputDir, this.plugin.manualFile)
64
+ this.plugin.customFiles.push(outputPath)
65
+ fs.writeFileSync(outputPath, file)
66
+ }
67
+ }