@liascript/exporter 2.6.1--0.10.31 → 2.6.3--0.10.31

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liascript/exporter",
3
- "version": "2.6.1--0.10.31",
3
+ "version": "2.6.3--0.10.31",
4
4
  "description": "A generic exporter for LiaScript",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -47,13 +47,13 @@
47
47
  "dependencies": {
48
48
  "@liascript/simple-scorm-packager": "^0.3.0",
49
49
  "archiver": "^5.3.0",
50
- "clean-html": "^1.5.0",
51
50
  "fs-extra": "^9.1.0",
52
51
  "jsonld": "^8.1.1",
53
52
  "minimist": "^1.2.5",
54
53
  "node-fetch": "^2.6.9",
55
54
  "path": "^0.12.7",
56
55
  "puppeteer": "^19.2.2",
56
+ "simply-beautiful": "^0.2.14",
57
57
  "temp": "^0.9.4",
58
58
  "xhr2": "^0.2.1",
59
59
  "yaml": "^2.1.3"
@@ -5,6 +5,7 @@ const temp = require('temp')
5
5
  const fs = require('fs-extra')
6
6
  const path = require('path')
7
7
  const archiver = require('archiver')
8
+ const beautify = require('simply-beautiful')
8
9
 
9
10
  export function tmpDir() {
10
11
  return new Promise((resolve, reject) => {
@@ -51,6 +52,12 @@ export function injectResponsivevoice(key: string, into: string): string {
51
52
  )
52
53
  }
53
54
 
55
+ /**
56
+ * Inject an arbitrary tag directly to the end of the html-head tag.
57
+ * @param element - new tag to be added
58
+ * @param into - old index.html content
59
+ * @returns - new index.html content
60
+ */
54
61
  export function inject(element: string, into: string): string {
55
62
  return into.replace('</head>', element + '</head>')
56
63
  }
@@ -67,15 +74,16 @@ export async function iframe(
67
74
  tmpPath,
68
75
  filename: string,
69
76
  readme: string,
77
+ jsonLD: string,
70
78
  style?: string,
71
79
  index?: string
72
80
  ) {
73
81
  await writeFile(
74
82
  path.join(tmpPath, filename),
75
- `<!DOCTYPE html>
83
+ prettify(`<!DOCTYPE html>
76
84
  <html style="height:100%; overflow: hidden">
77
85
  <head>
78
-
86
+ ${jsonLD}
79
87
  </head>
80
88
  <body style="height:100%; margin: 0px">
81
89
 
@@ -97,7 +105,7 @@ export async function iframe(
97
105
 
98
106
  </body>
99
107
  </html>
100
- `
108
+ `)
101
109
  )
102
110
  }
103
111
 
@@ -203,3 +211,12 @@ async function checkFileExists(fileUrl: string) {
203
211
  return false
204
212
  }
205
213
  }
214
+
215
+ export function prettify(html: string) {
216
+ return beautify.html(html, {
217
+ indent_size: 4,
218
+ space_before_conditional: true,
219
+ jslint_happy: true,
220
+ max_char: 0,
221
+ })
222
+ }
package/src/export/ims.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as helper from './helper'
2
+ import * as RDF from './rdf'
2
3
 
3
4
  const path = require('path')
4
5
  const fs = require('fs-extra')
@@ -67,7 +68,15 @@ export async function exporter(
67
68
  await fs.move(old_, new_)
68
69
  }
69
70
 
70
- await helper.iframe(tmpPath, 'start.html', argument.readme, argument.style)
71
+ const jsonLD = await RDF.script(argument, json)
72
+
73
+ await helper.iframe(
74
+ tmpPath,
75
+ 'start.html',
76
+ argument.readme,
77
+ jsonLD,
78
+ argument.style
79
+ )
71
80
 
72
81
  helper.zip(tmpPath, argument.output)
73
82
  }
@@ -4,11 +4,11 @@ import * as IMS from './ims'
4
4
  import * as SCORM12 from './scorm12'
5
5
  import * as SCORM2004 from './scorm2004'
6
6
  import * as ANDROID from './android'
7
+ import * as RDF from './rdf'
7
8
 
8
9
  const fs = require('fs-extra')
9
10
  const path = require('path')
10
11
  const { execSync } = require('child_process')
11
- const cleaner = require('clean-html')
12
12
 
13
13
  var Categories: Set<string> = new Set([])
14
14
 
@@ -62,6 +62,36 @@ export function storeNext(collection: any, data: any) {
62
62
  return
63
63
  }
64
64
 
65
+ export function help() {
66
+ console.log('\nProject settings:')
67
+ console.log('')
68
+ console.log(
69
+ '--project-no-meta Disable the generation of meta information for OpenGraph and Twitter-cards.'
70
+ )
71
+ console.log('--project-no-rdf Disable the generation of json-ld.')
72
+ console.log(
73
+ '--project-no-categories Disable the filter for categories/tags.'
74
+ )
75
+ console.log(
76
+ '--project-category-blur Enable this and the categories will be blurred instead of deleted.'
77
+ )
78
+ console.log(
79
+ '--project-generate-scrom12 SCORM12 and pass additional scrom settings.'
80
+ )
81
+ console.log(
82
+ '--project-generate-scrom2004 SCORM2004 and pass additional scrom settings.'
83
+ )
84
+ console.log(
85
+ '--project-generate-ims IMS resources with additional config settings.'
86
+ )
87
+ console.log(
88
+ '--project-generate-pdf PDFs are automatically generated and added to every card.'
89
+ )
90
+ console.log(
91
+ '--project-generate-cache Only generate new files, if they do not exist.'
92
+ )
93
+ }
94
+
65
95
  export async function exporter(
66
96
  argument: {
67
97
  input: string
@@ -85,21 +115,41 @@ export async function exporter(
85
115
 
86
116
  let cards = ''
87
117
  const output = argument.output
118
+ const itemList: any[] = []
88
119
 
89
120
  for (let i = 0; i < json.collection.length; i++) {
90
121
  let course = json.collection[i]
91
122
 
92
123
  if (course.collection) {
93
124
  let subCards = ''
125
+ let subItemList: any[] = []
94
126
 
95
127
  for (let j = 0; j < course.collection.length; j++) {
128
+ let { html, json } = await toCard(argument, course.collection[j], true)
96
129
  subCards += `<div class='col-sm-6 col-md-4 col-lg-3 ${
97
130
  course.grid ? 'mb-3' : ''
98
131
  }'>
99
- ${await toCard(argument, course.collection[j], true)}
132
+ ${html}
100
133
  </div>`
134
+
135
+ subItemList.push(json)
136
+ }
137
+
138
+ const itemListElement = {
139
+ '@context': 'http://schema.org',
140
+ '@type': 'ItemList',
141
+ itemListElement: subItemList,
142
+ }
143
+
144
+ if (course.title) {
145
+ itemListElement['name'] = course.title
146
+ }
147
+ if (course.comment) {
148
+ itemListElement['description'] = course.comment
101
149
  }
102
150
 
151
+ itemList.push(itemListElement)
152
+
103
153
  cards += `
104
154
  <div class="col-12">
105
155
  <div class="card">
@@ -121,7 +171,10 @@ export async function exporter(
121
171
  } else if (course.html) {
122
172
  cards += "<div class='col-12'>" + course.html + '</div>'
123
173
  } else {
124
- cards += "<div class='col'>" + (await toCard(argument, course)) + '</div>'
174
+ let { html, json } = await toCard(argument, course)
175
+ cards += "<div class='col'>" + html + '</div>'
176
+
177
+ itemList.push(json)
125
178
  }
126
179
  }
127
180
 
@@ -145,10 +198,21 @@ export async function exporter(
145
198
  '</select>'
146
199
  }
147
200
 
201
+ const jsonLD = {
202
+ '@context': 'http://schema.org',
203
+ '@type': 'ItemList',
204
+ itemList: itemList,
205
+ }
206
+
148
207
  let title = json.title || 'LiaScript Course Index'
149
208
 
150
209
  if (json.title) {
151
- title = title.replace(/<[^>]+>/g, '')
210
+ title = cleanHTML(title).replace(/\s+/g, ' ').trim()
211
+ jsonLD['name'] = title
212
+ }
213
+
214
+ if (json.comment) {
215
+ jsonLD['description'] = cleanHTML(json.comment).replace(/\s+/g, ' ').trim()
152
216
  }
153
217
 
154
218
  const html = `<!DOCTYPE html>
@@ -156,6 +220,10 @@ export async function exporter(
156
220
  <head>
157
221
  <title>${title}</title>
158
222
 
223
+ <script type="application/ld+json">
224
+ ${JSON.stringify(jsonLD, null, 2)}
225
+ </script>
226
+
159
227
  ${
160
228
  json.icon
161
229
  ? '<link rel="icon" type="image/x-icon" href="' + json.icon + '">'
@@ -233,26 +301,8 @@ export async function exporter(
233
301
  </body>
234
302
  </html>
235
303
  `
236
- cleaner.clean(
237
- html,
238
- {
239
- wrap: 0,
240
- 'break-around-tags': [
241
- 'a',
242
- 'head',
243
- 'link',
244
- 'meta',
245
- 'p',
246
- 'script',
247
- 'small',
248
- 'span',
249
- 'title',
250
- ],
251
- },
252
- function (htmlCleaned: string) {
253
- helper.writeFile(output + '.html', htmlCleaned)
254
- }
255
- )
304
+
305
+ helper.writeFile(output + '.html', helper.prettify(helper.prettify(html)))
256
306
  }
257
307
 
258
308
  async function moveFile(oldPath, newPath) {
@@ -301,7 +351,11 @@ function hash(url: string) {
301
351
  return value.startsWith('-') ? '0' + value.slice(1) : value
302
352
  }
303
353
 
304
- async function toCard(argument: any, course: any, small: boolean = false) {
354
+ async function toCard(
355
+ argument: any,
356
+ course: any,
357
+ small: boolean = false
358
+ ): Promise<{ html: string; json: any }> {
305
359
  // if other parameters are defined for a specific course
306
360
  // then they are treated
307
361
 
@@ -457,15 +511,20 @@ async function toCard(argument: any, course: any, small: boolean = false) {
457
511
  execSync('rm -rf tmp')
458
512
  }
459
513
 
460
- return card(
461
- small,
462
- course.data.lia.readme,
463
- overwrite(course.title, course.data.lia.str_title),
464
- overwrite(course.comment, course.data.lia.comment),
465
- tagList,
466
- downloads,
467
- overwrite(course.logo, course.data.lia.definition.logo)
468
- )
514
+ argument['rdf-url'] = course.data.lia.readme
515
+
516
+ return {
517
+ html: card(
518
+ small,
519
+ course.data.lia.readme,
520
+ overwrite(course.title, course.data.lia.str_title),
521
+ overwrite(course.comment, course.data.lia.comment),
522
+ tagList,
523
+ downloads,
524
+ overwrite(course.logo, course.data.lia.definition.logo)
525
+ ),
526
+ json: await RDF.parse(argument, course.data),
527
+ }
469
528
  }
470
529
 
471
530
  function card(
@@ -482,7 +541,7 @@ function card(
482
541
  apk?: string
483
542
  },
484
543
  img_url?: string
485
- ) {
544
+ ): string {
486
545
  let image = ''
487
546
 
488
547
  if (img_url) {
@@ -563,10 +622,6 @@ function card(
563
622
  '">Android APK</a></li>'
564
623
  : ''
565
624
  }
566
-
567
-
568
-
569
-
570
625
  </ul>
571
626
  </div>
572
627
  </div>
@@ -585,8 +640,7 @@ function card(
585
640
  ${tag_list}
586
641
  </div>
587
642
  ${footer}
588
- </div>
589
- `
643
+ </div>`
590
644
  }
591
645
 
592
646
  function stringToColor(str: string) {
package/src/export/rdf.ts CHANGED
@@ -49,6 +49,80 @@ export async function exporter(
49
49
  'rdf-educationalLevel'?: string
50
50
  },
51
51
  json
52
+ ) {
53
+ let doc = parse(argument, json)
54
+
55
+ if (argument['rdf-format'] === 'n-quads') {
56
+ const nquads = await jsonld.toRDF(doc, { format: 'application/n-quads' })
57
+ if (argument['rdf-preview']) {
58
+ console.log(nquads)
59
+ } else {
60
+ fs.writeFile(argument.output + '.nq', nquads, function (err) {
61
+ if (err) console.error(err)
62
+ })
63
+ }
64
+ } else {
65
+ doc = clean(doc)
66
+ if (argument['rdf-preview']) {
67
+ console.log(JSON.stringify(doc, null, 2))
68
+ } else {
69
+ fs.writeFile(
70
+ argument.output + '.jsonld',
71
+ JSON.stringify(doc, null, 2),
72
+ function (err) {
73
+ if (err) console.error(err)
74
+ }
75
+ )
76
+ }
77
+ }
78
+ }
79
+
80
+ export async function script(
81
+ argument: {
82
+ input: string
83
+ readme: string
84
+ output: string
85
+ format: string
86
+ path: string
87
+ key?: string
88
+ style?: string
89
+
90
+ // special cases for RDF
91
+ 'rdf-format'?: string
92
+ 'rdf-preview'?: string
93
+ 'rdf-url'?: string
94
+ 'rdf-type'?: string
95
+ 'rdf-template'?: string
96
+ 'rdf-license'?: string
97
+ 'rdf-educationalLevel'?: string
98
+ },
99
+ json
100
+ ) {
101
+ return `<script type="application/ld+json">
102
+ ${JSON.stringify(await parse(argument, json), null, 2)}
103
+ </script>`
104
+ }
105
+
106
+ export async function parse(
107
+ argument: {
108
+ input: string
109
+ readme: string
110
+ output: string
111
+ format: string
112
+ path: string
113
+ key?: string
114
+ style?: string
115
+
116
+ // special cases for RDF
117
+ 'rdf-format'?: string
118
+ 'rdf-preview'?: string
119
+ 'rdf-url'?: string
120
+ 'rdf-type'?: string
121
+ 'rdf-template'?: string
122
+ 'rdf-license'?: string
123
+ 'rdf-educationalLevel'?: string
124
+ },
125
+ json
52
126
  ) {
53
127
  let doc = {}
54
128
 
@@ -96,29 +170,7 @@ export async function exporter(
96
170
  doc = await licenseInformation(doc, argument, baseURL)
97
171
  doc = await jsonld.compact(doc, 'http://schema.org')
98
172
 
99
- if (argument['rdf-format'] === 'n-quads') {
100
- const nquads = await jsonld.toRDF(doc, { format: 'application/n-quads' })
101
- if (argument['rdf-preview']) {
102
- console.log(nquads)
103
- } else {
104
- fs.writeFile(argument.output + '.nq', nquads, function (err) {
105
- if (err) console.error(err)
106
- })
107
- }
108
- } else {
109
- doc = clean(doc)
110
- if (argument['rdf-preview']) {
111
- console.log(JSON.stringify(doc, null, 2))
112
- } else {
113
- fs.writeFile(
114
- argument.output + '.jsonld',
115
- JSON.stringify(doc, null, 2),
116
- function (err) {
117
- if (err) console.error(err)
118
- }
119
- )
120
- }
121
- }
173
+ return clean(doc)
122
174
  }
123
175
 
124
176
  /**
@@ -1,4 +1,5 @@
1
1
  import * as helper from './helper'
2
+ import * as RDF from './rdf'
2
3
 
3
4
  const scormPackager = require('@liascript/simple-scorm-packager')
4
5
  const path = require('path')
@@ -51,11 +52,20 @@ export async function exporter(
51
52
  ';'
52
53
  )
53
54
 
55
+ const jsonLD = await RDF.script(argument, json)
56
+
54
57
  if (argument['scorm-iframe']) {
55
- await helper.iframe(tmpPath, 'start.html', argument.readme, argument.style)
58
+ await helper.iframe(
59
+ tmpPath,
60
+ 'start.html',
61
+ argument.readme,
62
+ jsonLD,
63
+ argument.style
64
+ )
56
65
  }
57
66
 
58
67
  try {
68
+ index = helper.inject(jsonLD, index)
59
69
  await helper.writeFile(path.join(tmpPath, 'index.html'), index)
60
70
  } catch (e) {
61
71
  console.warn(e)
@@ -1,5 +1,7 @@
1
1
  import * as helper from './helper'
2
2
 
3
+ import * as RDF from './rdf'
4
+
3
5
  const scormPackager = require('@liascript/simple-scorm-packager')
4
6
  const path = require('path')
5
7
  const fs = require('fs-extra')
@@ -50,11 +52,20 @@ export async function exporter(
50
52
  ';'
51
53
  )
52
54
 
55
+ const jsonLD = await RDF.script(argument, json)
56
+
53
57
  if (argument['scorm-iframe']) {
54
- await helper.iframe(tmpPath, 'start.html', argument.readme, argument.style)
58
+ await helper.iframe(
59
+ tmpPath,
60
+ 'start.html',
61
+ argument.readme,
62
+ jsonLD,
63
+ argument.style
64
+ )
55
65
  }
56
66
 
57
67
  try {
68
+ index = helper.inject(jsonLD, index)
58
69
  await helper.writeFile(path.join(tmpPath, 'index.html'), index)
59
70
  } catch (e) {
60
71
  console.warn(e)
package/src/export/web.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as helper from './helper'
2
+ import * as RDF from './rdf'
2
3
 
3
4
  const path = require('path')
4
5
  const fs = require('fs-extra')
@@ -16,6 +17,15 @@ export async function exporter(
16
17
  'web-iframe'?: boolean
17
18
  'web-indexeddb'?: boolean
18
19
  'web-zip'?: boolean
20
+
21
+ // special cases for RDF
22
+ 'rdf-format'?: string
23
+ 'rdf-preview'?: string
24
+ 'rdf-url'?: string
25
+ 'rdf-type'?: string
26
+ 'rdf-template'?: string
27
+ 'rdf-license'?: string
28
+ 'rdf-educationalLevel'?: string
19
29
  },
20
30
  json: any
21
31
  ) {
@@ -109,6 +119,8 @@ export async function exporter(
109
119
  console.warn('could not add image')
110
120
  }
111
121
 
122
+ const jsonLD = await RDF.script(argument, json)
123
+
112
124
  try {
113
125
  if (argument['web-iframe']) {
114
126
  await helper.writeFile(path.join(tmpPath, 'start.html'), index)
@@ -116,10 +128,14 @@ export async function exporter(
116
128
  tmpPath,
117
129
  'index.html',
118
130
  argument.readme,
131
+ jsonLD,
119
132
  argument.style,
120
133
  'start.html'
121
134
  )
122
135
  } else {
136
+ index = helper.inject(jsonLD, index)
137
+ index = helper.prettify(index)
138
+
123
139
  await helper.writeFile(path.join(tmpPath, 'index.html'), index)
124
140
  }
125
141
  } catch (e) {
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@ import fetch from 'node-fetch'
22
22
 
23
23
  // -------------------------------Main Execution-------------------------------
24
24
  if (argv.v || argv.version) {
25
- console.log('version: 2.6.0--0.10.31')
25
+ console.log('version: 2.6.3--0.10.31')
26
26
  } else if (argv.h || argv.help) {
27
27
  help()
28
28
  } else if (argv.i || argv.input) {
@@ -309,37 +309,7 @@ function help() {
309
309
  '--pdf-omitBackground Hides default white background and allows capturing screenshots with transparency. Defaults to true. '
310
310
  )
311
311
 
312
- console.log('\nProject settings:')
313
- console.log('')
314
- console.log(
315
- '--project-no-meta Disable the generation of meta information for OpenGraph and Twitter-cards.'
316
- )
317
- console.log(
318
- '--project-no-categories Disable the filter for categories/tags.'
319
- )
320
- console.log(
321
- '--project-category-blur Enable this and the categories will be blurred instead of deleted.'
322
- )
323
-
324
- console.log(
325
- '--project-generate-scrom12 SCORM12 and pass additional scrom settings.'
326
- )
327
-
328
- console.log(
329
- '--project-generate-scrom2004 SCORM2004 and pass additional scrom settings.'
330
- )
331
-
332
- console.log(
333
- '--project-generate-ims IMS resources with additional config settings.'
334
- )
335
-
336
- console.log(
337
- '--project-generate-pdf PDFs are automatically generated and added to every card.'
338
- )
339
-
340
- console.log(
341
- '--project-generate-cache Only generate new files, if they do not exist.'
342
- )
312
+ PROJECT.help()
343
313
 
344
314
  RDF.help()
345
315
  }
@@ -408,6 +378,7 @@ function parseArguments() {
408
378
 
409
379
  // project settings
410
380
  'project-no-meta': argv['project-no-meta'],
381
+ 'project-no-rdf': argv['project-no-rdf'],
411
382
  'project-no-categories': argv['project-no-categories'],
412
383
  'project-category-blur': argv['project-category-blur'],
413
384
  'project-generate-pdf': argv['project-generate-pdf'],