diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b801639 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: node_js +env: + - CXX=g++-4.8 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 + +node_js: + - "4.1" + - "0.12" + - "0.10" diff --git a/README.md b/README.md index 021f830..66789c8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Gumbo Parser -(npm install not fixed on windows yet) +[![Build Status](https://travis-ci.org/karlwestin/node-gumbo-parser.svg)](https://travis-ci.org/karlwestin/node-gumbo-parser) Using [google's gumbo parser](https://github.com/google/gumbo-parser) to parse HTML in node. @@ -142,6 +142,8 @@ npm test ``` ## Changes +**0.2.2** Update to use the latest NaN api, so it works for node 4.0 + **0.2.1** Celebrating some new stuff with a MINOR version change * Fragment parsing supports fragmentContext and fragmentNamespace Uses version 0.10.1, Big changes from the gumbo-parser-team: diff --git a/node-gumbo.cc b/node-gumbo.cc index ef0dc38..6497569 100644 --- a/node-gumbo.cc +++ b/node-gumbo.cc @@ -12,22 +12,26 @@ Local read_element(GumboNode* node); Local read_attribute(GumboAttribute* attr); Local read_document(GumboNode* node); -void record_location(Local node, GumboSourcePosition* pos, const char* name) { - Local position = NanNew(); - position->Set(NanNew("line"), - NanNew(pos->line)); - position->Set(NanNew("column"), - NanNew(pos->column)); - position->Set(NanNew("offset"), - NanNew(pos->offset)); - node->Set(NanNew(name), position); +void record_location(v8::Local node, GumboSourcePosition* pos, const char* name) { + v8::Local position = Nan::New(); + Nan::Set(position, + Nan::New("line").ToLocalChecked(), + Nan::New(pos->line)); + Nan::Set(position, + Nan::New("column").ToLocalChecked(), + Nan::New(pos->column)); + Nan::Set(position, + Nan::New("offset").ToLocalChecked(), + Nan::New(pos->offset)); + + Nan::Set(node, Nan::New(name).ToLocalChecked(), position); } Local read_attribute(GumboAttribute* attr) { - Local obj = NanNew(); - obj->Set(NanNew("nodeType"), NanNew(2)); - obj->Set(NanNew("name"), NanNew(attr->name)); - obj->Set(NanNew("value"), NanNew(attr->value)); + v8::Local obj = Nan::New(); + Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), Nan::New(2)); + Nan::Set(obj, Nan::New("name").ToLocalChecked(), Nan::New(attr->name).ToLocalChecked()); + Nan::Set(obj, Nan::New("value").ToLocalChecked(), Nan::New(attr->value).ToLocalChecked()); record_location(obj, &attr->name_start, "nameStart"); record_location(obj, &attr->name_end, "nameEnd"); @@ -52,100 +56,112 @@ Handle get_tag_namespace(GumboNamespaceEnum tag_namespace) { namespace_name = "MATHML"; break; default: - NanThrowTypeError("Unknown tag namespace"); + Nan::ThrowTypeError("Unknown tag namespace"); } - return NanNew(namespace_name); + return Nan::New(namespace_name).ToLocalChecked(); } Local read_text(GumboNode* node) { - Local obj = NanNew(); - Local type = NanNew(3); - Local name; + Local obj = Nan::New(); + Local type = Nan::New(3); + const char* name; switch(node->type) { case GUMBO_NODE_TEXT: case GUMBO_NODE_WHITESPACE: - name = NanNew("#text"); + name = "#text"; break; case GUMBO_NODE_CDATA: - name = NanNew("#cdata-section"); + name = ("#cdata-section"); break; } - obj->Set(NanNew("nodeType"), type); - obj->Set(NanNew("nodeName"), name); - obj->Set(NanNew("textContent"), NanNew(node->v.text.text)); + + Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), type); + Nan::Set(obj, Nan::New("nodeName").ToLocalChecked(), Nan::New(name).ToLocalChecked()); + Nan::Set(obj, Nan::New("textContent").ToLocalChecked(), Nan::New(node->v.text.text).ToLocalChecked()); record_location(obj, &node->v.text.start_pos, "startPos"); return obj; } Local read_comment(GumboNode* node) { - Local obj = NanNew(); - obj->Set(NanNew("nodeType"), NanNew(8)); - obj->Set(NanNew("nodeName"), NanNew("#comment")); - obj->Set(NanNew("textContent"), NanNew(node->v.text.text)); - obj->Set(NanNew("nodeValue"), NanNew(node->v.text.text)); + Local obj = Nan::New(); + Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), Nan::New(8)); + Nan::Set(obj, Nan::New("nodeName").ToLocalChecked(), Nan::New("#comment").ToLocalChecked()); + Nan::Set(obj, Nan::New("textContent").ToLocalChecked(), Nan::New(node->v.text.text).ToLocalChecked()); + Nan::Set(obj, Nan::New("nodeValue").ToLocalChecked(), Nan::New(node->v.text.text).ToLocalChecked()); return obj; } +Local get_tag_name(GumboNode* node) { + const char* tagName = gumbo_normalized_tagname(node->v.element.tag); + if(strlen(tagName) > 0) { + return Nan::New(tagName).ToLocalChecked(); + } + + // if we don't have a tagname (i.e. it's a custom tag), + // extract the tagname from the original text + GumboStringPiece clone = node->v.element.original_tag; + gumbo_tag_from_original_text(&clone); + return Nan::New(clone.data, clone.length).ToLocalChecked(); +} + Local read_element(GumboNode* node) { - Local obj = NanNew(); - Local tag = NanNew(gumbo_normalized_tagname(node->v.element.tag)); + Local obj = Nan::New(); - obj->Set(NanNew("originalTag"), - NanNew(node->v.element.original_tag.data, - node->v.element.original_tag.length)); + Nan::Set(obj, + Nan::New("originalTag").ToLocalChecked(), + Nan::New(node->v.element.original_tag.data, + node->v.element.original_tag.length).ToLocalChecked()); - obj->Set(NanNew("originalEndTag"), - NanNew(node->v.element.original_end_tag.data, - node->v.element.original_end_tag.length)); + Nan::Set(obj, + Nan::New("originalEndTag").ToLocalChecked(), + Nan::New(node->v.element.original_end_tag.data, + node->v.element.original_end_tag.length).ToLocalChecked()); - if(tag->Length() == 0) { - // if we don't have a tagname (i.e. it's a custom tag), - // extract the tagname from the original text - GumboStringPiece clone = node->v.element.original_tag; - gumbo_tag_from_original_text(&clone); - tag = NanNew(clone.data, clone.length); - } + Local tag = get_tag_name(node); - obj->Set(NanNew("nodeType"), NanNew(1)); - obj->Set(NanNew("nodeName"), tag); - obj->Set(NanNew("tagName"), tag); + Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), Nan::New(1)); + Nan::Set(obj, Nan::New("nodeName").ToLocalChecked(), tag); + Nan::Set(obj, Nan::New("tagName").ToLocalChecked(), tag); - obj->Set(NanNew("tagNamespace"), - get_tag_namespace(node->v.element.tag_namespace)); + Nan::Set(obj, Nan::New("tagNamespace").ToLocalChecked(), get_tag_namespace(node->v.element.tag_namespace)); - obj->Set(NanNew("originalTag"), - NanNew(node->v.element.original_tag.data, - node->v.element.original_tag.length)); + Nan::Set(obj, + Nan::New("originalTag").ToLocalChecked(), + Nan::New(node->v.element.original_tag.data, + node->v.element.original_tag.length).ToLocalChecked()); - obj->Set(NanNew("originalEndTag"), - NanNew(node->v.element.original_end_tag.data, - node->v.element.original_end_tag.length)); + Nan::Set(obj, + Nan::New("originalEndTag").ToLocalChecked(), + Nan::New(node->v.element.original_end_tag.data, + node->v.element.original_end_tag.length).ToLocalChecked()); GumboVector* children = &node->v.element.children; - Local childNodes = NanNew(children->length); + Local childNodes = Nan::New(children->length); if(children->length > 0) { for (unsigned int i = 0; i < children->length; ++i) { childNodes->Set(i, recursive_search(static_cast(children->data[i]))); } } - obj->Set(NanNew("childNodes"), childNodes); + + Nan::Set(obj, Nan::New("childNodes").ToLocalChecked(), childNodes); GumboVector* attributes = &node->v.element.attributes; - Local attrs = NanNew(attributes->length); + Local attrs = Nan::New(attributes->length); if(attributes->length > 0) { for (unsigned int i = 0; i < attributes->length; ++i) { attrs->Set(i, read_attribute(static_cast(attributes->data[i]))); } } - obj->Set(NanNew("attributes"), attrs); + + Nan::Set(obj, Nan::New("attributes").ToLocalChecked(), attrs); // set location if the element actually comes from the source if (node->v.element.original_tag.length == 0) { - obj->Set(NanNew("startPos"), NanUndefined()); + Nan::Set(obj, Nan::New("startPos").ToLocalChecked(), Nan::Undefined()); } else { record_location(obj, &node->v.element.start_pos, "startPos"); record_location(obj, &node->v.element.end_pos, "endPos"); @@ -156,23 +172,23 @@ Local read_element(GumboNode* node) { Local read_document(GumboNode* node) { GumboDocument* doc = &node->v.document; - Local obj = NanNew(); - obj->Set(NanNew("nodeType"), NanNew(9)); - obj->Set(NanNew("nodeName"), NanNew("#document")); - obj->Set(NanNew("hasDoctype"), NanNew(doc->has_doctype)); - - obj->Set(NanNew("name"), NanNew(doc->name)); - obj->Set(NanNew("publicIdentifier"), NanNew(doc->public_identifier)); - obj->Set(NanNew("systemIdentifier"), NanNew(doc->system_identifier)); + Local obj = Nan::New(); + Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), Nan::New(9)); + Nan::Set(obj, Nan::New("nodeName").ToLocalChecked(), Nan::New("#document").ToLocalChecked()); + Nan::Set(obj, Nan::New("hasDoctype").ToLocalChecked(), Nan::New(doc->has_doctype)); + obj, + Nan::Set(obj, Nan::New("name").ToLocalChecked(), Nan::New(doc->name).ToLocalChecked()); + Nan::Set(obj, Nan::New("publicIdentifier").ToLocalChecked(), Nan::New(doc->public_identifier).ToLocalChecked()); + Nan::Set(obj, Nan::New("systemIdentifier").ToLocalChecked(), Nan::New(doc->system_identifier).ToLocalChecked()); GumboVector* children = &doc->children; - Local childNodes = NanNew(children->length); + Local childNodes = Nan::New(children->length); if(children->length > 0) { for (unsigned int i = 0; i < children->length; ++i) { childNodes->Set(i, recursive_search(static_cast(children->data[i]))); } } - obj->Set(NanNew("childNodes"), childNodes); + Nan::Set(obj, Nan::New("childNodes").ToLocalChecked(), childNodes); return obj; } @@ -198,18 +214,17 @@ Local recursive_search(GumboNode* node) { } NAN_METHOD(Method) { - NanScope(); /* * getting options */ - Local config = Local::Cast(args[1]); - Local s_o_f = config->Get(NanNew("stopOnFirstError")); + Local config = Local::Cast(info[1]); + Local s_o_f = Nan::Get(config, Nan::New("stopOnFirstError").ToLocalChecked()).ToLocalChecked(); bool stop_on_first_error = false; if (s_o_f->IsBoolean()) { stop_on_first_error = s_o_f->ToBoolean()->Value(); } - Local t_s = config->Get(NanNew("tabStop")); + Local t_s = Nan::Get(config, Nan::New("tabStop").ToLocalChecked()).ToLocalChecked(); int tab_stop = 8; if (t_s->IsNumber()) { tab_stop = t_s->ToInteger()->Value(); @@ -218,9 +233,9 @@ NAN_METHOD(Method) { /* * getting text */ - Local str = args[0]; + Local str = info[0]; if(!str->IsString() ) { - return NanThrowError("The first argument needs to be a string"); + return Nan::ThrowError("The first argument needs to be a string"); } v8::String::Utf8Value string(str); @@ -236,14 +251,16 @@ NAN_METHOD(Method) { /* * find out context for fragment parsing */ - Local fragment_context = config->Get(NanNew("fragmentContext")); - Local fragment_namespace = config->Get(NanNew("fragmentNamespace")); + Local fragment_context = Nan::Get(config, Nan::New("fragmentContext").ToLocalChecked()).ToLocalChecked(); + Local fragment_namespace = Nan::Get(config, Nan::New("fragmentNamespace").ToLocalChecked()).ToLocalChecked(); if(fragment_context->IsString()) { - GumboTag context = gumbo_tag_enum(*NanUtf8String(fragment_context->ToString())); + Nan::Utf8String f_c(fragment_context->ToString()); + GumboTag context = gumbo_tag_enum(*f_c); GumboNamespaceEnum ns = GUMBO_NAMESPACE_HTML; if(fragment_namespace->IsString()) { - char *nsString = *NanUtf8String(fragment_namespace->ToString()); + Nan::Utf8String f_n(fragment_namespace->ToString()); + char *nsString = *f_n; if(strcmp(nsString, "svg") == 0) { ns = GUMBO_NAMESPACE_SVG; } else if (strcmp(nsString, "mathml") == 0) { @@ -262,24 +279,25 @@ NAN_METHOD(Method) { // root points to html tag // document points to document - Local ret = NanNew(); + Local ret = Nan::New(); if(!fragment) { Local doc = recursive_search(output->document); - ret->Set(NanNew("document"), doc); + Nan::Set(ret, Nan::New("document").ToLocalChecked(), doc); } else { Local root = recursive_search(output->root); - ret->Set(NanNew("root"), root); + Nan::Set(ret, Nan::New("root").ToLocalChecked(), root); } // TODO: Parse errors gumbo_destroy_output(&options, output); - NanReturnValue(ret); + info.GetReturnValue().Set(ret); } void init(Handle exports) { - exports->Set(NanNew("gumbo"), - NanNew(Method)->GetFunction()); + Nan::Set(exports, + Nan::New("gumbo").ToLocalChecked(), + Nan::New(Method)->GetFunction()); } NODE_MODULE(binding, init); diff --git a/package.json b/package.json index bbb98d1..fde7dcd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gumbo-parser", - "version": "0.2.1", + "version": "0.2.2", "author": "Karl Westin ", "contributors": [ { @@ -22,13 +22,13 @@ "parser" ], "devDependencies": { - "node-gyp": "0.10.x" + "node-gyp": "3.0.x" }, "license": "MIT", "engines": { "node": ">=0.10" }, "dependencies": { - "nan": "^1.7.0" + "nan": "^2.0.x" } }