Skip to content

Commit e8247d5

Browse files
committed
Add list separator plugin
1 parent 549ee91 commit e8247d5

File tree

3 files changed

+179
-0
lines changed

3 files changed

+179
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
Mavo.Plugins.register("list-separator", {
2+
hooks: {
3+
"collection-init-end": function() {
4+
this.separator = this.element.getAttribute("mv-list-separator");
5+
6+
if (["\\n", "\\r", "\\r\\n"].includes(this.separator)) {
7+
// Handle line breaks specially, parse any line break, store with detected line break
8+
this.separator = /\r?\n/g;
9+
this.joinSeparator = "\n"; // Default line break to join with
10+
}
11+
12+
// TODO ignore separator if this is not a collection of primitives and print error
13+
},
14+
"node-getdata-end": function(env) {
15+
if (this instanceof Mavo.Collection && this.separator) {
16+
// Escape separator in data
17+
let data = env.data.map(s => (s + "").replaceAll(this.separator, "\\$&"));
18+
env.data = data.join(this.joinSeparator ?? this.separator);
19+
}
20+
},
21+
"node-render-start": function(env) {
22+
if (this instanceof Mavo.Collection && this.separator && env.data.split) {
23+
let separatorString = this.separator.source ?? this.separator;
24+
let separator = RegExp(`(?<!\\\\)${separatorString}`, "g");
25+
let data = env.data.split(separator);
26+
27+
if (this.separator instanceof RegExp && data.length > 1) {
28+
// If the separator is a regexp, we need to store the first occurrence and use it to join when saving
29+
this.joinSeparator = env.data.match(separator)[0];
30+
}
31+
32+
// Unescape separator in the data
33+
data = data.map(s => s.replace(RegExp(`\\\\(?=${separatorString})`, "g"), ""));
34+
env.data = data;
35+
}
36+
}
37+
}
38+
});

list-separator/test.html

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<!DOCTYPE html>
2+
<html lang="el">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>List separator tests</title>
6+
<link rel="stylesheet" href="https://test.mavo.io/style.css" />
7+
<link rel="stylesheet" href="https://get.mavo.io/mavo.css" />
8+
<script src="https://get.mavo.io/mavo.js"></script>
9+
<style>
10+
[mv-list-item] {
11+
border: 1px solid silver;
12+
padding: .2em;
13+
margin: .2em;
14+
background: hsl(0 0% 100% / .3);
15+
white-space: pre-line
16+
}
17+
</style>
18+
</head>
19+
<body>
20+
21+
<h1>List separator tests</h1>
22+
<pre id="datarr">
23+
{
24+
"foo": ["1, 4", "2", "3"]
25+
}
26+
</pre>
27+
28+
<section>
29+
<h1>Basic</h1>
30+
31+
<table class="reftest" data-click=".mv-bar .mv-save wait .1s">
32+
<tr title="Load array, save string">
33+
<td mv-app mv-source="#datarr" mv-storage="#data2">
34+
<div mv-list="foo" mv-list-separator=", ">
35+
<span mv-list-item=""></span>
36+
</div>
37+
</td>
38+
<td>
39+
1, 423
40+
</td>
41+
</tr>
42+
<tr>
43+
<td>
44+
<pre id="data2"></pre>
45+
</td>
46+
<td>
47+
<pre>{
48+
"foo": "1\\, 4, 2, 3"
49+
}</pre>
50+
</td>
51+
</tr>
52+
<tr title="Load string, save string" data-click="[mv-action] after mv-load wait .1s, .mv-save after mv-load wait .3s">
53+
<td mv-app mv-source="#data2" mv-storage="#data3">
54+
<div mv-list="foo" mv-list-separator=", ">
55+
<span mv-list-item=""></span>
56+
</div>
57+
<button mv-action="add(5, foo)" class="test-content-ignore">Add foo</button>
58+
</td>
59+
<td>
60+
1, 4235
61+
</td>
62+
</tr>
63+
<tr>
64+
<td>
65+
<pre id="data3"></pre>
66+
</td>
67+
<td>
68+
<pre>{
69+
"foo": "1\\, 4, 2, 3, 5"
70+
}</pre>
71+
</td>
72+
</tr>
73+
</table>
74+
</section>
75+
76+
<section>
77+
<h1>Line breaks</h1>
78+
79+
<pre id="datarr2">{
80+
"foo": ["1\n4", "2", "3"]
81+
}</pre>
82+
83+
<table class="reftest" data-click=".mv-bar .mv-save wait .1s">
84+
<tr title="Load array, save string">
85+
<td mv-app mv-source="#datarr2" mv-storage="#data4">
86+
<div mv-list="foo" mv-list-separator="\n">
87+
<span mv-list-item=""></span>
88+
</div>
89+
</td>
90+
<td>
91+
1
92+
423
93+
</td>
94+
</tr>
95+
<tr>
96+
<td>
97+
<pre id="data4"></pre>
98+
</td>
99+
<td>
100+
<pre>{
101+
"foo": "1\\\n4\n2\n3"
102+
}</pre>
103+
</td>
104+
</tr>
105+
<tr title="Load string, save string" data-click="[mv-action] after mv-load wait .1s, .mv-save after mv-load wait .3s">
106+
<td mv-app mv-source="#data4" mv-storage="#data5">
107+
<div mv-list="foo" mv-list-separator="\n">
108+
<span mv-list-item=""></span>
109+
</div>
110+
<button mv-action="add(5, foo)" class="test-content-ignore">Add foo</button>
111+
</td>
112+
<td>
113+
1
114+
4235
115+
</td>
116+
</tr>
117+
<tr>
118+
<td>
119+
<pre id="data5"></pre>
120+
</td>
121+
<td>
122+
<pre>{
123+
"foo": "1\\\n4\n2\n3\n5"
124+
}</pre>
125+
</td>
126+
</tr>
127+
</table>
128+
</section>
129+
130+
<script src="mavo-list-separator.js"></script>
131+
<script src="https://test.mavo.io/test.js"></script>
132+
133+
</body>
134+
</html>

plugins.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@
9090
"repo": "DmitrySharabin/mavo-gsheets",
9191
"author": "dmitrysharabin"
9292
},
93+
{
94+
"name": "List Separator",
95+
"id": "list-separator",
96+
"description": "Store and read lists of simple properties as a single text value. Useful in conjunction with the Google Sheets plugin to store multiple values in a single cell.",
97+
"tag": [],
98+
"author": "leaverou"
99+
},
93100
{
94101
"name": "Google Drive",
95102
"id": "gdrive",

0 commit comments

Comments
 (0)