@jinntec/fore 1.0.0-0 → 1.0.0-3
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 +17 -1
- package/dist/fore-all.js +10 -10
- package/dist/fore.js +1 -1
- package/index.js +8 -0
- package/package.json +4 -1
- package/resources/fore.css +111 -1
- package/src/DependencyNotifyingDomFacade.js +9 -1
- package/src/ForeElementMixin.js +25 -17
- package/src/actions/abstract-action.js +8 -7
- package/src/actions/fx-action.js +6 -1
- package/src/actions/fx-dispatch.js +10 -2
- package/src/actions/fx-hide.js +23 -0
- package/src/actions/fx-insert.js +14 -10
- package/src/actions/fx-send.js +1 -1
- package/src/actions/fx-setvalue.js +2 -4
- package/src/actions/fx-show.js +23 -0
- package/src/dep_graph.js +9 -0
- package/src/drawdown.js +172 -0
- package/src/fore.js +94 -3
- package/src/functions/fx-function.js +2 -2
- package/src/fx-bind.js +20 -17
- package/src/fx-fore.js +306 -33
- package/src/fx-instance.js +27 -6
- package/src/fx-model.js +182 -41
- package/src/fx-submission.js +29 -7
- package/src/fx-var.js +43 -0
- package/src/getInScopeContext.js +28 -7
- package/src/modelitem.js +1 -0
- package/src/ui/abstract-control.js +21 -6
- package/src/ui/fx-alert.js +16 -20
- package/src/ui/fx-container.js +9 -4
- package/src/ui/fx-control.js +76 -39
- package/src/ui/fx-dialog.js +68 -0
- package/src/ui/fx-inspector.js +44 -0
- package/src/ui/fx-items.js +120 -0
- package/src/ui/fx-output.js +77 -9
- package/src/ui/fx-repeat.js +86 -16
- package/src/ui/fx-repeatitem.js +16 -3
- package/src/ui/fx-trigger.js +3 -0
- package/src/xpath-evaluation.js +609 -267
- package/src/xpath-util.js +52 -12
|
@@ -9,7 +9,7 @@ import { getBucketsForNode } from 'fontoxpath';
|
|
|
9
9
|
*/
|
|
10
10
|
export class DependencyNotifyingDomFacade {
|
|
11
11
|
/**
|
|
12
|
-
* @param
|
|
12
|
+
* @param onNodeTouched - onNodeTouched A function what will be executed whenever a node is 'touched' by the XPath
|
|
13
13
|
*/
|
|
14
14
|
constructor(onNodeTouched) {
|
|
15
15
|
this._onNodeTouched = onNodeTouched;
|
|
@@ -45,13 +45,21 @@ export class DependencyNotifyingDomFacade {
|
|
|
45
45
|
* @param bucket - The bucket that matches the attribute that will be used.
|
|
46
46
|
*/
|
|
47
47
|
// eslint-disable-next-line class-methods-use-this
|
|
48
|
+
/*
|
|
48
49
|
getChildNodes(node, bucket) {
|
|
49
50
|
const matchingNodes = Array.from(node.childNodes).filter(
|
|
50
51
|
childNode => !bucket || getBucketsForNode(childNode).includes(bucket),
|
|
51
52
|
);
|
|
52
53
|
return matchingNodes;
|
|
53
54
|
}
|
|
55
|
+
*/
|
|
54
56
|
|
|
57
|
+
getChildNodes(node, bucket) {
|
|
58
|
+
const matchingNodes = Array.from(node.childNodes).filter(
|
|
59
|
+
childNode => !bucket || getBucketsForNode(childNode).includes(bucket));
|
|
60
|
+
matchingNodes.forEach(matchingNode => this._onNodeTouched(matchingNode));
|
|
61
|
+
return matchingNodes;
|
|
62
|
+
}
|
|
55
63
|
/**
|
|
56
64
|
* Get the data of this node.
|
|
57
65
|
*
|
package/src/ForeElementMixin.js
CHANGED
|
@@ -23,12 +23,6 @@ export const foreElementMixin = superclass =>
|
|
|
23
23
|
model: {
|
|
24
24
|
type: Object,
|
|
25
25
|
},
|
|
26
|
-
/**
|
|
27
|
-
* XPath binding expression pointing to bound node
|
|
28
|
-
*/
|
|
29
|
-
ref: {
|
|
30
|
-
type: String,
|
|
31
|
-
},
|
|
32
26
|
/**
|
|
33
27
|
* The modelitem object associated to the bound node holding the evaluated state.
|
|
34
28
|
*/
|
|
@@ -41,6 +35,15 @@ export const foreElementMixin = superclass =>
|
|
|
41
35
|
nodeset: {
|
|
42
36
|
type: Object,
|
|
43
37
|
},
|
|
38
|
+
/**
|
|
39
|
+
* XPath binding expression pointing to bound node
|
|
40
|
+
*/
|
|
41
|
+
ref: {
|
|
42
|
+
type: String,
|
|
43
|
+
},
|
|
44
|
+
inScopeVariables: {
|
|
45
|
+
type: Map,
|
|
46
|
+
},
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -50,6 +53,7 @@ export const foreElementMixin = superclass =>
|
|
|
50
53
|
this.model = null;
|
|
51
54
|
this.modelItem = {};
|
|
52
55
|
this.ref = this.hasAttribute('ref') ? this.getAttribute('ref') : '';
|
|
56
|
+
this.inScopeVariables = null;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
getModel() {
|
|
@@ -90,7 +94,7 @@ export const foreElementMixin = superclass =>
|
|
|
90
94
|
*/
|
|
91
95
|
evalInContext() {
|
|
92
96
|
// const inscopeContext = this.getInScopeContext();
|
|
93
|
-
const inscopeContext = getInScopeContext(this, this.ref);
|
|
97
|
+
const inscopeContext = getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
|
|
94
98
|
if (!inscopeContext) {
|
|
95
99
|
console.warn('no in scopeContext for ', this);
|
|
96
100
|
return;
|
|
@@ -98,26 +102,26 @@ export const foreElementMixin = superclass =>
|
|
|
98
102
|
if (this.ref === '') {
|
|
99
103
|
this.nodeset = inscopeContext;
|
|
100
104
|
} else if (Array.isArray(inscopeContext)) {
|
|
105
|
+
/*
|
|
101
106
|
inscopeContext.forEach(n => {
|
|
102
107
|
if (XPathUtil.isSelfReference(this.ref)) {
|
|
103
108
|
this.nodeset = inscopeContext;
|
|
104
109
|
} else {
|
|
105
|
-
const localResult = evaluateXPathToFirstNode(this.ref, n,
|
|
110
|
+
const localResult = evaluateXPathToFirstNode(this.ref, n, this);
|
|
106
111
|
// console.log('local result: ', localResult);
|
|
107
112
|
this.nodeset.push(localResult);
|
|
108
113
|
}
|
|
109
114
|
});
|
|
115
|
+
*/
|
|
116
|
+
this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext[0], this);
|
|
110
117
|
} else {
|
|
111
118
|
// this.nodeset = fx.evaluateXPathToFirstNode(this.ref, inscopeContext, null, {namespaceResolver: this.namespaceResolver});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (inscopeContext.nodeType) {
|
|
116
|
-
this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext, formElement);
|
|
119
|
+
const { nodeType } = inscopeContext;
|
|
120
|
+
if (nodeType) {
|
|
121
|
+
this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext, this);
|
|
117
122
|
} else {
|
|
118
|
-
this.nodeset = evaluateXPath(this.ref, inscopeContext,
|
|
123
|
+
this.nodeset = evaluateXPath(this.ref, inscopeContext, this);
|
|
119
124
|
}
|
|
120
|
-
// this.nodeset = evaluateXPath(this.ref,inscopeContext,formElement)
|
|
121
125
|
}
|
|
122
126
|
// console.log('UiElement evaluated to nodeset: ', this.nodeset);
|
|
123
127
|
}
|
|
@@ -217,7 +221,11 @@ export const foreElementMixin = superclass =>
|
|
|
217
221
|
}
|
|
218
222
|
|
|
219
223
|
getInScopeContext() {
|
|
220
|
-
return getInScopeContext(this, this.ref);
|
|
224
|
+
return getInScopeContext(this.getAttributeNode('ref') || this, this.ref);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
setInScopeVariables(inScopeVariables) {
|
|
228
|
+
this.inScopeVariables = inScopeVariables;
|
|
221
229
|
}
|
|
222
230
|
|
|
223
231
|
dispatch(eventName, detail) {
|
|
@@ -226,7 +234,7 @@ export const foreElementMixin = superclass =>
|
|
|
226
234
|
bubbles: true,
|
|
227
235
|
detail,
|
|
228
236
|
});
|
|
229
|
-
console.log('firing', event);
|
|
237
|
+
// console.log('firing', event);
|
|
230
238
|
this.dispatchEvent(event);
|
|
231
239
|
}
|
|
232
240
|
};
|
|
@@ -81,7 +81,9 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
81
81
|
|
|
82
82
|
this.target = this.getAttribute('target');
|
|
83
83
|
if (this.target) {
|
|
84
|
-
if (this.target === '#
|
|
84
|
+
if (this.target === '#window') {
|
|
85
|
+
window.addEventListener(this.event, e => this.execute(e));
|
|
86
|
+
} else if (this.target === '#document') {
|
|
85
87
|
document.addEventListener(this.event, e => this.execute(e));
|
|
86
88
|
} else {
|
|
87
89
|
this.targetElement = document.getElementById(this.target);
|
|
@@ -122,7 +124,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
// First check if 'if' condition is true - otherwise exist right away
|
|
125
|
-
if (this.ifExpr && !evaluateXPathToBoolean(this.ifExpr, this.nodeset, this
|
|
127
|
+
if (this.ifExpr && !evaluateXPathToBoolean(this.ifExpr, this.nodeset, this)) {
|
|
126
128
|
return;
|
|
127
129
|
}
|
|
128
130
|
|
|
@@ -137,7 +139,7 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
137
139
|
return;
|
|
138
140
|
}
|
|
139
141
|
|
|
140
|
-
if (!evaluateXPathToBoolean(this.whileExpr, this.nodeset, this
|
|
142
|
+
if (!evaluateXPathToBoolean(this.whileExpr, this.nodeset, this)) {
|
|
141
143
|
// Done with iterating
|
|
142
144
|
return;
|
|
143
145
|
}
|
|
@@ -190,15 +192,14 @@ export class AbstractAction extends foreElementMixin(HTMLElement) {
|
|
|
190
192
|
const model = this.getModel();
|
|
191
193
|
model.recalculate();
|
|
192
194
|
model.revalidate();
|
|
193
|
-
model.parentNode.refresh();
|
|
194
|
-
this.
|
|
195
|
+
model.parentNode.refresh(true);
|
|
196
|
+
this.dispatchActionPerformed();
|
|
195
197
|
}
|
|
196
198
|
}
|
|
197
199
|
|
|
198
200
|
/**
|
|
199
|
-
* @private
|
|
200
201
|
*/
|
|
201
|
-
|
|
202
|
+
dispatchActionPerformed() {
|
|
202
203
|
console.log('action-performed ', this);
|
|
203
204
|
this.dispatchEvent(
|
|
204
205
|
new CustomEvent('action-performed', { composed: true, bubbles: true, detail: {} }),
|
package/src/actions/fx-action.js
CHANGED
|
@@ -41,11 +41,16 @@ export class FxAction extends AbstractAction {
|
|
|
41
41
|
script.src = this.src;
|
|
42
42
|
this.appendChild(script);
|
|
43
43
|
} else {
|
|
44
|
-
Array.from(children).forEach(
|
|
44
|
+
Array.from(children).forEach(actionOrVar => {
|
|
45
|
+
if (actionOrVar.localName === 'fx-var') {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const action = actionOrVar;
|
|
45
49
|
action.detail = this.detail;
|
|
46
50
|
// action.perform();
|
|
47
51
|
action.execute();
|
|
48
52
|
});
|
|
53
|
+
this.dispatchActionPerformed();
|
|
49
54
|
// this.needsUpdate = false;
|
|
50
55
|
}
|
|
51
56
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AbstractAction } from './abstract-action.js';
|
|
2
|
-
import { evaluateXPath } from '../xpath-evaluation.js';
|
|
2
|
+
import { evaluateXPath, resolveId } from '../xpath-evaluation.js';
|
|
3
|
+
import { XPathUtil } from '../xpath-util.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* `fx-dispatch`
|
|
@@ -89,7 +90,14 @@ export class FxDispatch extends AbstractAction {
|
|
|
89
90
|
|
|
90
91
|
// ### when targetid is given dispatch to that if present (throw an error if not) - otherwise dispatch to document
|
|
91
92
|
if (this.targetid) {
|
|
92
|
-
const target = document.getElementById(this.targetid);
|
|
93
|
+
// const target = document.getElementById(this.targetid);
|
|
94
|
+
let target;
|
|
95
|
+
if (XPathUtil.isRepeated(this)) {
|
|
96
|
+
target = resolveId(this.targetid, this.parentNode, null);
|
|
97
|
+
} else {
|
|
98
|
+
target = document.getElementById(this.targetid);
|
|
99
|
+
}
|
|
100
|
+
console.log('target', target);
|
|
93
101
|
if (!target) {
|
|
94
102
|
throw new Error(`targetid ${this.targetid} does not exist in document`);
|
|
95
103
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FxAction } from './fx-action.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `fx-hide`
|
|
5
|
+
* hides a dialog
|
|
6
|
+
*
|
|
7
|
+
* @customElement
|
|
8
|
+
* @demo demo/project.html
|
|
9
|
+
*/
|
|
10
|
+
export class FxHide extends FxAction {
|
|
11
|
+
connectedCallback() {
|
|
12
|
+
this.dialog = this.getAttribute('dialog');
|
|
13
|
+
if(!this.dialog){
|
|
14
|
+
this.dispatch('error',{message:'dialog does not exist'})
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
perform() {
|
|
19
|
+
document.getElementById(this.dialog).hide();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
window.customElements.define('fx-hide', FxHide);
|
package/src/actions/fx-insert.js
CHANGED
|
@@ -77,7 +77,7 @@ export class FxInsert extends AbstractAction {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
perform() {
|
|
80
|
-
super.perform();
|
|
80
|
+
// super.perform();
|
|
81
81
|
|
|
82
82
|
/*
|
|
83
83
|
todo: !!! calling super here does not correctly give the nodeset - it's likely still a bug in ForeElementMixin !!!
|
|
@@ -86,11 +86,11 @@ export class FxInsert extends AbstractAction {
|
|
|
86
86
|
*/
|
|
87
87
|
|
|
88
88
|
// ### obtaining targetSequence
|
|
89
|
-
const inscope = getInScopeContext(this, this.ref);
|
|
89
|
+
const inscope = getInScopeContext(this.getAttributeNode('ref'), this.ref);
|
|
90
90
|
|
|
91
91
|
// @ts-ignore
|
|
92
92
|
const targetSequence = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
|
|
93
|
-
console.log('insert nodeset ', targetSequence);
|
|
93
|
+
// console.log('insert nodeset ', targetSequence);
|
|
94
94
|
|
|
95
95
|
// ### obtaining originSequence
|
|
96
96
|
/*
|
|
@@ -117,8 +117,8 @@ export class FxInsert extends AbstractAction {
|
|
|
117
117
|
let insertLocationNode;
|
|
118
118
|
let index;
|
|
119
119
|
|
|
120
|
-
const idx = this._getInsertIndex(inscope, targetSequence);
|
|
121
|
-
console.log('insert index', idx);
|
|
120
|
+
// const idx = this._getInsertIndex(inscope, targetSequence);
|
|
121
|
+
// console.log('insert index', idx);
|
|
122
122
|
|
|
123
123
|
// if the targetSequence is empty but we got an originSequence use inscope as context and ignore 'at' and 'position'
|
|
124
124
|
if (targetSequence.length === 0) {
|
|
@@ -151,7 +151,7 @@ export class FxInsert extends AbstractAction {
|
|
|
151
151
|
|
|
152
152
|
insertLocationNode = targetSequence;
|
|
153
153
|
const context = evaluateXPath('count(preceding::*)', targetSequence, this.getOwnerForm());
|
|
154
|
-
console.log('context', context);
|
|
154
|
+
// console.log('context', context);
|
|
155
155
|
index = context + 1;
|
|
156
156
|
// index = targetSequence.findIndex(insertLocationNode);
|
|
157
157
|
}
|
|
@@ -171,15 +171,19 @@ export class FxInsert extends AbstractAction {
|
|
|
171
171
|
|
|
172
172
|
// console.log('insert context item ', insertLocationNode);
|
|
173
173
|
// console.log('parent ', insertLocationNode.parentNode);
|
|
174
|
-
console.log('instance ', this.getModel().getDefaultContext());
|
|
174
|
+
// console.log('instance ', this.getModel().getDefaultContext());
|
|
175
175
|
|
|
176
|
-
console.log('<<<<<<< at', this.at);
|
|
177
|
-
console.log('<<<<<<< index', index);
|
|
176
|
+
// console.log('<<<<<<< at', this.at);
|
|
177
|
+
// console.log('<<<<<<< index', index);
|
|
178
|
+
// todo: this actually should dispatch to respective instance
|
|
178
179
|
document.dispatchEvent(
|
|
179
180
|
new CustomEvent('insert', {
|
|
180
181
|
composed: true,
|
|
181
182
|
bubbles: true,
|
|
182
|
-
detail: {
|
|
183
|
+
detail: {
|
|
184
|
+
insertedNodes: originSequenceClone,
|
|
185
|
+
position: index,
|
|
186
|
+
},
|
|
183
187
|
}),
|
|
184
188
|
);
|
|
185
189
|
|
package/src/actions/fx-send.js
CHANGED
|
@@ -17,7 +17,7 @@ class FxSend extends AbstractAction {
|
|
|
17
17
|
connectedCallback() {
|
|
18
18
|
// eslint-disable-next-line wc/guard-super-call
|
|
19
19
|
super.connectedCallback();
|
|
20
|
-
console.log('connectedCallback ', this);
|
|
20
|
+
// console.log('connectedCallback ', this);
|
|
21
21
|
this.submission = this.getAttribute('submission');
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -44,7 +44,7 @@ export default class FxSetvalue extends AbstractAction {
|
|
|
44
44
|
super.perform();
|
|
45
45
|
let { value } = this;
|
|
46
46
|
if (this.valueAttr !== null) {
|
|
47
|
-
value = evaluateXPath(this.valueAttr, this.nodeset, this
|
|
47
|
+
value = evaluateXPath(this.valueAttr, this.nodeset, this, this.detail);
|
|
48
48
|
} else if (this.textContent !== '') {
|
|
49
49
|
value = this.textContent;
|
|
50
50
|
} else {
|
|
@@ -62,10 +62,8 @@ export default class FxSetvalue extends AbstractAction {
|
|
|
62
62
|
|
|
63
63
|
if (item.value !== newVal) {
|
|
64
64
|
item.value = newVal;
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
this.getModel().changed.push(modelItem);
|
|
67
66
|
this.needsUpdate = true;
|
|
68
|
-
|
|
69
67
|
console.log('setvalue[2] ', item, newVal);
|
|
70
68
|
}
|
|
71
69
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FxAction } from './fx-action.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `fx-confirm`
|
|
5
|
+
* Displays a simple confirmation before actually executing the nested actions.
|
|
6
|
+
*
|
|
7
|
+
* @customElement
|
|
8
|
+
* @demo demo/project.html
|
|
9
|
+
*/
|
|
10
|
+
export class FxShow extends FxAction {
|
|
11
|
+
connectedCallback() {
|
|
12
|
+
this.dialog = this.getAttribute('dialog');
|
|
13
|
+
if(!this.dialog){
|
|
14
|
+
this.dispatch('error',{message:'dialog does not exist'})
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
perform() {
|
|
19
|
+
document.getElementById(this.dialog).open();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
window.customElements.define('fx-show', FxShow);
|
package/src/dep_graph.js
CHANGED
|
@@ -320,6 +320,15 @@ DepGraph.prototype = {
|
|
|
320
320
|
}
|
|
321
321
|
throw new Error(`Node does not exist: ${node}`);
|
|
322
322
|
},
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Get an array of nodes that have no dependants (i.e. nothing depends on them).
|
|
326
|
+
*/
|
|
327
|
+
entryNodes() {
|
|
328
|
+
const self = this;
|
|
329
|
+
return Object.keys(this.nodes).filter(node => self.incomingEdges[node].length === 0);
|
|
330
|
+
},
|
|
331
|
+
|
|
323
332
|
/**
|
|
324
333
|
* Construct the overall processing order for the dependency graph.
|
|
325
334
|
*
|
package/src/drawdown.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* drawdown.js
|
|
3
|
+
* (c) Adam Leggett
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
function markdown(src) {
|
|
7
|
+
var rx_lt = /</g;
|
|
8
|
+
var rx_gt = />/g;
|
|
9
|
+
var rx_space = /\t|\r|\uf8ff/g;
|
|
10
|
+
var rx_escape = /\\([\\\|`*_{}\[\]()#+\-~])/g;
|
|
11
|
+
var rx_hr = /^([*\-=_] *){3,}$/gm;
|
|
12
|
+
var rx_blockquote = /\n *> *([^]*?)(?=(\n|$){2})/g;
|
|
13
|
+
var rx_list = /\n( *)(?:[*\-+]|((\d+)|([a-z])|[A-Z])[.)]) +([^]*?)(?=(\n|$){2})/g;
|
|
14
|
+
var rx_listjoin = /<\/(ol|ul)>\n\n<\1>/g;
|
|
15
|
+
var rx_highlight = /(^|[^A-Za-z\d\\])(([*_])|(~)|(\^)|(--)|(\+\+)|`)(\2?)([^<]*?)\2\8(?!\2)(?=\W|_|$)/g;
|
|
16
|
+
var rx_code = /\n((```|~~~).*\n?([^]*?)\n?\2|(( .*?\n)+))/g;
|
|
17
|
+
var rx_link = /((!?)\[(.*?)\]\((.*?)( ".*")?\)|\\([\\`*_{}\[\]()#+\-.!~]))/g;
|
|
18
|
+
var rx_table = /\n(( *\|.*?\| *\n)+)/g;
|
|
19
|
+
var rx_thead = /^.*\n( *\|( *\:?-+\:?-+\:? *\|)* *\n|)/;
|
|
20
|
+
var rx_row = /.*\n/g;
|
|
21
|
+
var rx_cell = /\||(.*?[^\\])\|/g;
|
|
22
|
+
var rx_heading = /(?=^|>|\n)([>\s]*?)(#{1,6}) (.*?)( #*)? *(?=\n|$)/g;
|
|
23
|
+
var rx_para = /(?=^|>|\n)\s*\n+([^<]+?)\n+\s*(?=\n|<|$)/g;
|
|
24
|
+
var rx_stash = /-\d+\uf8ff/g;
|
|
25
|
+
|
|
26
|
+
function replace(rex, fn) {
|
|
27
|
+
src = src.replace(rex, fn);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function element(tag, content) {
|
|
31
|
+
return '<' + tag + '>' + content + '</' + tag + '>';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function blockquote(src) {
|
|
35
|
+
return src.replace(rx_blockquote, function(all, content) {
|
|
36
|
+
return element('blockquote', blockquote(highlight(content.replace(/^ *> */gm, ''))));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function list(src) {
|
|
41
|
+
return src.replace(rx_list, function(all, ind, ol, num, low, content) {
|
|
42
|
+
var entry = element(
|
|
43
|
+
'li',
|
|
44
|
+
highlight(
|
|
45
|
+
content
|
|
46
|
+
.split(RegExp('\n ?' + ind + '(?:(?:\\d+|[a-zA-Z])[.)]|[*\\-+]) +', 'g'))
|
|
47
|
+
.map(list)
|
|
48
|
+
.join('</li><li>'),
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
'\n' +
|
|
54
|
+
(ol
|
|
55
|
+
? '<ol start="' +
|
|
56
|
+
(num
|
|
57
|
+
? ol + '">'
|
|
58
|
+
: parseInt(ol, 36) -
|
|
59
|
+
9 +
|
|
60
|
+
'" style="list-style-type:' +
|
|
61
|
+
(low ? 'low' : 'upp') +
|
|
62
|
+
'er-alpha">') +
|
|
63
|
+
entry +
|
|
64
|
+
'</ol>'
|
|
65
|
+
: element('ul', entry))
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function highlight(src) {
|
|
71
|
+
return src.replace(rx_highlight, function(all, _, p1, emp, sub, sup, small, big, p2, content) {
|
|
72
|
+
return (
|
|
73
|
+
_ +
|
|
74
|
+
element(
|
|
75
|
+
emp
|
|
76
|
+
? p2
|
|
77
|
+
? 'strong'
|
|
78
|
+
: 'em'
|
|
79
|
+
: sub
|
|
80
|
+
? p2
|
|
81
|
+
? 's'
|
|
82
|
+
: 'sub'
|
|
83
|
+
: sup
|
|
84
|
+
? 'sup'
|
|
85
|
+
: small
|
|
86
|
+
? 'small'
|
|
87
|
+
: big
|
|
88
|
+
? 'big'
|
|
89
|
+
: 'code',
|
|
90
|
+
highlight(content),
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function unesc(str) {
|
|
97
|
+
return str.replace(rx_escape, '$1');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
var stash = [];
|
|
101
|
+
var si = 0;
|
|
102
|
+
|
|
103
|
+
src = '\n' + src + '\n';
|
|
104
|
+
|
|
105
|
+
replace(rx_lt, '<');
|
|
106
|
+
replace(rx_gt, '>');
|
|
107
|
+
replace(rx_space, ' ');
|
|
108
|
+
|
|
109
|
+
// blockquote
|
|
110
|
+
src = blockquote(src);
|
|
111
|
+
|
|
112
|
+
// horizontal rule
|
|
113
|
+
replace(rx_hr, '<hr/>');
|
|
114
|
+
|
|
115
|
+
// list
|
|
116
|
+
src = list(src);
|
|
117
|
+
replace(rx_listjoin, '');
|
|
118
|
+
|
|
119
|
+
// code
|
|
120
|
+
replace(rx_code, function(all, p1, p2, p3, p4) {
|
|
121
|
+
stash[--si] = element('pre', element('code', p3 || p4.replace(/^ /gm, '')));
|
|
122
|
+
return si + '\uf8ff';
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// link or image
|
|
126
|
+
replace(rx_link, function(all, p1, p2, p3, p4, p5, p6) {
|
|
127
|
+
stash[--si] = p4
|
|
128
|
+
? p2
|
|
129
|
+
? '<img src="' + p4 + '" alt="' + p3 + '"/>'
|
|
130
|
+
: '<a href="' + p4 + '">' + unesc(highlight(p3)) + '</a>'
|
|
131
|
+
: p6;
|
|
132
|
+
return si + '\uf8ff';
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// table
|
|
136
|
+
replace(rx_table, function(all, table) {
|
|
137
|
+
var sep = table.match(rx_thead)[1];
|
|
138
|
+
return (
|
|
139
|
+
'\n' +
|
|
140
|
+
element(
|
|
141
|
+
'table',
|
|
142
|
+
table.replace(rx_row, function(row, ri) {
|
|
143
|
+
return row == sep
|
|
144
|
+
? ''
|
|
145
|
+
: element(
|
|
146
|
+
'tr',
|
|
147
|
+
row.replace(rx_cell, function(all, cell, ci) {
|
|
148
|
+
return ci ? element(sep && !ri ? 'th' : 'td', unesc(highlight(cell || ''))) : '';
|
|
149
|
+
}),
|
|
150
|
+
);
|
|
151
|
+
}),
|
|
152
|
+
)
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// heading
|
|
157
|
+
replace(rx_heading, function(all, _, p1, p2) {
|
|
158
|
+
return _ + element('h' + p1.length, unesc(highlight(p2)));
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// paragraph
|
|
162
|
+
replace(rx_para, function(all, content) {
|
|
163
|
+
return element('p', unesc(highlight(content)));
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// stash
|
|
167
|
+
replace(rx_stash, function(all) {
|
|
168
|
+
return stash[parseInt(all)];
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return src.trim();
|
|
172
|
+
}
|