script-engine-lib 0.4.3 → 1.0.0-rc0
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/dist/index.d.mts +191 -0
- package/dist/index.d.ts +191 -5
- package/dist/index.js +21 -29
- package/dist/index.mjs +21 -0
- package/package.json +56 -52
- package/src/index.ts +10 -0
- package/dist/decorators/action-before-testing.d.ts +0 -2
- package/dist/decorators/action-before-testing.js +0 -23
- package/dist/decorators/action-before-testing.test.d.ts +0 -1
- package/dist/decorators/action-before-testing.test.js +0 -82
- package/dist/engine/script-engine.d.ts +0 -35
- package/dist/engine/script-engine.js +0 -175
- package/dist/engine/script-engine.test.d.ts +0 -1
- package/dist/engine/script-engine.test.js +0 -1277
- package/dist/engine/story-engine.d.ts +0 -35
- package/dist/engine/story-engine.js +0 -175
- package/dist/engine/story-engine.test.d.ts +0 -1
- package/dist/engine/story-engine.test.js +0 -1277
- package/dist/interfaces.d.ts +0 -51
- package/dist/interfaces.js +0 -27
- package/dist/simulator/decorators.d.ts +0 -2
- package/dist/simulator/decorators.js +0 -23
- package/dist/simulator/decorators.test.d.ts +0 -1
- package/dist/simulator/decorators.test.js +0 -81
- package/dist/simulator/event-branches-map.d.ts +0 -16
- package/dist/simulator/event-branches-map.js +0 -114
- package/dist/simulator/event-branches-map.test.d.ts +0 -1
- package/dist/simulator/event-branches-map.test.js +0 -120
- package/dist/simulator/event-test-simulator.d.ts +0 -42
- package/dist/simulator/event-test-simulator.js +0 -373
- package/dist/simulator/event-test-simulator.test.d.ts +0 -1
- package/dist/simulator/event-test-simulator.test.js +0 -1960
- package/dist/simulator/execution-history.d.ts +0 -6
- package/dist/simulator/execution-history.js +0 -22
- package/dist/simulator/helpers/event-branches-map.d.ts +0 -16
- package/dist/simulator/helpers/event-branches-map.js +0 -114
- package/dist/simulator/helpers/event-branches-map.test.d.ts +0 -1
- package/dist/simulator/helpers/event-branches-map.test.js +0 -120
- package/dist/simulator/helpers/execution-history.d.ts +0 -6
- package/dist/simulator/helpers/execution-history.js +0 -22
- package/dist/simulator/helpers/script-branches-map.d.ts +0 -16
- package/dist/simulator/helpers/script-branches-map.js +0 -114
- package/dist/simulator/helpers/script-branches-map.test.d.ts +0 -1
- package/dist/simulator/helpers/script-branches-map.test.js +0 -120
- package/dist/simulator/script-test-simulator.d.ts +0 -42
- package/dist/simulator/script-test-simulator.js +0 -373
- package/dist/simulator/script-test-simulator.test.d.ts +0 -1
- package/dist/simulator/script-test-simulator.test.js +0 -2013
- package/dist/structured-text/index.d.ts +0 -9
- package/dist/structured-text/index.js +0 -8
- package/dist/structured-text/rich-text-separator.d.ts +0 -48
- package/dist/structured-text/rich-text-separator.js +0 -146
- package/dist/structured-text/rich-text-separator.test.d.ts +0 -1
- package/dist/structured-text/rich-text-separator.test.js +0 -166
- package/dist/structured-text/rich-text-validator.d.ts +0 -19
- package/dist/structured-text/rich-text-validator.js +0 -73
- package/dist/structured-text/rich-text-validator.test.d.ts +0 -1
- package/dist/structured-text/rich-text-validator.test.js +0 -59
- package/dist/test.spec.d.ts +0 -0
- package/dist/test.spec.js +0 -7
- package/dist/test.test.d.ts +0 -1
- package/dist/test.test.js +0 -9
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interface representing a text segment with text content and associated tags
|
|
3
|
-
*/
|
|
4
|
-
export interface TextSegment {
|
|
5
|
-
text: string;
|
|
6
|
-
tags: string[];
|
|
7
|
-
}
|
|
8
|
-
export { RichTextSeparator } from './rich-text-separator';
|
|
9
|
-
export { RichTextValidator } from './rich-text-validator';
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RichTextValidator = exports.RichTextSeparator = void 0;
|
|
4
|
-
var rich_text_separator_1 = require("./rich-text-separator");
|
|
5
|
-
Object.defineProperty(exports, "RichTextSeparator", { enumerable: true, get: function () { return rich_text_separator_1.RichTextSeparator; } });
|
|
6
|
-
var rich_text_validator_1 = require("./rich-text-validator");
|
|
7
|
-
Object.defineProperty(exports, "RichTextValidator", { enumerable: true, get: function () { return rich_text_validator_1.RichTextValidator; } });
|
|
8
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { TextSegment } from '.';
|
|
2
|
-
/**
|
|
3
|
-
* Class to separate text with XML tags into structured segments
|
|
4
|
-
*/
|
|
5
|
-
export declare class RichTextSeparator {
|
|
6
|
-
/**
|
|
7
|
-
* Processes a string with XML tags and returns structured text segments
|
|
8
|
-
* @param input The input string containing XML tags Sample: "text <outer>with <inner>nested</inner> content</outer>"
|
|
9
|
-
* @param tags Optional set of allowed tags. If provided, all tags must be included in this set
|
|
10
|
-
* @returns Array of TextSegment objects Sample: [
|
|
11
|
-
{
|
|
12
|
-
text: 'text ',
|
|
13
|
-
tags: []
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
text: 'with ',
|
|
17
|
-
tags: ['outer']
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
text: 'nested',
|
|
21
|
-
tags: ['outer', 'inner']
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
text: ' content',
|
|
25
|
-
tags: ['outer']
|
|
26
|
-
}
|
|
27
|
-
]
|
|
28
|
-
* @throws Error if the input contains invalid tag structure
|
|
29
|
-
*/
|
|
30
|
-
static process(input: string, tags?: Set<string>): TextSegment[];
|
|
31
|
-
/**
|
|
32
|
-
* Combines adjacent segments that have the same tags
|
|
33
|
-
* @param segments Array of text segments
|
|
34
|
-
* @returns Array of combined text segments
|
|
35
|
-
*/
|
|
36
|
-
private static combineAdjacentSegmentsWithSameTags;
|
|
37
|
-
/**
|
|
38
|
-
* Processes text with a current stack of tags
|
|
39
|
-
* @param input Text to process
|
|
40
|
-
* @param currentTags Current stack of tags
|
|
41
|
-
* @returns Array of flat TextSegment objects
|
|
42
|
-
*/
|
|
43
|
-
private static processWithTags;
|
|
44
|
-
/**
|
|
45
|
-
* Finds the position of the matching closing tag, taking into account nesting
|
|
46
|
-
*/
|
|
47
|
-
private static findMatchingClosingTag;
|
|
48
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RichTextSeparator = void 0;
|
|
4
|
-
const rich_text_validator_1 = require("./rich-text-validator");
|
|
5
|
-
/**
|
|
6
|
-
* Class to separate text with XML tags into structured segments
|
|
7
|
-
*/
|
|
8
|
-
class RichTextSeparator {
|
|
9
|
-
/**
|
|
10
|
-
* Processes a string with XML tags and returns structured text segments
|
|
11
|
-
* @param input The input string containing XML tags Sample: "text <outer>with <inner>nested</inner> content</outer>"
|
|
12
|
-
* @param tags Optional set of allowed tags. If provided, all tags must be included in this set
|
|
13
|
-
* @returns Array of TextSegment objects Sample: [
|
|
14
|
-
{
|
|
15
|
-
text: 'text ',
|
|
16
|
-
tags: []
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
text: 'with ',
|
|
20
|
-
tags: ['outer']
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
text: 'nested',
|
|
24
|
-
tags: ['outer', 'inner']
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
text: ' content',
|
|
28
|
-
tags: ['outer']
|
|
29
|
-
}
|
|
30
|
-
]
|
|
31
|
-
* @throws Error if the input contains invalid tag structure
|
|
32
|
-
*/
|
|
33
|
-
static process(input, tags) {
|
|
34
|
-
rich_text_validator_1.RichTextValidator.validate(input, tags);
|
|
35
|
-
let segments = this.processWithTags(input, []);
|
|
36
|
-
return this.combineAdjacentSegmentsWithSameTags(segments);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Combines adjacent segments that have the same tags
|
|
40
|
-
* @param segments Array of text segments
|
|
41
|
-
* @returns Array of combined text segments
|
|
42
|
-
*/
|
|
43
|
-
static combineAdjacentSegmentsWithSameTags(segments) {
|
|
44
|
-
if (segments.length <= 1) {
|
|
45
|
-
return segments;
|
|
46
|
-
}
|
|
47
|
-
let result = [];
|
|
48
|
-
let current = segments[0];
|
|
49
|
-
for (let i = 1; i < segments.length; i++) {
|
|
50
|
-
let next = segments[i];
|
|
51
|
-
let tagsEqual = current.tags.length === next.tags.length && current.tags.every((tag, index) => tag === next.tags[index]);
|
|
52
|
-
if (tagsEqual) {
|
|
53
|
-
current = {
|
|
54
|
-
text: current.text + next.text,
|
|
55
|
-
tags: current.tags
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
result.push(current);
|
|
60
|
-
current = next;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
result.push(current);
|
|
64
|
-
return result;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Processes text with a current stack of tags
|
|
68
|
-
* @param input Text to process
|
|
69
|
-
* @param currentTags Current stack of tags
|
|
70
|
-
* @returns Array of flat TextSegment objects
|
|
71
|
-
*/
|
|
72
|
-
static processWithTags(input, currentTags) {
|
|
73
|
-
let result = [];
|
|
74
|
-
let currentPos = 0;
|
|
75
|
-
if (input === '') {
|
|
76
|
-
return [
|
|
77
|
-
{
|
|
78
|
-
text: '',
|
|
79
|
-
tags: []
|
|
80
|
-
}
|
|
81
|
-
];
|
|
82
|
-
}
|
|
83
|
-
while (currentPos < input.length) {
|
|
84
|
-
let nextTagPos = input.indexOf('<', currentPos);
|
|
85
|
-
if (nextTagPos === -1) {
|
|
86
|
-
if (currentPos < input.length) {
|
|
87
|
-
let text = input.substring(currentPos);
|
|
88
|
-
if (text.length > 0) {
|
|
89
|
-
result.push({
|
|
90
|
-
text: text,
|
|
91
|
-
tags: [...currentTags]
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
if (nextTagPos > currentPos) {
|
|
98
|
-
let text = input.substring(currentPos, nextTagPos);
|
|
99
|
-
if (text.length > 0) {
|
|
100
|
-
result.push({
|
|
101
|
-
text: text,
|
|
102
|
-
tags: [...currentTags]
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
let openTagEnd = input.indexOf('>', nextTagPos);
|
|
107
|
-
let tagName = input.substring(nextTagPos + 1, openTagEnd);
|
|
108
|
-
let closeTagStart = this.findMatchingClosingTag(input, tagName, openTagEnd + 1);
|
|
109
|
-
let tagContent = input.substring(openTagEnd + 1, closeTagStart);
|
|
110
|
-
if (tagContent.length === 0) {
|
|
111
|
-
currentPos = closeTagStart + tagName.length + 3; // +3 for '</>'
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
let newTags = [...currentTags, tagName];
|
|
115
|
-
let nestedSegments = this.processWithTags(tagContent, newTags);
|
|
116
|
-
result.push(...nestedSegments);
|
|
117
|
-
currentPos = closeTagStart + tagName.length + 3; // +3 for '</>'
|
|
118
|
-
}
|
|
119
|
-
return result;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Finds the position of the matching closing tag, taking into account nesting
|
|
123
|
-
*/
|
|
124
|
-
static findMatchingClosingTag(input, tagName, startPos) {
|
|
125
|
-
let searchPos = startPos;
|
|
126
|
-
let nestLevel = 1;
|
|
127
|
-
while (searchPos < input.length && nestLevel > 0) {
|
|
128
|
-
let nextOpenTag = input.indexOf('<' + tagName, searchPos);
|
|
129
|
-
let nextCloseTag = input.indexOf('</' + tagName + '>', searchPos);
|
|
130
|
-
if (nextOpenTag !== -1 && nextOpenTag < nextCloseTag) {
|
|
131
|
-
nestLevel++;
|
|
132
|
-
searchPos = nextOpenTag + 1;
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
nestLevel--;
|
|
136
|
-
if (nestLevel === 0) {
|
|
137
|
-
return nextCloseTag;
|
|
138
|
-
}
|
|
139
|
-
searchPos = nextCloseTag + 1;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return input.length;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
exports.RichTextSeparator = RichTextSeparator;
|
|
146
|
-
//# sourceMappingURL=rich-text-separator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const rich_text_separator_1 = require("./rich-text-separator");
|
|
5
|
-
(0, vitest_1.describe)('RichTextSeparator', () => {
|
|
6
|
-
(0, vitest_1.describe)('process method', () => {
|
|
7
|
-
(0, vitest_1.test)('should handle empty text without tags', () => {
|
|
8
|
-
let input = '';
|
|
9
|
-
let result = rich_text_separator_1.RichTextSeparator.process(input);
|
|
10
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
11
|
-
{
|
|
12
|
-
text: '',
|
|
13
|
-
tags: []
|
|
14
|
-
}
|
|
15
|
-
]);
|
|
16
|
-
});
|
|
17
|
-
(0, vitest_1.test)('should handle plain text without tags', () => {
|
|
18
|
-
let input = 'Simple text without any tags';
|
|
19
|
-
let result = rich_text_separator_1.RichTextSeparator.process(input);
|
|
20
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
21
|
-
{
|
|
22
|
-
text: 'Simple text without any tags',
|
|
23
|
-
tags: []
|
|
24
|
-
}
|
|
25
|
-
]);
|
|
26
|
-
});
|
|
27
|
-
(0, vitest_1.test)('should handle single tag correctly', () => {
|
|
28
|
-
let input = '<b>Bold text</b>';
|
|
29
|
-
let result = rich_text_separator_1.RichTextSeparator.process(input);
|
|
30
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
31
|
-
{
|
|
32
|
-
text: 'Bold text',
|
|
33
|
-
tags: ['b']
|
|
34
|
-
}
|
|
35
|
-
]);
|
|
36
|
-
});
|
|
37
|
-
(0, vitest_1.test)('should handle text with surrounding tags', () => {
|
|
38
|
-
let input = 'some text <b>with tags</b>';
|
|
39
|
-
let result = rich_text_separator_1.RichTextSeparator.process(input);
|
|
40
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
41
|
-
{
|
|
42
|
-
text: 'some text ',
|
|
43
|
-
tags: []
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
text: 'with tags',
|
|
47
|
-
tags: ['b']
|
|
48
|
-
}
|
|
49
|
-
]);
|
|
50
|
-
});
|
|
51
|
-
(0, vitest_1.test)('should handle multiple tags', () => {
|
|
52
|
-
let input = '<h1>Header</h1> with <p>paragraph</p>';
|
|
53
|
-
let result = rich_text_separator_1.RichTextSeparator.process(input);
|
|
54
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
55
|
-
{
|
|
56
|
-
text: 'Header',
|
|
57
|
-
tags: ['h1']
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
text: ' with ',
|
|
61
|
-
tags: []
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
text: 'paragraph',
|
|
65
|
-
tags: ['p']
|
|
66
|
-
}
|
|
67
|
-
]);
|
|
68
|
-
});
|
|
69
|
-
(0, vitest_1.test)('should ignore empty tags', () => {
|
|
70
|
-
let input = 'Text with <empty></empty>tags';
|
|
71
|
-
let result = rich_text_separator_1.RichTextSeparator.process(input);
|
|
72
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
73
|
-
{
|
|
74
|
-
text: 'Text with tags',
|
|
75
|
-
tags: []
|
|
76
|
-
}
|
|
77
|
-
]);
|
|
78
|
-
});
|
|
79
|
-
(0, vitest_1.test)('should handle nested tags', () => {
|
|
80
|
-
let input = 'text <outer>with <inner>nested</inner> content</outer>';
|
|
81
|
-
let result = rich_text_separator_1.RichTextSeparator.process(input);
|
|
82
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
83
|
-
{
|
|
84
|
-
text: 'text ',
|
|
85
|
-
tags: []
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
text: 'with ',
|
|
89
|
-
tags: ['outer']
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
text: 'nested',
|
|
93
|
-
tags: ['outer', 'inner']
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
text: ' content',
|
|
97
|
-
tags: ['outer']
|
|
98
|
-
}
|
|
99
|
-
]);
|
|
100
|
-
});
|
|
101
|
-
(0, vitest_1.test)('should handle the complex example from requirements', () => {
|
|
102
|
-
let input = 'some text <b>with tags</b> with <b>multiple<i>nested<n>tags</n></i></b>';
|
|
103
|
-
let result = rich_text_separator_1.RichTextSeparator.process(input);
|
|
104
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
105
|
-
{
|
|
106
|
-
text: 'some text ',
|
|
107
|
-
tags: []
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
text: 'with tags',
|
|
111
|
-
tags: ['b']
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
text: ' with ',
|
|
115
|
-
tags: []
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
text: 'multiple',
|
|
119
|
-
tags: ['b']
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
text: 'nested',
|
|
123
|
-
tags: ['b', 'i']
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
text: 'tags',
|
|
127
|
-
tags: ['b', 'i', 'n']
|
|
128
|
-
}
|
|
129
|
-
]);
|
|
130
|
-
});
|
|
131
|
-
(0, vitest_1.test)('should throw error for malformed input', () => {
|
|
132
|
-
// Missing closing tag
|
|
133
|
-
let input1 = '<div>unclosed tag';
|
|
134
|
-
(0, vitest_1.expect)(() => rich_text_separator_1.RichTextSeparator.process(input1)).toThrow(`Unclosed tag: div`);
|
|
135
|
-
// Unclosed tag with content
|
|
136
|
-
let input2 = 'text with <b>bold text but no closing tag';
|
|
137
|
-
(0, vitest_1.expect)(() => rich_text_separator_1.RichTextSeparator.process(input2)).toThrow(`Unclosed tag: b`);
|
|
138
|
-
// Mismatched tags
|
|
139
|
-
let input3 = '<div>text</span>';
|
|
140
|
-
(0, vitest_1.expect)(() => rich_text_separator_1.RichTextSeparator.process(input3)).toThrow(`Mismatched tags: expected closing tag for 'div', but found 'span' at position 9`);
|
|
141
|
-
});
|
|
142
|
-
(0, vitest_1.test)('should validate against allowed tags set', () => {
|
|
143
|
-
let allowedTags = new Set(['b', 'i', 'p']);
|
|
144
|
-
// Valid input with allowed tags
|
|
145
|
-
let validInput = 'This is <b>bold</b> and <i>italic</i> text with a <p>paragraph</p>';
|
|
146
|
-
let result = rich_text_separator_1.RichTextSeparator.process(validInput, allowedTags);
|
|
147
|
-
(0, vitest_1.expect)(result).toEqual([
|
|
148
|
-
{ text: 'This is ', tags: [] },
|
|
149
|
-
{ text: 'bold', tags: ['b'] },
|
|
150
|
-
{ text: ' and ', tags: [] },
|
|
151
|
-
{ text: 'italic', tags: ['i'] },
|
|
152
|
-
{ text: ' text with a ', tags: [] },
|
|
153
|
-
{ text: 'paragraph', tags: ['p'] }
|
|
154
|
-
]);
|
|
155
|
-
// Invalid input with disallowed tag
|
|
156
|
-
let invalidInput = 'This is <b>bold</b> with <div>div tag</div>';
|
|
157
|
-
(0, vitest_1.expect)(() => rich_text_separator_1.RichTextSeparator.process(invalidInput, allowedTags)).toThrow(`Unknown tag 'div' at position 25. Only these tags are allowed: b, i, p`);
|
|
158
|
-
});
|
|
159
|
-
(0, vitest_1.test)('should process correctly with empty allowed tags set', () => {
|
|
160
|
-
let emptyAllowedTags = new Set();
|
|
161
|
-
let input = 'Text with <any>tags</any>';
|
|
162
|
-
(0, vitest_1.expect)(() => rich_text_separator_1.RichTextSeparator.process(input, emptyAllowedTags)).toThrow(`Unknown tag 'any' at position 10. Only these tags are allowed: `);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
//# sourceMappingURL=rich-text-separator.test.js.map
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Class responsible for validating XML-like tags in text
|
|
3
|
-
*/
|
|
4
|
-
export declare class RichTextValidator {
|
|
5
|
-
/**
|
|
6
|
-
* Checks if the input has valid tag structure
|
|
7
|
-
* @param input The input string containing XML-like tags
|
|
8
|
-
* @param tags Optional set of allowed tags. If provided, all tags must be included in this set
|
|
9
|
-
* @returns true if all tags are valid, false otherwise
|
|
10
|
-
*/
|
|
11
|
-
static isValid(input: string, tags?: Set<string>): boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Validates if all tags in the text are properly opened and closed
|
|
14
|
-
* @param input The input string containing XML-like tags
|
|
15
|
-
* @param tags Optional set of allowed tags. If provided, all tags must be included in this set
|
|
16
|
-
* @throws Error if tags are not properly formed with details about the issue
|
|
17
|
-
*/
|
|
18
|
-
static validate(input: string, tags?: Set<string>): void;
|
|
19
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RichTextValidator = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Class responsible for validating XML-like tags in text
|
|
6
|
-
*/
|
|
7
|
-
class RichTextValidator {
|
|
8
|
-
/**
|
|
9
|
-
* Checks if the input has valid tag structure
|
|
10
|
-
* @param input The input string containing XML-like tags
|
|
11
|
-
* @param tags Optional set of allowed tags. If provided, all tags must be included in this set
|
|
12
|
-
* @returns true if all tags are valid, false otherwise
|
|
13
|
-
*/
|
|
14
|
-
static isValid(input, tags) {
|
|
15
|
-
try {
|
|
16
|
-
this.validate(input, tags);
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Validates if all tags in the text are properly opened and closed
|
|
25
|
-
* @param input The input string containing XML-like tags
|
|
26
|
-
* @param tags Optional set of allowed tags. If provided, all tags must be included in this set
|
|
27
|
-
* @throws Error if tags are not properly formed with details about the issue
|
|
28
|
-
*/
|
|
29
|
-
static validate(input, tags) {
|
|
30
|
-
let stack = [];
|
|
31
|
-
let pos = 0;
|
|
32
|
-
while (pos < input.length) {
|
|
33
|
-
let tagStart = input.indexOf('<', pos);
|
|
34
|
-
if (tagStart === -1) {
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
let isClosingTag = input[tagStart + 1] === '/';
|
|
38
|
-
let tagNameStart = tagStart + (isClosingTag ? 2 : 1);
|
|
39
|
-
let tagEnd = input.indexOf('>', tagStart);
|
|
40
|
-
if (tagEnd === -1) {
|
|
41
|
-
throw new Error(`Malformed tag at position ${tagStart}: missing closing bracket '>'`);
|
|
42
|
-
}
|
|
43
|
-
let tagName = input.substring(tagNameStart, tagEnd);
|
|
44
|
-
if (tagName.trim() === '') {
|
|
45
|
-
throw new Error(`Empty tag name found at position ${tagStart}`);
|
|
46
|
-
}
|
|
47
|
-
if (/\s/.test(tagName)) {
|
|
48
|
-
throw new Error(`Invalid tag name '${tagName}' at position ${tagStart}: contains whitespace`);
|
|
49
|
-
}
|
|
50
|
-
if (tags && !isClosingTag && !tags.has(tagName)) {
|
|
51
|
-
throw new Error(`Unknown tag '${tagName}' at position ${tagStart}. Only these tags are allowed: ${[...tags].join(', ')}`);
|
|
52
|
-
}
|
|
53
|
-
if (isClosingTag) {
|
|
54
|
-
if (stack.length === 0) {
|
|
55
|
-
throw new Error(`Closing tag '${tagName}' at position ${tagStart} has no matching opening tag`);
|
|
56
|
-
}
|
|
57
|
-
let lastOpenTag = stack.pop();
|
|
58
|
-
if (lastOpenTag !== tagName) {
|
|
59
|
-
throw new Error(`Mismatched tags: expected closing tag for '${lastOpenTag}', but found '${tagName}' at position ${tagStart}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
stack.push(tagName);
|
|
64
|
-
}
|
|
65
|
-
pos = tagEnd + 1;
|
|
66
|
-
}
|
|
67
|
-
if (stack.length > 0) {
|
|
68
|
-
throw new Error(`Unclosed tag${stack.length > 1 ? 's' : ''}: ${stack.join(', ')}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
exports.RichTextValidator = RichTextValidator;
|
|
73
|
-
//# sourceMappingURL=rich-text-validator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const rich_text_validator_1 = require("./rich-text-validator");
|
|
5
|
-
(0, vitest_1.describe)('RichTextValidator', () => {
|
|
6
|
-
(0, vitest_1.describe)('validate method', () => {
|
|
7
|
-
(0, vitest_1.test)('should not throw error for valid tag structure', () => {
|
|
8
|
-
let validInputs = [
|
|
9
|
-
'Simple text without any tags',
|
|
10
|
-
'<b>Bold text</b>',
|
|
11
|
-
'some text <b>with tags</b>',
|
|
12
|
-
'<h1>Header</h1> with <p>paragraph</p>',
|
|
13
|
-
'<outer>with <inner>nested</inner> content</outer>',
|
|
14
|
-
'some text <b>with tags</b> with <b>multiple<i>nested<n>tags</n></i></b>',
|
|
15
|
-
'' // empty string is valid
|
|
16
|
-
];
|
|
17
|
-
validInputs.forEach(input => {
|
|
18
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate(input)).not.toThrow();
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
(0, vitest_1.test)('should throw errors with specific messages for invalid tag structures', () => {
|
|
22
|
-
// Unclosed tag
|
|
23
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('<div>unclosed tag')).toThrow('Unclosed tag: div');
|
|
24
|
-
// Tag with no closing bracket
|
|
25
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('<div unclosed')).toThrow(`Malformed tag at position 0: missing closing bracket '>'`);
|
|
26
|
-
// Mismatched tags
|
|
27
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('<div>text</span>')).toThrow(`Mismatched tags: expected closing tag for 'div', but found 'span' at position 9`);
|
|
28
|
-
// Improperly nested tags
|
|
29
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('<a><b></a></b>')).toThrow(`Mismatched tags: expected closing tag for 'b', but found 'a' at position 6`);
|
|
30
|
-
// Empty tag
|
|
31
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('<>')).toThrow(`Empty tag name found at position 0`);
|
|
32
|
-
// Invalid tag name with whitespace
|
|
33
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('< invalid>')).toThrow(`Invalid tag name ' invalid' at position 0: contains whitespace`);
|
|
34
|
-
// Closing tag without opening tag
|
|
35
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('</p>text')).toThrow(`Closing tag 'p' at position 0 has no matching opening tag`);
|
|
36
|
-
});
|
|
37
|
-
(0, vitest_1.test)('should validate tags against provided allowed tags set', () => {
|
|
38
|
-
let allowedTags = new Set(['b', 'i', 'p']);
|
|
39
|
-
// Valid input with allowed tags
|
|
40
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('<b>Bold</b> and <i>italic</i>', allowedTags)).not.toThrow();
|
|
41
|
-
// Invalid input with disallowed tag
|
|
42
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('<div>Not allowed</div>', allowedTags)).toThrow(`Unknown tag 'div' at position 0. Only these tags are allowed: b, i, p`);
|
|
43
|
-
// Mixed valid and invalid tags
|
|
44
|
-
(0, vitest_1.expect)(() => rich_text_validator_1.RichTextValidator.validate('<p>Paragraph</p> with <h1>header</h1>', allowedTags)).toThrow(`Unknown tag 'h1' at position 22. Only these tags are allowed: b, i, p`);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
(0, vitest_1.describe)('isValid method', () => {
|
|
48
|
-
(0, vitest_1.test)('should return boolean value instead of throwing errors', () => {
|
|
49
|
-
(0, vitest_1.expect)(rich_text_validator_1.RichTextValidator.isValid('<b>valid</b>')).toBe(true);
|
|
50
|
-
(0, vitest_1.expect)(rich_text_validator_1.RichTextValidator.isValid('<div>invalid')).toBe(false);
|
|
51
|
-
});
|
|
52
|
-
(0, vitest_1.test)('should validate against allowed tags set and return boolean', () => {
|
|
53
|
-
let allowedTags = new Set(['b', 'i']);
|
|
54
|
-
(0, vitest_1.expect)(rich_text_validator_1.RichTextValidator.isValid('<b>valid</b>', allowedTags)).toBe(true);
|
|
55
|
-
(0, vitest_1.expect)(rich_text_validator_1.RichTextValidator.isValid('<span>invalid</span>', allowedTags)).toBe(false);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
//# sourceMappingURL=rich-text-validator.test.js.map
|
package/dist/test.spec.d.ts
DELETED
|
File without changes
|
package/dist/test.spec.js
DELETED
package/dist/test.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/test.test.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
(0, vitest_1.describe)('Test Sample', () => {
|
|
5
|
-
(0, vitest_1.test)('should success', () => {
|
|
6
|
-
(0, vitest_1.expect)(true).toBeTruthy();
|
|
7
|
-
});
|
|
8
|
-
});
|
|
9
|
-
//# sourceMappingURL=test.test.js.map
|