manyfest 1.0.43 → 1.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -260
- package/docs/.nojekyll +0 -0
- package/docs/README.md +108 -0
- package/docs/_sidebar.md +17 -0
- package/docs/address-notation.md +244 -0
- package/docs/cover.md +11 -0
- package/docs/hash-translation.md +202 -0
- package/docs/index.html +51 -0
- package/docs/quickstart.md +203 -0
- package/docs/reading.md +339 -0
- package/docs/schema-manipulation.md +186 -0
- package/docs/schema.md +319 -0
- package/docs/validating.md +344 -0
- package/docs/writing.md +300 -0
- package/package.json +1 -1
- package/source/Manyfest-ObjectAddress-CheckAddressExists.js +3 -4
- package/source/Manyfest-ObjectAddress-DeleteValue.js +7 -5
- package/source/Manyfest-ObjectAddress-GetValue.js +2 -6
- package/source/Manyfest-ObjectAddress-Parser.js +3 -3
- package/source/Manyfest-ObjectAddress-SetValue.js +7 -4
- package/source/Manyfest-ParseConditionals.js +0 -13
- package/source/Manyfest.js +28 -15
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# Address Notation
|
|
2
|
+
|
|
3
|
+
Addresses are the core of manyfest. They describe locations inside nested JavaScript objects using a compact string syntax. Every read, write, existence check and validation operation resolves through the address system.
|
|
4
|
+
|
|
5
|
+
## Basic Dot Notation
|
|
6
|
+
|
|
7
|
+
Dots separate levels of nesting:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
const manifest = new libManyfest();
|
|
11
|
+
|
|
12
|
+
const data = {
|
|
13
|
+
user: {
|
|
14
|
+
profile: {
|
|
15
|
+
name: 'Alice'
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
manifest.getValueAtAddress(data, 'user'); // { profile: { name: 'Alice' } }
|
|
21
|
+
manifest.getValueAtAddress(data, 'user.profile'); // { name: 'Alice' }
|
|
22
|
+
manifest.getValueAtAddress(data, 'user.profile.name'); // 'Alice'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Paths are case-sensitive. `user.Profile` and `user.profile` resolve to different locations.
|
|
26
|
+
|
|
27
|
+
## Array Access
|
|
28
|
+
|
|
29
|
+
Square brackets with a numeric index access array elements:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
const data = {
|
|
33
|
+
items: ['first', 'second', 'third'],
|
|
34
|
+
users: [
|
|
35
|
+
{ name: 'Alice', scores: [95, 88] },
|
|
36
|
+
{ name: 'Bob', scores: [72, 91] }
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
manifest.getValueAtAddress(data, 'items[0]'); // 'first'
|
|
41
|
+
manifest.getValueAtAddress(data, 'items[2]'); // 'third'
|
|
42
|
+
manifest.getValueAtAddress(data, 'users[0].name'); // 'Alice'
|
|
43
|
+
manifest.getValueAtAddress(data, 'users[1].scores[0]'); // 72
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Indices are zero-based. Accessing an out-of-bounds index returns `undefined`.
|
|
47
|
+
|
|
48
|
+
### Set Access
|
|
49
|
+
|
|
50
|
+
Empty brackets access the full array:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
manifest.getValueAtAddress(data, 'users[]');
|
|
54
|
+
// Returns all user objects
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
When combined with further path resolution, this produces an object keyed by each element's full address:
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
manifest.getValueAtAddress(data, 'users[].name');
|
|
61
|
+
// { 'users[0].name': 'Alice', 'users[1].name': 'Bob' }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Boxed Properties
|
|
65
|
+
|
|
66
|
+
Properties with special characters in their keys (dots, spaces, dashes) cannot use dot notation. Wrap them in brackets with quotes instead:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
const data = {
|
|
70
|
+
'my-key': 'value1',
|
|
71
|
+
'another key': 'value2',
|
|
72
|
+
nested: {
|
|
73
|
+
'some.dotted.key': 'value3'
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
manifest.getValueAtAddress(data, '["my-key"]'); // 'value1'
|
|
78
|
+
manifest.getValueAtAddress(data, "['another key']"); // 'value2'
|
|
79
|
+
manifest.getValueAtAddress(data, 'nested["some.dotted.key"]'); // 'value3'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Single quotes, double quotes and backticks all work as the wrapping character.
|
|
83
|
+
|
|
84
|
+
## Object Set Access
|
|
85
|
+
|
|
86
|
+
The `{}` marker enumerates all keys of an object, resolving a sub-path on each:
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
const data = {
|
|
90
|
+
departments: {
|
|
91
|
+
engineering: { budget: 50000, headcount: 12 },
|
|
92
|
+
marketing: { budget: 30000, headcount: 8 },
|
|
93
|
+
sales: { budget: 40000, headcount: 15 }
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
manifest.getValueAtAddress(data, 'departments{}.budget');
|
|
98
|
+
// {
|
|
99
|
+
// 'departments.engineering.budget': 50000,
|
|
100
|
+
// 'departments.marketing.budget': 30000,
|
|
101
|
+
// 'departments.sales.budget': 40000
|
|
102
|
+
// }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
This is useful for extracting a single field across all entries of an object-based collection.
|
|
106
|
+
|
|
107
|
+
## Back-Navigation
|
|
108
|
+
|
|
109
|
+
Double dots (`..`) navigate upward through the object hierarchy. Each dot beyond the first separator moves one level up from the current position:
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
const data = {
|
|
113
|
+
Bundle: {
|
|
114
|
+
Contract: {
|
|
115
|
+
IDContract: 500
|
|
116
|
+
},
|
|
117
|
+
Project: {
|
|
118
|
+
IDProject: 42
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// From IDContract, navigate back up to Bundle, then down into Project
|
|
124
|
+
manifest.getValueAtAddress(data, 'Bundle.Contract.IDContract...Project.IDProject');
|
|
125
|
+
// 42
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The address resolves as:
|
|
129
|
+
1. Navigate to `Bundle.Contract.IDContract`
|
|
130
|
+
2. `..` means go up -- one dot goes back to `Contract`, the second goes back to `Bundle`
|
|
131
|
+
3. Continue forward into `Project.IDProject`
|
|
132
|
+
|
|
133
|
+
Back-navigation always resolves relative to the root object.
|
|
134
|
+
|
|
135
|
+
## Function Calls
|
|
136
|
+
|
|
137
|
+
If a property in the path is a function, it can be called using parentheses:
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
const data = {
|
|
141
|
+
items: [10, 20, 30],
|
|
142
|
+
getTotal: function() {
|
|
143
|
+
return this.items.reduce((a, b) => a + b, 0);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
manifest.getValueAtAddress(data, 'getTotal()'); // 60
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### With Arguments
|
|
151
|
+
|
|
152
|
+
Arguments inside the parentheses are resolved as addresses on the root object:
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
const data = {
|
|
156
|
+
basePrice: 100,
|
|
157
|
+
taxRate: 0.08,
|
|
158
|
+
calculate: function(price, rate) {
|
|
159
|
+
return price + (price * rate);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
manifest.getValueAtAddress(data, 'calculate(basePrice,taxRate)'); // 108
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
String literals can be passed by wrapping them in quotes:
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
const data = {
|
|
170
|
+
greet: function(name) { return 'Hello, ' + name; }
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
manifest.getValueAtAddress(data, 'greet("World")'); // 'Hello, World'
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Functions are called with `apply`, bound to their containing object so `this` works as expected.
|
|
177
|
+
|
|
178
|
+
### Chained Function Calls
|
|
179
|
+
|
|
180
|
+
A function's return value can be navigated further:
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
const data = {
|
|
184
|
+
getUser: function() {
|
|
185
|
+
return { name: 'Alice', role: 'admin' };
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
manifest.getValueAtAddress(data, 'getUser().name'); // 'Alice'
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Address Linting
|
|
193
|
+
|
|
194
|
+
Manyfest automatically cleans up common address issues before resolution:
|
|
195
|
+
|
|
196
|
+
- Leading and trailing whitespace is trimmed
|
|
197
|
+
- A trailing single `.` is removed (but `..` for back-navigation is preserved)
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
manifest.getValueAtAddress(data, ' user.name '); // Works
|
|
201
|
+
manifest.getValueAtAddress(data, 'user.name.'); // Trailing dot removed
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Writing with Addresses
|
|
205
|
+
|
|
206
|
+
All of the notation above works for write operations too. Manyfest creates intermediate objects as needed:
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
const data = {};
|
|
210
|
+
|
|
211
|
+
manifest.setValueAtAddress(data, 'user.profile.name', 'Alice');
|
|
212
|
+
// { user: { profile: { name: 'Alice' } } }
|
|
213
|
+
|
|
214
|
+
manifest.setValueAtAddress(data, 'items[0]', 'first');
|
|
215
|
+
// Also creates the items array if needed
|
|
216
|
+
|
|
217
|
+
manifest.setValueAtAddress(data, '["special-key"]', 'value');
|
|
218
|
+
// { 'special-key': 'value', user: { ... }, items: [...] }
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Address Syntax Summary
|
|
222
|
+
|
|
223
|
+
| Syntax | Example | Description |
|
|
224
|
+
|--------|---------|-------------|
|
|
225
|
+
| `property` | `Name` | Direct property access |
|
|
226
|
+
| `a.b.c` | `user.profile.name` | Nested property access |
|
|
227
|
+
| `a[0]` | `items[0]` | Array element by index |
|
|
228
|
+
| `a[].b` | `users[].name` | Property across all array elements |
|
|
229
|
+
| `a["b"]` | `data["my-key"]` | Boxed property (special characters) |
|
|
230
|
+
| `a{}.b` | `depts{}.budget` | Property across all object keys |
|
|
231
|
+
| `a..b` | `x.y..z` | Back-navigation (up one level) |
|
|
232
|
+
| `a()` | `getTotal()` | Function call |
|
|
233
|
+
| `a(b)` | `calc(price)` | Function call with address argument |
|
|
234
|
+
| `a("b")` | `greet("World")` | Function call with string literal |
|
|
235
|
+
|
|
236
|
+
## Notes
|
|
237
|
+
|
|
238
|
+
- Addresses are case-sensitive
|
|
239
|
+
- Non-existent paths return `undefined` on read (no exceptions)
|
|
240
|
+
- Non-existent intermediate objects are created on write
|
|
241
|
+
- Array indices are zero-based
|
|
242
|
+
- Function calls require the function to exist on the object at that path
|
|
243
|
+
- Back-navigation resolves from the root object
|
|
244
|
+
- The address system is shared by all operations: get, set, check, delete and validate
|
package/docs/cover.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Manyfest <small>1</small>
|
|
2
|
+
|
|
3
|
+
> JSON Object Manifest for Data Description and Parsing
|
|
4
|
+
|
|
5
|
+
- Safe read and write access to deeply nested objects
|
|
6
|
+
- Schema-driven validation with data type checking
|
|
7
|
+
- Hash-based lookups for friendly access to complex paths
|
|
8
|
+
- Works in both Node.js and browser environments
|
|
9
|
+
|
|
10
|
+
[GitHub](https://github.com/stevenvelozo/manyfest)
|
|
11
|
+
[Get Started](#manyfest)
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Hash Translation
|
|
2
|
+
|
|
3
|
+
Hash translation tables let you reuse the same schema structure while resolving hashes to different addresses. This is useful when the same logical data model maps to objects with different property names -- for instance, when two APIs return the same information in different shapes.
|
|
4
|
+
|
|
5
|
+
## Core Concept
|
|
6
|
+
|
|
7
|
+
Normally, a descriptor's `Hash` property maps to its `Address`:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
// Schema: Hash "Title" maps to address "metadata.title"
|
|
11
|
+
manifest.getValueByHash(data, 'Title'); // resolves to data.metadata.title
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
A translation table adds a layer of indirection. It intercepts hash lookups and redirects them before the normal hash-to-address resolution runs:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
Hash Lookup → Translation Table → Descriptor Hash Table → Address → Value
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Access
|
|
21
|
+
|
|
22
|
+
Translation tables live on the `hashTranslations` property of a manifest instance:
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
const manifest = new libManyfest({
|
|
26
|
+
Scope: 'Media',
|
|
27
|
+
Descriptors: {
|
|
28
|
+
'metadata.title': { Hash: 'Title', DataType: 'String' },
|
|
29
|
+
'metadata.creator': { Hash: 'Creator', DataType: 'String' }
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Add translations
|
|
34
|
+
manifest.hashTranslations.addTranslation({
|
|
35
|
+
'Title': 'info.name',
|
|
36
|
+
'Creator': 'info.author'
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
After adding translations, `getValueByHash(data, 'Title')` resolves to `data.info.name` instead of `data.metadata.title`.
|
|
41
|
+
|
|
42
|
+
## Adding Translations
|
|
43
|
+
|
|
44
|
+
### addTranslation
|
|
45
|
+
|
|
46
|
+
Pass an object where each key is the source hash and each value is the destination hash or address:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
manifest.hashTranslations.addTranslation({
|
|
50
|
+
'SourceHash': 'DestinationHash',
|
|
51
|
+
'AnotherSource': 'AnotherDestination'
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Multiple calls are additive. Later calls can overwrite earlier translations for the same source hash.
|
|
56
|
+
|
|
57
|
+
## Removing Translations
|
|
58
|
+
|
|
59
|
+
### removeTranslation
|
|
60
|
+
|
|
61
|
+
Remove by passing a string (single hash) or an object (multiple hashes):
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// Remove a single translation
|
|
65
|
+
manifest.hashTranslations.removeTranslation('Title');
|
|
66
|
+
|
|
67
|
+
// Remove multiple at once
|
|
68
|
+
manifest.hashTranslations.removeTranslation({
|
|
69
|
+
'Title': 'info.name',
|
|
70
|
+
'Creator': 'info.author'
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
When an object is passed, only the keys matter. The values are ignored.
|
|
75
|
+
|
|
76
|
+
### clearTranslations
|
|
77
|
+
|
|
78
|
+
Remove all translations at once:
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
manifest.hashTranslations.clearTranslations();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Checking the Table
|
|
85
|
+
|
|
86
|
+
### translationCount
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
manifest.hashTranslations.translationCount(); // Number of active translations
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### translate
|
|
93
|
+
|
|
94
|
+
Translate a single hash. Returns the original hash if no translation exists:
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
manifest.hashTranslations.translate('Title'); // 'info.name' (if translated)
|
|
98
|
+
manifest.hashTranslations.translate('Unknown'); // 'Unknown' (passthrough)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Resolution Order
|
|
102
|
+
|
|
103
|
+
When `getValueByHash` (or any hash-based method) resolves a hash, the following order is used:
|
|
104
|
+
|
|
105
|
+
1. **Element hash table only** -- if the hash is in the descriptor table and not in the translation table, resolve normally
|
|
106
|
+
2. **Translation table then element hash table** -- if the hash is in the translation table and the translated result is in the element hash table, resolve through both
|
|
107
|
+
3. **Translation table only** -- if the hash is in the translation table but the translated result is not in the element hash table, use the translated value as a direct address
|
|
108
|
+
4. **Passthrough** -- if the hash is in neither table, treat it as a direct address
|
|
109
|
+
|
|
110
|
+
This means translations can override built-in descriptor hashes.
|
|
111
|
+
|
|
112
|
+
## Use Cases
|
|
113
|
+
|
|
114
|
+
### Multiple API Formats
|
|
115
|
+
|
|
116
|
+
When two APIs return the same data in different shapes, one schema handles both:
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const mediaSchema = new libManyfest({
|
|
120
|
+
Scope: 'Media',
|
|
121
|
+
Descriptors: {
|
|
122
|
+
'title': { Hash: 'Title', DataType: 'String' },
|
|
123
|
+
'author': { Hash: 'Author', DataType: 'String' },
|
|
124
|
+
'year': { Hash: 'Year', DataType: 'Integer' }
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// API A returns: { title: '...', author: '...', year: 2024 }
|
|
129
|
+
// Works out of the box:
|
|
130
|
+
mediaSchema.getValueByHash(apiAResponse, 'Title');
|
|
131
|
+
|
|
132
|
+
// API B returns: { metadata: { name: '...', creator: '...' }, info: { published: 2024 } }
|
|
133
|
+
// Add translations for API B's shape:
|
|
134
|
+
mediaSchema.hashTranslations.addTranslation({
|
|
135
|
+
'Title': 'metadata.name',
|
|
136
|
+
'Author': 'metadata.creator',
|
|
137
|
+
'Year': 'info.published'
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
mediaSchema.getValueByHash(apiBResponse, 'Title'); // reads metadata.name
|
|
141
|
+
mediaSchema.getValueByHash(apiBResponse, 'Author'); // reads metadata.creator
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Locale-Specific Field Names
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
const formSchema = new libManyfest({
|
|
148
|
+
Scope: 'Form',
|
|
149
|
+
Descriptors: {
|
|
150
|
+
'firstName': { Hash: 'FirstName', DataType: 'String' },
|
|
151
|
+
'lastName': { Hash: 'LastName', DataType: 'String' }
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Japanese form data uses different field names
|
|
156
|
+
formSchema.hashTranslations.addTranslation({
|
|
157
|
+
'FirstName': 'mei',
|
|
158
|
+
'LastName': 'sei'
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const jpData = { mei: 'Taro', sei: 'Yamada' };
|
|
162
|
+
formSchema.getValueByHash(jpData, 'FirstName'); // 'Taro'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Temporary Overrides
|
|
166
|
+
|
|
167
|
+
Apply translations for a specific operation, then clear them:
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
manifest.hashTranslations.addTranslation({ 'Name': 'display_name' });
|
|
171
|
+
|
|
172
|
+
const displayName = manifest.getValueByHash(record, 'Name');
|
|
173
|
+
|
|
174
|
+
manifest.hashTranslations.clearTranslations();
|
|
175
|
+
// Back to normal resolution
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Serialization
|
|
179
|
+
|
|
180
|
+
Hash translations are included when you serialize a manifest:
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
const state = manifest.getManifest();
|
|
184
|
+
// { Scope: '...', Descriptors: {...}, HashTranslations: {...} }
|
|
185
|
+
|
|
186
|
+
const json = manifest.serialize();
|
|
187
|
+
// HashTranslations included in the JSON string
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
And restored when you clone:
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const copy = manifest.clone();
|
|
194
|
+
// copy.hashTranslations contains the same translations
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Notes
|
|
198
|
+
|
|
199
|
+
- Translations are checked before the built-in hash table, so they can override descriptor hashes
|
|
200
|
+
- If a translation points to a hash that also has a translation, only one level of indirection is resolved
|
|
201
|
+
- Translations work with all hash-based methods: `getValueByHash`, `setValueByHash`, `deleteValueByHash`, `checkAddressExistsByHash`, `getDescriptorByHash`
|
|
202
|
+
- The translation table is a simple `{ source: destination }` object -- no nesting or chaining
|
package/docs/index.html
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>Manyfest Documentation</title>
|
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
|
7
|
+
<meta name="description" content="Documentation for Manyfest - JSON Object Manifest for Data Description and Parsing" />
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
|
9
|
+
<meta name="keywords" content="manyfest, manifest, json, object, schema, data, description, parsing, javascript" />
|
|
10
|
+
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css" />
|
|
11
|
+
<style>
|
|
12
|
+
:root {
|
|
13
|
+
--theme-color: #42b983;
|
|
14
|
+
}
|
|
15
|
+
</style>
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<div id="app"></div>
|
|
19
|
+
<script>
|
|
20
|
+
window.$docsify = {
|
|
21
|
+
name: 'Manyfest',
|
|
22
|
+
repo: 'https://github.com/stevenvelozo/manyfest',
|
|
23
|
+
loadSidebar: '_sidebar.md',
|
|
24
|
+
subMaxLevel: 3,
|
|
25
|
+
auto2top: true,
|
|
26
|
+
coverpage: 'cover.md',
|
|
27
|
+
onlyCover: false,
|
|
28
|
+
search: {
|
|
29
|
+
placeholder: 'Search',
|
|
30
|
+
noData: 'No results found',
|
|
31
|
+
depth: 3
|
|
32
|
+
},
|
|
33
|
+
copyCode: {
|
|
34
|
+
buttonText: 'Copy',
|
|
35
|
+
successText: 'Copied'
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
</script>
|
|
39
|
+
<!-- Docsify v4 -->
|
|
40
|
+
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
|
|
41
|
+
<!-- Syntax highlighting -->
|
|
42
|
+
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-javascript.min.js"></script>
|
|
43
|
+
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-json.min.js"></script>
|
|
44
|
+
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
|
|
45
|
+
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-markdown.min.js"></script>
|
|
46
|
+
<!-- Search plugin -->
|
|
47
|
+
<script src="//cdn.jsdelivr.net/npm/docsify@4/lib/plugins/search.min.js"></script>
|
|
48
|
+
<!-- Copy code plugin -->
|
|
49
|
+
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code@2"></script>
|
|
50
|
+
</body>
|
|
51
|
+
</html>
|