Skip to content

Commit

Permalink
Merge pull request #18 from karlwestin/fix/update-nan
Browse files Browse the repository at this point in the history
Fix/update nan
  • Loading branch information
karlwestin committed Sep 30, 2015
2 parents 92a9426 + e97d3a9 commit df78752
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 89 deletions.
14 changes: 14 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -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:
Expand Down
188 changes: 103 additions & 85 deletions node-gumbo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,26 @@ Local<Object> read_element(GumboNode* node);
Local<Object> read_attribute(GumboAttribute* attr);
Local<Object> read_document(GumboNode* node);

void record_location(Local<Object> node, GumboSourcePosition* pos, const char* name) {
Local<Object> position = NanNew<Object>();
position->Set(NanNew<String>("line"),
NanNew<Number>(pos->line));
position->Set(NanNew<String>("column"),
NanNew<Number>(pos->column));
position->Set(NanNew<String>("offset"),
NanNew<Number>(pos->offset));
node->Set(NanNew<String>(name), position);
void record_location(v8::Local<Object> node, GumboSourcePosition* pos, const char* name) {
v8::Local<Object> position = Nan::New<v8::Object>();
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<Object> read_attribute(GumboAttribute* attr) {
Local<Object> obj = NanNew<Object>();
obj->Set(NanNew<String>("nodeType"), NanNew<Integer>(2));
obj->Set(NanNew<String>("name"), NanNew(attr->name));
obj->Set(NanNew<String>("value"), NanNew(attr->value));
v8::Local<Object> obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), Nan::New<Integer>(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");
Expand All @@ -52,100 +56,112 @@ Handle<Value> get_tag_namespace(GumboNamespaceEnum tag_namespace) {
namespace_name = "MATHML";
break;
default:
NanThrowTypeError("Unknown tag namespace");
Nan::ThrowTypeError("Unknown tag namespace");
}

return NanNew<String>(namespace_name);
return Nan::New(namespace_name).ToLocalChecked();
}

Local<Object> read_text(GumboNode* node) {
Local<Object> obj = NanNew<Object>();
Local<Integer> type = NanNew<Integer>(3);
Local<String> name;
Local<Object> obj = Nan::New<v8::Object>();
Local<Integer> type = Nan::New<v8::Integer>(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<String>("nodeType"), type);
obj->Set(NanNew<String>("nodeName"), name);
obj->Set(NanNew<String>("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<Object> read_comment(GumboNode* node) {
Local<Object> obj = NanNew<Object>();
obj->Set(NanNew<String>("nodeType"), NanNew<Integer>(8));
obj->Set(NanNew<String>("nodeName"), NanNew("#comment"));
obj->Set(NanNew<String>("textContent"), NanNew(node->v.text.text));
obj->Set(NanNew<String>("nodeValue"), NanNew(node->v.text.text));
Local<Object> obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), Nan::New<v8::Integer>(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<String> 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<Object> read_element(GumboNode* node) {
Local<Object> obj = NanNew<Object>();
Local<String> tag = NanNew(gumbo_normalized_tagname(node->v.element.tag));
Local<Object> obj = Nan::New<v8::Object>();


obj->Set(NanNew<String>("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<String>("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<String> tag = get_tag_name(node);

obj->Set(NanNew<String>("nodeType"), NanNew<Integer>(1));
obj->Set(NanNew<String>("nodeName"), tag);
obj->Set(NanNew<String>("tagName"), tag);
Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), Nan::New<v8::Integer>(1));
Nan::Set(obj, Nan::New("nodeName").ToLocalChecked(), tag);
Nan::Set(obj, Nan::New("tagName").ToLocalChecked(), tag);

obj->Set(NanNew<String>("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<String>("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<String>("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<Array> childNodes = NanNew<Array>(children->length);
Local<Array> childNodes = Nan::New<v8::Array>(children->length);
if(children->length > 0) {
for (unsigned int i = 0; i < children->length; ++i) {
childNodes->Set(i, recursive_search(static_cast<GumboNode*>(children->data[i])));
}
}
obj->Set(NanNew<String>("childNodes"), childNodes);

Nan::Set(obj, Nan::New("childNodes").ToLocalChecked(), childNodes);

GumboVector* attributes = &node->v.element.attributes;
Local<Array> attrs = NanNew<Array>(attributes->length);
Local<Array> attrs = Nan::New<v8::Array>(attributes->length);
if(attributes->length > 0) {
for (unsigned int i = 0; i < attributes->length; ++i) {
attrs->Set(i, read_attribute(static_cast<GumboAttribute*>(attributes->data[i])));
}
}
obj->Set(NanNew<String>("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<String>("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");
Expand All @@ -156,23 +172,23 @@ Local<Object> read_element(GumboNode* node) {

Local<Object> read_document(GumboNode* node) {
GumboDocument* doc = &node->v.document;
Local<Object> obj = NanNew<Object>();
obj->Set(NanNew<String>("nodeType"), NanNew<Integer>(9));
obj->Set(NanNew<String>("nodeName"), NanNew("#document"));
obj->Set(NanNew<String>("hasDoctype"), NanNew<Boolean>(doc->has_doctype));

obj->Set(NanNew<String>("name"), NanNew(doc->name));
obj->Set(NanNew<String>("publicIdentifier"), NanNew(doc->public_identifier));
obj->Set(NanNew<String>("systemIdentifier"), NanNew(doc->system_identifier));
Local<Object> obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New("nodeType").ToLocalChecked(), Nan::New<v8::Integer>(9));
Nan::Set(obj, Nan::New("nodeName").ToLocalChecked(), Nan::New("#document").ToLocalChecked());
Nan::Set(obj, Nan::New("hasDoctype").ToLocalChecked(), Nan::New<v8::Boolean>(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<Array> childNodes = NanNew<Array>(children->length);
Local<Array> childNodes = Nan::New<v8::Array>(children->length);
if(children->length > 0) {
for (unsigned int i = 0; i < children->length; ++i) {
childNodes->Set(i, recursive_search(static_cast<GumboNode*>(children->data[i])));
}
}
obj->Set(NanNew<String>("childNodes"), childNodes);
Nan::Set(obj, Nan::New("childNodes").ToLocalChecked(), childNodes);
return obj;
}

Expand All @@ -198,18 +214,17 @@ Local<Object> recursive_search(GumboNode* node) {
}

NAN_METHOD(Method) {
NanScope();
/*
* getting options
*/
Local<Object> config = Local<Object>::Cast(args[1]);
Local<Value> s_o_f = config->Get(NanNew("stopOnFirstError"));
Local<Object> config = Local<Object>::Cast(info[1]);
Local<Value> 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<Value> t_s = config->Get(NanNew("tabStop"));
Local<Value> t_s = Nan::Get(config, Nan::New("tabStop").ToLocalChecked()).ToLocalChecked();
int tab_stop = 8;
if (t_s->IsNumber()) {
tab_stop = t_s->ToInteger()->Value();
Expand All @@ -218,9 +233,9 @@ NAN_METHOD(Method) {
/*
* getting text
*/
Local<Value> str = args[0];
Local<Value> 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);
Expand All @@ -236,14 +251,16 @@ NAN_METHOD(Method) {
/*
* find out context for fragment parsing
*/
Local<Value> fragment_context = config->Get(NanNew("fragmentContext"));
Local<Value> fragment_namespace = config->Get(NanNew("fragmentNamespace"));
Local<Value> fragment_context = Nan::Get(config, Nan::New("fragmentContext").ToLocalChecked()).ToLocalChecked();
Local<Value> 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) {
Expand All @@ -262,24 +279,25 @@ NAN_METHOD(Method) {

// root points to html tag
// document points to document
Local<Object> ret = NanNew<Object>();
Local<Object> ret = Nan::New<Object>();
if(!fragment) {
Local<Object> doc = recursive_search(output->document);
ret->Set(NanNew<String>("document"), doc);
Nan::Set(ret, Nan::New("document").ToLocalChecked(), doc);
} else {
Local<Object> root = recursive_search(output->root);
ret->Set(NanNew<String>("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<Object> exports) {
exports->Set(NanNew<String>("gumbo"),
NanNew<FunctionTemplate>(Method)->GetFunction());
Nan::Set(exports,
Nan::New("gumbo").ToLocalChecked(),
Nan::New<FunctionTemplate>(Method)->GetFunction());
}

NODE_MODULE(binding, init);
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gumbo-parser",
"version": "0.2.1",
"version": "0.2.2",
"author": "Karl Westin <[email protected]>",
"contributors": [
{
Expand All @@ -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"
}
}

0 comments on commit df78752

Please sign in to comment.