2025-04-15 16:39:47 +02:00

111 lines
2.8 KiB
JavaScript

/*!
* extract-comments <https://github.com/jonschlinkert/extract-comments>
*
* Copyright (c) 2014-present Jon Schlinkert.
* Licensed under the MIT license.
*/
'use strict';
const esprima = require('esprima-extract-comments');
const BlockComment = require('./block');
const LineComment = require('./line');
const Context = require('./context');
/**
* If you need to customize the generated comment objects, you
* can create an instance of `Extractor`:
*
* ```js
* const extract = require('extract-comments');
* const Extractor = extract.Extractor;
* const comments = new Extractor(options);
* ```
* @param {String} `string`
* @param {Object} `options`
* @param {Object} `options.first` Return the first comment only
* @param {Object} `options.banner` alias for `options.first`
* @param {Function} `fn` Optionally pass a transform function to call on each token (comment) in the AST.
* @return {String}
* @api public
*/
class Extractor {
constructor(options, fn) {
if (typeof options === 'function') {
fn = options;
options = {};
}
this.options = Object.assign({ transform: fn }, options);
}
extract(str) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
const opts = Object.assign({ keepProtected: true }, this.options);
const extract = opts.extractor || esprima;
const tokens = extract(str, opts);
const comments = [];
let filter = opts.filter;
let keep = opts.stripProtected === true ? false : opts.keepProtected === true;
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
const nextToken = tokens[i + 1];
if (typeof filter === 'function' && filter(token) === false) {
continue;
}
if (/^\*?!/.test(token.value) && keep === false) {
continue;
}
const comment = toComment(str, token, nextToken, opts);
if (comment) comments.push(comment);
if ((opts.first || opts.banner) && comments.length === 1) {
break;
}
}
return comments;
}
}
function toComment(str, token, nextToken, options) {
if (typeof options.transform === 'function') {
token = options.transform(token, options) || token;
}
if (isBlock(token.type) && options.block !== false) {
let comment = new BlockComment(str, token, options);
if (nextToken) nextToken = toComment(str, nextToken, null, options);
comment.code = new Context(str, comment, nextToken, options);
return comment;
}
if (isLine(token.type) && options.line !== false) {
return new LineComment(str, token, options);
}
}
function isLine(type) {
return type === 'Line' || type === 'CommentLine' || type === 'LineComment';
}
function isBlock(type) {
return type === 'Block' || type === 'CommentBlock' || type === 'BlockComment';
}
/**
* Expose `Extractor` constructor
*/
module.exports = Extractor;