File : LinkBuilder.js

1
/*
2
Copyright - 2021 - wwwouaiebe - Contact: https://www.ouaie.be/
3
4
This  program is free software;
5
you can redistribute it and/or modify it under the terms of the
6
GNU General Public License as published by the Free Software Foundation;
7
either version 3 of the License, or any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
*/
18
/*
19
Changes:
20
    - v1.0.0:
21
        - created
22
    - v1.1.0:
23
        - Issue ♯3 : String.substr ( ) is deprecated... Replace...
24
Doc reviewed 20211111
25
*/
26
/* ------------------------------------------------------------------------------------------------------------------------- */
27
28
import { marked } from 'marked';
29
30
/* ------------------------------------------------------------------------------------------------------------------------- */
31
/**
32
Store all the links  created from the source document and get the links completed with the path for others classes
33
*/
34
/* ------------------------------------------------------------------------------------------------------------------------- */
35
36
class LinkBuilder {
37
38
    /**
39
    A cache for the sources links
40
    @type {Array.<Array.<String>>}
41
    */
42
43
    #sourcesLinksCache;
44
45
    /**
46
    The links to the sources  files
47
    @type {Map.<String>}
48
    */
49
50
    #sourcesLinks;
51
52
    /**
53
    A cache for the classes links
54
    @type {Array.<Array.<String>>}
55
    */
56
57
    #classesLinksCache;
58
59
    /**
60
    The links to the classes  files
61
    @type {Map.<String>}
62
    */
63
64
    #classesLinks;
65
66
    /**
67
    A cache for the variables links
68
    @type {Array.<Array.<String>>}
69
    */
70
71
    #variablesLinksCache;
72
73
    /**
74
    The links to the variables file and the variables in the file
75
    @type {Map.<String>}
76
    */
77
78
    #variablesLinks;
79
80
    /**
81
    The links to the mdn documentation
82
    @type {Object}
83
    */
84
85
    #mdnLinks = Object.freeze (
86
        {
87
88
            // Global objects
89
            Array : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array',
90
            ArrayBuffer : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer',
91
            Boolean : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean',
92
            Error : 'https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Error',
93
            Function : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function',
94
            Map : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map',
95
            Number : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number',
96
            Object : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object',
97
            Promise : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise',
98
            RegExp : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp',
99
            String : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String',
100
            Uint8Array : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array',
101
102
            // Statements
103
            Class : 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class',
104
105
            // API
106
            CryptoKey : 'https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey',
107
            Event : 'https://developer.mozilla.org/en-US/docs/Web/API/Event',
108
            GeolocationPosition : 'https://developer.mozilla.org/fr/docs/Web/API/GeolocationPosition',
109
            GeolocationPositionError : 'https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError',
110
            IDBFactory : 'https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory',
111
            HTMLElement : 'https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement',
112
            Node : 'https://developer.mozilla.org/en-US/docs/Web/API/Node',
113
            NodeList : 'https://developer.mozilla.org/fr/docs/Web/API/NodeList',
114
            SVGElement : 'https://developer.mozilla.org/en-US/docs/Web/API/SVGElement',
115
            XMLDocument : 'https://developer.mozilla.org/en-US/docs/Web/API/XMLDocument',
116
117
            // Others
118
            LeafletObject : 'https://leafletjs.com/reference.html',
119
            OsmElement : 'https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL',
120
            JsonObject : 'https://www.json.org/json-en.html'
121
        }
122
    );
123
124
    /**
125
    The constructor
126
    */
127
128
    constructor ( ) {
129
        Object.freeze ( this );
130
        this.#sourcesLinks = new Map ( );
131
        this.#classesLinks = new Map ( );
132
        this.#variablesLinks = new Map ( );
133
    }
134
135
    /**
136
    Get the html link to a class file
137
    @param {String} className The name of the class for witch the link must be created
138
    @param {String} rootPath The path between the file where the link will be inserted and theConfig.destDir
139
    ( something like '../../../', depending of the folders tree )
140
    @return {String} An html string with the link or the className when the link is not found
141
    */
142
143
    getClassLink ( className, rootPath ) {
144
        const classLink = this.#classesLinks.get ( className );
145
        return classLink ? `<a href="${rootPath + classLink}">${className}</a>` : className;
146
    }
147
148
    /**
149
    Store a link to a class file
150
    @param {ClassDoc} classDoc the doc with the class documentation
151
    */
152
153
    setClassLink ( classDoc ) {
154
        this.#classesLinks.set (
155
            classDoc.name,
156
            classDoc.file.substring ( 0, classDoc.file.lastIndexOf ( '/' ) + 1 ) + classDoc.name + '.html'
157
        );
158
    }
159
160
    /**
161
    Get all the classes links. Each subAray contains the class name and the class link.
162
    @type {Array.<Array.<String>>}
163
    */
164
165
    get classesLinks ( ) {
166
        if ( ! this.#classesLinksCache ) {
167
168
            // Create the cache if not exists
169
            this.#classesLinksCache = this.#classesLinksCache ?? Array.from ( this.#classesLinks ).sort (
170
                ( first, second ) => first [ 0 ] .localeCompare ( second [ 0 ] )
171
            );
172
        }
173
174
        return this.#classesLinksCache;
175
    }
176
177
    /**
178
    Get a link to a source file
179
    @param {VariableDoc|MethodOrPropertyDoc|VariableDoc} doc The doc for witch the link to the source file must be created.
180
    @return {?String} The link to the source file
181
    */
182
183
    getSourceLink ( doc ) {
184
        let sourceLink = this.#sourcesLinks.get ( doc.file );
185
        if ( sourceLink ) {
186
            return doc.rootPath + sourceLink + '#L' + String ( doc.line ).padStart ( 5, '_' );
187
        }
188
        return null;
189
    }
190
191
    /**
192
    Store a link to a source file
193
    @param {String} fileName The file name
194
    @param {String} path The path since theConfig.destDir, included file name
195
    */
196
197
    setSourceLink ( fileName, path ) {
198
        this.#sourcesLinks.set ( fileName, path );
199
    }
200
201
    /**
202
    Get all the sources links. Each subAray contains the source file name and the path
203
    between theConfig.destDir  and the source file, included file name
204
    @type {Array.<Array.<String>>}
205
    */
206
207
    get sourcesLinks ( ) {
208
        if ( ! this.#sourcesLinksCache ) {
209
            this.#sourcesLinksCache = Array.from ( this.#sourcesLinks ).sort (
210
                ( first, second ) => first [ 0 ] .localeCompare ( second [ 0 ] )
211
            );
212
        }
213
        return this.#sourcesLinksCache;
214
    }
215
216
    /**
217
    Store a link to a variable in the variables.html file
218
    @param {VariableDoc} variableDoc the doc with the variable documentation
219
    */
220
221
    setVariableLink ( variableDoc ) {
222
        this.#variablesLinks.set (
223
            variableDoc.name,
224
            `variables.html#${variableDoc.name}`
225
        );
226
    }
227
228
    /**
229
    Get all the variables links. Each subAray contains the variable name and the variable link.
230
    @type {Array.<Array.<String>>}
231
    */
232
233
    get variablesLinks ( ) {
234
        if ( ! this.#variablesLinksCache ) {
235
            this.#variablesLinksCache = Array.from ( this.#variablesLinks ).sort (
236
                ( first, second ) => first [ 0 ] .localeCompare ( second [ 0 ] )
237
            );
238
        }
239
        return this.#variablesLinksCache;
240
    }
241
242
    /**
243
    Get the link to a type
244
    @param {String} type The type for witch the link must be created. Must be a single word
245
    @param {String} rootPath The path between the file where the link will be inserted and theConfig.destDir
246
    ( something like '../../../', depending of the folders tree )
247
    @return {String} The link to the type. We search first in the classes links, then in the mdn links. If nothing
248
    found, the type without html link is returned.
249
    */
250
251
    #getTypeLink ( type, rootPath ) {
252
        if ( 'constructor' === type ) {
253
            return type;
254
        }
255
        const classLink = this.#classesLinks.get ( type );
256
        if ( classLink ) {
257
            return `<a href="${rootPath + classLink}">${type}</a>`;
258
        }
259
        const mdnLink = this.#mdnLinks [ type ];
260
        if ( mdnLink ) {
261
            return `<a href="${mdnLink}">${type}</a>`;
262
        }
263
        const variableLink = this.#variablesLinks.get ( type );
264
        if ( variableLink ) {
265
            return `<a href="${variableLink}">${type}</a>`;
266
        }
267
        return type;
268
    }
269
270
    /**
271
    Verify that a given type is a known type ( = present in the @classesLinks map
272
    or the mdnLinks object
273
    @param {String} type The type to verify
274
    @return {Boolean} True when the type is known
275
    */
276
277
    isKnownType ( type ) {
278
        return Boolean ( this.#classesLinks.get ( type ) || this.#mdnLinks [ type ] );
279
    }
280
281
    /**
282
    Get the links to a type
283
    @param {String} type The types for witch the link must be created. Can be multiple word
284
    @param {String} rootPath The path between the file where the link will be inserted and theConfig.destDir
285
    ( something like '../../../', depending of the folders tree )
286
    @return {String} The html links to the types. We search first in the classes links, then in the mdn links. If nothing
287
    found, the types without html link is returned.
288
    */
289
290
    getTypeLinks ( type, rootPath ) {
291
        if ( ! type ) {
292
            return 'null';
293
        }
294
        let returnType = '';
295
        type.split ( ' ' ).forEach (
296
            tmpType => returnType += this.#getTypeLink ( tmpType, rootPath ) + ' '
297
        );
298
299
        return returnType.trimEnd ( );
300
    }
301
302
    /**
303
    Add links to a description
304
    @param {String} desc The description to complete with links
305
    @param {String} rootPath The path between the file where the link will be inserted and theConfig.destDir
306
    ( something like '../../../', depending of the folders tree )
307
    @return {String} The description completed with html links
308
    */
309
310
    getDescLink ( desc, rootPath ) {
311
        let returnDesc = '';
312
        desc.split ( ' ' ).forEach (
313
            word => returnDesc += this.#getTypeLink ( word, rootPath ) + ' '
314
        );
315
        return marked.parse ( returnDesc.trimEnd ( ) );
316
    }
317
}
318
319
/**
320
The one and only one instance of LinkBuilder class
321
@type {LinkBuilder}
322
*/
323
324
const theLinkBuilder = new LinkBuilder ( );
325
326
export default theLinkBuilder;
327
328
/* --- End of file --------------------------------------------------------------------------------------------------------- */
329