summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/models/summaryArticle.js1
-rw-r--r--lib/modifiers/summary/__tests__/insertArticle.js78
-rw-r--r--lib/modifiers/summary/__tests__/moveArticle.js2
-rw-r--r--lib/modifiers/summary/__tests__/moveArticleAfter.js82
-rw-r--r--lib/modifiers/summary/__tests__/removeArticle.js54
-rw-r--r--lib/modifiers/summary/editArticleRef.js17
-rw-r--r--lib/modifiers/summary/index.js8
-rw-r--r--lib/modifiers/summary/insertArticle.js4
-rw-r--r--lib/modifiers/summary/insertPart.js19
-rw-r--r--lib/modifiers/summary/moveArticle.js63
-rw-r--r--lib/modifiers/summary/moveArticleAfter.js60
-rw-r--r--lib/modifiers/summary/removePart.js15
12 files changed, 337 insertions, 66 deletions
diff --git a/lib/models/summaryArticle.js b/lib/models/summaryArticle.js
index 08baac3..f072e7b 100644
--- a/lib/models/summaryArticle.js
+++ b/lib/models/summaryArticle.js
@@ -54,7 +54,6 @@ SummaryArticle.prototype.getPath = function() {
return undefined;
}
-
var parts = ref.split('#');
var pathname = (parts.length > 1? parts.slice(0, -1).join('#') : ref);
diff --git a/lib/modifiers/summary/__tests__/insertArticle.js b/lib/modifiers/summary/__tests__/insertArticle.js
new file mode 100644
index 0000000..1ee1c8a
--- /dev/null
+++ b/lib/modifiers/summary/__tests__/insertArticle.js
@@ -0,0 +1,78 @@
+var Summary = require('../../../models/summary');
+var SummaryArticle = require('../../../models/summaryArticle');
+var File = require('../../../models/file');
+
+describe('insertArticle', function() {
+ var insertArticle = require('../insertArticle');
+ var summary = Summary.createFromParts(File(), [
+ {
+ articles: [
+ {
+ title: '1.1',
+ path: '1.1'
+ },
+ {
+ title: '1.2',
+ path: '1.2'
+ }
+ ]
+ },
+ {
+ title: 'Part I',
+ articles: [
+ {
+ title: '2.1',
+ path: '2.1',
+ articles: [
+ {
+ title: '2.1.1',
+ path: '2.1.1'
+ },
+ {
+ title: '2.1.2',
+ path: '2.1.2'
+ }
+ ]
+ },
+ {
+ title: '2.2',
+ path: '2.2'
+ }
+ ]
+ }
+ ]);
+
+ it('should insert an article at a given level', function() {
+ var article = SummaryArticle.create({
+ title: 'Inserted'
+ }, 'fake.level');
+
+ var newSummary = insertArticle(summary, article, '2.1.1');
+
+ var inserted = newSummary.getByLevel('2.1.1');
+ var nextOne = newSummary.getByLevel('2.1.2');
+
+ expect(inserted.getTitle()).toBe('Inserted');
+ expect(inserted.getLevel()).toBe('2.1.1');
+
+ expect(nextOne.getTitle()).toBe('2.1.1');
+ expect(nextOne.getLevel()).toBe('2.1.2');
+ });
+
+ it('should insert an article in last position', function() {
+ var article = SummaryArticle.create({
+ title: 'Inserted'
+ }, 'fake.level');
+
+ var newSummary = insertArticle(summary, article, '2.2');
+
+ var inserted = newSummary.getByLevel('2.2');
+ var previousOne = newSummary.getByLevel('2.1');
+
+ expect(inserted.getTitle()).toBe('Inserted');
+ expect(inserted.getLevel()).toBe('2.2');
+
+ expect(previousOne.getTitle()).toBe('2.1'); // Unchanged
+ expect(previousOne.getLevel()).toBe('2.1');
+ });
+});
diff --git a/lib/modifiers/summary/__tests__/moveArticle.js b/lib/modifiers/summary/__tests__/moveArticle.js
index 9a101f6..aed0b94 100644
--- a/lib/modifiers/summary/__tests__/moveArticle.js
+++ b/lib/modifiers/summary/__tests__/moveArticle.js
@@ -42,7 +42,7 @@ describe('moveArticle', function() {
}
]);
- it('should move an article at in place', function() {
+ it('should move an article to the same place', function() {
var newSummary = moveArticle(summary, '2.1', '2.1');
expect(Immutable.is(summary, newSummary)).toBe(true);
diff --git a/lib/modifiers/summary/__tests__/moveArticleAfter.js b/lib/modifiers/summary/__tests__/moveArticleAfter.js
new file mode 100644
index 0000000..c380575
--- /dev/null
+++ b/lib/modifiers/summary/__tests__/moveArticleAfter.js
@@ -0,0 +1,82 @@
+var Immutable = require('immutable');
+var Summary = require('../../../models/summary');
+var File = require('../../../models/file');
+
+describe('moveArticleAfter', function() {
+ var moveArticleAfter = require('../moveArticleAfter');
+ var summary = Summary.createFromParts(File(), [
+ {
+ articles: [
+ {
+ title: '1.1',
+ path: '1.1'
+ },
+ {
+ title: '1.2',
+ path: '1.2'
+ }
+ ]
+ },
+ {
+ title: 'Part I',
+ articles: [
+ {
+ title: '2.1',
+ path: '2.1',
+ articles: [
+ {
+ title: '2.1.1',
+ path: '2.1.1'
+ },
+ {
+ title: '2.1.2',
+ path: '2.1.2'
+ }
+ ]
+ },
+ {
+ title: '2.2',
+ path: '2.2'
+ }
+ ]
+ }
+ ]);
+
+ it('moving right after itself should be invariant', function() {
+ var newSummary = moveArticleAfter(summary, '2.1', '2.1');
+
+ expect(Immutable.is(summary, newSummary)).toBe(true);
+ });
+
+ it('moving after previous one should be invariant too', function() {
+ var newSummary = moveArticleAfter(summary, '2.1', '2.0');
+
+ expect(Immutable.is(summary, newSummary)).toBe(true);
+ });
+
+ it('should move an article after a previous level', function() {
+ var newSummary = moveArticleAfter(summary, '2.2', '2.0');
+ var moved = newSummary.getByLevel('2.1');
+
+ expect(moved.getTitle()).toBe('2.2');
+ expect(newSummary.getByLevel('2.2').getTitle()).toBe('2.1');
+ });
+
+ it('should move an article after a previous and less deep level', function() {
+ var newSummary = moveArticleAfter(summary, '2.1.1', '2.0');
+ var moved = newSummary.getByLevel('2.1');
+
+ expect(moved.getTitle()).toBe('2.1.1');
+ expect(newSummary.getByLevel('2.2.1').getTitle()).toBe('2.1.2');
+ expect(newSummary.getByLevel('2.2').getTitle()).toBe('2.1');
+ });
+
+ it('should move an article after a next level', function() {
+ var newSummary = moveArticleAfter(summary, '2.1', '2.2');
+ var moved = newSummary.getByLevel('2.2');
+
+ expect(moved.getTitle()).toBe('2.1');
+ expect(newSummary.getByLevel('2.1').getTitle()).toBe('2.2');
+ });
+
+});
diff --git a/lib/modifiers/summary/__tests__/removeArticle.js b/lib/modifiers/summary/__tests__/removeArticle.js
new file mode 100644
index 0000000..c961f14
--- /dev/null
+++ b/lib/modifiers/summary/__tests__/removeArticle.js
@@ -0,0 +1,54 @@
+var Summary = require('../../../models/summary');
+var SummaryArticle = require('../../../models/summaryArticle');
+var File = require('../../../models/file');
+
+describe('removeArticle', function() {
+ var removeArticle = require('../removeArticle');
+ var summary = Summary.createFromParts(File(), [
+ {
+ articles: [
+ {
+ title: '1.1',
+ path: '1.1'
+ },
+ {
+ title: '1.2',
+ path: '1.2'
+ }
+ ]
+ },
+ {
+ title: 'Part I',
+ articles: [
+ {
+ title: '2.1',
+ path: '2.1',
+ articles: [
+ {
+ title: '2.1.1',
+ path: '2.1.1'
+ },
+ {
+ title: '2.1.2',
+ path: '2.1.2'
+ }
+ ]
+ },
+ {
+ title: '2.2',
+ path: '2.2'
+ }
+ ]
+ }
+ ]);
+
+ it('should remove an article at a given level', function() {
+ var newSummary = removeArticle(summary, '2.1.1');
+
+ var removed = newSummary.getByLevel('2.1.1');
+ var nextOne = newSummary.getByLevel('2.1.2');
+
+ expect(removed.getTitle()).toBe('2.1.2');
+ expect(nextOne).toBe(null);
+ });
+});
diff --git a/lib/modifiers/summary/editArticleRef.js b/lib/modifiers/summary/editArticleRef.js
new file mode 100644
index 0000000..7106960
--- /dev/null
+++ b/lib/modifiers/summary/editArticleRef.js
@@ -0,0 +1,17 @@
+var mergeAtLevel = require('./mergeAtLevel');
+
+/**
+ Edit the ref of an article
+
+ @param {Summary} summary
+ @param {String} level
+ @param {String} newRef
+ @return {Summary}
+*/
+function editArticleRef(summary, level, newRef) {
+ return mergeAtLevel(summary, level, {
+ ref: newRef
+ });
+}
+
+module.exports = editArticleRef;
diff --git a/lib/modifiers/summary/index.js b/lib/modifiers/summary/index.js
index 4498287..f91fdb6 100644
--- a/lib/modifiers/summary/index.js
+++ b/lib/modifiers/summary/index.js
@@ -1,9 +1,13 @@
module.exports = {
insertArticle: require('./insertArticle'),
moveArticle: require('./moveArticle'),
+ moveArticleAfter: require('./moveArticleAfter'),
removeArticle: require('./removeArticle'),
unshiftArticle: require('./unshiftArticle'),
+ editArticleTitle: require('./editArticleTitle'),
+ editArticleRef: require('./editArticleRef'),
- editPartTitle: require('./editPartTitle'),
- editArticleTitle: require('./editArticleTitle')
+ insertPart: require('./insertPart'),
+ removePart: require('./removePart'),
+ editPartTitle: require('./editPartTitle')
};
diff --git a/lib/modifiers/summary/insertArticle.js b/lib/modifiers/summary/insertArticle.js
index 849f39e..3a084b3 100644
--- a/lib/modifiers/summary/insertArticle.js
+++ b/lib/modifiers/summary/insertArticle.js
@@ -8,11 +8,11 @@ var indexArticleLevels = require('./indexArticleLevels');
subsequent article shifted.
@param {Summary} summary
- @param {String|Article} level: level to insert at
@param {Article} article
+ @param {String|Article} level: level to insert at
@return {Summary}
*/
-function insertArticle(summary, level, article) {
+function insertArticle(summary, article, level) {
article = SummaryArticle(article);
level = is.string(level)? level : level.getLevel();
diff --git a/lib/modifiers/summary/insertPart.js b/lib/modifiers/summary/insertPart.js
new file mode 100644
index 0000000..199cba7
--- /dev/null
+++ b/lib/modifiers/summary/insertPart.js
@@ -0,0 +1,19 @@
+var SummaryPart = require('../../models/summaryPart');
+var indexLevels = require('./indexLevels');
+
+/**
+ Returns a new Summary with a part inserted at given index
+
+ @param {Summary} summary
+ @param {Part} part
+ @param {Number} index
+ @return {Summary}
+*/
+function insertPart(summary, part, index) {
+ part = SummaryPart(part);
+
+ var parts = summary.getParts().insert(index, part);
+ return indexLevels(summary.set('parts', parts));
+}
+
+module.exports = insertPart;
diff --git a/lib/modifiers/summary/moveArticle.js b/lib/modifiers/summary/moveArticle.js
index 06d82ca..5cb1868 100644
--- a/lib/modifiers/summary/moveArticle.js
+++ b/lib/modifiers/summary/moveArticle.js
@@ -15,68 +15,11 @@ function moveArticle(summary, origin, target) {
// Coerce to level
var originLevel = is.string(origin)? origin : origin.getLevel();
var targetLevel = is.string(target)? target : target.getLevel();
-
var article = summary.getByLevel(originLevel);
- // Remove
- var removed = removeArticle(summary, origin);
-
- // Adjust targetLevel if removing impacted it
- targetLevel = arrayToLevel(
- shiftLevel(levelToArray(originLevel),
- levelToArray(targetLevel)));
- // Re-insert
- return insertArticle(removed, target, article);
-}
-
-/**
- @param {Array<Number>} removedLevel
- @param {Array<Number>} level The level to udpate
- @return {Array<Number>}
- */
-function shiftLevel(removedLevel, level) {
- if (level.length === 0) {
- // `removedLevel` is under level, so no effect
- return level;
- } else if (removedLevel.length === 0) {
- // Either `level` is a child of `removedLevel`... or they are equal
- // This is undefined behavior.
- return level;
- }
-
- var removedRoot = removedLevel[0];
- var root = level[0];
- var removedRest = removedLevel.slice(1);
- var rest = level.slice(1);
-
- if (removedRoot < root) {
- // It will shift levels at this point. The rest is unchanged.
- return Array.prototype.concat(root - 1, rest);
- } else if (removedRoot === root) {
- // Look deeper
- return Array.prototype.concat(root, shiftLevel(removedRest, rest));
- } else {
- // No impact
- return level;
- }
-}
-
-/**
- @param {String}
- @return {Array<Number>}
- */
-function levelToArray(l) {
- return l.split('.').map(function (char) {
- return parseInt(char, 10);
- });
-}
-
-/**
- @param {Array<Number>}
- @return {String}
- */
-function arrayToLevel(a) {
- return a.join('.');
+ // Remove first
+ var removed = removeArticle(summary, originLevel);
+ return insertArticle(removed, article, targetLevel);
}
module.exports = moveArticle;
diff --git a/lib/modifiers/summary/moveArticleAfter.js b/lib/modifiers/summary/moveArticleAfter.js
new file mode 100644
index 0000000..e268f73
--- /dev/null
+++ b/lib/modifiers/summary/moveArticleAfter.js
@@ -0,0 +1,60 @@
+var is = require('is');
+var removeArticle = require('./removeArticle');
+var insertArticle = require('./insertArticle');
+
+/**
+ Returns a new summary, with the an article moved after another
+ article. Unlike `moveArticle`, does not ensure that the article
+ will be found at the target's level plus one.
+
+ @param {Summary} summary
+ @param {String|SummaryArticle} origin
+ @param {String|SummaryArticle} afterTarget
+ @return {Summary}
+*/
+function moveArticleAfter(summary, origin, afterTarget) {
+ // Coerce to level
+ var originLevel = is.string(origin)? origin : origin.getLevel();
+ var afterTargetLevel = is.string(afterTarget)? afterTarget : afterTarget.getLevel();
+ var article = summary.getByLevel(originLevel);
+
+ var targetLevel = increment(afterTargetLevel);
+
+ if (targetLevel < origin) {
+ // Remove first
+ var removed = removeArticle(summary, originLevel);
+ // Insert then
+ return insertArticle(removed, article, targetLevel);
+ } else {
+ // Insert right after first
+ var inserted = insertArticle(summary, article, targetLevel);
+ // Remove old one
+ return removeArticle(inserted, originLevel);
+ }
+}
+
+/**
+ @param {String}
+ @return {Array<Number>}
+ */
+function levelToArray(l) {
+ return l.split('.').map(function (char) {
+ return parseInt(char, 10);
+ });
+}
+
+/**
+ @param {Array<Number>}
+ @return {String}
+ */
+function arrayToLevel(a) {
+ return a.join('.');
+}
+
+function increment(level) {
+ level = levelToArray(level);
+ level[level.length - 1]++;
+ return arrayToLevel(level);
+}
+
+module.exports = moveArticleAfter;
diff --git a/lib/modifiers/summary/removePart.js b/lib/modifiers/summary/removePart.js
new file mode 100644
index 0000000..2f8affc
--- /dev/null
+++ b/lib/modifiers/summary/removePart.js
@@ -0,0 +1,15 @@
+var indexLevels = require('./indexLevels');
+
+/**
+ Remove a part at given index
+
+ @param {Summary} summary
+ @param {Number|} index
+ @return {Summary}
+*/
+function removePart(summary, index) {
+ var parts = summary.getParts().remove(index);
+ return indexLevels(summary.set('parts', parts));
+}
+
+module.exports = removePart;