mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-13 22:41:32 -05:00
Sort newest to oldest in sitemap files
Closes #4611 Refactored generateXmlFromNodes to pull the urlElements itself from sorted values in the lookup Added some checks to existing unit tests to validate ordering.
This commit is contained in:
parent
8906f794c7
commit
ef16c67a15
2 changed files with 73 additions and 19 deletions
|
@ -19,6 +19,7 @@ XMLNS_DECLS = {
|
||||||
function BaseSiteMapGenerator() {
|
function BaseSiteMapGenerator() {
|
||||||
this.lastModified = 0;
|
this.lastModified = 0;
|
||||||
this.nodeLookup = {};
|
this.nodeLookup = {};
|
||||||
|
this.nodeTimeLookup = {};
|
||||||
this.siteMapContent = '';
|
this.siteMapContent = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,11 +54,11 @@ _.extend(BaseSiteMapGenerator.prototype, {
|
||||||
return _.map(data, function (datum) {
|
return _.map(data, function (datum) {
|
||||||
var node = self.createUrlNodeFromDatum(datum, permalinks);
|
var node = self.createUrlNodeFromDatum(datum, permalinks);
|
||||||
self.updateLastModified(datum);
|
self.updateLastModified(datum);
|
||||||
self.nodeLookup[datum.id] = node;
|
self.updateLookups(datum, node);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
});
|
});
|
||||||
}).then(self.generateXmlFromNodes);
|
}).then(this.generateXmlFromNodes.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
getPermalinksValue: function () {
|
getPermalinksValue: function () {
|
||||||
|
@ -77,14 +78,28 @@ _.extend(BaseSiteMapGenerator.prototype, {
|
||||||
this.permalinks = permalinks;
|
this.permalinks = permalinks;
|
||||||
|
|
||||||
// Re-generate xml with new permalinks values
|
// Re-generate xml with new permalinks values
|
||||||
this.updateXmlFromNodes(_.values(this.nodeLookup));
|
this.updateXmlFromNodes();
|
||||||
},
|
},
|
||||||
|
|
||||||
generateXmlFromNodes: function (urlElements) {
|
generateXmlFromNodes: function () {
|
||||||
var data = {
|
var self = this,
|
||||||
// Concat the elements to the _attr declaration
|
// Get a mapping of node to timestamp
|
||||||
urlset: [XMLNS_DECLS].concat(urlElements)
|
timedNodes = _.map(this.nodeLookup, function (node, id) {
|
||||||
};
|
return {
|
||||||
|
id: id,
|
||||||
|
// Using negative here to sort newest to oldest
|
||||||
|
ts: -(self.nodeTimeLookup[id] || 0),
|
||||||
|
node: node
|
||||||
|
};
|
||||||
|
}, []),
|
||||||
|
// Sort nodes by timestamp
|
||||||
|
sortedNodes = _.sortBy(timedNodes, 'ts'),
|
||||||
|
// Grab just the nodes
|
||||||
|
urlElements = _.pluck(sortedNodes, 'node'),
|
||||||
|
data = {
|
||||||
|
// Concat the elements to the _attr declaration
|
||||||
|
urlset: [XMLNS_DECLS].concat(urlElements)
|
||||||
|
};
|
||||||
|
|
||||||
// Return the xml
|
// Return the xml
|
||||||
return utils.getDeclarations() + xml(data);
|
return utils.getDeclarations() + xml(data);
|
||||||
|
@ -103,19 +118,18 @@ _.extend(BaseSiteMapGenerator.prototype, {
|
||||||
return this.getPermalinksValue().then(function (permalinks) {
|
return this.getPermalinksValue().then(function (permalinks) {
|
||||||
var node = self.createUrlNodeFromDatum(datum, permalinks);
|
var node = self.createUrlNodeFromDatum(datum, permalinks);
|
||||||
self.updateLastModified(datum);
|
self.updateLastModified(datum);
|
||||||
self.nodeLookup[datum.id] = node;
|
self.updateLookups(datum, node);
|
||||||
|
|
||||||
return self.updateXmlFromNodes(_.values(self.nodeLookup));
|
return self.updateXmlFromNodes();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeUrl: function (datum) {
|
removeUrl: function (datum) {
|
||||||
var lookup = this.nodeLookup;
|
this.removeFromLookups(datum);
|
||||||
delete lookup[datum.id];
|
|
||||||
|
|
||||||
this.lastModified = Date.now();
|
this.lastModified = Date.now();
|
||||||
|
|
||||||
return this.updateXmlFromNodes(_.values(lookup));
|
return this.updateXmlFromNodes();
|
||||||
},
|
},
|
||||||
|
|
||||||
updateUrl: function (datum) {
|
updateUrl: function (datum) {
|
||||||
|
@ -124,9 +138,9 @@ _.extend(BaseSiteMapGenerator.prototype, {
|
||||||
var node = self.createUrlNodeFromDatum(datum, permalinks);
|
var node = self.createUrlNodeFromDatum(datum, permalinks);
|
||||||
self.updateLastModified(datum);
|
self.updateLastModified(datum);
|
||||||
// TODO: Check if the node values changed, and if not don't regenerate
|
// TODO: Check if the node values changed, and if not don't regenerate
|
||||||
self.nodeLookup[datum.id] = node;
|
self.updateLookups(datum, node);
|
||||||
|
|
||||||
return self.updateXmlFromNodes(_.values(self.nodeLookup));
|
return self.updateXmlFromNodes();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -142,6 +156,10 @@ _.extend(BaseSiteMapGenerator.prototype, {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getLastModifiedForDatum: function (datum) {
|
||||||
|
return datum.updated_at || datum.published_at || datum.created_at;
|
||||||
|
},
|
||||||
|
|
||||||
createUrlNodeFromDatum: function (datum, permalinks) {
|
createUrlNodeFromDatum: function (datum, permalinks) {
|
||||||
var url = this.getUrlForDatum(datum, permalinks),
|
var url = this.getUrlForDatum(datum, permalinks),
|
||||||
priority = this.getPriorityForDatum(datum);
|
priority = this.getPriorityForDatum(datum);
|
||||||
|
@ -149,7 +167,7 @@ _.extend(BaseSiteMapGenerator.prototype, {
|
||||||
return {
|
return {
|
||||||
url: [
|
url: [
|
||||||
{loc: url},
|
{loc: url},
|
||||||
{lastmod: moment(datum.updated_at || datum.published_at || datum.created_at).toISOString()},
|
{lastmod: moment(this.getLastModifiedForDatum(datum)).toISOString()},
|
||||||
{changefreq: CHANGE_FREQ},
|
{changefreq: CHANGE_FREQ},
|
||||||
{priority: priority}
|
{priority: priority}
|
||||||
]
|
]
|
||||||
|
@ -161,11 +179,24 @@ _.extend(BaseSiteMapGenerator.prototype, {
|
||||||
},
|
},
|
||||||
|
|
||||||
updateLastModified: function (datum) {
|
updateLastModified: function (datum) {
|
||||||
var lastModified = datum.updated_at || datum.published_at || datum.created_at;
|
var lastModified = this.getLastModifiedForDatum(datum);
|
||||||
|
|
||||||
if (lastModified > this.lastModified) {
|
if (lastModified > this.lastModified) {
|
||||||
this.lastModified = lastModified;
|
this.lastModified = lastModified;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateLookups: function (datum, node) {
|
||||||
|
this.nodeLookup[datum.id] = node;
|
||||||
|
this.nodeTimeLookup[datum.id] = this.getLastModifiedForDatum(datum);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeFromLookups: function (datum) {
|
||||||
|
var lookup = this.nodeLookup;
|
||||||
|
delete lookup[datum.id];
|
||||||
|
|
||||||
|
lookup = this.nodeTimeLookup;
|
||||||
|
delete lookup[datum.id];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -384,6 +384,10 @@ describe('Sitemap', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
generator.init().then(function () {
|
generator.init().then(function () {
|
||||||
|
var idxFirst,
|
||||||
|
idxSecond,
|
||||||
|
idxThird;
|
||||||
|
|
||||||
should.exist(generator.siteMapContent);
|
should.exist(generator.siteMapContent);
|
||||||
|
|
||||||
// TODO: We should validate the contents against the XSD:
|
// TODO: We should validate the contents against the XSD:
|
||||||
|
@ -397,6 +401,14 @@ describe('Sitemap', function () {
|
||||||
validator.contains(generator.siteMapContent,
|
validator.contains(generator.siteMapContent,
|
||||||
'<loc>http://my-ghost-blog.com/url/300</loc>').should.equal(true);
|
'<loc>http://my-ghost-blog.com/url/300</loc>').should.equal(true);
|
||||||
|
|
||||||
|
// Validate order newest to oldest
|
||||||
|
idxFirst = generator.siteMapContent.indexOf('<loc>http://my-ghost-blog.com/url/300</loc>');
|
||||||
|
idxSecond = generator.siteMapContent.indexOf('<loc>http://my-ghost-blog.com/url/200</loc>');
|
||||||
|
idxThird = generator.siteMapContent.indexOf('<loc>http://my-ghost-blog.com/url/100</loc>');
|
||||||
|
|
||||||
|
idxFirst.should.be.below(idxSecond);
|
||||||
|
idxSecond.should.be.below(idxThird);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -442,12 +454,15 @@ describe('Sitemap', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
generator.init().then(function () {
|
generator.init().then(function () {
|
||||||
|
var idxFirst,
|
||||||
|
idxSecond,
|
||||||
|
idxThird;
|
||||||
|
|
||||||
should.exist(generator.siteMapContent);
|
should.exist(generator.siteMapContent);
|
||||||
|
|
||||||
// TODO: We should validate the contents against the XSD:
|
// TODO: We should validate the contents against the XSD:
|
||||||
// xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
// xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
// xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
|
// xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
|
||||||
// http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
|
|
||||||
|
|
||||||
validator.contains(generator.siteMapContent,
|
validator.contains(generator.siteMapContent,
|
||||||
'<loc>http://my-ghost-blog.com/url/100</loc>').should.equal(true);
|
'<loc>http://my-ghost-blog.com/url/100</loc>').should.equal(true);
|
||||||
|
@ -467,6 +482,14 @@ describe('Sitemap', function () {
|
||||||
'<image:loc>http://my-ghost-blog.com/images/post-300.jpg</image:loc>')
|
'<image:loc>http://my-ghost-blog.com/images/post-300.jpg</image:loc>')
|
||||||
.should.equal(true);
|
.should.equal(true);
|
||||||
|
|
||||||
|
// Validate order newest to oldest
|
||||||
|
idxFirst = generator.siteMapContent.indexOf('<loc>http://my-ghost-blog.com/url/300</loc>');
|
||||||
|
idxSecond = generator.siteMapContent.indexOf('<loc>http://my-ghost-blog.com/url/200</loc>');
|
||||||
|
idxThird = generator.siteMapContent.indexOf('<loc>http://my-ghost-blog.com/url/100</loc>');
|
||||||
|
|
||||||
|
idxFirst.should.be.below(idxSecond);
|
||||||
|
idxSecond.should.be.below(idxThird);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue