1
+ import { FormatBase } from "./FormatBase.js" ;
2
+ import jsdom from "jsdom" ;
3
+ import { NPTToSeconds , secondsToNPT } from "../util.js" ;
4
+
5
+ export class PodloveSimpleChapters extends FormatBase {
6
+
7
+ supportsPrettyPrint = true ;
8
+ filename = 'podlove-simple-chapters-fragment.xml' ;
9
+ mimeType = 'text/xml' ;
10
+
11
+ detect ( inputString ) {
12
+
13
+ return / < p s c : c h a p t e r s / . test ( inputString ) ;
14
+ }
15
+
16
+ parse ( string ) {
17
+ if ( ! this . detect ( string ) ) {
18
+ throw new Error ( 'Input must contain <psc:chapters ...> node' ) ;
19
+ }
20
+
21
+ let dom ;
22
+ if ( typeof DOMParser !== 'undefined' ) {
23
+ dom = ( new DOMParser ( ) ) . parseFromString ( string , 'application/xml' ) ;
24
+ } else {
25
+ const { JSDOM } = jsdom ;
26
+ dom = new JSDOM ( string , { contentType : 'application/xml' } ) ;
27
+ dom = dom . window . document ;
28
+ }
29
+
30
+
31
+ this . chapters = [ ...dom . querySelectorAll ( '[start]' ) ] . reduce ( ( acc , node ) => {
32
+
33
+ if ( node . tagName === 'psc:chapter' ) {
34
+ const start = node . getAttribute ( 'start' ) ;
35
+ const title = node . getAttribute ( 'title' ) ;
36
+ const image = node . getAttribute ( 'image' ) ;
37
+ const href = node . getAttribute ( 'href' ) ;
38
+
39
+ const chapter = {
40
+ startTime : NPTToSeconds ( start )
41
+ }
42
+
43
+ if ( title ) {
44
+ chapter . title = title ;
45
+ }
46
+ if ( image ) {
47
+ chapter . img = image ;
48
+ }
49
+ if ( href ) {
50
+ //is this ever used, except for this format?
51
+ chapter . href = href ;
52
+ }
53
+
54
+ acc . push ( chapter ) ;
55
+ }
56
+ return acc ;
57
+
58
+ } , [ ] ) ;
59
+
60
+ }
61
+
62
+ toString ( pretty = false ) {
63
+ const indent = ( depth , string , spacesPerDepth = 2 ) => ( pretty ? ' ' . repeat ( depth * spacesPerDepth ) : '' ) + string ;
64
+
65
+ let output = [
66
+ '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' ,
67
+ indent ( 1 , '<channel>' ) ,
68
+ indent ( 2 , '<!-- this is only a fragment of an rss feed, see -->' ) ,
69
+ indent ( 2 , '<!-- https://podlove.org/simple-chapters/#:~:text=37%20seconds-,Embedding%20Example,-This%20is%20an -->' ) ,
70
+ indent ( 2 , '<!-- for more information -->' ) ,
71
+ indent ( 2 , '<psc:chapters version="1.2" xmlns:psc="http://podlove.org/simple-chapters">' ) ,
72
+ ] ;
73
+
74
+ this . chapters . forEach ( chapter => {
75
+
76
+ const node = [
77
+ `<psc:chapter start="${ secondsToNPT ( chapter . startTime ) } "` ,
78
+ ] ;
79
+
80
+ if ( chapter . title ) {
81
+ node . push ( ` title="${ chapter . title } "` ) ;
82
+ }
83
+ if ( chapter . img ) {
84
+ node . push ( ` image="${ chapter . img } "` ) ;
85
+ }
86
+ if ( chapter . href ) {
87
+ node . push ( ` href="${ chapter . href } "` ) ;
88
+ }
89
+ node . push ( '/>' ) ;
90
+
91
+ output . push ( indent ( 3 , node . join ( '' ) ) ) ;
92
+
93
+ } ) ;
94
+
95
+ output . push (
96
+ indent ( 2 , '</psc:chapters>' ) ,
97
+ indent ( 1 , '</channel>' ) ,
98
+ indent ( 0 , '</rss>' )
99
+ ) ;
100
+
101
+ return output . join ( pretty ? "\n" : '' ) ;
102
+ }
103
+ }
0 commit comments