Skip to content

Commit

Permalink
Loose parsing of tw-passagedata
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Cox authored and Dan Cox committed Jan 16, 2024
1 parent 93b224b commit fb566ac
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 47 deletions.
24 changes: 18 additions & 6 deletions src/Twine2HTML/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function parse (content) {

// Can only parse string values.
if (typeof content !== 'string') {
throw new TypeError('Content is not a string!');
throw new TypeError('TypeError: Content is not a string!');
}

// Set default start node.
Expand All @@ -50,7 +50,7 @@ function parse (content) {
// Did we find any elements?
if (storyDataElements.length === 0) {
// If there is not a single `<tw-storydata>` element, this is not a Twine 2 story!
throw new Error('TypeError: Not Twine 2 HTML content!');
throw new TypeError('TypeError: Not Twine 2 HTML content!');
}

// We only parse the first element found.
Expand Down Expand Up @@ -185,15 +185,21 @@ function parse (content) {
* https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-htmloutput-spec.md#passages
*/
// Create a default value
let name = null;
let name = 'Untitled Passage';
// Does name exist?
if (Object.prototype.hasOwnProperty.call(attr, 'name')) {
// Escape the name
name = attr.name;
} else {
throw new Error('TypeError: Cannot parse passage data without name!');
console.warn('Warning: name attribute is missing! Default passage name will be used.');
}

/**
* tags: (string) Optional.
* A space-separated list of tags for the passage.
*
* https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-htmloutput-spec.md#passages
*/
// Create empty tag array.
let tags = [];
// Does the tags attribute exist?
Expand All @@ -211,6 +217,12 @@ function parse (content) {
tags = tags.filter(tag => tag !== '');
}

/**
* metadata: (object) Optional.
* An object containing additional metadata about the passage.
*
* Twine 2 HTML does not support metadata, but other formats do.
*/
// Create metadata for passage.
const metadata = {};

Expand All @@ -234,14 +246,14 @@ function parse (content) {
* https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-htmloutput-spec.md#passages
*/
// Create a default PID
let pid = -1;
let pid = 1;
// Does pid exist?
if (Object.prototype.hasOwnProperty.call(attr, 'pid')) {
// Parse string into int
// Update PID
pid = Number.parseInt(attr.pid, 10);
} else {
throw new Error('Passages are required to have PID!');
console.warn('Warning: pid attribute is missing! Default PID will be used.');
}

// Check the current PID against startNode number.
Expand Down
34 changes: 23 additions & 11 deletions test/Twine2HTML/Twine2HTML.Parse.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import { parse as parseTwine2HTML } from '../../src/Twine2HTML/parse.js';
const { version } = JSON.parse(readFileSync('package.json', 'utf-8'));

describe('Twine2HTMLParser', () => {
describe('#parse()', () => {
describe('Errors', () => {
it('Should throw error if content is not a string', () => {
expect(() => { parseTwine2HTML({}); }).toThrow();
});

it('Should throw error if content is not Twine-2 style HTML', () => {
expect(() => { parseTwine2HTML(''); }).toThrow();
});
});

describe('#parse()', () => {
it('Should be able to parse Twine 2 HTML for story name', () => {
const fr = readFileSync('test/Twine2HTML/Twine2HTMLParser/twineExample.html', 'utf-8');
const story = parseTwine2HTML(fr);
Expand Down Expand Up @@ -120,16 +122,6 @@ describe('Twine2HTMLParser', () => {
expect(stylesheetPassages.length).toBe(1);
});

it('Should throw error if passage name is missing', () => {
const fr = readFileSync('test/Twine2HTML/Twine2HTMLParser/missingPassageName.html', 'utf-8');
expect(() => { parseTwine2HTML(fr); }).toThrow();
});

it('Should throw error if passage PID is missing', () => {
const fr = readFileSync('test/Twine2HTML/Twine2HTMLParser/missingPID.html', 'utf-8');
expect(() => { parseTwine2HTML(fr); }).toThrow();
});

it('Should parse HTML without passage start node', () => {
const fr = readFileSync('test/Twine2HTML/Twine2HTMLParser/missingStartnode.html', 'utf-8');
const story = parseTwine2HTML(fr);
Expand Down Expand Up @@ -188,5 +180,25 @@ describe('Twine2HTMLParser', () => {
parseTwine2HTML(s);
expect(console.warn).toHaveBeenCalledWith('Warning: The IFID is not in valid UUIDv4 formatting on tw-storydata!');
});

it('Should generate warning if passage name is missing', () => {
const fr = `<tw-storydata name="Tags" startnode="1" creator="Twine" creator-version="2.3.9" ifid="1A6023FC-F68A-4E55-BE9A-5EDFDB7879E6" zoom="1" format="Harlowe" format-version="3.1.0" options="" hidden>
<style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>
<script role="script" id="twine-user-script" type="text/twine-javascript"></script>
<tw-passagedata pid="1" tags="this-one another-one-like-this" position="200,99" size="100,100">Double-click this passage to edit it.</tw-passagedata>
</tw-storydata>`;
parseTwine2HTML(fr);
expect(console.warn).toHaveBeenCalledWith('Warning: name attribute is missing! Default passage name will be used.');
});

it('Should generate error if passage PID is missing', () => {
const fr = `<tw-storydata name="Tags" startnode="1" creator="Twine" creator-version="2.3.9" ifid="1A6023FC-F68A-4E55-BE9A-5EDFDB7879E6" zoom="1" format="Harlowe" format-version="3.1.0" options="" hidden>
<style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>
<script role="script" id="twine-user-script" type="text/twine-javascript"></script>
<tw-passagedata name="Untitled Passage" tags="this-one another-one-like-this" position="200,99" size="100,100">Double-click this passage to edit it.</tw-passagedata>
</tw-storydata>`;
parseTwine2HTML(fr);
expect(console.warn).toHaveBeenCalledWith('Warning: pid attribute is missing! Default PID will be used.');
});
});
});
15 changes: 0 additions & 15 deletions test/Twine2HTML/Twine2HTMLParser/missingPID.html

This file was deleted.

15 changes: 0 additions & 15 deletions test/Twine2HTML/Twine2HTMLParser/missingPassageName.html

This file was deleted.

0 comments on commit fb566ac

Please sign in to comment.