Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
Tag.js
001 /**
002 * @constructor
003 *
004 * @param {number} type Tag's type
005 * @param {string} name Name of the tag
006 * @param {number} pos Position of the tag in the text
007 * @param {number} len Length of text consumed by the tag
008 * @param {number=} priority This tag's sorting tiebreaker
009 */
010 function Tag(type, name, pos, len, priority)
011 {
012 this.type = +type;
013 this.name = name;
014 this.pos = +pos;
015 this.len = +len;
016 this.sortPriority = +priority || 0;
017
018 this.attributes = {};
019 this.cascade = [];
020
021 // Invalidate this tag now if any value is not a number, they could wreck
022 // havoc in other parts of the program
023 if (isNaN(type + pos + len))
024 {
025 this.invalidate();
026 }
027 }
028
029 /** @const */
030 Tag.START_TAG = 1;
031
032 /** @const */
033 Tag.END_TAG = 2;
034
035 /** @const */
036 Tag.SELF_CLOSING_TAG = 3;
037
038 /**
039 * @type {!Object} Dictionary of attributes
040 */
041 Tag.prototype.attributes;
042
043 /**
044 * @type {!Array.<!Tag>} List of tags that are invalidated when this tag is invalidated
045 */
046 Tag.prototype.cascade;
047
048 /**
049 * @type {?Tag} End tag that unconditionally ends this start tag
050 */
051 Tag.prototype.endTag;
052
053 /**
054 * @type {boolean} Whether this tag is be invalid
055 */
056 Tag.prototype.invalid = false;
057
058 /**
059 * @type {number} Length of text consumed by this tag
060 */
061 Tag.prototype.len;
062
063 /**
064 * @type {string} Name of this tag
065 */
066 Tag.prototype.name;
067
068 /**
069 * @type {number} Position of this tag in the text
070 */
071 Tag.prototype.pos;
072
073 /**
074 * @type {number} Tiebreaker used when sorting identical tags
075 */
076 Tag.prototype.sortPriority;
077
078 /**
079 * @type {?Tag} Start tag that is unconditionally closed this end tag
080 */
081 Tag.prototype.startTag;
082
083 /**
084 * @type {number} Tag type
085 */
086 Tag.prototype.type;
087
088 /**
089 * Add a set of flags to this tag's
090 *
091 * @param {number} flags
092 */
093 Tag.prototype.addFlags = function(flags)
094 {
095 this.flags |= flags;
096 };
097
098 /**
099 * Set given tag to be invalidated if this tag is invalidated
100 *
101 * @param {!Tag} tag
102 */
103 Tag.prototype.cascadeInvalidationTo = function(tag)
104 {
105 this.cascade.push(tag);
106
107 // If this tag is already invalid, cascade it now
108 if (this.invalid)
109 {
110 tag.invalidate();
111 }
112 };
113
114 /**
115 * Invalidate this tag, as well as tags bound to this tag
116 */
117 Tag.prototype.invalidate = function()
118 {
119 // Only invalidate if this tag is valid to prevent infinite loops
120 if (!this.invalid)
121 {
122 this.invalid = true;
123 this.cascade.forEach(
124 /**
125 * @param {!Tag} tag
126 */
127 function(tag)
128 {
129 tag.invalidate();
130 }
131 );
132 }
133 };
134
135 /**
136 * Pair this tag with given tag
137 *
138 * @param {!Tag} tag
139 */
140 Tag.prototype.pairWith = function(tag)
141 {
142 if (this.canBePaired(this, tag))
143 {
144 this.endTag = tag;
145 tag.startTag = this;
146
147 this.cascadeInvalidationTo(tag);
148 }
149 else if (this.canBePaired(tag, this))
150 {
151 this.startTag = tag;
152 tag.endTag = this;
153 }
154 };
155
156 /**
157 * Test whether two tags can be paired
158 *
159 * @param {!Tag} startTag
160 * @param {!Tag} endTag
161 * @return {boolean}
162 */
163 Tag.prototype.canBePaired = function(startTag, endTag)
164 {
165 return startTag.name === endTag.name && startTag.type === Tag.START_TAG && endTag.type === Tag.END_TAG && startTag.pos <= startTag.pos;
166 };
167
168 /**
169 * Remove a set of flags from this tag's
170 *
171 * @param {number} flags
172 */
173 Tag.prototype.removeFlags = function(flags)
174 {
175 this.flags &= ~flags;
176 };
177
178 /**
179 * Set the bitfield of boolean rules that apply to this tag
180 *
181 * @param {number} flags Bitfield of boolean rules that apply to this tag
182 */
183 Tag.prototype.setFlags = function(flags)
184 {
185 this.flags = flags;
186 };
187
188 //==========================================================================
189 // Getters
190 //==========================================================================
191
192 /**
193 * Return this tag's attributes
194 *
195 * @return {!Object}
196 */
197 Tag.prototype.getAttributes = function()
198 {
199 var attributes = {};
200 for (var attrName in this.attributes)
201 {
202 attributes[attrName] = this.attributes[attrName];
203 }
204
205 return attributes;
206 };
207
208 /**
209 * Return this tag's end tag
210 *
211 * @return {?Tag} This tag's end tag
212 */
213 Tag.prototype.getEndTag = function()
214 {
215 return this.endTag;
216 };
217
218 /**
219 * Return the bitfield of boolean rules that apply to this tag
220 *
221 * @return {number}
222 */
223 Tag.prototype.getFlags = function()
224 {
225 return this.flags;
226 };
227
228 /**
229 * Return the length of text consumed by this tag
230 *
231 * @return {number}
232 */
233 Tag.prototype.getLen = function()
234 {
235 return this.len;
236 };
237
238 /**
239 * Return this tag's name
240 *
241 * @return {string}
242 */
243 Tag.prototype.getName = function()
244 {
245 return this.name;
246 };
247
248 /**
249 * Return this tag's position
250 *
251 * @return {number}
252 */
253 Tag.prototype.getPos = function()
254 {
255 return this.pos;
256 };
257
258 /**
259 * Return this tag's tiebreaker
260 *
261 * @return {number}
262 */
263 Tag.prototype.getSortPriority = function()
264 {
265 return this.sortPriority;
266 };
267
268 /**
269 * Return this tag's start tag
270 *
271 * @return {?Tag} This tag's start tag
272 */
273 Tag.prototype.getStartTag = function()
274 {
275 return this.startTag;
276 };
277
278 /**
279 * Return this tag's type
280 *
281 * @return {number}
282 */
283 Tag.prototype.getType = function()
284 {
285 return this.type;
286 };
287
288 //==========================================================================
289 // Tag's status
290 //==========================================================================
291
292 /**
293 * Test whether this tag can close given start tag
294 *
295 * @param {!Tag} startTag
296 * @return {boolean}
297 */
298 Tag.prototype.canClose = function(startTag)
299 {
300 if (this.invalid
301 || !this.canBePaired(startTag, this)
302 || (this.startTag && this.startTag !== startTag)
303 || (startTag.endTag && startTag.endTag !== this))
304 {
305 return false;
306 }
307
308 return true;
309 };
310
311 /**
312 * Test whether this tag is a br tag
313 *
314 * @return {boolean}
315 */
316 Tag.prototype.isBrTag = function()
317 {
318 return (this.name === 'br');
319 };
320
321 /**
322 * Test whether this tag is an end tag (self-closing tags inclusive)
323 *
324 * @return {boolean}
325 */
326 Tag.prototype.isEndTag = function()
327 {
328 return !!(this.type & Tag.END_TAG);
329 };
330
331 /**
332 * Test whether this tag is an ignore tag
333 *
334 * @return {boolean}
335 */
336 Tag.prototype.isIgnoreTag = function()
337 {
338 return (this.name === 'i');
339 };
340
341 /**
342 * Test whether this tag is invalid
343 *
344 * @return {boolean}
345 */
346 Tag.prototype.isInvalid = function()
347 {
348 return this.invalid;
349 };
350
351 /**
352 * Test whether this tag represents a paragraph break
353 *
354 * @return {boolean}
355 */
356 Tag.prototype.isParagraphBreak = function()
357 {
358 return (this.name === 'pb');
359 };
360
361 /**
362 * Test whether this tag is a self-closing tag
363 *
364 * @return {boolean}
365 */
366 Tag.prototype.isSelfClosingTag = function()
367 {
368 return (this.type === Tag.SELF_CLOSING_TAG);
369 };
370
371 /**
372 * Test whether this tag is a special tag: "br", "i", "pb" or "v"
373 *
374 * @return {boolean}
375 */
376 Tag.prototype.isSystemTag = function()
377 {
378 return ('br i pb v'.indexOf(this.name) > -1);
379 };
380
381 /**
382 * Test whether this tag is a start tag (self-closing tags inclusive)
383 *
384 * @return {boolean}
385 */
386 Tag.prototype.isStartTag = function()
387 {
388 return !!(this.type & Tag.START_TAG);
389 };
390
391 /**
392 * Test whether this tag represents verbatim text
393 *
394 * @return {boolean}
395 */
396 Tag.prototype.isVerbatim = function()
397 {
398 return (this.name === 'v');
399 };
400
401 //==========================================================================
402 // Attributes handling
403 //==========================================================================
404
405 /**
406 * Return the value of given attribute
407 *
408 * @param {string} attrName
409 * @return {string}
410 */
411 Tag.prototype.getAttribute = function(attrName)
412 {
413 return this.attributes[attrName];
414 };
415
416 /**
417 * Return whether given attribute is set
418 *
419 * @param {string} attrName
420 * @return {boolean}
421 */
422 Tag.prototype.hasAttribute = function(attrName)
423 {
424 return (attrName in this.attributes);
425 };
426
427 /**
428 * Remove given attribute
429 *
430 * @param {string} attrName
431 */
432 Tag.prototype.removeAttribute = function(attrName)
433 {
434 delete this.attributes[attrName];
435 };
436
437 /**
438 * Set the value of an attribute
439 *
440 * @param {string} attrName Attribute's name
441 * @param {*} attrValue Attribute's value
442 */
443 Tag.prototype.setAttribute = function(attrName, attrValue)
444 {
445 this.attributes[attrName] = attrValue;
446 };
447
448 /**
449 * Set all of this tag's attributes at once
450 *
451 * @param {!Object} attributes
452 */
453 Tag.prototype.setAttributes = function(attributes)
454 {
455 this.attributes = {};
456 for (var attrName in attributes)
457 {
458 this.attributes[attrName] = attributes[attrName];
459 }
460 };