Comment.js

import Node from './Node';

/** Return a new {@link Comment} {@link Node}.
* @extends Node
*/
class Comment extends Node {
	/**
	* @param {CommentSettings|string} settings - Custom settings applied to the Comment, or the content of the Comment.
	* @example
	* new Comment({ comment: ' Hello World ' }) // <!-- Hello -->
	*/
	constructor (settings) {
		super();

		if (typeof settings === 'string') {
			settings = { comment: settings };
		}

		/** Type identifier of the Comment
		* @type {'comment'} */
		this.type = 'comment';

		/** Node name of the Comment
		* @type {'#comment'} */
		this.name = '#comment';

		/** Content of the Comment
		* @type {string} */
		this.comment = String(Object(settings).comment || '');

		/** Source mapping of the Content
		* @type {CommentSource} */
		this.source = Object(Object(settings).source);
	}

	/** Return the stringified innerHTML of the current {@link Comment}.
	* @example
	* attrs.innerHTML // returns ' Hello World '
	*/
	get innerHTML () {
		return String(this.comment);
	}

	/** Return the stringified outerHTML of the current {@link Comment}.
	* @example
	* attrs.outerHTML // returns '<!-- Hello World -->'
	*/
	get outerHTML () {
		return String(this);
	}

	/** Return the stringified innerHTML from the source input.
	* @example
	* attrs.sourceInnerHTML // returns ' Hello World '
	*/
	get sourceInnerHTML () {
		return typeof Object(this.source.input).html !== 'string'
			? ''
		: this.source.input.html.slice(
			this.source.startOffset + 4,
			this.source.endOffset - 3
		);
	}

	/** Return the stringified outerHTML from the source input.
	* @example
	* attrs.sourceOuterHTML // returns '<!-- Hello World -->'
	*/
	get sourceOuterHTML () {
		return typeof Object(this.source.input).html !== 'string'
			? ''
		: this.source.input.html.slice(
			this.source.startOffset,
			this.source.endOffset
		);
	}

	/** Return a clone of the current {@link Comment}.
	* @param {Object} settings - Custom settings applied to the cloned Comment.
	* @returns {Comment}
	* @example
	* comment.clone()
	* @example <caption>Clone the current text with new source.</caption>
	* comment.clone({ source: { input: { html: 'modified source' } } })
	*/
	clone (settings) {
		return new this.constructor(Object.assign({}, this, settings, {
			source: Object.assign({}, this.source, Object(settings).source)
		}));
	}

	/** Return the current {@link Comment} as a String.
	* @example
	* attrs.toJSON() // returns '<!-- Hello World -->'
	*/
	toString () {
		return `<!--${this.comment}-->`;
	}

	/** Return the current {@link Comment} as a Object.
	* @example
	* attrs.toJSON() // returns { comment: ' Hello World ' }
	*/
	toJSON () {
		return {
			comment: this.comment
		};
	}
}

export default Comment;

/**
* @typedef {Object} CommentSettings - Custom settings applied to the Comment.
* @property {string} comment - Content of the Comment.
* @property {CommentSource} source - Source mapping of the Comment.
*
* @typedef {Object} CommentSource - Source mapping of the Comment.
* @property {CommentInput} input - Metadata of the Comment.
* @property {number} startOffset - Starting offset within the input source.
* @property {number} endOffset - Ending offset within the input source.
*
* @typedef {Object} CommentInput - Source of the Comment.
* @property {string} html - HTML source of the Comment.
*/