rx-player 4.0.0-beta.1 → 4.0.0-beta.2

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.
Files changed (169) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/CONTRIBUTING.md +48 -168
  3. package/FILES.md +40 -92
  4. package/VERSION +1 -1
  5. package/dist/_esm5.processed/compat/browser_detection.d.ts +3 -1
  6. package/dist/_esm5.processed/compat/browser_detection.js +7 -2
  7. package/dist/_esm5.processed/compat/eme/load_session.js +1 -1
  8. package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
  9. package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
  10. package/dist/_esm5.processed/config.d.ts +2 -0
  11. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +5 -4
  12. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
  13. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +106 -25
  14. package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
  15. package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
  16. package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
  17. package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
  18. package/dist/_esm5.processed/core/api/debug/render.js +1 -1
  19. package/dist/_esm5.processed/core/api/playback_observer.js +1 -0
  20. package/dist/_esm5.processed/core/api/public_api.d.ts +54 -1
  21. package/dist/_esm5.processed/core/api/public_api.js +232 -35
  22. package/dist/_esm5.processed/core/api/track_management/media_element_tracks_store.js +10 -1
  23. package/dist/_esm5.processed/core/api/track_management/track_dispatcher.d.ts +13 -1
  24. package/dist/_esm5.processed/core/api/track_management/track_dispatcher.js +30 -15
  25. package/dist/_esm5.processed/core/api/track_management/tracks_store.d.ts +3 -1
  26. package/dist/_esm5.processed/core/api/track_management/tracks_store.js +67 -152
  27. package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
  28. package/dist/_esm5.processed/core/api/utils.js +20 -0
  29. package/dist/_esm5.processed/core/decrypt/session_events_listener.js +7 -1
  30. package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
  31. package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
  32. package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
  33. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +47 -10
  34. package/dist/_esm5.processed/core/init/types.d.ts +9 -1
  35. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
  36. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +22 -9
  37. package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
  38. package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +84 -87
  39. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +36 -2
  40. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +82 -2
  41. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -7
  42. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +31 -40
  43. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +8 -0
  44. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +12 -0
  45. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +8 -0
  46. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +12 -0
  47. package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +11 -4
  48. package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
  49. package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts +47 -0
  50. package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +70 -0
  51. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +15 -8
  52. package/dist/_esm5.processed/core/stream/period/period_stream.js +1 -1
  53. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +22 -13
  54. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
  55. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +2 -2
  56. package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.d.ts +3 -2
  57. package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +8 -8
  58. package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.d.ts +2 -2
  59. package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.js +2 -3
  60. package/dist/_esm5.processed/default_config.d.ts +25 -0
  61. package/dist/_esm5.processed/default_config.js +27 -2
  62. package/dist/_esm5.processed/errors/index.d.ts +2 -2
  63. package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
  64. package/dist/_esm5.processed/errors/media_error.js +18 -5
  65. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +1 -1
  66. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +8 -7
  67. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +17 -9
  68. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/index.js +0 -2
  69. package/dist/_esm5.processed/manifest/adaptation.d.ts +21 -2
  70. package/dist/_esm5.processed/manifest/adaptation.js +76 -1
  71. package/dist/_esm5.processed/manifest/manifest.js +1 -1
  72. package/dist/_esm5.processed/manifest/period.js +2 -2
  73. package/dist/_esm5.processed/manifest/representation.d.ts +33 -2
  74. package/dist/_esm5.processed/manifest/representation.js +21 -0
  75. package/dist/_esm5.processed/manifest/utils.js +1 -3
  76. package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
  77. package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
  78. package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
  79. package/dist/_esm5.processed/public_types.d.ts +13 -3
  80. package/dist/_esm5.processed/tools/TextTrackRenderer/text_track_renderer.js +1 -1
  81. package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
  82. package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
  83. package/dist/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
  84. package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
  85. package/dist/mpd-parser.wasm +0 -0
  86. package/dist/rx-player.js +4709 -4218
  87. package/dist/rx-player.min.js +1 -1
  88. package/package.json +42 -36
  89. package/scripts/build/generate_build.js +1 -1
  90. package/scripts/fast_demo_build.js +4 -3
  91. package/scripts/generate_full_demo.js +1 -1
  92. package/sonar-project.properties +1 -1
  93. package/src/compat/browser_detection.ts +7 -1
  94. package/src/compat/eme/load_session.ts +1 -1
  95. package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
  96. package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
  97. package/src/core/adaptive/adaptive_representation_selector.ts +7 -4
  98. package/src/core/adaptive/buffer_based_chooser.ts +144 -26
  99. package/src/core/adaptive/guess_based_chooser.ts +9 -8
  100. package/src/core/adaptive/network_analyzer.ts +9 -4
  101. package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
  102. package/src/core/api/debug/render.ts +1 -1
  103. package/src/core/api/playback_observer.ts +1 -0
  104. package/src/core/api/public_api.ts +277 -44
  105. package/src/core/api/track_management/media_element_tracks_store.ts +17 -8
  106. package/src/core/api/track_management/track_dispatcher.ts +37 -14
  107. package/src/core/api/track_management/tracks_store.ts +77 -167
  108. package/src/core/api/utils.ts +26 -0
  109. package/src/core/decrypt/session_events_listener.ts +6 -1
  110. package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
  111. package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
  112. package/src/core/init/directfile_content_initializer.ts +1 -0
  113. package/src/core/init/media_source_content_initializer.ts +52 -9
  114. package/src/core/init/types.ts +9 -1
  115. package/src/core/init/utils/content_time_boundaries_observer.ts +46 -10
  116. package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +100 -112
  117. package/src/core/init/utils/rebuffering_controller.ts +114 -3
  118. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +56 -55
  119. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +16 -0
  120. package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +16 -0
  121. package/src/core/segment_buffers/implementations/types.ts +16 -4
  122. package/src/core/segment_buffers/index.ts +2 -0
  123. package/src/core/stream/adaptation/utils/create_representation_estimator.ts +114 -0
  124. package/src/core/stream/orchestrator/stream_orchestrator.ts +16 -8
  125. package/src/core/stream/period/period_stream.ts +2 -1
  126. package/src/core/stream/representation/representation_stream.ts +34 -22
  127. package/src/core/stream/representation/utils/append_segment_to_buffer.ts +8 -3
  128. package/src/core/stream/representation/utils/push_init_segment.ts +11 -6
  129. package/src/core/stream/representation/utils/push_media_segment.ts +3 -3
  130. package/src/default_config.ts +29 -2
  131. package/src/errors/__tests__/media_error.test.ts +6 -6
  132. package/src/errors/index.ts +4 -1
  133. package/src/errors/media_error.ts +67 -1
  134. package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +10 -7
  135. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +17 -6
  136. package/src/experimental/tools/mediaCapabilitiesProber/index.ts +0 -4
  137. package/src/manifest/__tests__/manifest.test.ts +7 -7
  138. package/src/manifest/__tests__/period.test.ts +90 -45
  139. package/src/manifest/adaptation.ts +89 -1
  140. package/src/manifest/manifest.ts +1 -1
  141. package/src/manifest/period.ts +4 -2
  142. package/src/manifest/representation.ts +67 -1
  143. package/src/manifest/utils.ts +1 -3
  144. package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
  145. package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
  146. package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
  147. package/src/public_types.ts +16 -1
  148. package/src/tools/TextTrackRenderer/text_track_renderer.ts +1 -1
  149. package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
  150. package/src/typings/globals.d.ts +20 -20
  151. package/src/utils/is_null_or_undefined.ts +1 -1
  152. package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
  153. package/scripts/doc-generator/construct_table_of_contents.js +0 -76
  154. package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
  155. package/scripts/doc-generator/create_documentation.js +0 -331
  156. package/scripts/doc-generator/create_documentation_page.js +0 -209
  157. package/scripts/doc-generator/create_page.js +0 -210
  158. package/scripts/doc-generator/generate_header_html.js +0 -147
  159. package/scripts/doc-generator/generate_page_html.js +0 -115
  160. package/scripts/doc-generator/generate_page_list_html.js +0 -92
  161. package/scripts/doc-generator/generate_sidebar_html.js +0 -85
  162. package/scripts/doc-generator/get_search_data_for_content.js +0 -137
  163. package/scripts/doc-generator/index.js +0 -34
  164. package/scripts/doc-generator/parse_doc_configs.js +0 -327
  165. package/scripts/doc-generator/scripts/lunr.js +0 -10
  166. package/scripts/doc-generator/scripts/script.js +0 -451
  167. package/scripts/doc-generator/styles/code.css +0 -99
  168. package/scripts/doc-generator/styles/style.css +0 -835
  169. package/scripts/doc-generator/utils.js +0 -74
@@ -22,6 +22,7 @@ import {
22
22
  IPersistentSessionInfoV4,
23
23
  } from "./core/decrypt";
24
24
  import {
25
+ IMediaErrorTrackContext,
25
26
  EncryptedMediaError,
26
27
  MediaError,
27
28
  NetworkError,
@@ -31,6 +32,8 @@ import Manifest from "./manifest";
31
32
  import { ILocalManifest } from "./parsers/manifest/local";
32
33
  import { IMetaPlaylist } from "./parsers/manifest/metaplaylist/metaplaylist_parser";
33
34
 
35
+ export { IMediaErrorTrackContext };
36
+
34
37
  /**
35
38
  * This file defines and exports types we want to expose to library users.
36
39
  * Those types are considered as part of the API.
@@ -693,6 +696,8 @@ export interface IAudioRepresentation {
693
696
  id : string|number;
694
697
  bitrate? : number | undefined;
695
698
  codec? : string | undefined;
699
+ isCodecSupported? : boolean | undefined;
700
+ seemsDecipherable? : boolean | undefined;
696
701
  }
697
702
 
698
703
  /** Audio track returned by the RxPlayer. */
@@ -720,7 +725,7 @@ export interface ITextTrack {
720
725
  * Kept equal to `language` if the attempt failed.
721
726
  */
722
727
  normalized : string;
723
- forced? : boolean | undefined;
728
+ forced : boolean | undefined;
724
729
  closedCaption : boolean;
725
730
  label? : string | undefined;
726
731
  id : number|string;
@@ -738,6 +743,8 @@ export interface IVideoRepresentation {
738
743
  codec? : string | undefined;
739
744
  frameRate? : number | undefined;
740
745
  hdrInfo?: IHDRInformation | undefined;
746
+ isCodecSupported? : boolean | undefined;
747
+ seemsDecipherable? : boolean | undefined;
741
748
  }
742
749
 
743
750
  /** Video track returned by the RxPlayer. */
@@ -916,6 +923,14 @@ export interface ITrackUpdateEventPayload {
916
923
  "manual" | // Manually and explicitely updated
917
924
  "trickmode-enabled" | // Video trickmode tracks being enabled
918
925
  "trickmode-disabled" | // Video trickmode tracks being disabled
926
+ "no-playable-representation" | // Previous track had no playable Representation
927
+ string;
928
+ }
929
+
930
+ export interface IRepresentationListUpdateContext {
931
+ period : IPeriod;
932
+ trackType : ITrackType;
933
+ reason : "decipherability-update" |
919
934
  string;
920
935
  }
921
936
 
@@ -79,7 +79,7 @@ export default class TextTrackRenderer {
79
79
  args.timeOffset :
80
80
  0;
81
81
  this._segmentBuffer.pushChunkSync({ inventoryInfos: null,
82
- data: { initSegment: null,
82
+ data: { initSegmentUniqueId: null,
83
83
  codec: args.type,
84
84
  timestampOffset,
85
85
  appendWindow: [0, Infinity],
@@ -33,7 +33,7 @@ import {
33
33
  * @param {Number} height
34
34
  * @param {Number} hRes - horizontal resolution, eg 72
35
35
  * @param {Number} vRes - vertical resolution, eg 72
36
- * @param {string} encDepth
36
+ * @param {string} encName
37
37
  * @param {Number} colorDepth - eg 24
38
38
  * @param {Uint8Array} avcc - Uint8Array representing the avcC atom
39
39
  * @returns {Uint8Array}
@@ -68,7 +68,7 @@ function createAVC1Box(
68
68
  * @param {Number} height
69
69
  * @param {Number} hRes - horizontal resolution, eg 72
70
70
  * @param {Number} vRes - vertical resolution, eg 72
71
- * @param {string} encDepth
71
+ * @param {string} encName
72
72
  * @param {Number} colorDepth - eg 24
73
73
  * @param {Uint8Array} avcc - Uint8Array representing the avcC atom
74
74
  * @param {Uint8Array} sinf - Uint8Array representing the sinf atom
@@ -108,8 +108,6 @@ function createENCVBox(
108
108
  * @param {Number} packetSize
109
109
  * @param {Number} sampleRate
110
110
  * @param {Uint8Array} esds - Uint8Array representing the esds atom
111
- * @param {Uint8Array} [sinf] - Uint8Array representing the sinf atom,
112
- * only if name == "enca"
113
111
  * @returns {Uint8Array}
114
112
  */
115
113
  function createMP4ABox(
@@ -164,7 +162,7 @@ function createENCABox(
164
162
  }
165
163
 
166
164
  /**
167
- * @param {url} Uint8Array
165
+ * @param {Uint8Array} url
168
166
  * @returns {Uint8Array}
169
167
  */
170
168
  function createDREFBox(url : Uint8Array) : Uint8Array {
@@ -415,7 +413,7 @@ function createSMHDBox() : Uint8Array {
415
413
  }
416
414
 
417
415
  /**
418
- * @param {Array.<Uint8Array>} representations - arrays of Uint8Array,
416
+ * @param {Array.<Uint8Array>} reps - arrays of Uint8Array,
419
417
  * typically [avc1] or [encv, avc1]
420
418
  * @returns {Uint8Array}
421
419
  */
@@ -20,24 +20,24 @@
20
20
  /* eslint-disable @typescript-eslint/naming-convention */
21
21
 
22
22
  declare const __FEATURES__ : {
23
- IS_ENABLED : number;
24
- IS_DISABLED : number;
23
+ IS_DISABLED : 0;
24
+ IS_ENABLED : 1;
25
25
 
26
- DASH : number;
27
- DIRECTFILE : number;
28
- EME : number;
29
- HTML_SAMI : number;
30
- HTML_SRT : number;
31
- HTML_TTML : number;
32
- HTML_VTT : number;
33
- LOCAL_MANIFEST : number;
34
- METAPLAYLIST : number;
35
- DEBUG_ELEMENT : number;
36
- NATIVE_SAMI : number;
37
- NATIVE_SRT : number;
38
- NATIVE_TTML : number;
39
- NATIVE_VTT : number;
40
- SMOOTH : number;
26
+ DASH : 0 | 1;
27
+ DIRECTFILE : 0 | 1;
28
+ EME : 0 | 1;
29
+ HTML_SAMI : 0 | 1;
30
+ HTML_SRT : 0 | 1;
31
+ HTML_TTML : 0 | 1;
32
+ HTML_VTT : 0 | 1;
33
+ LOCAL_MANIFEST : 0 | 1;
34
+ METAPLAYLIST : 0 | 1;
35
+ DEBUG_ELEMENT : 0 | 1;
36
+ NATIVE_SAMI : 0 | 1;
37
+ NATIVE_SRT : 0 | 1;
38
+ NATIVE_TTML : 0 | 1;
39
+ NATIVE_VTT : 0 | 1;
40
+ SMOOTH : 0 | 1;
41
41
  } | typeof FEATURES_ENUM;
42
42
 
43
43
  declare const enum FEATURES_ENUM {
@@ -62,9 +62,9 @@ declare const enum FEATURES_ENUM {
62
62
  }
63
63
 
64
64
  declare const __ENVIRONMENT__ : {
65
- CURRENT_ENV : number;
66
- DEV : number;
67
- PRODUCTION : number;
65
+ CURRENT_ENV : 0 | 1;
66
+ DEV : 0;
67
+ PRODUCTION : 1;
68
68
  } | typeof ENVIRONMENT_ENUM;
69
69
 
70
70
  declare const enum ENVIRONMENT_ENUM {
@@ -20,7 +20,7 @@
20
20
  * not always understood by newcomers to the code, and which can be overused when
21
21
  * only one of the possibility can arise.
22
22
  * @param {*} x
23
- * @returns {*}
23
+ * @returns {boolean}
24
24
  */
25
25
  export default function isNullOrUndefined(x : unknown) : x is null | undefined | void {
26
26
  return x === null || x === undefined;
@@ -1,56 +0,0 @@
1
- /**
2
- * Copyright 2015 CANAL+ Group
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- import Manifest from "../../../manifest";
17
- /**
18
- * Keep the MediaSource's duration up-to-date with what is being played.
19
- * @class MediaDurationUpdater
20
- */
21
- export default class MediaDurationUpdater {
22
- private _canceller;
23
- /**
24
- * The last known audio Adaptation (i.e. track) chosen for the last Period.
25
- * Useful to determinate the duration of the current content.
26
- * `undefined` if the audio track for the last Period has never been known yet.
27
- * `null` if there are no chosen audio Adaptation.
28
- */
29
- private _currentKnownDuration;
30
- /**
31
- * Create a new `MediaDurationUpdater` that will keep the given MediaSource's
32
- * duration as soon as possible.
33
- * This duration will be updated until the `stop` method is called.
34
- * @param {Object} manifest - The Manifest currently played.
35
- * For another content, you will have to create another `MediaDurationUpdater`.
36
- * @param {MediaSource} mediaSource - The MediaSource on which the content is
37
- * pushed.
38
- */
39
- constructor(manifest: Manifest, mediaSource: MediaSource);
40
- /**
41
- * By default, the `MediaDurationUpdater` only set a safe estimate for the
42
- * MediaSource's duration.
43
- * A more precize duration can be set by communicating to it a more precize
44
- * media duration through `updateKnownDuration`.
45
- * If the duration becomes unknown, `undefined` can be given to it so the
46
- * `MediaDurationUpdater` goes back to a safe estimate.
47
- * @param {number | undefined} newDuration
48
- */
49
- updateKnownDuration(newDuration: number | undefined): void;
50
- /**
51
- * Stop the `MediaDurationUpdater` from updating and free its resources.
52
- * Once stopped, it is not possible to start it again, beside creating another
53
- * `MediaDurationUpdater`.
54
- */
55
- stop(): void;
56
- }
@@ -1,76 +0,0 @@
1
- /**
2
- * Create table of contents in markdown referencing the h1 (#), h2 (##) and
3
- * h3 (###) titles.
4
- * Also add links to them to the original markdown.
5
- * @param {string} md - The markdown content
6
- * @returns {string}
7
- */
8
- function constructTableOfContents(md) {
9
- const tocLines = [];
10
- const newContent = [];
11
- const lines = md.split(/\r\n|\n|\r/);
12
-
13
- // Object used to avoid duplicates
14
- const generatedAnchors = {};
15
-
16
- // The inputed markdown is read line by line.
17
- // When a h1, h2 or h3 is encountered in it, add a new list entry
18
- // in the `tocLines` markdown respectively at top, second and third level.
19
- // To be able to link the table of content to the corresponding content,
20
- // add `<a>` links just before the corresponding h1, h2 or h3 elements in the
21
- // inputed markdown.
22
- // All Markdown parsing done here corresponds to the CommonMark spec (v0.29)
23
- // TODO this might be more efficient and less error-prone if integrated as a
24
- // markdown-it plugin.
25
- for (let i = 0, len = lines.length; i < len; i++) {
26
- if (/^ *# +/.test(lines[i])) {
27
- const regExec = /^ *# +(.*)$/.exec(lines[i]);
28
- if (regExec && regExec[1]) {
29
- const tocLine = regExec[1].replace(/ #* *$/, "").trim();
30
- let uri = generateAnchorName(tocLine);
31
- tocLines.push(`[${tocLine}](#${uri})`);
32
- newContent.push(`<a name="${uri}"></a>`);
33
- }
34
- } else if (/^ *## +/.test(lines[i])) {
35
- const regExec = /^ *## +(.*)$/.exec(lines[i]);
36
- if (regExec && regExec[1]) {
37
- const tocLine = regExec[1].replace(/ #* *$/, "").trim();
38
- let uri = generateAnchorName(tocLine);
39
- tocLines.push(` - [${tocLine}](#${uri})`);
40
- newContent.push(`<a name="${uri}"></a>`);
41
- }
42
- } else if (/^ *### +/.test(lines[i])) {
43
- const regExec = /^ *### +(.*)$/.exec(lines[i]);
44
- if (regExec && regExec[1]) {
45
- const tocLine = regExec[1].replace(/ #* *$/, "").trim();
46
- let uri = generateAnchorName(tocLine);
47
- tocLines.push(` - [${tocLine}](#${uri})`);
48
- newContent.push(`<a name="${uri}"></a>`);
49
- }
50
- }
51
- newContent.push(lines[i]);
52
- }
53
- return {
54
- tocMd: tocLines.join("\n"),
55
- nbTocElements: tocLines.length,
56
- content: newContent.join("\n"),
57
- };
58
-
59
- function generateAnchorName(title) {
60
- const baseUri = encodeURI(title.toLowerCase().replace(/ /g, "_"))
61
- if (generatedAnchors[baseUri] !== true) {
62
- generatedAnchors[baseUri] = true;
63
- return baseUri;
64
- }
65
- let i = 1;
66
- let resultUri;
67
- do {
68
- resultUri = `${baseUri}_(${i})`;
69
- i++;
70
- } while (generatedAnchors[resultUri] === true);
71
- generatedAnchors[resultUri] = true;
72
- return resultUri;
73
- }
74
- };
75
-
76
- module.exports = constructTableOfContents;
@@ -1,26 +0,0 @@
1
- const hljs = require("highlight.js");
2
- const md = require("markdown-it")({
3
- highlight(str, lang) {
4
- if (lang && hljs.getLanguage(lang)) {
5
- try {
6
- return hljs.highlight(str, { language: lang }).value;
7
- } catch (_) {
8
- /* don't care for now */
9
- }
10
- }
11
- return "";
12
- },
13
- html: true,
14
- linkify: true,
15
- typographer: true,
16
- xhtmlOut: true,
17
- });
18
-
19
- /**
20
- * Convert the Markdown document given into an HTML page.
21
- * @param {string} mdStr
22
- * @returns {string}
23
- */
24
- module.exports = function convertMDToHTML(mdStr) {
25
- return md.render(mdStr);
26
- };
@@ -1,331 +0,0 @@
1
- const { promisify } = require("util");
2
- const fs = require("fs");
3
- const path = require("path");
4
- const parseDocConfigs = require("./parse_doc_configs.js");
5
- const createDocumentationPage = require("./create_documentation_page.js");
6
- const generateHeaderHtml = require("./generate_header_html.js");
7
- const generatePageListHtml = require("./generate_page_list_html.js");
8
- const generateSidebarHtml = require("./generate_sidebar_html.js");
9
- const {
10
- mkdirParent,
11
- toUriCompatibleRelativePath,
12
- } = require("./utils.js");
13
-
14
- async function createDirIfDoesntExist(dir) {
15
- const doesCSSOutDirExists = await promisify(fs.exists)(dir);
16
- if (!doesCSSOutDirExists) {
17
- try {
18
- await mkdirParent(dir);
19
- } catch (err) {
20
- const srcMessage = (err ?? {}).message ?? "Unknown error";
21
- console.error(`Error: Could not create "${dir}" directory: ${srcMessage}`);
22
- process.exit(1);
23
- }
24
- }
25
- }
26
-
27
- /**
28
- * Create documentation for the directory given into the ouput directory given.
29
- * @param {string} baseInDir
30
- * @param {string} baseOutDir
31
- * @param {Object} [options={}]
32
- * @param {Function} [options.getPageTitle] - Callback returning the name of the
33
- * page, based on the name of a single markdown document.
34
- * If not set, the page title will just be the corresponding markdown's title.
35
- * @param {Array.<string>} [options.css] - Optional CSS files which will be
36
- * linked to each generated page.
37
- * Should be the path to each of those.
38
- * @param {string|undefined} [options.version] - String indicating the current
39
- * version of the documented application.
40
- * @returns {Promise} - Resolve when done
41
- */
42
- async function createDocumentation(
43
- baseInDir,
44
- baseOutDir,
45
- options = {},
46
- ) {
47
- const { css } = options;
48
-
49
- // Copy CSS files
50
- const cssOutputDir = path.join(path.resolve(baseOutDir), "styles");
51
- const cssOutputPaths = css.map(cssFilepath => {
52
- return path.join(cssOutputDir, path.basename(cssFilepath));
53
- });
54
-
55
- if (css.length > 0) {
56
- await createDirIfDoesntExist(cssOutputDir);
57
- await Promise.all(css.map(async (cssInput, i) => {
58
- await promisify(fs.copyFile)(cssInput, cssOutputPaths[i]);
59
- }));
60
- }
61
-
62
- // Copy JavaScript file
63
- const scriptOutputDir = path.join(path.resolve(baseOutDir), "scripts");
64
- const scripts = [
65
- path.join(__dirname, "scripts/lunr.js"),
66
- path.join(__dirname, "scripts/script.js"),
67
- ];
68
- const scriptOutputPaths = scripts.map(s =>
69
- path.join(scriptOutputDir, path.basename(s)));
70
-
71
- await createDirIfDoesntExist(scriptOutputDir);
72
- await Promise.all(scripts.map(async (s, i) => {
73
- await promisify(fs.copyFile)(s, scriptOutputPaths[i]);
74
- }));
75
-
76
- // Construct tree listing categories, pages, and relations between them.
77
- const config = await parseDocConfigs(baseInDir, baseOutDir, options.version);
78
-
79
- if (config.favicon !== undefined && typeof config.favicon.srcPath === "string") {
80
- await copyFileToOutputDir(config.favicon.srcPath, baseInDir, baseOutDir);
81
- }
82
- if (config.logo !== undefined && typeof config.logo.srcPath === "string") {
83
- await copyFileToOutputDir(config.logo.srcPath, baseInDir, baseOutDir);
84
- }
85
-
86
-
87
- // Construct a dictionary of markdown files to the corresponding output file.
88
- // This can be useful to redirect links to other converted markdowns.
89
- const fileDict = config.links.reduce((acc, linkInfo) => {
90
- if (linkInfo.type !== "local-doc") {
91
- return acc;
92
- }
93
- return linkInfo.pages.reduce((acc2, pageInfo) => {
94
- if (pageInfo.isPageGroup) {
95
- return pageInfo.pages.reduce((acc3, subPageInfo) => {
96
- acc3[subPageInfo.inputFile] = subPageInfo.outputFile;
97
- return acc3;
98
- }, acc2);
99
- } else {
100
- acc2[pageInfo.inputFile] = pageInfo.outputFile;
101
- }
102
- return acc2;
103
- }, acc);
104
- }, {});
105
-
106
- const searchIndex = [];
107
-
108
- // Create documentation pages
109
- for (let linkIdx = 0; linkIdx < config.links.length; linkIdx++) {
110
- const currentLink = config.links[linkIdx];
111
- if (currentLink.type !== "local-doc") {
112
- continue;
113
- }
114
- for (let pageIdx = 0; pageIdx < currentLink.pages.length; pageIdx++) {
115
- const currentPage = currentLink.pages[pageIdx];
116
- if (!currentPage.isPageGroup) {
117
- const { inputFile, outputFile } = currentPage;
118
- await prepareAndCreateDocumentationPage({
119
- baseOutDir,
120
- config,
121
- cssOutputPaths,
122
- fileDict,
123
- inputFile,
124
- linkIdx,
125
- outputFile,
126
- pageIdxs: [pageIdx],
127
- pageTitle: options.getPageTitle === undefined ?
128
- currentPage.displayName :
129
- options.getPageTitle(currentPage.displayName),
130
- scriptOutputPaths,
131
- searchIndex,
132
- });
133
- } else {
134
- for (
135
- let subPageIdx = 0;
136
- subPageIdx < currentPage.pages.length;
137
- subPageIdx++
138
- ) {
139
- const currentSubPage = currentPage.pages[subPageIdx];
140
- const { inputFile, outputFile } = currentSubPage;
141
- await prepareAndCreateDocumentationPage({
142
- baseOutDir,
143
- config,
144
- cssOutputPaths,
145
- fileDict,
146
- inputFile,
147
- linkIdx,
148
- outputFile,
149
- pageIdxs: [pageIdx, subPageIdx],
150
- pageTitle: options.getPageTitle === undefined ?
151
- currentSubPage.displayName :
152
- options.getPageTitle(currentSubPage.displayName),
153
- scriptOutputPaths,
154
- searchIndex,
155
- });
156
- }
157
- }
158
- }
159
- }
160
-
161
- try {
162
- const searchIndexLoc = path.join(path.resolve(baseOutDir), "searchIndex.json");
163
- await promisify(fs.writeFile)(searchIndexLoc, JSON.stringify(searchIndex));
164
- } catch (err) {
165
- const srcMessage = (err ?? {}).message ?? "Unknown error";
166
- console.error(`Error: Could not create search index file: ${srcMessage}`);
167
- }
168
- };
169
-
170
- async function prepareAndCreateDocumentationPage({
171
- baseOutDir,
172
- config,
173
- cssOutputPaths,
174
- fileDict,
175
- inputFile,
176
- linkIdx,
177
- outputFile,
178
- pageIdxs,
179
- pageTitle,
180
- scriptOutputPaths,
181
- searchIndex,
182
- }) {
183
- // Create output directory if it does not exist
184
- const outDir = path.dirname(outputFile);
185
- await createDirIfDoesntExist(outDir);
186
-
187
- let logoInfo = null;
188
- if (config.logo !== undefined) {
189
- logoInfo = {};
190
- if (config.logo !== undefined && typeof config.logo.link === "string") {
191
- logoInfo.link = config.logo.link;
192
- }
193
- if (config.logo !== undefined && typeof config.logo.srcPath === "string") {
194
- const fullPath = path.join(baseOutDir, config.logo.srcPath);
195
- logoInfo.url = toUriCompatibleRelativePath(fullPath, outDir);
196
- }
197
- }
198
- let faviconUrl = null;
199
- if (config.favicon !== undefined && typeof config.favicon.srcPath === "string") {
200
- const fullPath = path.join(baseOutDir, config.favicon.srcPath);
201
- faviconUrl = toUriCompatibleRelativePath(fullPath, outDir);
202
- }
203
- const pageListHtml = generatePageListHtml(config.links, linkIdx, pageIdxs, outputFile);
204
- const navBarHtml = generateHeaderHtml(config, linkIdx, outputFile, logoInfo);
205
- const pages = config.links[linkIdx].pages;
206
- const sidebarHtml = generateSidebarHtml(pages, pageIdxs, outputFile, logoInfo);
207
-
208
- let prevPageConfig = null;
209
- let nextPageConfig = null;
210
- if (pageIdxs.length > 1 && pageIdxs[1] > 0) {
211
- prevPageConfig = pages[pageIdxs[0]].pages[pageIdxs[1] - 1];
212
- } else if (pageIdxs[0] > 0) {
213
- prevPageConfig = pages[pageIdxs[0] - 1];
214
- }
215
- if (pageIdxs.length > 1 && pageIdxs[1] < pages[pageIdxs[0]].pages.length - 1) {
216
- nextPageConfig = pages[pageIdxs[0]].pages[pageIdxs[1] + 1];
217
- } else if (pageIdxs[0] < pages.length - 1) {
218
- nextPageConfig = pages[pageIdxs[0] + 1];
219
- }
220
- const prevPageInfo = prevPageConfig === null ?
221
- null :
222
- getRelativePageInfo(prevPageConfig, outputFile);
223
- const nextPageInfo = nextPageConfig === null ?
224
- null :
225
- getRelativePageInfo(nextPageConfig, outputFile);
226
-
227
- const cssUrls = cssOutputPaths
228
- .map(cssOutput => toUriCompatibleRelativePath(cssOutput, outDir));
229
- const scriptUrls = scriptOutputPaths
230
- .map(s => toUriCompatibleRelativePath(s, outDir));
231
-
232
- // add link translation to options
233
- const linkTranslator = linkTranslatorFactory(inputFile, outDir, fileDict);
234
- await createDocumentationPage({
235
- baseOutDir,
236
- cssUrls,
237
- faviconUrl,
238
- inputFile,
239
- linkTranslator,
240
- navBarHtml,
241
- nextPageInfo,
242
- outputFile,
243
- pageListHtml,
244
- pageTitle,
245
- prevPageInfo,
246
- scriptUrls,
247
- searchIndex,
248
- sidebarHtml,
249
- });
250
- }
251
-
252
- /**
253
- * Generate linkTranslator functions
254
- * @param {string} inputFile
255
- * @param {Object} fileDict
256
- * @returns {Function}
257
- */
258
- function linkTranslatorFactory(inputFile, outputDir, fileDict) {
259
- /**
260
- * Convert links to files that will be converted to the links of the
261
- * corresponding converted output files.
262
- * @param {string} link
263
- * @returns {string|undefined}
264
- */
265
- return (link) => {
266
- if (/^(?:[a-z]+:)/.test(link) || link[0] === "#") {
267
- return
268
- }
269
- const extname = path.extname(link);
270
- const indexOfAnchor = extname.indexOf("#");
271
-
272
- const anchor = indexOfAnchor > 0 ?
273
- extname.substring(indexOfAnchor) :
274
- "";
275
-
276
- const linkWithoutAnchor = link.substring(0, link.length - anchor.length);
277
- const completeLink = path.join(path.dirname(inputFile), linkWithoutAnchor);
278
- const normalizedLink = path.normalize(path.resolve(completeLink));
279
-
280
- const translation = fileDict[normalizedLink];
281
- if (translation === undefined) {
282
- console.warn("WARNING: Local link not found.\n",
283
- "File:", inputFile, "\n",
284
- "Link:", link, "\n");
285
- }
286
- return translation !== undefined ?
287
- toUriCompatibleRelativePath(translation, outputDir) + anchor :
288
- // TODO do something better?
289
- undefined;
290
- };
291
- }
292
-
293
- function getRelativePageInfo(
294
- pageConfig,
295
- currentPath
296
- ) {
297
- const {
298
- displayName: pDisplayName,
299
- outputFile: pOutputFile
300
- } = pageConfig.isPageGroup ?
301
- pageConfig.pages[0] :
302
- pageConfig;
303
-
304
- const relativeHref = toUriCompatibleRelativePath(pOutputFile, path.dirname(currentPath));
305
- return { name: pDisplayName, link: relativeHref };
306
- }
307
-
308
- async function copyFileToOutputDir(
309
- filePathFromInputDir,
310
- inputDir,
311
- outputDir
312
- ) {
313
- const inputPath = path.join(inputDir, filePathFromInputDir);
314
- const outputPath = path.join(outputDir, filePathFromInputDir);
315
- const doesOutDirExists = await promisify(fs.exists)(path.dirname(outputPath));
316
- if (!doesOutDirExists) {
317
- try {
318
- await mkdirParent(path.dirname(outputPath));
319
- } catch (err) {
320
- const srcMessage = (err ?? {}).message ?? "Unknown error";
321
- console.error(`Error: Could not create "${outputPath}" directory: ${srcMessage}`);
322
- process.exit(1);
323
- }
324
- }
325
- const doesOutFileExist = await promisify(fs.exists)(outputPath);
326
- if (!doesOutFileExist) {
327
- await promisify(fs.copyFile)(inputPath, outputPath);
328
- }
329
- }
330
-
331
- module.exports = createDocumentation;