Skip to content

Commit

Permalink
Adding access to Story.passages
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Cox authored and Dan Cox committed Jan 11, 2024
1 parent 2240425 commit 51a65ad
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 55 deletions.
3 changes: 1 addition & 2 deletions docs/objects/story.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Depending on the incoming format or creation method, many possible properties ca
- format ( string ) Name of the story format for Twine 2 HTML.
- formatVersion ( string ) Semantic version of the named story format for Twine 2 HTML or Twee 3.
- zoom ( float ) Zoom level for Twine 2 HTML or Twee 3.
- passages ( array(Passage) ) **[Read-only]** Collection of internal passages.
- passages ( array(Passage) ) Collection of internal passages.
- creator ( string ) Name of story creation tool. (Defaults to "Extwee").
- creatorVersion ( string ) Semantic version of named creation tool.
- metadata ( object ) Key-value pairs of metadata values.
Expand Down Expand Up @@ -41,7 +41,6 @@ As collections of passages, each **Story** has multiple methods for accessing an
- `getPassagesByTags(string)`: Returns an array of any passages containing a particular tag value.
- `getPassageByName(string)`: Returns either `null`` or the named passage.
- `size()`: Returns the number of passages in the collection.
- `forEachPassage(callback)`: Allows for iterating over the passage collection.

## Passage Creation Example

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 31 additions & 23 deletions src/Story.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,32 @@ class Story {
}
}

/**
* Passages in Story.
* @returns {Array} Passages
* @property {Array} passages - Passages
*/
get passages () { return this.#_passages; }

/**
* Set passages in Story.
* @param {Array} p - Replacement passages
* @property {Array} passages - Passages
* @throws {Error} Passages must be an Array!
* @throws {Error} Passages must be an Array of Passage objects!
*/
set passages (p) {
if (Array.isArray(p)) {
if (p.every((passage) => passage instanceof Passage)) {
this.#_passages = p;
} else {
throw new Error('Passages must be an Array of Passage objects!');
}
} else {
throw new Error('Passages must be an Array!');
}
}

/**
* Add a passage to the story.
* `StoryData` will override story metadata and `StoryTitle` will override story name.
Expand Down Expand Up @@ -375,24 +401,6 @@ class Story {
return this.#_passages.length;
}

/**
* forEach-style iterator of passages in Story.
* @param {Function} callback - Callback function
*/
forEachPassage (callback) {
// Check if argument is a function.
if (typeof callback !== 'function') {
// Throw error
throw new Error('Callback must be a function!');
}

// Use internal forEach.
this.#_passages.forEach((element, index) => {
// Call callback function with element and index.
callback(element, index);
});
}

/**
* Export Story as JSON representation.
* @returns {string} JSON string.
Expand All @@ -414,7 +422,7 @@ class Story {
};

// For each passage, convert into simple object.
this.forEachPassage((p) => {
this.passages.forEach((p) => {
s.passages.push({
name: p.name,
tags: p.tags,
Expand Down Expand Up @@ -500,7 +508,7 @@ class Story {
outputContents += '\n\n';

// For each passage, append it to the output.
this.forEachPassage((passage) => {
this.passages.forEach((passage) => {
outputContents += passage.toTwee();
});

Expand Down Expand Up @@ -539,7 +547,7 @@ class Story {
let startPID = 1;
// We have to do a bit of nonsense here.
// Twine 2 HTML cares about PID values.
this.forEachPassage((p) => {
this.passages.forEach((p) => {
// Have we found the starting passage?
if (p.name === this.start) {
// If so, set the PID based on index.
Expand Down Expand Up @@ -614,7 +622,7 @@ class Story {
PIDcounter = 1;

// Build the passages HTML.
this.forEachPassage((passage) => {
this.passages.forEach((passage) => {
// Append each passage element using the PID counter.
storyData += passage.toTwine2HTML(PIDcounter);
// Increase counter inside loop.
Expand All @@ -640,7 +648,7 @@ class Story {
let outputContents = '';

// Process passages (if any).
this.forEachPassage((p) => {
this.passages.forEach((p) => {
// Output HTML output per passage.
outputContents += `\t${p.toTwine1HTML()}`;
});
Expand Down
49 changes: 25 additions & 24 deletions test/Story.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,31 @@ describe('Story', () => {
});
});

describe('passages', () => {
let s = null;

beforeEach(() => {
s = new Story();
});

it('Set passages to a new array containing at least one Passage', () => {
s.passages = [new Passage()];
expect(s.passages.length).toBe(1);
});

it('Should throw error if trying to set to a non-Array type', () => {
expect(() => {
s.passages = null;
}).toThrow();
});

it('Should throw error if trying to set to an array containing non-Passage types', () => {
expect(() => {
s.passages = [null];
}).toThrow();
});
});

describe('addPassage()', () => {
let s = null;

Expand Down Expand Up @@ -351,30 +376,6 @@ describe('Story', () => {
});
});

describe('forEachPassage()', () => {
let s = null;

beforeEach(() => {
s = new Story();
});

it('forEachPassage() - should return if non-function', () => {
s.addPassage(new Passage('A'));
s.addPassage(new Passage('B'));
let passageNames = '';
s.forEachPassage((p) => {
passageNames += p.name;
});
expect(passageNames).toBe('AB');
});

it('forEachPassage() - should throw error if non-function', () => {
expect(() => {
s.forEachPassage(null);
}).toThrow();
});
});

describe('size()', () => {
let s = null;

Expand Down
8 changes: 4 additions & 4 deletions test/Twine2HTML/Twine2HTML.Compile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ describe('Twine2HTMLCompiler', () => {
let tags2 = '';

// Combine contents of tags.
story.forEachPassage((p) => {
story.passages.forEach((p) => {
tags += p.tags.join('');
});

// Combine contents of tags.
story2.forEachPassage((p) => {
story2.passages.forEach((p) => {
tags2 += p.tags.join('');
});

Expand Down Expand Up @@ -105,12 +105,12 @@ describe('Twine2HTMLCompiler', () => {
const story2 = parseTwine2HTML(fr3);

// Verify none of the directly created passages have position.
story.forEachPassage((passage) => {
story.passages.forEach((passage) => {
expect(Object.prototype.hasOwnProperty.call(passage.metadata, 'position')).toBe(false);
});

// Verify none parsed passages have position.
story2.forEachPassage((passage) => {
story2.passages.forEach((passage) => {
expect(Object.prototype.hasOwnProperty.call(passage.metadata, 'position')).toBe(false);
});
});
Expand Down

0 comments on commit 51a65ad

Please sign in to comment.