From 7b982ea80210778d05e38eef9557c191553d45fd Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Thu, 27 Jul 2017 13:47:18 -0400 Subject: [PATCH] revert(polyglot): Remove polyglot mode BREAKING CHANGE: I'd like to still support C++ and other languages in the future! But I'm much happier doing so by separating the extraction & input phases to the degree that documentation.js can read the output of another module that extracts JSDoc comments from C++ code, rather than having CPP support in it. Fixes #850. Fixes #731. Fixes #702. Fixes #132. --- __tests__/__snapshots__/bin.js.snap | 205 +------- __tests__/__snapshots__/test.js.snap | 8 +- __tests__/bin.js | 18 - __tests__/fixture/external.input.js | 2 - __tests__/fixture/polyglot/blend.cpp | 675 --------------------------- __tests__/lib/parsers/polyglot.js | 81 ---- declarations/comment.js | 1 - docs/NODE_API.md | 10 +- docs/POLYGLOT.md | 41 +- docs/USAGE.md | 2 - package.json | 1 - src/commands/shared_options.js | 40 +- src/index.js | 21 +- src/is_jsdoc_comment.js | 5 +- src/parsers/polyglot.js | 28 -- 15 files changed, 37 insertions(+), 1101 deletions(-) delete mode 100644 __tests__/fixture/polyglot/blend.cpp delete mode 100644 __tests__/lib/parsers/polyglot.js delete mode 100644 src/parsers/polyglot.js diff --git a/__tests__/__snapshots__/bin.js.snap b/__tests__/__snapshots__/bin.js.snap index 094c73747..f9c3a77bd 100644 --- a/__tests__/__snapshots__/bin.js.snap +++ b/__tests__/__snapshots__/bin.js.snap @@ -5,7 +5,7 @@ exports[`--config 1`] = ` - documentation 4.0.0-rc.1 | Documentation + documentation 4.0.0 | Documentation @@ -17,7 +17,7 @@ exports[`--config 1`] = `

documentation

-
4.0.0-rc.1
+
4.0.0
-#include -#include - -#include "zlib.h" - -#if defined(HAVE_PNG) -#include -#endif - -#if defined(HAVE_JPEG) -#define XMD_H -#include -#undef XMD_H -#endif - -#if defined(HAVE_WEBP) -#include -#endif - -#include "mapnik_palette.hpp" -#include "blend.hpp" -#include "tint.hpp" - -#include -#include -#include -#include - -using namespace v8; -using namespace node; - -namespace node_mapnik { - -/** - * This method moves a hex to a color - * @name hexToUInt32Color - * @param {string} hex - * @returns {number} color - */ -static bool hexToUInt32Color(char *hex, unsigned int & value) { - if (!hex) return false; - int len_original = strlen(hex); - // Return is the length of the string is less then six - // otherwise the line after this could go to some other - // pointer in memory, resulting in strange behaviours. - if (len_original < 6) return false; - if (hex[0] == '#') hex++; - int len = strlen(hex); - if (len != 6 && len != 8) return false; - - unsigned int color = 0; - std::stringstream ss; - ss << std::hex << hex; - ss >> color; - - if (len == 8) { - // Circular shift to get from RGBA to ARGB. - value = (color << 24) | ((color & 0xFF00) << 8) | ((color & 0xFF0000) >> 8) | ((color & 0xFF000000) >> 24); - return true; - } else { - value = 0xFF000000 | ((color & 0xFF) << 16) | (color & 0xFF00) | ((color & 0xFF0000) >> 16); - return true; - } -} - -NAN_METHOD(rgb2hsl) { - NanScope(); - if (args.Length() != 3) { - NanThrowTypeError("Please pass r,g,b integer values as three arguments"); - NanReturnUndefined(); - } - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { - NanThrowTypeError("Please pass r,g,b integer values as three arguments"); - NanReturnUndefined(); - } - unsigned r,g,b; - r = args[0]->IntegerValue(); - g = args[1]->IntegerValue(); - b = args[2]->IntegerValue(); - Local hsl = NanNew(3); - double h,s,l; - rgb_to_hsl(r,g,b,h,s,l); - hsl->Set(0,NanNew(h)); - hsl->Set(1,NanNew(s)); - hsl->Set(2,NanNew(l)); - NanReturnValue(hsl); -} - -NAN_METHOD(hsl2rgb) { - NanScope(); - if (args.Length() != 3) { - NanThrowTypeError("Please pass hsl fractional values as three arguments"); - NanReturnUndefined(); - } - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { - NanThrowTypeError("Please pass hsl fractional values as three arguments"); - NanReturnUndefined(); - } - double h,s,l; - h = args[0]->NumberValue(); - s = args[1]->NumberValue(); - l = args[2]->NumberValue(); - Local rgb = NanNew(3); - unsigned r,g,b; - hsl_to_rgb(h,s,l,r,g,b); - rgb->Set(0,NanNew(r)); - rgb->Set(1,NanNew(g)); - rgb->Set(2,NanNew(b)); - NanReturnValue(rgb); -} - -static void parseTintOps(Local const& tint, Tinter & tinter, std::string & msg) { - NanScope(); - Local hue = tint->Get(NanNew("h")); - if (!hue.IsEmpty() && hue->IsArray()) { - Local val_array = Local::Cast(hue); - if (val_array->Length() != 2) { - msg = "h array must be a pair of values"; - } - tinter.h0 = val_array->Get(0)->NumberValue(); - tinter.h1 = val_array->Get(1)->NumberValue(); - } - Local sat = tint->Get(NanNew("s")); - if (!sat.IsEmpty() && sat->IsArray()) { - Local val_array = Local::Cast(sat); - if (val_array->Length() != 2) { - msg = "s array must be a pair of values"; - } - tinter.s0 = val_array->Get(0)->NumberValue(); - tinter.s1 = val_array->Get(1)->NumberValue(); - } - Local light = tint->Get(NanNew("l")); - if (!light.IsEmpty() && light->IsArray()) { - Local val_array = Local::Cast(light); - if (val_array->Length() != 2) { - msg = "l array must be a pair of values"; - } - tinter.l0 = val_array->Get(0)->NumberValue(); - tinter.l1 = val_array->Get(1)->NumberValue(); - } - Local alpha = tint->Get(NanNew("a")); - if (!alpha.IsEmpty() && alpha->IsArray()) { - Local val_array = Local::Cast(alpha); - if (val_array->Length() != 2) { - msg = "a array must be a pair of values"; - } - tinter.a0 = val_array->Get(0)->NumberValue(); - tinter.a1 = val_array->Get(1)->NumberValue(); - } -} - -static inline void Blend_CompositePixel(unsigned int& target, unsigned int const& source) { - if (source <= 0x00FFFFFF) { - // Top pixel is fully transparent. - // - } else if (source >= 0xFF000000 || target <= 0x00FFFFFF) { - // Top pixel is fully opaque or bottom pixel is fully transparent. - target = source; - } else { - // Both pixels have transparency. - // From http://trac.mapnik.org/browser/trunk/include/mapnik/graphics.hpp#L337 - long a1 = (source >> 24) & 0xff; - long r1 = source & 0xff; - long g1 = (source >> 8) & 0xff; - long b1 = (source >> 16) & 0xff; - - long a0 = (target >> 24) & 0xff; - long r0 = (target & 0xff) * a0; - long g0 = ((target >> 8) & 0xff) * a0; - long b0 = ((target >> 16) & 0xff) * a0; - - a0 = ((a1 + a0) << 8) - a0 * a1; - r0 = ((((r1 << 8) - r0) * a1 + (r0 << 8)) / a0); - g0 = ((((g1 << 8) - g0) * a1 + (g0 << 8)) / a0); - b0 = ((((b1 << 8) - b0) * a1 + (b0 << 8)) / a0); - a0 = a0 >> 8; - target = (a0 << 24) | (b0 << 16) | (g0 << 8) | (r0); - } -} - -static inline void TintPixel(unsigned & r, - unsigned & g, - unsigned & b, - Tinter const& tint) { - double h; - double s; - double l; - rgb_to_hsl(r,g,b,h,s,l); - double h2 = tint.h0 + (h * (tint.h1 - tint.h0)); - double s2 = tint.s0 + (s * (tint.s1 - tint.s0)); - double l2 = tint.l0 + (l * (tint.l1 - tint.l0)); - if (h2 > 1) h2 = 1; - if (h2 < 0) h2 = 0; - if (s2 > 1) s2 = 1; - if (s2 < 0) s2 = 0; - if (l2 > 1) l2 = 1; - if (l2 < 0) l2 = 0; - hsl_to_rgb(h2,s2,l2,r,g,b); -} - - -static void Blend_Composite(unsigned int *target, BlendBaton *baton, BImage *image) { - const unsigned int *source = image->im_ptr->data(); - - int sourceX = std::max(0, -image->x); - int sourceY = std::max(0, -image->y); - int sourcePos = sourceY * image->width + sourceX; - - int width = image->width - sourceX - std::max(0, image->x + image->width - baton->width); - int height = image->height - sourceY - std::max(0, image->y + image->height - baton->height); - - int targetX = std::max(0, image->x); - int targetY = std::max(0, image->y); - int targetPos = targetY * baton->width + targetX; - bool tinting = !image->tint.is_identity(); - bool set_alpha = !image->tint.is_alpha_identity(); - if (tinting || set_alpha) { - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - unsigned int const& source_pixel = source[sourcePos + x]; - unsigned a = (source_pixel >> 24) & 0xff; - if (set_alpha) { - double a2 = image->tint.a0 + (a/255.0 * (image->tint.a1 - image->tint.a0)); - if (a2 < 0) a2 = 0; - a = static_cast(std::floor((a2 * 255.0)+.5)); - if (a > 255) a = 255; - } - unsigned r = source_pixel & 0xff; - unsigned g = (source_pixel >> 8 ) & 0xff; - unsigned b = (source_pixel >> 16) & 0xff; - if (a > 1 && tinting) { - TintPixel(r,g,b,image->tint); - } - unsigned int new_pixel = (a << 24) | (b << 16) | (g << 8) | (r); - Blend_CompositePixel(target[targetPos + x], new_pixel); - } - sourcePos += image->width; - targetPos += baton->width; - } - } else { - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - Blend_CompositePixel(target[targetPos + x], source[sourcePos + x]); - } - sourcePos += image->width; - targetPos += baton->width; - } - } -} - -static void Blend_Encode(mapnik::image_rgba8 const& image, BlendBaton* baton, bool alpha) { - try { - if (baton->format == BLEND_FORMAT_JPEG) { -#if defined(HAVE_JPEG) - if (baton->quality == 0) baton->quality = 85; - mapnik::save_as_jpeg(baton->stream, baton->quality, image); -#else - baton->message = "Mapnik not built with jpeg support"; -#endif - } else if (baton->format == BLEND_FORMAT_WEBP) { -#if defined(HAVE_WEBP) - if (baton->quality == 0) baton->quality = 80; - WebPConfig config; - // Default values set here will be lossless=0 and quality=75 (as least as of webp v0.3.1) - if (!WebPConfigInit(&config)) { - /* LCOV_EXCL_START */ - baton->message = "WebPConfigInit failed: version mismatch"; - /* LCOV_EXCL_END */ - } else { - // see for more details: https://github.com/mapnik/mapnik/wiki/Image-IO#webp-output-options - config.quality = baton->quality; - if (baton->compression > 0) { - config.method = baton->compression; - } - mapnik::save_as_webp(baton->stream,image,config,alpha); - } -#else - baton->message = "Mapnik not built with webp support"; -#endif - } else { - // Save as PNG. -#if defined(HAVE_PNG) - mapnik::png_options opts; - opts.compression = baton->compression; - if (baton->encoder == BLEND_ENCODER_MINIZ) opts.use_miniz = true; - if (baton->palette && baton->palette->valid()) { - mapnik::save_as_png8_pal(baton->stream, image, *baton->palette, opts); - } else if (baton->quality > 0) { - opts.colors = baton->quality; - // Paletted PNG. - if (alpha && baton->mode == BLEND_MODE_HEXTREE) { - mapnik::save_as_png8_hex(baton->stream, image, opts); - } else { - mapnik::save_as_png8_oct(baton->stream, image, opts); - } - } else { - mapnik::save_as_png(baton->stream, image, opts); - } -#else - baton->message = "Mapnik not built with png support"; -#endif - } - } catch (const std::exception& ex) { - baton->message = ex.what(); - } -} - -void Work_Blend(uv_work_t* req) { - BlendBaton* baton = static_cast(req->data); - - int total = baton->images.size(); - bool alpha = true; - int size = 0; - - // Iterate from the last to first image because we potentially don't have - // to decode all images if there's an opaque one. - Images::reverse_iterator rit = baton->images.rbegin(); - Images::reverse_iterator rend = baton->images.rend(); - for (int index = total - 1; rit != rend; rit++, index--) { - // If an image that is higher than the current is opaque, stop alltogether. - if (!alpha) break; - - BImage *image = &**rit; - std::unique_ptr image_reader; - try { - image_reader = std::unique_ptr(mapnik::get_image_reader(image->data, image->dataLength)); - } catch (std::exception const& ex) { - baton->message = ex.what(); - return; - } - - if (!image_reader || !image_reader.get()) { - // Not quite sure anymore how the pointer would not be returned - // from the reader and can't find a way to make this fail. - // So removing from coverage - /* LCOV_EXCL_START */ - baton->message = "Unknown image format"; - return; - /* LCOV_EXCL_END */ - } - - unsigned layer_width = image_reader->width(); - unsigned layer_height = image_reader->height(); - // Error out on invalid images. - if (layer_width == 0 || layer_height == 0) { - // No idea how to create a zero height or width image - // so removing from coverage, because I am fairly certain - // it is not possible in almost every image format. - /* LCOV_EXCL_START */ - baton->message = "zero width/height image encountered"; - return; - /* LCOV_EXCL_END */ - } - - int visibleWidth = (int)layer_width + image->x; - int visibleHeight = (int)layer_height + image->y; - // The first image that is in the viewport sets the width/height, if not user supplied. - if (baton->width <= 0) baton->width = std::max(0, visibleWidth); - if (baton->height <= 0) baton->height = std::max(0, visibleHeight); - - // Skip images that are outside of the viewport. - if (visibleWidth <= 0 || visibleHeight <= 0 || image->x >= baton->width || image->y >= baton->height) { - // Remove this layer from the list of layers we consider blending. - continue; - } - - bool layer_has_alpha = image_reader->has_alpha(); - - // Short-circuit when we're not reencoding. - if (size == 0 && !layer_has_alpha && !baton->reencode && - image->x == 0 && image->y == 0 && - (int)layer_width == baton->width && (int)layer_height == baton->height) - { - baton->stream.write((char *)image->data, image->dataLength); - return; - } - - // allocate image for decoded pixels - std::unique_ptr im_ptr(new mapnik::image_rgba8(layer_width,layer_height)); - // actually decode pixels now - try { - image_reader->read(0,0,*im_ptr); - } catch (std::exception const&) { - baton->message = "Could not decode image"; - return; - } - - bool coversWidth = image->x <= 0 && visibleWidth >= baton->width; - bool coversHeight = image->y <= 0 && visibleHeight >= baton->height; - if (!layer_has_alpha && coversWidth && coversHeight && image->tint.is_alpha_identity()) { - // Skip decoding more layers. - alpha = false; - } - - // Convenience aliases. - image->width = layer_width; - image->height = layer_height; - image->im_ptr = std::move(im_ptr); - size++; - - } - - // Now blend images. - int pixels = baton->width * baton->height; - if (pixels <= 0) { - std::ostringstream msg; - msg << "Image dimensions " << baton->width << "x" << baton->height << " are invalid"; - baton->message = msg.str(); - return; - } - - mapnik::image_rgba8 target(baton->width, baton->height); - // When we don't actually have transparent pixels, we don't need to set the matte. - if (alpha) { - target.set(baton->matte); - } - for (auto image_ptr : baton->images) - { - if (image_ptr && image_ptr->im_ptr.get()) - { - Blend_Composite(target.data(), baton, &*image_ptr); - } - } - Blend_Encode(target, baton, alpha); -} - -void Work_AfterBlend(uv_work_t* req) { - NanScope(); - BlendBaton* baton = static_cast(req->data); - - if (!baton->message.length()) { - std::string result = baton->stream.str(); - Local argv[] = { - NanNull(), - NanNewBufferHandle((char *)result.data(), result.length()), - }; - NanMakeCallback(NanGetCurrentContext()->Global(), NanNew(baton->callback), 2, argv); - } else { - Local argv[] = { - NanError(baton->message.c_str()) - }; - NanMakeCallback(NanGetCurrentContext()->Global(), NanNew(baton->callback), 1, argv); - } - delete baton; -} - -NAN_METHOD(Blend) { - NanScope(); - std::unique_ptr baton(new BlendBaton()); - - Local options; - if (args.Length() == 0 || !args[0]->IsArray()) { - NanThrowTypeError("First argument must be an array of Buffers."); - NanReturnUndefined(); - } else if (args.Length() == 1) { - NanThrowTypeError("Second argument must be a function"); - NanReturnUndefined(); - } else if (args.Length() == 2) { - // No options provided. - if (!args[1]->IsFunction()) { - NanThrowTypeError("Second argument must be a function."); - NanReturnUndefined(); - } - NanAssignPersistent(baton->callback,args[1].As()); - } else if (args.Length() >= 3) { - if (!args[1]->IsObject()) { - NanThrowTypeError("Second argument must be a an options object."); - NanReturnUndefined(); - } - options = Local::Cast(args[1]); - - if (!args[2]->IsFunction()) { - NanThrowTypeError("Third argument must be a function."); - NanReturnUndefined(); - } - NanAssignPersistent(baton->callback,args[2].As()); - } - - // Validate options - if (!options.IsEmpty()) { - baton->quality = options->Get(NanNew("quality"))->Int32Value(); - - Local format_val = options->Get(NanNew("format")); - if (!format_val.IsEmpty() && format_val->IsString()) { - if (strcmp(*String::Utf8Value(format_val), "jpeg") == 0 || - strcmp(*String::Utf8Value(format_val), "jpg") == 0) { - baton->format = BLEND_FORMAT_JPEG; - if (baton->quality == 0) baton->quality = 85; // 85 is same default as mapnik core jpeg - else if (baton->quality < 0 || baton->quality > 100) { - NanThrowTypeError("JPEG quality is range 0-100."); - NanReturnUndefined(); - } - } else if (strcmp(*String::Utf8Value(format_val), "png") == 0) { - if (baton->quality == 1 || baton->quality > 256) { - NanThrowTypeError("PNG images must be quantized between 2 and 256 colors."); - NanReturnUndefined(); - } - } else if (strcmp(*String::Utf8Value(format_val), "webp") == 0) { - baton->format = BLEND_FORMAT_WEBP; - if (baton->quality == 0) baton->quality = 80; - else if (baton->quality < 0 || baton->quality > 100) { - NanThrowTypeError("WebP quality is range 0-100."); - NanReturnUndefined(); - } - } else { - NanThrowTypeError("Invalid output format."); - NanReturnUndefined(); - } - } - - baton->reencode = options->Get(NanNew("reencode"))->BooleanValue(); - baton->width = options->Get(NanNew("width"))->Int32Value(); - baton->height = options->Get(NanNew("height"))->Int32Value(); - - Local matte_val = options->Get(NanNew("matte")); - if (!matte_val.IsEmpty() && matte_val->IsString()) { - if (!hexToUInt32Color(*String::Utf8Value(matte_val->ToString()), baton->matte)) - { - NanThrowTypeError("Invalid batte provided."); - NanReturnUndefined(); - } - - // Make sure we're reencoding in the case of single alpha PNGs - if (baton->matte && !baton->reencode) { - baton->reencode = true; - } - } - - Local palette_val = options->Get(NanNew("palette")); - if (!palette_val.IsEmpty() && palette_val->IsObject()) { - baton->palette = node::ObjectWrap::Unwrap(palette_val->ToObject())->palette(); - } - - Local mode_val = options->Get(NanNew("mode")); - if (!mode_val.IsEmpty() && mode_val->IsString()) { - if (strcmp(*String::Utf8Value(mode_val), "octree") == 0 || - strcmp(*String::Utf8Value(mode_val), "o") == 0) { - baton->mode = BLEND_MODE_OCTREE; - } - else if (strcmp(*String::Utf8Value(mode_val), "hextree") == 0 || - strcmp(*String::Utf8Value(mode_val), "h") == 0) { - baton->mode = BLEND_MODE_HEXTREE; - } - } - - Local encoder_val = options->Get(NanNew("encoder")); - if (!encoder_val.IsEmpty() && encoder_val->IsString()) { - if (strcmp(*String::Utf8Value(encoder_val), "miniz") == 0) { - baton->encoder = BLEND_ENCODER_MINIZ; - } - // default is libpng - } - - if (options->Has(NanNew("compression"))) { - Local compression_val = options->Get(NanNew("compression")); - if (!compression_val.IsEmpty() && compression_val->IsNumber()) - { - baton->compression = compression_val->Int32Value(); - } - else - { - NanThrowTypeError("Compression option must be a number"); - NanReturnUndefined(); - } - } - - int min_compression = Z_NO_COMPRESSION; - int max_compression = Z_BEST_COMPRESSION; - if (baton->format == BLEND_FORMAT_PNG) { - if (baton->compression < 0) baton->compression = Z_DEFAULT_COMPRESSION; - if (baton->encoder == BLEND_ENCODER_MINIZ) max_compression = 10; // MZ_UBER_COMPRESSION - } else if (baton->format == BLEND_FORMAT_WEBP) { - min_compression = 0, max_compression = 6; - if (baton->compression < 0) baton->compression = -1; - } - - if (baton->compression > max_compression) { - std::ostringstream msg; - msg << "Compression level must be between " - << min_compression << " and " << max_compression; - NanThrowTypeError(msg.str().c_str()); - NanReturnUndefined(); - } - } - - Local js_images = Local::Cast(args[0]); - uint32_t length = js_images->Length(); - if (length < 1 && !baton->reencode) { - NanThrowTypeError("First argument must contain at least one Buffer."); - NanReturnUndefined(); - } else if (length == 1 && !baton->reencode) { - Local buffer = js_images->Get(0); - if (Buffer::HasInstance(buffer)) { - // Directly pass through buffer if it's the only one. - Local argv[] = { - NanNull(), - buffer - }; - NanMakeCallback(NanGetCurrentContext()->Global(), NanNew(baton->callback), 2, argv); - NanReturnUndefined(); - } else { - // Check whether the argument is a complex image with offsets etc. - // In that case, we don't throw but continue going through the blend - // process below. - bool valid = false; - if (buffer->IsObject()) { - Local props = buffer->ToObject(); - valid = props->Has(NanNew("buffer")) && - Buffer::HasInstance(props->Get(NanNew("buffer"))); - } - if (!valid) { - NanThrowTypeError("All elements must be Buffers or objects with a 'buffer' property."); - NanReturnUndefined(); - } - } - } - - if (!(length >= 1 || (baton->width > 0 && baton->height > 0))) { - NanThrowTypeError("Without buffers, you have to specify width and height."); - NanReturnUndefined(); - } - - if (baton->width < 0 || baton->height < 0) { - NanThrowTypeError("Image dimensions must be greater than 0."); - NanReturnUndefined(); - } - - for (uint32_t i = 0; i < length; i++) { - ImagePtr image = std::make_shared(); - Local buffer = js_images->Get(i); - if (Buffer::HasInstance(buffer)) { - NanAssignPersistent(image->buffer,buffer.As()); - } else if (buffer->IsObject()) { - Local props = buffer->ToObject(); - if (props->Has(NanNew("buffer"))) { - buffer = props->Get(NanNew("buffer")); - if (Buffer::HasInstance(buffer)) { - NanAssignPersistent(image->buffer,buffer.As()); - } - } - image->x = props->Get(NanNew("x"))->Int32Value(); - image->y = props->Get(NanNew("y"))->Int32Value(); - - Local tint_val = props->Get(NanNew("tint")); - if (!tint_val.IsEmpty() && tint_val->IsObject()) { - Local tint = tint_val->ToObject(); - if (!tint.IsEmpty()) { - baton->reencode = true; - std::string msg; - parseTintOps(tint,image->tint,msg); - if (!msg.empty()) { - NanThrowTypeError(msg.c_str()); - NanReturnUndefined(); - } - } - } - } - - if (image->buffer.IsEmpty()) { - NanThrowTypeError("All elements must be Buffers or objects with a 'buffer' property."); - NanReturnUndefined(); - } - - image->data = node::Buffer::Data(buffer); - image->dataLength = node::Buffer::Length(buffer); - baton->images.push_back(image); - } - - uv_queue_work(uv_default_loop(), &(baton.release())->request, Work_Blend, (uv_after_work_cb)Work_AfterBlend); - - NanReturnUndefined(); -} - -} diff --git a/__tests__/lib/parsers/polyglot.js b/__tests__/lib/parsers/polyglot.js deleted file mode 100644 index 10b268c58..000000000 --- a/__tests__/lib/parsers/polyglot.js +++ /dev/null @@ -1,81 +0,0 @@ -var fs = require('fs'), - path = require('path'), - remark = require('remark'), - polyglot = require('../../../src/parsers/polyglot'); - -test('polyglot', function() { - var file = path.resolve( - path.join(__dirname, '../../fixture/polyglot/blend.cpp') - ); - var result = polyglot({ - file, - source: fs.readFileSync(file, 'utf8') - }); - delete result[0].context.file; - delete result[0].context.sortKey; - expect(result).toEqual([ - { - errors: [], - augments: [], - examples: [], - properties: [], - throws: [], - todos: [], - sees: [], - context: { - loc: { end: { column: 3, line: 40 }, start: { column: 1, line: 35 } } - }, - description: remark().parse('This method moves a hex to a color'), - loc: { end: { column: 3, line: 40 }, start: { column: 1, line: 35 } }, - name: 'hexToUInt32Color', - params: [ - { - lineNumber: 3, - title: 'param', - name: 'hex', - type: { - name: 'string', - type: 'NameExpression' - } - } - ], - returns: [ - { - title: 'returns', - description: remark().parse('color'), - type: { - name: 'number', - type: 'NameExpression' - } - } - ], - tags: [ - { - description: null, - lineNumber: 2, - name: 'hexToUInt32Color', - title: 'name' - }, - { - description: null, - lineNumber: 3, - name: 'hex', - title: 'param', - type: { - name: 'string', - type: 'NameExpression' - } - }, - { - description: 'color', - lineNumber: 4, - title: 'returns', - type: { - name: 'number', - type: 'NameExpression' - } - } - ] - } - ]); -}); diff --git a/declarations/comment.js b/declarations/comment.js index af0a51bf5..17d2c3e63 100644 --- a/declarations/comment.js +++ b/declarations/comment.js @@ -1,7 +1,6 @@ /* @flow */ /* eslint no-use-before-define: 0 */ type DocumentationConfig = { - polyglot?: boolean, inferPrivate?: string, noPackage?: boolean, toc?: Array, diff --git a/docs/NODE_API.md b/docs/NODE_API.md index 8be51f979..6a1cbe0ad 100644 --- a/docs/NODE_API.md +++ b/docs/NODE_API.md @@ -22,11 +22,8 @@ of lint information intended for human-readable output. - `args.external` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** a string regex / glob match pattern that defines what external modules will be whitelisted and included in the generated documentation. - - `args.polyglot` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** parse comments with a regex rather than - a proper parser. This enables support of non-JavaScript languages but - reduces documentation's ability to infer structure of code. (optional, default `false`) - `args.shallow` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** whether to avoid dependency parsing - even in JavaScript code. With the polyglot option set, this has no effect. (optional, default `false`) + even in JavaScript code. (optional, default `false`) - `args.inferPrivate` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** a valid regular expression string to infer whether a code element should be private, given its naming structure. For instance, you can specify `inferPrivate: '^_'` to automatically treat @@ -61,11 +58,8 @@ comments, given a root file as a path. - `args.external` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** a string regex / glob match pattern that defines what external modules will be whitelisted and included in the generated documentation. - - `args.polyglot` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** parse comments with a regex rather than - a proper parser. This enables support of non-JavaScript languages but - reduces documentation's ability to infer structure of code. (optional, default `false`) - `args.shallow` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** whether to avoid dependency parsing - even in JavaScript code. With the polyglot option set, this has no effect. (optional, default `false`) + even in JavaScript code. (optional, default `false`) - `args.order` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object))>** optional array that defines sorting order of documentation (optional, default `[]`) - `args.access` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** an array of access levels diff --git a/docs/POLYGLOT.md b/docs/POLYGLOT.md index c2c9373ce..f0005ae0b 100644 --- a/docs/POLYGLOT.md +++ b/docs/POLYGLOT.md @@ -1,39 +1,2 @@ -# About documentation.js, polyglot mode, and file extensions - -Base assumptions: - -* documentation.js subsists on a combination of _source comments_ and - _smart inferences from source code_. -* The default mode of documentation.js is parsing JavaScript, but it has another - mode, called `--polyglot` mode, that doesn't include any inference at all - and lets you document other kinds of source code. -* The default settings for everything should work for most projects, but - this is a guide for if you have a particular setup. - -## File extensions - -Let's talk about file extensions. We have two different flags for controlling -file extensions: `requireExtension` and `parseExtension`. - -* requireExtension adds additional filetypes to the node.js `require()` method. - By default, you can call, for instance, `require('foo')`, and the require algorithm - will look for `foo.js`, `foo` the module, and `foo.json`. Adding another - extension in requireExtension lets it look for `foo.otherextension`. -* parseExtension adds additional filetypes to the list of filetypes documentation.js - thinks it can parse, and it also adds those additional filetypes to the default - files it looks for when you specify a directory or glob as input. - -## Polyglot - -Polyglot mode switches documentation.js from running on babylon and [babel](https://babeljs.io/) -as a JavaScript parser, to using [get-comments](https://github.com/tunnckocore/get-comments). -This lets it grab comments formatted in the `/** Comment */` style from source -code that _isn't_ JavaScript, like C++ or CSS code. - -Since documentation.js doesn't _parse_ C++ and lots of other languages (parsing JavaScript is complicated enough!), -it can't make any of its smart inferences about their source code: it just -takes documentation comments and shows them as-is. - -You _can_ use polyglot mode to turn off inference across the board, but I don't recommend -it. See the 'too much inference' topic in [TROUBLESHOOTING.md](TROUBLESHOOTING.md) -for detail about that. +🚨 Polyglot mode is now deprecated. It will be replaced by a pluggable +input system in future versions. 🚨 diff --git a/docs/USAGE.md b/docs/USAGE.md index 6094961d0..677b15b39 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -30,8 +30,6 @@ Options: documentation. [default: null] --extension, -e only input source files matching this extension will be parsed, this option can be used multiple times. - --polyglot polyglot mode turns off dependency resolution and enables - multi-language support. use this to document c++[boolean] --private, -p generate documentation tagged as private [boolean] [default: false] --access, -a Include only comments with a given access level, out of diff --git a/package.json b/package.json index ad8580741..8c0a9beff 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "concat-stream": "^1.5.0", "disparity": "^2.0.0", "doctrine-temporary-fork": "2.0.0-alpha-allowarrayindex", - "get-comments": "^1.0.1", "get-port": "^3.1.0", "git-url-parse": "^6.0.1", "github-slugger": "1.1.3", diff --git a/src/commands/shared_options.js b/src/commands/shared_options.js index 2ffeb362c..73b1445b8 100644 --- a/src/commands/shared_options.js +++ b/src/commands/shared_options.js @@ -6,8 +6,9 @@ module.exports.sharedInputOptions = { strict: true, shallow: { - describe: 'shallow mode turns off dependency resolution, ' + - 'only processing the specified files (or the main script specified in package.json)', + describe: + 'shallow mode turns off dependency resolution, ' + + 'only processing the specified files (or the main script specified in package.json)', default: false, type: 'boolean' }, @@ -17,19 +18,22 @@ module.exports.sharedInputOptions = { type: 'string' }, 'no-package': { - describe: 'dont find and use package.json for project- configuration option defaults', + describe: + 'dont find and use package.json for project- configuration option defaults', alias: 'np', type: 'boolean', default: false }, external: { - describe: 'a string / glob match pattern that defines which external ' + - 'modules will be whitelisted and included in the generated documentation.', + describe: + 'a string / glob match pattern that defines which external ' + + 'modules will be whitelisted and included in the generated documentation.', default: null }, 'require-extension': { - describe: "additional extensions to include in require() and import's search algorithm." + - 'For instance, adding .es5 would allow require("adder") to find "adder.es5"', + describe: + "additional extensions to include in require() and import's search algorithm." + + 'For instance, adding .es5 would allow require("adder") to find "adder.es5"', // Ensure that the value is an array coerce: (value: string | Array) => [].concat(value), alias: 're' @@ -40,11 +44,6 @@ module.exports.sharedInputOptions = { coerce: (value: string | Array) => [].concat(value), alias: 'pe' }, - polyglot: { - type: 'boolean', - describe: 'polyglot mode turns off dependency resolution and ' + - 'enables multi-language support. use this to document c++' - }, private: { describe: 'generate documentation tagged as private', type: 'boolean', @@ -52,9 +51,10 @@ module.exports.sharedInputOptions = { alias: 'p' }, access: { - describe: 'Include only comments with a given access level, out of private, ' + - 'protected, public, undefined. By default, public, protected, and undefined access ' + - 'levels are included', + describe: + 'Include only comments with a given access level, out of private, ' + + 'protected, public, undefined. By default, public, protected, and undefined access ' + + 'levels are included', choices: ['public', 'private', 'protected', 'undefined'], array: true, alias: 'a' @@ -66,13 +66,15 @@ module.exports.sharedInputOptions = { }, 'infer-private': { type: 'string', - describe: 'Infer private access based on the name. This is a regular expression that ' + - 'is used to match the name' + describe: + 'Infer private access based on the name. This is a regular expression that ' + + 'is used to match the name' }, 'document-exported': { type: 'boolean', - describe: 'Generate documentation for all exported bindings and members ' + - 'even if there is no JSDoc for them', + describe: + 'Generate documentation for all exported bindings and members ' + + 'even if there is no JSDoc for them', default: false }, 'sort-order': { diff --git a/src/index.js b/src/index.js index e06f04986..d8e0b147b 100644 --- a/src/index.js +++ b/src/index.js @@ -6,7 +6,6 @@ var fs = require('fs'), dependency = require('./input/dependency'), shallow = require('./input/shallow'), parseJavaScript = require('./parsers/javascript'), - polyglot = require('./parsers/polyglot'), github = require('./github'), hierarchy = require('./hierarchy'), inferName = require('./infer/name'), @@ -69,7 +68,7 @@ function expandInputs(indexes, config) { // Ensure that indexes is an array of strings indexes = [].concat(indexes); - if (config.polyglot || config.shallow || config.documentExported) { + if (config.shallow || config.documentExported) { return shallow(indexes, config); } @@ -84,8 +83,6 @@ function buildInternal(inputsAndConfig) { config.access = ['public', 'undefined', 'protected']; } - var parseFn = config.polyglot ? polyglot : parseJavaScript; - var buildPipeline = pipeline([ inferName, inferAccess(config.inferPrivate), @@ -106,7 +103,7 @@ function buildInternal(inputsAndConfig) { sourceFile.source = fs.readFileSync(sourceFile.file, 'utf8'); } - return parseFn(sourceFile, config).map(buildPipeline); + return parseJavaScript(sourceFile, config).map(buildPipeline); }).filter(Boolean); return filterAccess( @@ -119,8 +116,6 @@ function lintInternal(inputsAndConfig) { let inputs = inputsAndConfig.inputs; let config = inputsAndConfig.config; - let parseFn = config.polyglot ? polyglot : parseJavaScript; - let lintPipeline = pipeline([ lintComments, inferName, @@ -140,7 +135,7 @@ function lintInternal(inputsAndConfig) { sourceFile.source = fs.readFileSync(sourceFile.file, 'utf8'); } - return parseFn(sourceFile, config).map(lintPipeline); + return parseJavaScript(sourceFile, config).map(lintPipeline); }).filter(Boolean); return formatLint(hierarchy(extractedComments)); @@ -156,11 +151,8 @@ function lintInternal(inputsAndConfig) { * @param {Array} args.external a string regex / glob match pattern * that defines what external modules will be whitelisted and included in the * generated documentation. - * @param {boolean} [args.polyglot=false] parse comments with a regex rather than - * a proper parser. This enables support of non-JavaScript languages but - * reduces documentation's ability to infer structure of code. * @param {boolean} [args.shallow=false] whether to avoid dependency parsing - * even in JavaScript code. With the polyglot option set, this has no effect. + * even in JavaScript code. * @param {string} [args.inferPrivate] a valid regular expression string * to infer whether a code element should be private, given its naming structure. * For instance, you can specify `inferPrivate: '^_'` to automatically treat @@ -190,11 +182,8 @@ let lint = (indexes, args) => configure(indexes, args).then(lintInternal); * @param {Array} args.external a string regex / glob match pattern * that defines what external modules will be whitelisted and included in the * generated documentation. - * @param {boolean} [args.polyglot=false] parse comments with a regex rather than - * a proper parser. This enables support of non-JavaScript languages but - * reduces documentation's ability to infer structure of code. * @param {boolean} [args.shallow=false] whether to avoid dependency parsing - * even in JavaScript code. With the polyglot option set, this has no effect. + * even in JavaScript code. * @param {Array} [args.order=[]] optional array that * defines sorting order of documentation * @param {Array} [args.access=[]] an array of access levels diff --git a/src/is_jsdoc_comment.js b/src/is_jsdoc_comment.js index d24fb7a2e..9fd9605f1 100644 --- a/src/is_jsdoc_comment.js +++ b/src/is_jsdoc_comment.js @@ -20,9 +20,6 @@ module.exports = function isJSDocComment( ) { var asterisks = comment.value.match(/^(\*+)/); return ( - (comment.type === 'CommentBlock' || // estree - comment.type === 'Block') && // get-comments / traditional - asterisks && - asterisks[1].length === 1 + comment.type === 'CommentBlock' && asterisks && asterisks[1].length === 1 ); }; diff --git a/src/parsers/polyglot.js b/src/parsers/polyglot.js deleted file mode 100644 index a323972bc..000000000 --- a/src/parsers/polyglot.js +++ /dev/null @@ -1,28 +0,0 @@ -/* @flow */ - -var getComments = require('get-comments'), - _ = require('lodash'), - isJSDocComment = require('../is_jsdoc_comment'), - parse = require('../parse'); - -/** - * Documentation stream parser: this receives a module-dep item, - * reads the file, parses the JavaScript, parses the JSDoc, and - * emits parsed comments. - * @param sourceFile a chunk of data provided by module-deps - * @return {Array} adds to memo - */ -function parsePolyglot(sourceFile: SourceFile) { - return getComments(sourceFile.source, true) - .filter(isJSDocComment) - .map(comment => { - var context = { - loc: _.clone(comment.loc), - file: sourceFile.file, - sortKey: sourceFile.file + ' ' + comment.loc.start.line - }; - return parse(comment.value, comment.loc, context); - }); -} - -module.exports = parsePolyglot;