diff --git a/README.md b/README.md
index 4840522..1e9b8fb 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,9 @@ html-metadata
# MetaData html scraper and parser for Node.js (supports Promises and callback style)
-The aim of this library is to be a comprehensive source for extracting all html embedded metadata. Currently it supports Schema.org microdata using a third party library, a native BEPress, Dublin Core, Highwire Press, Open Graph, EPrints, and COinS implementation, and some general metadata that doesn't belong to a particular standard (for instance, the content of the title tag, or meta description tags).
+The aim of this library is to be a comprehensive source for extracting all html embedded metadata. Currently it supports Schema.org microdata using a third party library, a native BEPress, Dublin Core, Highwire Press, Open Graph, Twitter, EPrints, and COinS implementation, and some general metadata that doesn't belong to a particular standard (for instance, the content of the title tag, or meta description tags).
-Planned is support for RDFa, Twitter, AGLS, and other yet unheard of metadata types. Contributions and requests for other metadata types welcome!
+Planned is support for RDFa, AGLS, and other yet unheard of metadata types. Contributions and requests for other metadata types welcome!
## Install
diff --git a/index.js b/index.js
index 2ca1005..84dd8bf 100644
--- a/index.js
+++ b/index.js
@@ -143,6 +143,17 @@ exports.parseSchemaOrgMicrodata = function(chtml, callback){
return index.parseSchemaOrgMicrodata(chtml).nodeify(callback);
};
+/**
+ * Scrapes Twitter data given html object
+ *
+ * @param {Object} chtml html Cheerio object
+ * @param {Function} [callback] optional callback function
+ * @return {Object} BBPromise for metadata
+ */
+exports.parseTwitter = function(chtml, callback){
+ return index.parseTwitter(chtml).nodeify(callback);
+};
+
/**
* Global exportable list of scraping promises with string keys
* @type {Object}
diff --git a/lib/index.js b/lib/index.js
index 05f00fd..33d7254 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -448,6 +448,102 @@ exports.parseSchemaOrgMicrodata = BBPromise.method(function(chtml){
return meta;
});
+
+/**
+ * Scrapes twitter microdata given Cheerio html object
+ * @param {Object} chtml html Cheerio object
+ * @return {Object} promise of twitter metadata object
+ */
+exports.parseTwitter = BBPromise.method(function(chtml) {
+ if (!chtml) {
+ throw new Error('Undefined argument');
+ }
+
+ var meta = {};
+ var metaTags = chtml('meta');
+
+ // These properties can either be strings or objects
+ var dualStateSubProperties = {
+ image : 'url',
+ player : 'url',
+ creator : '@username'
+ };
+
+ metaTags.each(function() {
+ var element = chtml(this);
+ var propertyValue = element.attr('name');
+
+ var property;
+ var content = element.attr('content');
+ var node;
+
+ // Exit if not a twitter tag
+ if (!propertyValue){
+ return;
+ } else {
+ propertyValue = propertyValue.toLowerCase().split(':');
+ property = propertyValue[1];
+ }
+
+ // Exit if tag not twitter metadata
+ if(propertyValue[0] !== 'twitter') {
+ return;
+ }
+
+ // Handle nested properties
+ if(propertyValue.length > 2) {
+ var subProperty = propertyValue[2];
+
+ // Upgrade the property to an object if it needs to be
+ if(property in dualStateSubProperties && !(meta[property] instanceof Object)) {
+ node = {};
+ node[dualStateSubProperties[property]] = meta[property];
+ meta[property] = []; // Clear out the existing string as we just placed it into our new node
+ }else {
+ node = meta[property] ? meta[property] : {}; // Either create a new node or ammend the existing one
+ }
+
+ // Differentiate betweeen twice and thrice nested properties
+ // Not the prettiest solution, but twitter metadata guidelines are fairly strict so it's not nessesary
+ // to anticipate strange data.
+ if(propertyValue.length === 3) {
+ node[subProperty] = content;
+ } else if (propertyValue.length === 4) {
+ // Solve the very specific twitter:player:stream:content_type case where stream needs to be upgraded to an object
+ if(subProperty.toLowerCase() === "stream"){
+ node[subProperty] = {url: node[subProperty] };
+ }else {
+ node[subProperty] = node[subProperty] ? node[subProperty] : {}; //Either create a new subnode or ammend the existing one
+ }
+ node[subProperty][propertyValue[3]] = content;
+ } else {
+ // Something is malformed, so exit
+ return;
+ }
+ }else {
+ node = content;
+ }
+
+ // Create array if property exists and is not a nested object
+ if(meta[property] && !(meta[property] instanceof Object)) {
+ if (meta[property] instanceof Array) {
+ meta[property].push(node);
+ } else {
+ meta[property] = [meta[property], node];
+ }
+ }else {
+ meta[property] = node;
+ }
+ });
+
+ if(Object.keys(meta).length === 0) {
+ throw new Error("No twitter metadata found on this page");
+ }
+
+ return meta;
+});
+
+
/**
* Global exportable list of scraping promises with string keys
* @type {Object}
@@ -460,5 +556,6 @@ exports.metadataFunctions = {
'general': exports.parseGeneral,
'highwirePress': exports.parseHighwirePress,
'openGraph': exports.parseOpenGraph,
- 'schemaOrg': exports.parseSchemaOrgMicrodata
+ 'schemaOrg': exports.parseSchemaOrgMicrodata,
+ 'twitter': exports.parseTwitter
};
diff --git a/package.json b/package.json
index b0a3a20..9298175 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "html-metadata",
- "version": "1.4.4",
+ "version": "1.5.0",
"description": "Scrapes metadata of several different standards",
"main": "index.js",
"dependencies": {
diff --git a/test/errors.js b/test/errors.js
index baab186..33c0211 100644
--- a/test/errors.js
+++ b/test/errors.js
@@ -88,6 +88,16 @@ describe('errors', function() {
});
});
+ it('should not find twitter metadata, reject promise', function() {
+ var url = 'http://example.com';
+ return preq.get(url)
+ .then(function(callRes) {
+ var $ = cheerio.load(callRes.body);
+ var prom = meta.parseTwitter($);
+ return assert.fails(prom);
+ });
+ });
+
//TODO: Add test for lacking general metadata
//TODO: Add test for lacking any metadata
diff --git a/test/scraping.js b/test/scraping.js
index efc02e7..edd1411 100644
--- a/test/scraping.js
+++ b/test/scraping.js
@@ -16,7 +16,7 @@ var cheerio = require('cheerio');
describe('scraping', function() {
- this.timeout(40000);
+ this.timeout(50000);
var url;
@@ -144,4 +144,29 @@ describe('scraping', function() {
});
});
+ describe('twitter tests', function() {
+ it('should get most basic twitter info', function() {
+ url = 'http://www.aftenposten.no/kultur/Pinlig-for-Skaber-555558b.html';
+ return meta(url)
+ .catch(function(e){throw e;})
+ .then(function(res) {
+ ['card', 'site', 'description', 'title', 'image'].forEach(function(key) {
+ if(!res.twitter[key]) {
+ throw new Error('Expected to find the ' + key + ' key in the response!');
+ }
+ });
+ });
+ });
+
+ it('should get twitter nested data correctly', function() {
+ url = 'http://www.theguardian.com/us';
+ return meta(url)
+ .catch(function(e){throw e;})
+ .then(function(res) {
+ var expected = '{"app":{"id":{"iphone":"409128287","ipad":"409128287","googleplay":"com.guardian"},"name":{"googleplay":"The Guardian","ipad":"The Guardian","iphone":"The Guardian"},"url":{"ipad":"gnmguardian://us?contenttype=front&source=twitter","iphone":"gnmguardian://us?contenttype=front&source=twitter"}},"site":"@guardian","card":"summary","url":"https://www.theguardian.com/us"}';
+ assert.deepEqual(JSON.stringify(res.twitter), expected);
+ });
+ });
+ });
+
});
diff --git a/test/static.js b/test/static.js
index bbdacae..f3425b1 100644
--- a/test/static.js
+++ b/test/static.js
@@ -17,7 +17,7 @@ describe('static files', function() {
var expected;
it('should get correct info from turtle movie file', function() {
- expected = {"dublinCore":{"title":"Turtles of the Jungle","creator":"http://www.example.com/turtlelvr","description":"A 2008 film about jungle turtles.","date":"2012-02-04 12:00:00","type":"Image.Moving"},"general":{"author":"Turtle Lvr","authorlink":"http://examples.com/turtlelvr","canonical":"http://example.com/turtles","description":"Exposition on the awesomeness of turtles","publisher":"https://mediawiki.org","robots":"we welcome our robot overlords","shortlink":"http://example.com/c","title":"Turtles are AWESOME!!1 | Awesome Turtles Website", "lang":"en"},"openGraph":{"locale":"en_US","type":"video.movie","title":"Turtles of the Jungle","description":"A 2008 film about jungle turtles.","url":"http://example.com","site_name":"Awesome Turtle Movies Website","image":[{"url":"http://example.com/turtle.jpg"},{"url":"http://example.com/shell.jpg"}],"tag":["turtle","movie","awesome"],"director":"http://www.example.com/PhilTheTurtle","actor":["http://www.example.com/PatTheTurtle","http://www.example.com/SaminaTheTurtle"],"writer":"http://www.example.com/TinaTheTurtle","release_date":"2015-01-14T19:14:27+00:00","duration":"1000000"}};
+ expected = {"dublinCore":{"title":"Turtles of the Jungle","creator":"http://www.example.com/turtlelvr","description":"A 2008 film about jungle turtles.","date":"2012-02-04 12:00:00","type":"Image.Moving"},"general":{"author":"Turtle Lvr","authorlink":"http://examples.com/turtlelvr","canonical":"http://example.com/turtles","description":"Exposition on the awesomeness of turtles","publisher":"https://mediawiki.org","robots":"we welcome our robot overlords","shortlink":"http://example.com/c","title":"Turtles are AWESOME!!1 | Awesome Turtles Website", "lang":"en"},"openGraph":{"locale":"en_US","type":"video.movie","title":"Turtles of the Jungle","description":"A 2008 film about jungle turtles.","url":"http://example.com","site_name":"Awesome Turtle Movies Website","image":[{"url":"http://example.com/turtle.jpg"},{"url":"http://example.com/shell.jpg"}],"tag":["turtle","movie","awesome"],"director":"http://www.example.com/PhilTheTurtle","actor":["http://www.example.com/PatTheTurtle","http://www.example.com/SaminaTheTurtle"],"writer":"http://www.example.com/TinaTheTurtle","release_date":"2015-01-14T19:14:27+00:00","duration":"1000000"},"twitter":{"card":"summary","site":"@Turtlessssssssss","creator":"@Turtlessssssssss","url":"http://www.example.com/turtles","title":"Turtles of the Jungle","description":"A 2008 film about jungle turtles.","player":{"url":"http://www.example.com/turtles/player","width":"400","height":"400","stream":{"url":"http://www.example.com/turtles/turtle.mp4","content_type":"video/mp4"}}}};
$ = cheerio.load(fs.readFileSync('./test/static/turtle_movie.html'));
return meta.parseAll($).then(function(results){
assert.deepEqual(results, expected);
@@ -25,7 +25,7 @@ describe('static files', function() {
});
it('should get correct info from turtle article file', function() {
- expected = {"bePress":{"series_title":"Turtles","author":"Turtle Lvr","author_institution":"Mediawiki","title":"Turtles are AWESOME!!1","date":"2012","pdf_url":"http://www.example.com/turtlelvr/pdf","abstract_html_url":"http://www.example.com/turtlelvr","publisher":"Turtles Society","online_date":"2012/02/04"},"coins":[{"ctx_ver":"Z39.88-2004","rft_id":"info:doi/http://dx.doi.org/10.5555/12345678","rfr_id":"info:sid/crossref.org:search","rft_val_fmt":"info:ofi/fmt:kev:mtx:journal","rft":{"atitle":"Toward a Unified Theory of High-Energy Metaphysics: Silly String Theory","jtitle":"Journal of Psychoceramics","date":"2008","volume":"5","issue":"11","spage":"1","epage":"3","aufirst":"Josiah","aulast":"Carberry","genre":"article","au":["Josiah Carberry"]}}],"dublinCore":{"title":"Turtles are AWESOME!!1","creator":"http://www.example.com/turtlelvr","description":"Exposition on the awesomeness of turtles","date":"2012-02-04 12:00:00","type":"Text.Article"},"general":{"author":"Turtle Lvr","authorlink":"http://examples.com/turtlelvr","canonical":"http://example.com/turtles","description":"Exposition on the awesomeness of turtles","publisher":"https://mediawiki.org","robots":"we welcome our robot overlords","shortlink":"http://example.com/c","title":"Turtles are AWESOME!!1 | Awesome Turtles Website", "lang":"en"},"highwirePress":{"journal_title":"Turtles","issn":"1234-5678","doi":"10.1000/123","publication_date":"2012-02-04","title":"Turtles are AWESOME!!1","author":"Turtle Lvr","author_institution":"Mediawiki","volume":"150","issue":"1","firstpage":"123","lastpage":"456","publisher":"Turtles Society","abstract":"Exposition on the awesomeness of turtles."},"openGraph":{"locale":"en_US","type":"article","title":"Turtles are AWESOME!!1","description":"Exposition on the awesomeness of turtles","url":"http://example.com","site_name":"Awesome Turtles Website","image":[{"url":"http://example.com/turtle.jpg","secure_url":"https://secure.example.com/turtle.jpg","type":"image/jpeg","width":"400","height":"300"},{"url":"http://example.com/shell.jpg","width":"200","height":"150"}],"audio":{"url":"http://example.com/sound.mp3","secure_url":"https://secure.example.com/sound.mp3","type":"audio/mpeg"},"tag":["turtles","are","awesome"],"section":["Turtles are tough","Turtles are flawless","Turtles are cute"],"published_time":"2012-02-04T12:00:00+00:00","modified_time":"2015-01-14T19:14:27+00:00","author":"http://examples.com/turtlelvr","publisher":"http://mediawiki.org"},"eprints":{"title":"Turtles are AWESOME!!1","creators_name":"http://www.example.com/turtlelvr","abstract":"Exposition on the awesomeness of turtles","datestamp":"2012-02-04 12:00:00","type":"article"}};
+ expected = {"bePress":{"series_title":"Turtles","author":"Turtle Lvr","author_institution":"Mediawiki","title":"Turtles are AWESOME!!1","date":"2012","pdf_url":"http://www.example.com/turtlelvr/pdf","abstract_html_url":"http://www.example.com/turtlelvr","publisher":"Turtles Society","online_date":"2012/02/04"},"coins":[{"ctx_ver":"Z39.88-2004","rft_id":"info:doi/http://dx.doi.org/10.5555/12345678","rfr_id":"info:sid/crossref.org:search","rft_val_fmt":"info:ofi/fmt:kev:mtx:journal","rft":{"atitle":"Toward a Unified Theory of High-Energy Metaphysics: Silly String Theory","jtitle":"Journal of Psychoceramics","date":"2008","volume":"5","issue":"11","spage":"1","epage":"3","aufirst":"Josiah","aulast":"Carberry","genre":"article","au":["Josiah Carberry"]}}],"dublinCore":{"title":"Turtles are AWESOME!!1","creator":"http://www.example.com/turtlelvr","description":"Exposition on the awesomeness of turtles","date":"2012-02-04 12:00:00","type":"Text.Article"},"general":{"author":"Turtle Lvr","authorlink":"http://examples.com/turtlelvr","canonical":"http://example.com/turtles","description":"Exposition on the awesomeness of turtles","publisher":"https://mediawiki.org","robots":"we welcome our robot overlords","shortlink":"http://example.com/c","title":"Turtles are AWESOME!!1 | Awesome Turtles Website", "lang":"en"},"highwirePress":{"journal_title":"Turtles","issn":"1234-5678","doi":"10.1000/123","publication_date":"2012-02-04","title":"Turtles are AWESOME!!1","author":"Turtle Lvr","author_institution":"Mediawiki","volume":"150","issue":"1","firstpage":"123","lastpage":"456","publisher":"Turtles Society","abstract":"Exposition on the awesomeness of turtles."},"openGraph":{"locale":"en_US","type":"article","title":"Turtles are AWESOME!!1","description":"Exposition on the awesomeness of turtles","url":"http://example.com","site_name":"Awesome Turtles Website","image":[{"url":"http://example.com/turtle.jpg","secure_url":"https://secure.example.com/turtle.jpg","type":"image/jpeg","width":"400","height":"300"},{"url":"http://example.com/shell.jpg","width":"200","height":"150"}],"audio":{"url":"http://example.com/sound.mp3","secure_url":"https://secure.example.com/sound.mp3","type":"audio/mpeg"},"tag":["turtles","are","awesome"],"section":["Turtles are tough","Turtles are flawless","Turtles are cute"],"published_time":"2012-02-04T12:00:00+00:00","modified_time":"2015-01-14T19:14:27+00:00","author":"http://examples.com/turtlelvr","publisher":"http://mediawiki.org"},"eprints":{"title":"Turtles are AWESOME!!1","creators_name":"http://www.example.com/turtlelvr","abstract":"Exposition on the awesomeness of turtles","datestamp":"2012-02-04 12:00:00","type":"article"},"twitter":{"card":"summary","site":"@Turtlessssssssss","creator":["@Turtlessssssssss","@Turtlezzzzzzzzzz"],"url":"http://www.example.com/turtles","title":"Turtles are AWESOME!!1","description":"Exposition on the awesomeness of turtles","image":{"url":"http://example.com/turtles.jpg","alt":"It's a bunch of turtles!"},"app":{"url":{"iphone":"turtle://","googleplay":"turtle://"},"id":{"iphone":"000","googleplay":"superturtlearticle.androidapp"}}}};
$ = cheerio.load(fs.readFileSync('./test/static/turtle_article.html'));
return meta.parseAll($).then(function(results){
assert.deepEqual(results, expected);
@@ -33,7 +33,7 @@ describe('static files', function() {
});
it('should be case insensitive on Turtle Article file', function() {
- expected = {"bePress":{"series_title":"Turtles","author":"Turtle Lvr","author_institution":"Mediawiki","title":"Turtles are AWESOME!!1","date":"2012","pdf_url":"http://www.example.com/turtlelvr/pdf","abstract_html_url":"http://www.example.com/turtlelvr","publisher":"Turtles Society","online_date":"2012/02/04"},"coins":[{"ctx_ver":"Z39.88-2004","rft_id":"info:doi/http://dx.doi.org/10.5555/12345678","rfr_id":"info:sid/crossref.org:search","rft_val_fmt":"info:ofi/fmt:kev:mtx:journal","rft":{"atitle":"Toward a Unified Theory of High-Energy Metaphysics: Silly String Theory","jtitle":"Journal of Psychoceramics","date":"2008","volume":"5","issue":"11","spage":"1","epage":"3","aufirst":"Josiah","aulast":"Carberry","genre":"article","au":["Josiah Carberry"]}}],"dublinCore":{"title":"Turtles are AWESOME!!1","creator":"http://www.example.com/turtlelvr","description":"Exposition on the awesomeness of turtles","date":"2012-02-04 12:00:00","type":"Text.Article"},"general":{"author":"Turtle Lvr","authorlink":"http://examples.com/turtlelvr","canonical":"http://example.com/turtles","description":"Exposition on the awesomeness of turtles","publisher":"https://mediawiki.org","robots":"we welcome our robot overlords","shortlink":"http://example.com/c","title":"Turtles are AWESOME!!1 | Awesome Turtles Website", "lang":"en"},"highwirePress":{"journal_title":"Turtles","issn":"1234-5678","doi":"10.1000/123","publication_date":"2012-02-04","title":"Turtles are AWESOME!!1","author":"Turtle Lvr","author_institution":"Mediawiki","volume":"150","issue":"1","firstpage":"123","lastpage":"456","publisher":"Turtles Society","abstract":"Exposition on the awesomeness of turtles."},"openGraph":{"locale":"en_US","type":"article","title":"Turtles are AWESOME!!1","description":"Exposition on the awesomeness of turtles","url":"http://example.com","site_name":"Awesome Turtles Website","image":[{"url":"http://example.com/turtle.jpg","secure_url":"https://secure.example.com/turtle.jpg","type":"image/jpeg","width":"400","height":"300"},{"url":"http://example.com/shell.jpg","width":"200","height":"150"}],"audio":{"url":"http://example.com/sound.mp3","secure_url":"https://secure.example.com/sound.mp3","type":"audio/mpeg"},"tag":["turtles","are","awesome"],"section":["Turtles are tough","Turtles are flawless","Turtles are cute"],"published_time":"2012-02-04T12:00:00+00:00","modified_time":"2015-01-14T19:14:27+00:00","author":"http://examples.com/turtlelvr","publisher":"http://mediawiki.org"},"eprints":{"title":"Turtles are AWESOME!!1","creators_name":"http://www.example.com/turtlelvr","abstract":"Exposition on the awesomeness of turtles","datestamp":"2012-02-04 12:00:00","type":"article"}};
+ expected = {"bePress":{"series_title":"Turtles","author":"Turtle Lvr","author_institution":"Mediawiki","title":"Turtles are AWESOME!!1","date":"2012","pdf_url":"http://www.example.com/turtlelvr/pdf","abstract_html_url":"http://www.example.com/turtlelvr","publisher":"Turtles Society","online_date":"2012/02/04"},"coins":[{"ctx_ver":"Z39.88-2004","rft_id":"info:doi/http://dx.doi.org/10.5555/12345678","rfr_id":"info:sid/crossref.org:search","rft_val_fmt":"info:ofi/fmt:kev:mtx:journal","rft":{"atitle":"Toward a Unified Theory of High-Energy Metaphysics: Silly String Theory","jtitle":"Journal of Psychoceramics","date":"2008","volume":"5","issue":"11","spage":"1","epage":"3","aufirst":"Josiah","aulast":"Carberry","genre":"article","au":["Josiah Carberry"]}}],"dublinCore":{"title":"Turtles are AWESOME!!1","creator":"http://www.example.com/turtlelvr","description":"Exposition on the awesomeness of turtles","date":"2012-02-04 12:00:00","type":"Text.Article"},"general":{"author":"Turtle Lvr","authorlink":"http://examples.com/turtlelvr","canonical":"http://example.com/turtles","description":"Exposition on the awesomeness of turtles","publisher":"https://mediawiki.org","robots":"we welcome our robot overlords","shortlink":"http://example.com/c","title":"Turtles are AWESOME!!1 | Awesome Turtles Website", "lang":"en"},"highwirePress":{"journal_title":"Turtles","issn":"1234-5678","doi":"10.1000/123","publication_date":"2012-02-04","title":"Turtles are AWESOME!!1","author":"Turtle Lvr","author_institution":"Mediawiki","volume":"150","issue":"1","firstpage":"123","lastpage":"456","publisher":"Turtles Society","abstract":"Exposition on the awesomeness of turtles."},"openGraph":{"locale":"en_US","type":"article","title":"Turtles are AWESOME!!1","description":"Exposition on the awesomeness of turtles","url":"http://example.com","site_name":"Awesome Turtles Website","image":[{"url":"http://example.com/turtle.jpg","secure_url":"https://secure.example.com/turtle.jpg","type":"image/jpeg","width":"400","height":"300"},{"url":"http://example.com/shell.jpg","width":"200","height":"150"}],"audio":{"url":"http://example.com/sound.mp3","secure_url":"https://secure.example.com/sound.mp3","type":"audio/mpeg"},"tag":["turtles","are","awesome"],"section":["Turtles are tough","Turtles are flawless","Turtles are cute"],"published_time":"2012-02-04T12:00:00+00:00","modified_time":"2015-01-14T19:14:27+00:00","author":"http://examples.com/turtlelvr","publisher":"http://mediawiki.org"},"eprints":{"title":"Turtles are AWESOME!!1","creators_name":"http://www.example.com/turtlelvr","abstract":"Exposition on the awesomeness of turtles","datestamp":"2012-02-04 12:00:00","type":"article"},"twitter":{"card":"summary","site":"@Turtlessssssssss","creator":["@Turtlessssssssss","@Turtlezzzzzzzzzz"],"url":"http://www.example.com/turtles","title":"Turtles are AWESOME!!1","description":"Exposition on the awesomeness of turtles","image":{"url":"http://example.com/turtles.jpg","alt":"It's a bunch of turtles!"},"app":{"url":{"iphone":"turtle://","googleplay":"turtle://"},"id":{"iphone":"000","googleplay":"superturtlearticle.androidapp"}}}};
$ = cheerio.load(fs.readFileSync('./test/static/Turtle_Article.html'));
return meta.parseAll($).then(function(results){
assert.deepEqual(results, expected);
diff --git a/test/static/Turtle_Article.html b/test/static/Turtle_Article.html
index ff433f1..56ceb53 100644
--- a/test/static/Turtle_Article.html
+++ b/test/static/Turtle_Article.html
@@ -71,9 +71,16 @@
+
+
+
+
+
+
+
diff --git a/test/static/turtle_article.html b/test/static/turtle_article.html
index 20f4ab2..4b71765 100644
--- a/test/static/turtle_article.html
+++ b/test/static/turtle_article.html
@@ -69,9 +69,16 @@
+
+
+
+
+
+
+
diff --git a/test/static/turtle_movie.html b/test/static/turtle_movie.html
index de2b9c4..0a598b4 100644
--- a/test/static/turtle_movie.html
+++ b/test/static/turtle_movie.html
@@ -55,6 +55,11 @@
+
+
+
+
+