bare-script 3.2.2 → 3.3.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.
@@ -0,0 +1,155 @@
1
+ # Licensed under the MIT License
2
+ # https://github.com/craigahobbs/markdown-up/blob/main/LICENSE
3
+
4
+
5
+ # Include sentinel
6
+ if systemGlobalGet('diffSentinel'):
7
+ return
8
+ endif
9
+ diffSentinel = true
10
+
11
+
12
+ # The text line difference model
13
+ diffTypes = schemaParse( \
14
+ 'group "diff.bare"', \
15
+ '', \
16
+ '', \
17
+ '# A list of text line differences', \
18
+ 'typedef Difference[] Differences', \
19
+ '', \
20
+ '', \
21
+ '# A difference', \
22
+ 'struct Difference', \
23
+ '', \
24
+ ' # The type of difference', \
25
+ ' DifferenceType type', \
26
+ '', \
27
+ ' # The text lines of this difference', \
28
+ ' string[] lines', \
29
+ '', \
30
+ '', \
31
+ '# A difference type', \
32
+ 'enum DifferenceType', \
33
+ '', \
34
+ ' # The lines are identical', \
35
+ ' Identical', \
36
+ '', \
37
+ ' # The lines were added', \
38
+ ' Add', \
39
+ '', \
40
+ ' # The lines were removed', \
41
+ ' Remove' \
42
+ )
43
+
44
+
45
+ # $function: diffLines
46
+ # $group: diff.bare
47
+ # $doc: Compute the line-differences of two strings or arrays of strings
48
+ # $arg left: The "left" string or array of strings
49
+ # $arg right: The "right" string or array of strings
50
+ # $return: The array of [difference models](includeModel.html#var.vName='Differences')
51
+ function diffLines(left, right):
52
+ diffs = arrayNew()
53
+
54
+ # Split the left into an array of lines
55
+ if systemType(left) == 'array':
56
+ leftLines = arrayNew()
57
+ for leftPart in left:
58
+ arrayExtend(leftLines, regexSplit(diffRegexLineSplit, leftPart))
59
+ endfor
60
+ else:
61
+ leftLines = regexSplit(diffRegexLineSplit, left)
62
+ endif
63
+
64
+ # Split the right into an array of lines
65
+ if systemType(right) == 'array':
66
+ rightLines = arrayNew()
67
+ for rightPart in right:
68
+ arrayExtend(rightLines, regexSplit(diffRegexLineSplit, rightPart))
69
+ endfor
70
+ else:
71
+ rightLines = regexSplit(diffRegexLineSplit, right)
72
+ endif
73
+
74
+ # Compute the differences
75
+ ixLeft = 0
76
+ ixRight = 0
77
+ leftLength = arrayLength(leftLines)
78
+ rightLength = arrayLength(rightLines)
79
+ while ixLeft < leftLength || ixRight < rightLength:
80
+ # If we've run out of lines on either side
81
+ if ixLeft >= leftLength:
82
+ if ixRight < rightLength:
83
+ arrayPush(diffs, objectNew('type', 'Add', 'lines', arraySlice(rightLines, ixRight)))
84
+ endif
85
+ break
86
+ endif
87
+ if ixRight >= rightLength:
88
+ if ixLeft < leftLength:
89
+ arrayPush(diffs, objectNew('type', 'Remove', 'lines', arraySlice(leftLines, ixLeft)))
90
+ endif
91
+ break
92
+ endif
93
+
94
+ # Find consecutive identical lines
95
+ identicalLines = arrayNew()
96
+ while ixLeft < leftLength && ixRight < rightLength && arrayGet(leftLines, ixLeft) == arrayGet(rightLines, ixRight):
97
+ arrayPush(identicalLines, arrayGet(leftLines, ixLeft))
98
+ ixLeft = ixLeft + 1
99
+ ixRight = ixRight + 1
100
+ endwhile
101
+ if identicalLines:
102
+ arrayPush(objectdiffs, objectNew('type', 'Identical', 'lines', identicalLines))
103
+ continue
104
+ endif
105
+
106
+ # Look ahead to find next matching point
107
+ foundMatch = False
108
+ ixLeftTmp = ixLeft
109
+ while ixLeftTmp < leftLength:
110
+ ixRightTmp = ixRight
111
+ while ixRightTmp < rightLength:
112
+ if arrayGet(leftLines, ixLeftTmp) == arrayGet(rightLines, ixRightTmp):
113
+ foundMatch = true
114
+ break
115
+ endif
116
+ ixRightTmp = ixRightTmp + 1
117
+ endwhile
118
+ if foundMatch:
119
+ break
120
+ endif
121
+ ixLeftTmp = ixLeftTmp + 1
122
+ endwhile
123
+
124
+ # If no match found, use remaining lines
125
+ if !foundMatch:
126
+ if ixLeft < leftLength:
127
+ arrayPush(diffs, objectNew('type', 'Remove', 'lines', arraySlice(leftLines, ixLeft)))
128
+ ixLeft = leftLength
129
+ endif
130
+ if ixRight < rightLength:
131
+ arrayPush(diffs, objectNew('type', 'Add', 'lines', arraySlice(rightLines, ixRight)))
132
+ ixRight = rightLength
133
+ endif
134
+ continue
135
+ endif
136
+
137
+ # Add removed lines if any
138
+ if ixLeftTmp > ixLeft:
139
+ arrayPush(diffs, objectNew('type', 'Remove', 'lines', arraySlice(leftLines, ixLeft, ixLeftTmp)))
140
+ ixLeft = ixLeftTmp
141
+ endif
142
+
143
+ # Add added lines if any
144
+ if ixRightTmp > ixRight:
145
+ arrayPush(diffs, objectNew('type', 'Add', 'lines', arraySlice(rightLines, ixRight, ixRightTmp)))
146
+ ixRight = ixRightTmp
147
+ endif
148
+ endwhile
149
+
150
+ return diffs
151
+ endfunction
152
+
153
+
154
+ # Regex for splitting lines
155
+ diffRegexLineSplit = regexNew(stringFromCharCode(13) + '?' + stringFromCharCode(10))
@@ -0,0 +1,79 @@
1
+ # Licensed under the MIT License
2
+ # https://github.com/craigahobbs/markdown-up/blob/main/LICENSE
3
+
4
+
5
+ # Include sentinel
6
+ if systemGlobalGet('formsSentinel'):
7
+ return
8
+ endif
9
+ formsSentinel = true
10
+
11
+
12
+ # $function: formsTextElements
13
+ # $group: forms.bare
14
+ # $doc: Create a text input [element model](https://github.com/craigahobbs/element-model#readme)
15
+ # $arg id: The text input element ID
16
+ # $arg text: The initial text of the text input element
17
+ # $arg size: Optional (default is null). The size, in characters, of the text input element
18
+ # $arg onEnter: Optional (default is null). The text input element on-enter event handler
19
+ # $return: The text input [element model](https://github.com/craigahobbs/element-model#readme)
20
+ function formsTextElements(id, text, size, onEnter):
21
+ return objectNew( \
22
+ 'html', 'input', \
23
+ 'attr', objectNew( \
24
+ 'autocomplete', 'off', \
25
+ 'id', id, \
26
+ 'style', 'font-size: inherit; border: thin solid black; padding: 0.4em;', \
27
+ 'type', 'text', \
28
+ 'value', text, \
29
+ 'size', size \
30
+ ), \
31
+ 'callback', if(onEnter != null, objectNew('keyup', systemPartial(formsTextOnKeyup, onEnter))) \
32
+ )
33
+ endfunction
34
+
35
+
36
+ async function formsTextOnKeyup(onEnter, keyCode):
37
+ if keyCode == 13:
38
+ onEnter()
39
+ endif
40
+ endfunction
41
+
42
+
43
+ # $function: formsLinkButtonElements
44
+ # $group: forms.bare
45
+ # $doc: Create a link button [element model](https://github.com/craigahobbs/element-model#readme)
46
+ # $arg text: The link button's text
47
+ # $arg onClick: The link button's click event handler
48
+ # $return: The link button [element model](https://github.com/craigahobbs/element-model#readme)
49
+ function formsLinkButtonElements(text, onClick):
50
+ return objectNew( \
51
+ 'html', 'a', \
52
+ 'attr', objectNew('style', 'cursor: pointer; user-select: none;'), \
53
+ 'elem', objectNew('text', text), \
54
+ 'callback', objectNew('click', onClick) \
55
+ )
56
+ endfunction
57
+
58
+
59
+ # $function: formsLinkElements
60
+ # $group: forms.bare
61
+ # $doc: Create a link [element model](https://github.com/craigahobbs/element-model#readme)
62
+ # $arg text: The link's text
63
+ # $arg url: The link's URL. If null, the link is rendered as text.
64
+ # $return: The link [element model](https://github.com/craigahobbs/element-model#readme)
65
+ function formsLinkElements(text, url):
66
+ if url == null:
67
+ return objectNew( \
68
+ 'html', 'span', \
69
+ 'attr', objectNew('style', 'user-select: none;'), \
70
+ 'elem', objectNew('text', text) \
71
+ )
72
+ endif
73
+
74
+ return objectNew( \
75
+ 'html', 'a', \
76
+ 'attr', objectNew('href', documentURL(url)), \
77
+ 'elem', objectNew('text', text) \
78
+ )
79
+ endfunction
@@ -6,74 +6,7 @@
6
6
  if systemGlobalGet('formsSentinel'):
7
7
  return
8
8
  endif
9
- formsSentinel = true
10
9
 
11
10
 
12
- # $function: formsTextElements
13
- # $group: forms.mds
14
- # $doc: Create a text input [element model](https://github.com/craigahobbs/element-model#readme)
15
- # $arg id: The text input element ID
16
- # $arg text: The initial text of the text input element
17
- # $arg size: Optional (default is null). The size, in characters, of the text input element
18
- # $arg onEnter: Optional (default is null). The text input element on-enter event handler
19
- # $return: The text input [element model](https://github.com/craigahobbs/element-model#readme)
20
- function formsTextElements(id, text, size, onEnter):
21
- return objectNew( \
22
- 'html', 'input', \
23
- 'attr', objectNew( \
24
- 'autocomplete', 'off', \
25
- 'id', id, \
26
- 'style', 'font-size: inherit; border: thin solid black; padding: 0.4em;', \
27
- 'type', 'text', \
28
- 'value', text, \
29
- 'size', size \
30
- ), \
31
- 'callback', if(onEnter != null, objectNew('keyup', systemPartial(formsTextOnKeyup, onEnter))) \
32
- )
33
- endfunction
34
-
35
-
36
- async function formsTextOnKeyup(onEnter, keyCode):
37
- if keyCode == 13:
38
- onEnter()
39
- endif
40
- endfunction
41
-
42
-
43
- # $function: formsLinkButtonElements
44
- # $group: forms.mds
45
- # $doc: Create a link button [element model](https://github.com/craigahobbs/element-model#readme)
46
- # $arg text: The link button's text
47
- # $arg onClick: The link button's click event handler
48
- # $return: The link button [element model](https://github.com/craigahobbs/element-model#readme)
49
- function formsLinkButtonElements(text, onClick):
50
- return objectNew( \
51
- 'html', 'a', \
52
- 'attr', objectNew('style', 'cursor: pointer; user-select: none;'), \
53
- 'elem', objectNew('text', text), \
54
- 'callback', objectNew('click', onClick) \
55
- )
56
- endfunction
57
-
58
-
59
- # $function: formsLinkElements
60
- # $group: forms.mds
61
- # $doc: Create a link [element model](https://github.com/craigahobbs/element-model#readme)
62
- # $arg text: The link's text
63
- # $arg url: The link's URL. If null, the link is rendered as text.
64
- # $return: The link [element model](https://github.com/craigahobbs/element-model#readme)
65
- function formsLinkElements(text, url):
66
- if url == null:
67
- return objectNew( \
68
- 'html', 'span', \
69
- 'attr', objectNew('style', 'user-select: none;'), \
70
- 'elem', objectNew('text', text) \
71
- )
72
- endif
73
-
74
- return objectNew( \
75
- 'html', 'a', \
76
- 'attr', objectNew('href', documentURL(url)), \
77
- 'elem', objectNew('text', text) \
78
- )
79
- endfunction
11
+ systemLog('MarkdownUp - forms.mds: forms.mds is now forms.bare - please update before 2025-06-01')
12
+ include 'forms.bare'
@@ -0,0 +1,236 @@
1
+ # Licensed under the MIT License
2
+ # https://github.com/craigahobbs/markdown-up/blob/main/LICENSE
3
+
4
+
5
+ # Include sentinel
6
+ if systemGlobalGet('pagerSentinel'):
7
+ return
8
+ endif
9
+ pagerSentinel = true
10
+
11
+
12
+ include 'args.bare'
13
+
14
+
15
+ # The pager model
16
+ pagerTypes = schemaParse( \
17
+ 'group "pager.bare"', \
18
+ '', \
19
+ '', \
20
+ '# A pager application model', \
21
+ 'struct Pager', \
22
+ '', \
23
+ " # The application's pages", \
24
+ ' PagerPage[len > 0] pages', \
25
+ '', \
26
+ '', \
27
+ '# A page model', \
28
+ 'struct PagerPage', \
29
+ '', \
30
+ ' # The page name', \
31
+ ' string name', \
32
+ '', \
33
+ ' # If true, the page is hidden', \
34
+ ' optional bool hidden', \
35
+ '', \
36
+ ' # The page type', \
37
+ ' PagerPageType type', \
38
+ '', \
39
+ '', \
40
+ '# The page type', \
41
+ 'union PagerPageType', \
42
+ '', \
43
+ ' # A function page', \
44
+ ' PagerPageFunction function', \
45
+ '', \
46
+ ' # A markdown resource page', \
47
+ ' PagerPageMarkdown markdown', \
48
+ '', \
49
+ ' # A navigation link', \
50
+ ' PagerPageLink link', \
51
+ '', \
52
+ '', \
53
+ '# A page function', \
54
+ 'struct PagerPageFunction', \
55
+ '', \
56
+ ' # The page function', \
57
+ ' object function', \
58
+ '', \
59
+ ' # The page title', \
60
+ ' optional string title', \
61
+ '', \
62
+ '', \
63
+ '# A Markdown resource page', \
64
+ 'struct PagerPageMarkdown', \
65
+ '', \
66
+ ' # The Markdown resource URL', \
67
+ ' string url', \
68
+ '', \
69
+ '', \
70
+ '# A page link', \
71
+ 'struct PagerPageLink', \
72
+ '', \
73
+ ' # The link URL', \
74
+ ' string url' \
75
+ )
76
+
77
+
78
+ # $function: pagerValidate
79
+ # $group: pager.bare
80
+ # $doc: Validate a pager model
81
+ # $arg pagerModel: The [pager model](includeModel.html#var.vName='Pager')
82
+ # $return: The validated [pager model](includeModel.html#var.vName='Pager') or null if validation fails
83
+ function pagerValidate(pagerModel):
84
+ return schemaValidate(pagerTypes, 'Pager', pagerModel)
85
+ endfunction
86
+
87
+
88
+ # $function: pagerMain
89
+ # $group: pager.bare
90
+ # $doc: The pager application main entry point
91
+ # $arg pagerModel: The [pager model](includeModel.html#var.vName='Pager')
92
+ # $arg options: The pager application options. The following options are available:
93
+ # $arg options: - **arguments** - The [arguments model](includeModel.html#var.vName='ArgsArguments').
94
+ # $arg options: Must contain a string argument named "page".
95
+ # $arg options: - **hideMenu** - Hide the menu links
96
+ # $arg options: - **hideNav** - Hide the navigation links
97
+ # $arg options: - **start** - The start page name
98
+ async function pagerMain(pagerModel, options):
99
+ if options == null:
100
+ options = objectNew()
101
+ endif
102
+
103
+ # Validate the pager model
104
+ pagerModel = pagerValidate(pagerModel)
105
+ if pagerModel == null:
106
+ return
107
+ endif
108
+
109
+ # Compute the visible and navigable pages
110
+ pages = objectGet(pagerModel, 'pages')
111
+ visiblePages = arrayNew()
112
+ navPages = arrayNew()
113
+ for page in pages:
114
+ # Visible page?
115
+ if !objectGet(page, 'hidden'):
116
+ arrayPush(visiblePages, page)
117
+
118
+ # Navigable page?
119
+ pageTypeKey = arrayGet(objectKeys(objectGet(page, 'type')), 0)
120
+ if pageTypeKey != 'link':
121
+ arrayPush(navPages, page)
122
+ endif
123
+ endif
124
+ endfor
125
+
126
+ # Parse arguments
127
+ startPageName = objectGet(options, 'start', if(arrayLength(navPages), objectGet(arrayGet(navPages, 0), 'name'), null))
128
+ if objectHas(options, 'arguments'):
129
+ arguments = argsValidate(objectGet(options, 'arguments'))
130
+ if arguments == null:
131
+ return
132
+ endif
133
+ else:
134
+ arguments = arrayNew(objectNew('name', 'page', 'default', startPageName))
135
+ endif
136
+ args = argsParse(arguments)
137
+
138
+ # Determine the current page
139
+ curPage = null
140
+ startPage = null
141
+ for page in pages:
142
+ if objectGet(page, 'name') == objectGet(args, 'page'):
143
+ curPage = page
144
+ endif
145
+ if objectGet(page, 'name') == startPageName:
146
+ startPage = page
147
+ endif
148
+ endfor
149
+ if startPage == null:
150
+ systemLogDebug('MarkdownUp - pager.bare: Unknown start page' + if(startPageName != null, '"' + startPageName + '"', ''))
151
+ return
152
+ endif
153
+ if curPage == null:
154
+ curPage = startPage
155
+ endif
156
+
157
+ # Determine the current page's navigable index, if any
158
+ ixCurPage = -1
159
+ for navPage, ixNavPage in navPages:
160
+ if objectGet(navPage, 'name') == objectGet(curPage, 'name'):
161
+ ixCurPage = ixNavPage
162
+ break
163
+ endif
164
+ endfor
165
+
166
+ # Render the menu
167
+ if !objectGet(options, 'hideMenu'):
168
+ for page, ixPage in visiblePages:
169
+ pageName = objectGet(page, 'name')
170
+ pageType = objectGet(page, 'type')
171
+ pageTypeKey = arrayGet(objectKeys(pageType), 0)
172
+
173
+ # Render the menu link
174
+ pageNameNbsp = stringReplace(pageName, ' ', '&nbsp;')
175
+ separator = if(ixPage != arrayLength(visiblePages) - 1, '&nbsp;|', '')
176
+ if pageTypeKey == 'link':
177
+ pageLinkURL = objectGet(objectGet(pageType, 'link'), 'url')
178
+ markdownPrint('[' + markdownEscape(pageNameNbsp) + '](' + urlEncode(pageLinkURL) + ')' + separator)
179
+ elif pageName == objectGet(curPage, 'name'):
180
+ markdownPrint(markdownEscape(pageNameNbsp) + separator)
181
+ else:
182
+ markdownPrint(argsLink(arguments, pageNameNbsp, objectNew('page', pageName)) + separator)
183
+ endif
184
+ endfor
185
+ markdownPrint('')
186
+ endif
187
+
188
+ # Render the start/next/prev buttons
189
+ if !objectGet(options, 'hideNav') && arrayLength(navPages) > 1 && ixCurPage != -1:
190
+ if startPageName == objectGet(curPage, 'name'):
191
+ startPageName = null
192
+ endif
193
+ prevPageName = if(ixCurPage != -1 && ixCurPage - 1 >= 0, objectGet(arrayGet(navPages, ixCurPage - 1), 'name'), null)
194
+ nextPageName = if(ixCurPage != -1 && ixCurPage + 1 < arrayLength(navPages), objectGet(arrayGet(navPages, ixCurPage + 1), 'name'), null)
195
+ markdownPrint( \
196
+ '(&nbsp;' + if(startPageName != null, argsLink(arguments, 'Start', objectNew('page', startPageName)), 'Start') + '&nbsp;|', \
197
+ if(prevPageName != null, argsLink(arguments, 'Previous', objectNew('page', prevPageName)), 'Previous') + '&nbsp;|', \
198
+ if(nextPageName != null, argsLink(arguments, 'Next', objectNew('page', nextPageName)), 'Next') + '&nbsp;)', \
199
+ '' \
200
+ )
201
+ endif
202
+
203
+ # Function page?
204
+ curPageType = objectGet(curPage, 'type')
205
+ curPageTypeKey = arrayGet(objectKeys(curPageType), 0)
206
+ if curPageTypeKey == 'function':
207
+ # Set the title
208
+ title = objectGet(objectGet(curPageType, 'function'), 'title')
209
+ if title != null:
210
+ documentSetTitle(title)
211
+ markdownPrint('# ' + markdownEscape(title), '')
212
+ endif
213
+
214
+ # Call the page function
215
+ pageFn = objectGet(objectGet(curPageType, 'function'), 'function')
216
+ pageFn(args)
217
+ elif curPageTypeKey == 'markdown':
218
+ # Fetch the Markdown text
219
+ url = objectGet(objectGet(curPageType, 'markdown'), 'url')
220
+ markdownText = systemFetch(url)
221
+ if markdownText == null:
222
+ markdownPrint('**Error:** Failed to load "' + url + '"')
223
+ else:
224
+ # Compute and set the page title
225
+ markdownModel = markdownParse(markdownText)
226
+ title = markdownTitle(markdownModel)
227
+ if title == null:
228
+ title = 'No Title'
229
+ endif
230
+ documentSetTitle(title)
231
+
232
+ # Render the Markdown text
233
+ markdownPrint('', markdownText)
234
+ endif
235
+ endif
236
+ endfunction