Skip to content

Commit e1f0c3e

Browse files
authored
NEW: add MultiLangString model (#115)
closes #47
1 parent 938051d commit e1f0c3e

16 files changed

Lines changed: 274 additions & 167 deletions

File tree

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
- [ ] Write code to pass the tests. (`npm test`)
1717

18-
- [ ] Add inline code commenting (using [JSDoc][JSDoc] style).
18+
- [ ] Add inline code commenting (using [JSDoc][JSDoc] style). Add links to cross-referenced modules, and the DLx data format.
1919

2020
- [ ] Generate the developer documentation (`npm run docs`) and check your changes by opening `docs/index.html` in a browser.
2121

archive/models/MultiLangString/MultiLangString.js

Lines changed: 0 additions & 78 deletions
This file was deleted.

archive/models/MultiLangString/MultiLangString.test.js

Lines changed: 0 additions & 55 deletions
This file was deleted.

src/core/Model.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
/**
2-
* @module
3-
*/
4-
51
/**
62
* A base Model class
3+
* @memberof core
74
*/
85
class Model {
96

src/core/index.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
/**
2-
* @module core
2+
* @namespace core
33
*/
44

5-
/**
6-
* @member Model
7-
* @instance
8-
* @see module:core/Model
9-
*/
105
import Model from './Model.js';
116

127
export default { Model };

src/models/Language.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
/**
2-
* @module
3-
*/
4-
51
import Model from '../core/Model.js';
62

73
/**
84
* A class representing a language
5+
* @memberof models
96
* @extends Model
107
*/
118
class Language extends Model {

src/models/Language.test.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
1-
const {
2-
core: { Model },
3-
models: { Language },
4-
} = require(`../../test`);
1+
const { models: { Language } } = require(`../../test`);
52

63
describe(`Language`, () => {
74

8-
it(`is a Model`, () => {
9-
expect(new Language).toBeInstanceOf(Model);
10-
});
11-
125
it(`is a Language class`, () => {
136
expect(Language.name).toBe(`Language`);
147
});

src/models/MultiLangString.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* @module models.MultiLangString
3+
*/
4+
5+
import isLanguageTag from '../utilities/validate/isLanguageTag.js';
6+
7+
/**
8+
* Proxy traps for the MultiLangString class
9+
* @type {Object}
10+
*/
11+
const classTraps = {
12+
construct(Target, args) {
13+
14+
const map = Reflect.construct(Target, args);
15+
16+
Object.defineProperty(map, `set`, {
17+
configurable: true,
18+
enumerable: false,
19+
get() {
20+
return function(key, val) { // eslint-disable-line func-names
21+
validateLanguageTag(key);
22+
validateString(val);
23+
return map.set.apply(this, [key, val]); // eslint-disable-line no-invalid-this
24+
};
25+
},
26+
});
27+
28+
return map;
29+
30+
},
31+
};
32+
33+
/**
34+
* Validates a language tag. Throws a type error if the input is not a valid IETF language tag.
35+
* @param {Any} input The input to validate
36+
*/
37+
function validateLanguageTag(input) {
38+
if (!isLanguageTag(input)) {
39+
const e = new TypeError(`Each language key must be a valid IETF language tag.`);
40+
e.name = `LanguageTagError`;
41+
throw e;
42+
}
43+
}
44+
45+
/**
46+
* Validates a String for MultiLangStrings. Throws a type error if the input is not a String.
47+
* @param {Any} input The input to validate
48+
*/
49+
function validateString(input) {
50+
if (typeof input !== `string`) {
51+
const e = new TypeError(`Each piece of data in a MultiLangString must be a String of text in a particular language.`);
52+
e.name = `MultiLangStringError`;
53+
throw e;
54+
}
55+
}
56+
57+
/**
58+
* A class representing a Multi-Language Text / String
59+
* @memberof models
60+
* @extends Map
61+
*
62+
* @example
63+
* const translation = new MultiLangString({
64+
* spa: 'Hola, me llamo Daniel.',
65+
* eng: 'Hello, my name is Daniel.',
66+
* });
67+
*
68+
* console.log(translation.get(`spa`)); // Hola, me llamo Daniel.
69+
*/
70+
class MultiLangString extends Map {
71+
72+
/**
73+
* Create a new MultiLangString
74+
* @param {Map|Object|String} [data={}] The data to use for this MultiLangString, as either a Map, an Object, or a String. If a String is provided, it is assumed to be English.
75+
*/
76+
constructor(data = {}) {
77+
78+
// VALIDATE ARGUMENTS
79+
80+
if (!(
81+
typeof data === `string`
82+
|| typeof data === `object`
83+
)) {
84+
const e = new TypeError(`The data passed to the MultiLangString constructor must be an Object or String.`);
85+
e.name = `MultiLangStringDataError`;
86+
throw e;
87+
}
88+
89+
// STANDARDIZE DATA
90+
91+
/* eslint-disable no-param-reassign */
92+
if (data && typeof data === `string`) data = { eng: data };
93+
if (data instanceof Map) data = Object.fromEntries(data);
94+
/* eslint-enable no-param-reassign */
95+
96+
// VALIDATE DATA
97+
98+
Object.keys(data).forEach(validateLanguageTag);
99+
Object.values(data).forEach(validateString);
100+
101+
// INSTANTIATE MODEL
102+
103+
super(Object.entries(data));
104+
105+
}
106+
}
107+
108+
export default new Proxy(MultiLangString, classTraps);

0 commit comments

Comments
 (0)