onelaraveljs 1.0.0
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 +87 -0
- package/docs/integration_analysis.md +116 -0
- package/docs/onejs_analysis.md +108 -0
- package/docs/optimization_implementation_group2.md +458 -0
- package/docs/optimization_plan.md +130 -0
- package/index.js +16 -0
- package/package.json +13 -0
- package/src/app.js +61 -0
- package/src/core/API.js +72 -0
- package/src/core/ChildrenRegistry.js +410 -0
- package/src/core/DOMBatcher.js +207 -0
- package/src/core/ErrorBoundary.js +226 -0
- package/src/core/EventDelegator.js +416 -0
- package/src/core/Helper.js +817 -0
- package/src/core/LoopContext.js +97 -0
- package/src/core/OneDOM.js +246 -0
- package/src/core/OneMarkup.js +444 -0
- package/src/core/Router.js +996 -0
- package/src/core/SEOConfig.js +321 -0
- package/src/core/SectionEngine.js +75 -0
- package/src/core/TemplateEngine.js +83 -0
- package/src/core/View.js +273 -0
- package/src/core/ViewConfig.js +229 -0
- package/src/core/ViewController.js +1410 -0
- package/src/core/ViewControllerOptimized.js +164 -0
- package/src/core/ViewIdentifier.js +361 -0
- package/src/core/ViewLoader.js +272 -0
- package/src/core/ViewManager.js +1962 -0
- package/src/core/ViewState.js +761 -0
- package/src/core/ViewSystem.js +301 -0
- package/src/core/ViewTemplate.js +4 -0
- package/src/core/helpers/BindingHelper.js +239 -0
- package/src/core/helpers/ConfigHelper.js +37 -0
- package/src/core/helpers/EventHelper.js +172 -0
- package/src/core/helpers/LifecycleHelper.js +17 -0
- package/src/core/helpers/ReactiveHelper.js +169 -0
- package/src/core/helpers/RenderHelper.js +15 -0
- package/src/core/helpers/ResourceHelper.js +89 -0
- package/src/core/helpers/TemplateHelper.js +11 -0
- package/src/core/managers/BindingManager.js +671 -0
- package/src/core/managers/ConfigurationManager.js +136 -0
- package/src/core/managers/EventManager.js +309 -0
- package/src/core/managers/LifecycleManager.js +356 -0
- package/src/core/managers/ReactiveManager.js +334 -0
- package/src/core/managers/RenderEngine.js +292 -0
- package/src/core/managers/ResourceManager.js +441 -0
- package/src/core/managers/ViewHierarchyManager.js +258 -0
- package/src/core/managers/ViewTemplateManager.js +127 -0
- package/src/core/reactive/ReactiveComponent.js +592 -0
- package/src/core/services/EventService.js +418 -0
- package/src/core/services/HttpService.js +106 -0
- package/src/core/services/LoggerService.js +57 -0
- package/src/core/services/StateService.js +512 -0
- package/src/core/services/StorageService.js +856 -0
- package/src/core/services/StoreService.js +258 -0
- package/src/core/services/TemplateDetectorService.js +361 -0
- package/src/core/services/Test.js +18 -0
- package/src/helpers/devWarnings.js +205 -0
- package/src/helpers/performance.js +226 -0
- package/src/helpers/utils.js +287 -0
- package/src/init.js +343 -0
- package/src/plugins/auto-plugin.js +34 -0
- package/src/services/Test.js +18 -0
- package/src/types/index.js +193 -0
- package/src/utils/date-helper.js +51 -0
- package/src/utils/helpers.js +39 -0
- package/src/utils/validation.js +32 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import { __defineProp, __hasOwnProp } from '../helpers/utils.js';
|
|
2
|
+
import OneDOM from './OneDOM.js';
|
|
3
|
+
import { TemplateDetectorService } from './services/TemplateDetectorService.js';
|
|
4
|
+
|
|
5
|
+
export class OneMarkupModel {
|
|
6
|
+
constructor(fullName, openTag, closeTag, attributes = {}, nodes = []) {
|
|
7
|
+
/**
|
|
8
|
+
* @type {Element|Comment}
|
|
9
|
+
*/
|
|
10
|
+
this.__openTag = openTag;
|
|
11
|
+
/**
|
|
12
|
+
* @type {Element|Comment}
|
|
13
|
+
*/
|
|
14
|
+
this.__closeTag = closeTag;
|
|
15
|
+
this.__attributes = attributes;
|
|
16
|
+
/**
|
|
17
|
+
* @type {Array<Element|Comment>}
|
|
18
|
+
*/
|
|
19
|
+
this.__nodes = nodes;
|
|
20
|
+
this.__definedAttributes = [];
|
|
21
|
+
this.__tagName = fullName.split(':')[1];
|
|
22
|
+
this.__fullName = fullName;
|
|
23
|
+
this.__defineAttributes(Object.keys(attributes));
|
|
24
|
+
}
|
|
25
|
+
__update(fullName, openTag, closeTag, attributes = {}, nodes = []) {
|
|
26
|
+
this.__openTag = openTag;
|
|
27
|
+
this.__closeTag = closeTag;
|
|
28
|
+
this.__attributes = attributes;
|
|
29
|
+
this.__nodes = nodes;
|
|
30
|
+
this.__tagName = fullName.split(':')[1];
|
|
31
|
+
this.__fullName = fullName;
|
|
32
|
+
this.__defineAttributes(Object.keys(attributes));
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
__defineAttributes(attributeKeys = []) {
|
|
36
|
+
for (let i = 0; i < attributeKeys.length; i++) {
|
|
37
|
+
const key = attributeKeys[i];
|
|
38
|
+
this.__defineAttribute(key);
|
|
39
|
+
}
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
__defineAttribute(name) {
|
|
43
|
+
if (this.__definedAttributes.includes(name)) {
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
this.__definedAttributes.push(name);
|
|
47
|
+
__defineProp(this, name, {
|
|
48
|
+
set: (value) => {
|
|
49
|
+
this.__attributes[name] = value;
|
|
50
|
+
return value;
|
|
51
|
+
},
|
|
52
|
+
get: () => {
|
|
53
|
+
return this.__attributes[name];
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
get tagName() {
|
|
59
|
+
return this.__tagName;
|
|
60
|
+
}
|
|
61
|
+
set tagName(name) {
|
|
62
|
+
// this.__tagName = name;
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
get fullName() {
|
|
66
|
+
return this.__fullName;
|
|
67
|
+
}
|
|
68
|
+
set fullName(name) {
|
|
69
|
+
// this.__fullName = name;
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
get openTag() {
|
|
73
|
+
return this.__openTag;
|
|
74
|
+
}
|
|
75
|
+
get closeTag() {
|
|
76
|
+
return this.__closeTag;
|
|
77
|
+
}
|
|
78
|
+
get attributes() {
|
|
79
|
+
return this.__attributes;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get the nodes of the markup element
|
|
83
|
+
* @returns {Array<Element|Comment>} - The nodes of the markup element
|
|
84
|
+
*/
|
|
85
|
+
get nodes() {
|
|
86
|
+
return this.__nodes;
|
|
87
|
+
}
|
|
88
|
+
getAttribute(name) {
|
|
89
|
+
return this.__attributes[name];
|
|
90
|
+
}
|
|
91
|
+
setAttribute(name, value) {
|
|
92
|
+
this.__defineAttribute(name);
|
|
93
|
+
this.__attributes[name] = value;
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
__match(attributes = {}) {
|
|
97
|
+
let keys = Object.keys(attributes);
|
|
98
|
+
for (let i = 0; i < keys.length; i++) {
|
|
99
|
+
const key = keys[i];
|
|
100
|
+
const value = attributes[key];
|
|
101
|
+
if (key === 'tagName') {
|
|
102
|
+
if (this.__tagName !== value) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
else if (key === 'openTag') {
|
|
108
|
+
if (this.__openTag !== value) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
else if (key === 'closeTag') {
|
|
114
|
+
if (this.__closeTag !== value) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
else if (key === 'attributes') {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
else if (key === 'nodes') {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
else if (this.__attributes[key] !== value) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
__scan() {
|
|
132
|
+
const nodes = [];
|
|
133
|
+
let currentNode = this.__openTag.nextSibling;
|
|
134
|
+
while (currentNode && currentNode !== this.__closeTag) {
|
|
135
|
+
nodes.push(currentNode);
|
|
136
|
+
currentNode = currentNode.nextSibling;
|
|
137
|
+
}
|
|
138
|
+
this.__nodes.length = 0;
|
|
139
|
+
this.__nodes.push(...nodes);
|
|
140
|
+
return this.__nodes;
|
|
141
|
+
}
|
|
142
|
+
updateNodes(nodes = []) {
|
|
143
|
+
this.__nodes = nodes;
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
replaceContent(content) {
|
|
148
|
+
if (this.__nodes.length > 0) {
|
|
149
|
+
this.__nodes.forEach(node => {
|
|
150
|
+
node.parentNode.removeChild(node);
|
|
151
|
+
});
|
|
152
|
+
this.__nodes.length = 0;
|
|
153
|
+
}
|
|
154
|
+
OneDOM.before(this.__closeTag, content);
|
|
155
|
+
this.__scan();
|
|
156
|
+
return this;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export class OneMarkupCollection {
|
|
161
|
+
constructor(elements = []) {
|
|
162
|
+
this.__models = elements.map(element => (element instanceof OneMarkupModel) ? element : new OneMarkupModel(element.fullName, element.openTag, element.closeTag, element.attributes, element.nodes));
|
|
163
|
+
}
|
|
164
|
+
get models() {
|
|
165
|
+
return this.__models;
|
|
166
|
+
}
|
|
167
|
+
get length() {
|
|
168
|
+
return this.__models.length;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Get the first model in the collection
|
|
173
|
+
* @returns {OneMarkupModel} - The first model in the collection
|
|
174
|
+
*/
|
|
175
|
+
get first() {
|
|
176
|
+
return this.__models[0];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get the last model in the collection
|
|
180
|
+
*/
|
|
181
|
+
get last() {
|
|
182
|
+
return this.__models[this.__models.length - 1];
|
|
183
|
+
}
|
|
184
|
+
push(model) {
|
|
185
|
+
if (!(model instanceof OneMarkupModel)) {
|
|
186
|
+
model = new OneMarkupModel(model.fullName, model.openTag, model.closeTag, model.attributes, model.nodes);
|
|
187
|
+
}
|
|
188
|
+
this.__models.push(model);
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
191
|
+
pop() {
|
|
192
|
+
return this.__models.pop();
|
|
193
|
+
}
|
|
194
|
+
shift() {
|
|
195
|
+
return this.__models.shift();
|
|
196
|
+
}
|
|
197
|
+
unshift(model) {
|
|
198
|
+
if (!(model instanceof OneMarkupModel)) {
|
|
199
|
+
model = new OneMarkupModel(model.fullName, model.openTag, model.closeTag, model.attributes, model.nodes);
|
|
200
|
+
}
|
|
201
|
+
this.__models.unshift(model);
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
splice(start, deleteCount, ...items) {
|
|
205
|
+
if (!(items instanceof OneMarkupCollection)) {
|
|
206
|
+
items = new OneMarkupCollection(items);
|
|
207
|
+
}
|
|
208
|
+
this.__models.splice(start, deleteCount, ...items.__models);
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
slice(start, end) {
|
|
212
|
+
return this.__models.slice(start, end);
|
|
213
|
+
}
|
|
214
|
+
concat(models) {
|
|
215
|
+
if (!(models instanceof OneMarkupCollection)) {
|
|
216
|
+
models = new OneMarkupCollection(models);
|
|
217
|
+
}
|
|
218
|
+
return new OneMarkupCollection(this.__models.concat(models.__models));
|
|
219
|
+
}
|
|
220
|
+
reverse() {
|
|
221
|
+
return new OneMarkupCollection(this.__models.reverse());
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Get the model at the given index
|
|
226
|
+
* @param {number} index - The index of the model to get
|
|
227
|
+
* @returns {OneMarkupModel} - The model at the given index
|
|
228
|
+
*/
|
|
229
|
+
get(index) {
|
|
230
|
+
return this.__models[index];
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Set the model at the given index
|
|
234
|
+
* @param {number} index - The index of the model to set
|
|
235
|
+
* @param {OneMarkupModel} model - The model to set at the given index
|
|
236
|
+
* @returns {OneMarkupCollection} - The collection
|
|
237
|
+
*/
|
|
238
|
+
set(index, model) {
|
|
239
|
+
this.__models[index] = model;
|
|
240
|
+
return this;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Map the collection to a new array
|
|
245
|
+
* @param {function} callback - The callback function to map the collection
|
|
246
|
+
* @returns {Array} - The new array
|
|
247
|
+
*/
|
|
248
|
+
map(callback) {
|
|
249
|
+
return this.__models.map(callback);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Filter the collection to a new array
|
|
253
|
+
* @param {function} callback - The callback function to filter the collection
|
|
254
|
+
* @returns {Array} - The new array
|
|
255
|
+
*/
|
|
256
|
+
filter(callback) {
|
|
257
|
+
return this.__models.filter(callback);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Reduce the collection to a single value
|
|
261
|
+
* @param {function} callback - The callback function to reduce the collection
|
|
262
|
+
* @param {any} initialValue - The initial value to reduce the collection
|
|
263
|
+
* @returns {any} - The reduced value
|
|
264
|
+
*/
|
|
265
|
+
reduce(callback, initialValue) {
|
|
266
|
+
return this.__models.reduce(callback, initialValue);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* For each the collection
|
|
270
|
+
* @param {function} callback - The callback function to for each the collection
|
|
271
|
+
* @returns {OneMarkupCollection} - The collection
|
|
272
|
+
*/
|
|
273
|
+
forEach(callback) {
|
|
274
|
+
return this.__models.forEach(callback);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Some the collection
|
|
278
|
+
* @param {function} callback - The callback function to some the collection
|
|
279
|
+
* @returns {boolean} - True if some of the collection matches the callback, false otherwise
|
|
280
|
+
*/
|
|
281
|
+
some(callback) {
|
|
282
|
+
return this.__models.some(callback);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Every the collection
|
|
286
|
+
* @param {function} callback - The callback function to every the collection
|
|
287
|
+
* @returns {boolean} - True if every of the collection matches the callback, false otherwise
|
|
288
|
+
*/
|
|
289
|
+
every(callback) {
|
|
290
|
+
return this.__models.every(callback);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Query the collection
|
|
294
|
+
* @param {object} attributes - The attributes to query the collection
|
|
295
|
+
* @returns {Array} - The filtered array
|
|
296
|
+
*/
|
|
297
|
+
query(attributes = {}) {
|
|
298
|
+
return this.__models.filter(model => model.__match(attributes));
|
|
299
|
+
}
|
|
300
|
+
find(attributes = {}) {
|
|
301
|
+
return this.query(attributes)[0] || null;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export class OneMarkupService {
|
|
306
|
+
constructor() {
|
|
307
|
+
/**
|
|
308
|
+
* @type {TemplateDetectorService}
|
|
309
|
+
*/
|
|
310
|
+
this.detector = new TemplateDetectorService(document.documentElement);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Find the first element that matches the pattern and attributes
|
|
315
|
+
* @param {string} pattern - The pattern to find
|
|
316
|
+
* @param {object} attributes - The attributes to find
|
|
317
|
+
* @param {object} options - The options to find
|
|
318
|
+
* @param {number} total - The total to find
|
|
319
|
+
* @returns {OneMarkupModel|OneMarkupCollection} - The first element that matches the pattern and attributes
|
|
320
|
+
*/
|
|
321
|
+
find(pattern = '*', attributes = {}, options = {}, total = false, isOne = false) {
|
|
322
|
+
if (!__hasOwnProp(this, 'useCache')) {
|
|
323
|
+
options.useCache = false;
|
|
324
|
+
}
|
|
325
|
+
const elements = this.detector.find("one:" + pattern, options);
|
|
326
|
+
const isTotal = total && typeof total === 'number' && total !== 0;
|
|
327
|
+
const isLast = isTotal && total === -1 && isOne;
|
|
328
|
+
const isFirst = total && total === 1 && isOne;
|
|
329
|
+
const isRight = isTotal && total < 0 && !isOne;
|
|
330
|
+
const oneIndex = isOne && isTotal && !isLast && !isFirst ? (total >= 0 ? (elements.length - total > 0 ? total : 0) : 0) : (elements.length + total > 0 ? (elements.length + total - 1): elements.length - 1);
|
|
331
|
+
|
|
332
|
+
if (elements.length === 0) {
|
|
333
|
+
if (isLast || isFirst) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
return new OneMarkupCollection([]);
|
|
337
|
+
}
|
|
338
|
+
if (typeof attributes !== 'object' || attributes === null || Object.keys(attributes).length === 0) {
|
|
339
|
+
if (!isTotal) {
|
|
340
|
+
return new OneMarkupCollection(elements);
|
|
341
|
+
}
|
|
342
|
+
if (isLast) {
|
|
343
|
+
const lastElement = elements[elements.length - 1];
|
|
344
|
+
return new OneMarkupModel(lastElement.fullName, lastElement.openTag, lastElement.closeTag, lastElement.attributes, lastElement.nodes);
|
|
345
|
+
}
|
|
346
|
+
if (isFirst) {
|
|
347
|
+
return new OneMarkupModel(elements[0].fullName, elements[0].openTag, elements[0].closeTag, elements[0].attributes, elements[0].nodes);
|
|
348
|
+
}
|
|
349
|
+
if (isRight) {
|
|
350
|
+
let rightIndex = elements.length - total;
|
|
351
|
+
if (rightIndex < 0) {
|
|
352
|
+
rightIndex = 0;
|
|
353
|
+
}
|
|
354
|
+
return new OneMarkupCollection(elements.slice(rightIndex));
|
|
355
|
+
}
|
|
356
|
+
if(isOne){
|
|
357
|
+
const element = elements[oneIndex];
|
|
358
|
+
if(!element){
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
return new OneMarkupModel(element.fullName, element.openTag, element.closeTag, element.attributes, element.nodes);
|
|
362
|
+
}
|
|
363
|
+
return new OneMarkupCollection(elements.slice(0, total));
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
}
|
|
367
|
+
const keys = Object.keys(attributes);
|
|
368
|
+
const result = [];
|
|
369
|
+
const elementCount = elements.length;
|
|
370
|
+
const lastIndex = elementCount - 1;
|
|
371
|
+
let findIndex = 0;
|
|
372
|
+
for (let i = 0; i < elementCount; i++) {
|
|
373
|
+
if (isLast && findIndex < lastIndex) {
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
const element = elements[i];
|
|
377
|
+
let isMatch = true;
|
|
378
|
+
for (let j = 0; j < keys.length; j++) {
|
|
379
|
+
const key = keys[j];
|
|
380
|
+
const value = attributes[key];
|
|
381
|
+
if (element.attributes[key] !== value) {
|
|
382
|
+
isMatch = false;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (!isMatch) {
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
if (isFirst) {
|
|
390
|
+
return new OneMarkupModel(element.fullName, element.openTag, element.closeTag, element.attributes, element.nodes);
|
|
391
|
+
}
|
|
392
|
+
else if (isLast) {
|
|
393
|
+
if(findIndex === lastIndex) {
|
|
394
|
+
return new OneMarkupModel(element.fullName, element.openTag, element.closeTag, element.attributes, element.nodes);
|
|
395
|
+
}
|
|
396
|
+
findIndex++;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
else if(isRight) {
|
|
400
|
+
if(findIndex >= rightIndex) {
|
|
401
|
+
result.push(element);
|
|
402
|
+
}
|
|
403
|
+
findIndex++;
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
else if(isTotal) {
|
|
407
|
+
result.push(element);
|
|
408
|
+
findIndex++;
|
|
409
|
+
if(result.length >= total) {
|
|
410
|
+
return new OneMarkupCollection(result);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
else if(isOne && findIndex === oneIndex){
|
|
414
|
+
return new OneMarkupModel(element.fullName, element.openTag, element.closeTag, element.attributes, element.nodes);
|
|
415
|
+
}
|
|
416
|
+
else{
|
|
417
|
+
result.push(element);
|
|
418
|
+
findIndex++;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if(result.length === 0) {
|
|
422
|
+
if (isLast || isFirst || isOne) {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return new OneMarkupCollection(result);
|
|
427
|
+
}
|
|
428
|
+
findOne(pattern = '*', attributes = {}, options = {}, index = 0) {
|
|
429
|
+
return this.find(pattern, attributes, options, index, true);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
first(pattern = '*', attributes = {}, options = {}) {
|
|
433
|
+
return this.find(pattern, attributes, options, 1, true);
|
|
434
|
+
}
|
|
435
|
+
last(pattern = '*', attributes = {}, options = {}) {
|
|
436
|
+
return this.find(pattern, attributes, options, -1, true);
|
|
437
|
+
}
|
|
438
|
+
right(pattern = '*', attributes = {}, total = 1, options = {}) {
|
|
439
|
+
return this.find(pattern, attributes, options, -total, false);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export const OneMarkup = new OneMarkupService();
|
|
444
|
+
export default OneMarkup;
|