-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8c6db98
commit 945c4e6
Showing
10 changed files
with
200 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
node_modules | ||
dist | ||
.nyc_output | ||
coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,6 @@ node_js: | |
- "6" | ||
- "5" | ||
- "4" | ||
- "0.12" | ||
after_success: | ||
- npm run coveralls | ||
- npm run coverage && npm run coveralls |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* @module Jour | ||
*/ | ||
|
||
/** | ||
* Create a new Saxophone object, ready | ||
* to parse XML data | ||
* | ||
* @return {Saxophone} A Saxophone object | ||
*/ | ||
const Saxophone = () => { | ||
return Object.create(saxophonePrototype); | ||
}; | ||
|
||
// export the factory before importing the submodules | ||
// for circular dependencies | ||
module.exports = Saxophone; | ||
|
||
// load the prototype from the submodules | ||
const saxophonePrototype = Object.assign( | ||
{}, | ||
require('events').prototype, | ||
require('./prototype/parse') | ||
); | ||
|
||
// load the static properties and methods | ||
require('./static/attrs')(Saxophone); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/** | ||
* Check if a character is a whitespace character according | ||
* to the XML spec (space, carriage return, line feed or tab) | ||
* | ||
* @param {string} character Character to check | ||
* @return {bool} Whether the character is whitespace or not | ||
*/ | ||
const isWhitespace = character => character === ' ' || | ||
character === '\r' || character === '\n' || character === '\t'; | ||
|
||
/** | ||
* Parse a string of XML attributes to a map of attribute names | ||
* to their values | ||
* | ||
* @memberof Saxophone | ||
* @param {string} input A string of XML attributes | ||
* @throws {Error} If the string is malformed | ||
* @return {Object} A map of attribute names to their values | ||
*/ | ||
const parseAttrs = input => { | ||
const attrs = {}, end = input.length; | ||
let position = 0; | ||
|
||
while (position < end) { | ||
// skip all whitespace | ||
if (isWhitespace(input[position])) { | ||
position += 1; | ||
continue; | ||
} | ||
|
||
// check that the attribute name contains valid chars | ||
const startName = position; | ||
|
||
while (input[position] !== '=' && position < end) { | ||
if (isWhitespace(input[position])) { | ||
throw new Error('Attribute names may not contain whitespace'); | ||
} | ||
|
||
position += 1; | ||
} | ||
|
||
// this is XML so we need a value for the attribute | ||
if (position === end) { | ||
throw new Error('Expected a value for the attribute'); | ||
} | ||
|
||
const attrName = input.slice(startName, position); | ||
position += 1; | ||
const startQuote = input[position]; | ||
position += 1; | ||
|
||
if (startQuote !== '"' && startQuote !== "'") { | ||
throw new Error('Attribute values should be quoted'); | ||
} | ||
|
||
const endQuote = input.indexOf(startQuote, position); | ||
|
||
if (endQuote === -1) { | ||
throw new Error('Unclosed attribute value'); | ||
} | ||
|
||
const attrValue = input.slice(position, endQuote); | ||
|
||
attrs[attrName] = attrValue; | ||
position = endQuote + 1; | ||
} | ||
|
||
return attrs; | ||
}; | ||
|
||
module.exports = Saxophone => { | ||
Saxophone.parseAttrs = parseAttrs; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
const test = require('tape'); | ||
const Saxophone = require('../'); | ||
|
||
test('should parse tag attributes', assert => { | ||
assert.deepEqual( | ||
Saxophone.parseAttrs(' first="one" second="two" third="three " '), | ||
{ | ||
first: 'one', | ||
second: 'two', | ||
third: 'three ' | ||
} | ||
); | ||
|
||
assert.end(); | ||
}); | ||
|
||
test('should not parse attributes without a value', assert => { | ||
assert.throws(() => { | ||
Saxophone.parseAttrs(' first'); | ||
}, /Expected a value for the attribute/); | ||
assert.end(); | ||
}); | ||
|
||
test('should not parse invalid attribute names', assert => { | ||
assert.throws(() => { | ||
Saxophone.parseAttrs(' this is an attribute="value"'); | ||
}, /Attribute names may not contain whitespace/); | ||
assert.end(); | ||
}); | ||
|
||
test('should not parse unquoted attribute values', assert => { | ||
assert.throws(() => { | ||
Saxophone.parseAttrs(' attribute=value value=invalid'); | ||
}, /Attribute values should be quoted/); | ||
assert.end(); | ||
}); | ||
|
||
test('should not parse misquoted attribute values', assert => { | ||
assert.throws(() => { | ||
Saxophone.parseAttrs(' attribute="value\''); | ||
}, /Unclosed attribute value/); | ||
assert.end(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.