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,105 @@
1
+ import DocsifyPluginWrapper from './DocsifyPluginWrapper.js'
2
+ import { exec } from 'child_process'
3
+ import { fileURLToPath } from 'url'
4
+ import fs from 'fs-extra'
5
+ import { globSync } from 'glob'
6
+ import path from 'path'
7
+ import { promisify } from 'util'
8
+
9
+ const execPromise = promisify(exec)
10
+
11
+ function resolvePath (relativePath) {
12
+ return fileURLToPath(new URL(relativePath, import.meta.url))
13
+ }
14
+
15
+ /**
16
+ * Copies all doc files ready for the generator
17
+ */
18
+ export default async function docsify (app, configs, outputdir, manualIndex, sourceIndex) {
19
+ const dir = path.resolve(outputdir, 'manual')
20
+ const sectionsConf = app.config.get('adapt-authoring-docs.manualSections')
21
+ const defaultSection = Object.entries(sectionsConf).reduce((m, [id, data]) => data.default ? id : m)
22
+ /**
23
+ * init docsify folder
24
+ */
25
+ await execPromise(`npx docsify init ${dir}`)
26
+ /**
27
+ * Collate data & run custom plugins
28
+ */
29
+ const titleMap = {}
30
+ await Promise.all(configs.map(async c => {
31
+ const customFiles = []
32
+ if (c.manualPlugins) {
33
+ await Promise.all(c.manualPlugins.map(async p => {
34
+ try {
35
+ const wrapper = await new DocsifyPluginWrapper({
36
+ ...c,
37
+ app,
38
+ docsRootDir: outputdir,
39
+ pluginEntry: path.resolve(c.rootDir, p),
40
+ outputDir: dir
41
+ })
42
+ await wrapper.init()
43
+ customFiles.push(...wrapper.customFiles)
44
+ } catch (e) {
45
+ console.log(`Failed to load ${c.name} doc manual plugin ${path.basename(p)}, ${e}`)
46
+ }
47
+ }))
48
+ }
49
+ if (c.manualSections) {
50
+ Object.entries(c.manualSections).forEach(([key, data]) => {
51
+ if (!sectionsConf[key]) sectionsConf[key] = data
52
+ })
53
+ }
54
+ [...customFiles, ...globSync('docs/*.md', { cwd: c.rootDir, absolute: true })].forEach(f => {
55
+ if (f === sourceIndex) {
56
+ return
57
+ }
58
+ const title = path.basename(f)
59
+ const sectionName = c.manualPages && c.manualPages[title] ? c.manualPages[title] : defaultSection
60
+
61
+ if (!sectionsConf[sectionName]) sectionsConf[sectionName] = {}
62
+ if (!sectionsConf[sectionName].pages) sectionsConf[sectionName].pages = []
63
+
64
+ sectionsConf[sectionName].pages.push(title)
65
+
66
+ titleMap[title] = { path: f, title }
67
+ try {
68
+ titleMap[title].title = fs.readFileSync(f).toString().match(/^#(?!#)\s?(.*)/)[1]
69
+ } catch (e) {}
70
+ })
71
+ }))
72
+ /**
73
+ * Copy files
74
+ */
75
+ await fs.copy(resolvePath('./index.html'), `${dir}/index.html`)
76
+ await fs.copy(resolvePath('../assets'), `${dir}/assets`)
77
+ await fs.copy(resolvePath('./js'), `${dir}/js`)
78
+ await fs.copy(resolvePath('./styles'), `${dir}/styles`)
79
+ if (manualIndex) {
80
+ await fs.copy(manualIndex, `${dir}/_coverpage.md`)
81
+ }
82
+ await Promise.allSettled(Object.entries(titleMap).map(([filename, v]) => fs.copy(v.path, `${dir}/${filename}`)))
83
+ /**
84
+ * Generate custom sidebar
85
+ */
86
+ let sidebarMd = ''
87
+ Object.entries(sectionsConf)
88
+ .forEach(([id, { title, pages = [] }]) => {
89
+ const filtered = pages.filter(f => {
90
+ const p = titleMap[f].path
91
+ return p !== manualIndex && p !== sourceIndex
92
+ })
93
+ if (!filtered || !filtered.length) {
94
+ return
95
+ }
96
+ sidebarMd += `\n\n<ul class="header"><li>${title}</li></ul>\n\n`
97
+ filtered
98
+ .sort((a, b) => a.localeCompare(b))
99
+ .forEach(f => {
100
+ sidebarMd += ` - [${titleMap[f].title}](${f})\n`
101
+ })
102
+ })
103
+
104
+ await fs.writeFile(`${dir}/_sidebar.md`, sidebarMd)
105
+ }
@@ -0,0 +1,33 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Adapt authoring tool - Developer Guides</title>
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
7
+ <meta name="description" content="Description">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
9
+ <link rel="icon" href="assets/favicon.png" sizes="any">
10
+ <link id="light-theme" rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css" />
11
+ <link id="dark-theme" disabled rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/themes/dark.css" />
12
+ <link rel="stylesheet" href="styles/adapt.css">
13
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
14
+ </head>
15
+ <body>
16
+ <a id="dark-mode" href="#"><i class="material-icons">brightness_6</i></a>
17
+ <nav>
18
+ <a href="https://adapt-security.github.io/adapt-authoring-documentation/" target="_blank"><i class="material-icons">language</i> Documentation home</a>
19
+ <a href="https://www.adaptlearning.org" target="_blank"><i class="material-icons">language</i> Project website</a>
20
+ <a href="https://community.adaptlearning.org/mod/forum/view.php?id=4" target="_blank"><i class="material-icons">forum</i> Official forum</a>
21
+ <a href="https://gitter.im/adaptlearning" target="_blank"><i class="material-icons">textsms</i> Gitter chatrooms</a>
22
+ </nav>
23
+ <div id="docsify">
24
+ <div id="app"><!-- Docsify will load in here --></div>
25
+ </div>
26
+ <!-- Docsify v4 -->
27
+ <script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
28
+ <!-- Plugins -->
29
+ <script src="js/adapt.js"></script>
30
+ <script src="//unpkg.com/docsify-material-icons/dist/docsify-material-icons.min.js"></script>
31
+ <script src="https://unpkg.com/docsify-copy-code@2"></script>
32
+ </body>
33
+ </html>
@@ -0,0 +1,32 @@
1
+ /* global addEventListener localStorage */
2
+
3
+ window.$docsify = {
4
+ name: '<img class="logo" src="assets/logo-outline-colour.png" />Adapt authoring tool<h2>Developer guides</h2>',
5
+ repo: 'https://github.com/adapt-security/adapt-authoring',
6
+ themeColor: '#36cde8',
7
+ loadSidebar: true,
8
+ loadNavbar: false,
9
+ autoHeader: true,
10
+ coverpage: true
11
+ }
12
+
13
+ function onLoad () {
14
+ updateTheme()
15
+ }
16
+
17
+ function darkModeClick (event) {
18
+ event.preventDefault()
19
+ localStorage.setItem('darkMode', localStorage.getItem('darkMode') === 'true' ? 'false' : 'true')
20
+ updateTheme()
21
+ }
22
+
23
+ function updateTheme () {
24
+ const darkMode = localStorage.getItem('darkMode') === 'true'
25
+ document.getElementById('light-theme').disabled = darkMode
26
+ document.getElementById('dark-theme').disabled = !darkMode
27
+ const classList = document.getElementsByTagName('body')[0].classList
28
+ darkMode ? classList.add('dark') : classList.remove('dark')
29
+ }
30
+
31
+ addEventListener('load', onLoad)
32
+ document.getElementById('dark-mode').addEventListener('click', darkModeClick)
@@ -0,0 +1,230 @@
1
+ @import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,700|Roboto+Mono);
2
+
3
+ #dark-mode {
4
+ position: fixed;
5
+ display: block;
6
+ z-index: 5000;
7
+ width: 40px;
8
+ text-align: center;
9
+ height: 36px;
10
+ background-color: var(--theme-color);
11
+ color: white;
12
+ }
13
+ #dark-mode i {
14
+ font-size: 24px;
15
+ }
16
+
17
+ body {
18
+ font-family: 'Open Sans', sans-serif;
19
+ font-size: 14px;
20
+ padding-left: 0;
21
+ padding-right: 0;
22
+ }
23
+
24
+ h1, h2, h3, h4, h5, h6,
25
+ h1 > a, h2 > a, h3 > a, h4 > a, h5 > a, h6 > a {
26
+ font-family: 'Open Sans', sans-serif;
27
+ font-weight: 300 !important;
28
+ }
29
+
30
+ summary {
31
+ font-size: 1.15rem;
32
+ cursor: pointer;
33
+ margin-bottom: 1em;
34
+ }
35
+
36
+ i.material-icons {
37
+ top: 5px;
38
+ position: relative;
39
+ }
40
+
41
+ nav.app-nav {
42
+ margin-top: 15px;
43
+ color: white;
44
+ }
45
+ nav.app-nav a {
46
+ font-size: 14px;
47
+ }
48
+ nav.app-nav a:hover {
49
+ color: white;
50
+ text-decoration: underline;
51
+ }
52
+
53
+ section.cover {
54
+ background: linear-gradient(to left bottom, #00dd95 0%,#34bee0 100%) !important;
55
+ color: white;
56
+ }
57
+ section.cover h2 {
58
+ font-size: 70px;
59
+ }
60
+ section.cover .anchor span {
61
+ color: white;
62
+ }
63
+ section.cover .cover-main > p:last-child a,
64
+ section.cover .cover-main > p:last-child a:last-child {
65
+ color: white;
66
+ border-color: white;
67
+ background: transparent;
68
+ }
69
+ section.cover .cover-main > p:last-child a:hover,
70
+ section.cover .cover-main > p:last-child a:last-child:hover {
71
+ background: white;
72
+ color: #34bee0;
73
+ }
74
+
75
+ .sidebar {
76
+ font-weight: bold;
77
+ width: 350px;
78
+ }
79
+ .sidebar ul li {
80
+ margin: 3px 10px;
81
+ }
82
+ .sidebar ul li a {
83
+ font-weight: normal;
84
+ font-size: 14px;
85
+ }
86
+ .sidebar ul.header {
87
+ padding-top: 20px;
88
+ padding-bottom: 5px;
89
+ font-size: 16px;
90
+ }
91
+ .sidebar ul.header li {
92
+ margin-left: 0;
93
+ }
94
+
95
+ .sidebar .app-name {
96
+ margin-bottom: 25px;
97
+ }
98
+ .sidebar .app-name .logo {
99
+ display: block;
100
+ margin: 0 auto;
101
+ width: 100px;
102
+ }
103
+ .sidebar h1.app-name {
104
+ font-size: 18px;
105
+ }
106
+ .sidebar .app-name h2 {
107
+ margin-top: 5px;
108
+ }
109
+
110
+ section.content {
111
+ left: 350px;
112
+ }
113
+
114
+ .markdown-section code,
115
+ .token.boolean,
116
+ .token.function,
117
+ .token.keyword,
118
+ .token.number {
119
+ color: #00dd95;
120
+ }
121
+
122
+ .markdown-section blockquote {
123
+ background: #e7fdf6;
124
+ padding-top: 5px;
125
+ padding-right: 15px;
126
+ padding-bottom: 5px;
127
+ border-top: 1px solid #92f2d3;
128
+ border-right: 1px solid #92f2d3;
129
+ border-bottom: 1px solid #92f2d3;
130
+ border-radius: 0 5px 5px 0;
131
+ border-left-color: #00dd95;
132
+ }
133
+
134
+ ul.toc {
135
+ margin-bottom: 3rem;
136
+ }
137
+
138
+ body.size-xl ul.toc:nth-child(n+10) {
139
+ columns: 4;
140
+ }
141
+ body.size-l ul.toc:nth-child(n+10) {
142
+ columns: 3;
143
+ }
144
+ body.size-m ul.toc:nth-child(n+10) {
145
+ }
146
+ ul.toc > li {
147
+ overflow: hidden;
148
+ white-space: nowrap;
149
+ text-overflow: ellipsis;
150
+ list-style-position: inside;
151
+ }
152
+
153
+ /**
154
+ * Navbar width
155
+ */
156
+ @media only screen and (min-width: 767px) {
157
+ .sidebar {
158
+ padding-left: 25px;
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Reusable schema styles
164
+ */
165
+ .options {
166
+ padding-left: 15px;
167
+ border-left: 3px solid #00dd95;
168
+ }
169
+ .attribute {
170
+ margin-bottom: 15px;
171
+ }
172
+ .attribute .inner {
173
+ padding-left: 15px;
174
+ }
175
+ .attribute .title {
176
+ margin-bottom: 10px;
177
+ }
178
+ .attribute .title .main {
179
+ font-weight: bold;
180
+ font-size: 16px;
181
+ }
182
+ .attribute .description {
183
+ margin: 5px 0;
184
+ }
185
+ .attribute .default .label {
186
+ font-weight: bold;
187
+ }
188
+ .attribute .default pre {
189
+ display: inline;
190
+ padding: 0 5px;
191
+ }
192
+ .markdown-section table.schema {
193
+ margin-top: 25px;
194
+ }
195
+ .markdown-section table.schema pre {
196
+ padding: 0.25rem 1rem;
197
+ text-align: center;
198
+ max-width: 250px;
199
+ overflow: hidden;
200
+ text-overflow: ellipsis;
201
+
202
+ }
203
+ .markdown-section .required {
204
+ font-weight: bold;
205
+ }
206
+ .markdown-section .desc {
207
+ font-size: 16px;
208
+ margin-bottom: 15px;
209
+ }
210
+ .markdown-section .extension {
211
+ margin-bottom: 10px;
212
+ font-weight: bold;
213
+ }
214
+
215
+ /**
216
+ * Dark mode overrides
217
+ */
218
+ body.dark strong,
219
+ body.dark em {
220
+ color: inherit;
221
+ }
222
+
223
+ body.dark .markdown-section tr:nth-child(2n) {
224
+ background-color: #606060;
225
+ }
226
+
227
+ body.dark .markdown-section blockquote {
228
+ background: #004a32;
229
+ color: inherit;
230
+ }
@@ -0,0 +1,106 @@
1
+ import { exec } from 'child_process'
2
+ import { fileURLToPath } from 'url'
3
+ import fs from 'fs-extra'
4
+ import { globSync } from 'glob'
5
+ import { promisify } from 'util'
6
+
7
+ const execPromise = promisify(exec)
8
+
9
+ const configPath = resolvePath('.jsdocConfig.json')
10
+
11
+ let cachedConfigs
12
+
13
+ function resolvePath (relativePath) {
14
+ return fileURLToPath(new URL(relativePath, import.meta.url))
15
+ }
16
+
17
+ async function writeConfig (app, outputdir, indexFile) {
18
+ return fs.writeFile(configPath, JSON.stringify({
19
+ source: {
20
+ include: getSourceIncludes(indexFile)
21
+ },
22
+ docdash: {
23
+ collapse: true,
24
+ typedefs: true,
25
+ search: true,
26
+ static: true,
27
+ menu: {
28
+ [`<img class="logo" src="assets/logo-outline-colour.png" />Adapt authoring tool back-end API documentation<br><span class="version">v${app.pkg.version}</span>`]: {
29
+ class: 'menu-title'
30
+ },
31
+ 'Documentation home': {
32
+ href: 'https://adapt-security.github.io/adapt-authoring-documentation/',
33
+ target: '_self',
34
+ class: 'menu-item',
35
+ id: 'home_link'
36
+ },
37
+ 'Project Website': {
38
+ href: 'https://www.adaptlearning.org/',
39
+ target: '_blank',
40
+ class: 'menu-item',
41
+ id: 'website_link'
42
+ },
43
+ 'Technical Discussion Forum': {
44
+ href: 'https://community.adaptlearning.org/mod/forum/view.php?id=4',
45
+ target: '_blank',
46
+ class: 'menu-item',
47
+ id: 'forum_link'
48
+ }
49
+ },
50
+ sectionOrder: [ // Order the main section in the navbar (default order shown here)
51
+ 'Namespaces',
52
+ 'Classes',
53
+ 'Modules',
54
+ 'Externals',
55
+ 'Events',
56
+ 'Mixins',
57
+ 'Tutorials',
58
+ 'Interfaces'
59
+ ],
60
+ meta: {
61
+ title: 'Adapt authoring tool UI documentation',
62
+ description: 'Adapt authoring tool UI documentation',
63
+ keyword: `v${app.pkg.version}`
64
+ },
65
+ scripts: [
66
+ 'styles/adapt.css',
67
+ 'scripts/adapt.js'
68
+ ]
69
+ },
70
+ opts: {
71
+ destination: outputdir,
72
+ template: 'node_modules/docdash'
73
+ }
74
+ }, null, 2))
75
+ }
76
+ /**
77
+ * Returns a list of modules to include.
78
+ * @note Source files must be located in /lib
79
+ */
80
+ function getSourceIncludes (indexFile) {
81
+ const includes = cachedConfigs.reduce((i, c) => {
82
+ return i.concat(
83
+ ...globSync('lib/**/*.js', { cwd: c.rootDir, absolute: true }),
84
+ ...(c.module ? globSync('index.js', { cwd: c.rootDir, absolute: true }) : [])
85
+ )
86
+ }, [])
87
+ if (indexFile) includes.push(indexFile)
88
+ return includes
89
+ }
90
+
91
+ export default async function jsdoc3 (app, configs, outputdir, sourceIndexFile) {
92
+ cachedConfigs = configs
93
+ const dir = `${outputdir}/backend`
94
+ await writeConfig(app, dir, sourceIndexFile)
95
+ try {
96
+ await execPromise(`npx jsdoc -c ${configPath}`)
97
+ } catch (e) {
98
+ console.log(e.stderr)
99
+ throw new Error('JSDoc exited with errors. See above for details.')
100
+ }
101
+ await Promise.all([
102
+ fs.copy(resolvePath('./styles/adapt.css'), `${dir}/styles/adapt.css`),
103
+ fs.copy(resolvePath('./scripts/adapt.js'), `${dir}/scripts/adapt.js`),
104
+ fs.copy(resolvePath('../assets'), `${dir}/assets`)
105
+ ])
106
+ }
@@ -0,0 +1,18 @@
1
+ const iconLink = document.createElement('link')
2
+ iconLink.rel = 'icon'
3
+ iconLink.href = 'assets/favicon.png'
4
+ iconLink.sizes = 'any'
5
+ document.querySelector('head').append(iconLink)
6
+
7
+ const container = document.createElement('div')
8
+ container.className = 'main-page-title'
9
+
10
+ const mainTitle = document.createElement('h1')
11
+ mainTitle.appendChild(document.createTextNode(document.querySelector('meta[name="description"]').content))
12
+ container.append(mainTitle)
13
+
14
+ const subTitle = document.createElement('h2')
15
+ subTitle.appendChild(document.createTextNode(document.querySelector('meta[name="keyword"]').content))
16
+ container.append(subTitle)
17
+
18
+ document.querySelector('#main').prepend(container)
@@ -0,0 +1,144 @@
1
+ @import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,700|Roboto+Mono);
2
+ .code {
3
+ font-family: 'Roboto Mono', monospace;
4
+ font-size: 13px;
5
+ }
6
+ body {
7
+ font-family: 'Open Sans', sans-serif;
8
+ font-size: 14px;
9
+ padding-left: 0;
10
+ padding-right: 0;
11
+ }
12
+
13
+ h1, h2, h3 {
14
+ font-family: 'Open Sans', sans-serif;
15
+ font-weight: 300;
16
+ }
17
+ h1.page-title {
18
+ font-size: 33px;
19
+ margin-bottom: 0;
20
+ }
21
+ .main-page-title {
22
+ background: #00dd95;
23
+ padding: 35px;
24
+ }
25
+ .main-page-title h1,
26
+ .main-page-title h2 {
27
+ color: white;
28
+ }
29
+ .main-page-title h1 {
30
+ margin: 0;
31
+ font-size: 40px;
32
+ }
33
+ .main-page-title h2 {
34
+ margin: 0;
35
+ font-size: 28px;
36
+ }
37
+
38
+
39
+ #main .usertext h1,
40
+ #main .usertext h2 {
41
+ font-family: inherit;
42
+ font-weight: 300;
43
+ }
44
+ #main .usertext h1 {
45
+ margin: 0 0 15px 0;
46
+ font-size: 40px;
47
+ }
48
+ #main .usertext h2 {
49
+ margin-top: 20px;
50
+ font-size: 30px;
51
+ }
52
+
53
+
54
+ h4.name {
55
+ background: #34bee0;
56
+ }
57
+ h4.name a,
58
+ .signature,
59
+ .type-signature {
60
+ color: #263944;
61
+ }
62
+ .type-signature:last-child {
63
+ color: #3a7da4;
64
+ }
65
+
66
+ nav {
67
+ padding-left: 25px;
68
+ padding-bottom: 2rem;
69
+ background-color: #263944;
70
+ }
71
+ nav #nav-search {
72
+ background: rgba(255,255,255,0.1);
73
+ border: navajowhite;
74
+ margin-bottom: 1rem;
75
+ color: white;
76
+ outline: none;
77
+ }
78
+ nav h2 {
79
+ font-size: 14px;
80
+ }
81
+ nav h2:first-child {
82
+ display: none;
83
+ }
84
+ nav .menu-title {
85
+ display: block;
86
+ font-size: 18px !important;
87
+ font-weight: bold;
88
+ text-align: center;
89
+ padding-right: 25px;
90
+ padding-bottom: 25px;
91
+ }
92
+ nav .menu-title img {
93
+ display: block;
94
+ width: 100px;
95
+ margin: 0 auto;
96
+ margin-top: 20px;
97
+ margin-bottom: 20px;
98
+ }
99
+ nav .menu-title .version {
100
+ font-size: 14px !important;
101
+ }
102
+ nav h3 {
103
+ color: #34bee0;
104
+ }
105
+ nav a,
106
+ nav > h2 > a {
107
+ font-family: 'Open Sans', sans-serif !important;
108
+ color: white !important;
109
+ font-size: 14px !important;
110
+ }
111
+ nav ul ul a {
112
+ border-left-color: #00dd95;
113
+ color: #b7b7b7 !important;
114
+ font-size: 13px !important;
115
+ }
116
+
117
+ section {
118
+ padding: 30px;
119
+ }
120
+ section.package {
121
+ display: none;
122
+ }
123
+
124
+ footer {
125
+ display: none;
126
+ }
127
+
128
+ /**
129
+ * Navbar width
130
+ */
131
+ @media only screen and (min-width: 681px) {
132
+ nav {
133
+ width: 300px;
134
+ }
135
+ nav #nav-search {
136
+ width: 240px;
137
+ }
138
+ #main {
139
+ width: calc(100% - 300px);
140
+ }
141
+ footer {
142
+ margin-left: 300px;
143
+ }
144
+ }