@zentered/issue-forms-body-parser 1.2.1 → 1.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,59 @@
1
+ name: "CodeQL"
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ # The branches below must be a subset of the branches above
8
+ branches: [ main ]
9
+ schedule:
10
+ - cron: '29 21 * * 5'
11
+
12
+ jobs:
13
+ analyze:
14
+ name: Analyze
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ actions: read
18
+ contents: read
19
+ security-events: write
20
+
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ language: [ 'javascript' ]
25
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
26
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v3
31
+
32
+ # Initializes the CodeQL tools for scanning.
33
+ - name: Initialize CodeQL
34
+ uses: github/codeql-action/init@v2
35
+ with:
36
+ languages: ${{ matrix.language }}
37
+ # If you wish to specify custom queries, you can do so here or in a config file.
38
+ # By default, queries listed here will override any specified in a config file.
39
+ # Prefix the list here with "+" to use these queries and those in the config file.
40
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
41
+
42
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
43
+ # If this step fails, then you should remove it and run the build manually (see below)
44
+ - name: Autobuild
45
+ uses: github/codeql-action/autobuild@v2
46
+
47
+ # ℹ️ Command-line programs to run using the OS shell.
48
+ # 📚 https://git.io/JvXDl
49
+
50
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
51
+ # and modify them (or add more) to build your code if your project
52
+ # uses a compiled language
53
+
54
+ #- run: |
55
+ # make bootstrap
56
+ # make release
57
+
58
+ - name: Perform CodeQL Analysis
59
+ uses: github/codeql-action/analyze@v2
package/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  ![Test](https://github.com/zentered/issue-forms-body-parser/workflows/Test/badge.svg)
4
4
  ![Release](https://github.com/zentered/issue-forms-body-parser/workflows/Publish/badge.svg)
5
- ![Semantic Release](https://github.com/zentered/issue-forms-body-parser/workflows/Semantic%20Release/badge.svg)
6
5
  [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
7
6
  [![zentered.co](https://img.shields.io/badge/%3E-zentered.co-blue.svg?style=flat)](https://zentered.co)
8
7
 
@@ -21,9 +20,9 @@ and provides structured data to create calendar entries (ie `.ics` files for
21
20
  [calendar subscriptions with GitEvents](https://github.com/gitevents/ics)),
22
21
  calling 3rd party APIs, etc.
23
22
 
24
- \_Inspired by:
23
+ _Inspired by:
25
24
  [Peter Murray's Issue Forms Body Parser](https://github.com/peter-murray/issue-forms-body-parser)
26
- with valuable feedback from [Steffen](https://gist.github.com/steffen)\_
25
+ with valuable feedback from [Steffen](https://gist.github.com/steffen)_
27
26
 
28
27
  ## Features
29
28
 
@@ -62,25 +61,30 @@ Cafe Nero Finikoudes, Larnaka
62
61
  to structured, usable data:
63
62
 
64
63
  ```json
65
- [
66
- {
67
- "id": "event-description",
64
+ {
65
+ "event-description": {
66
+ "order": 0,
68
67
  "title": "Event Description",
69
- "text": "Let's meet for coffee and chat about tech, coding, Cyprus and the newly formed\nCDC (Cyprus Developer Community).\n"
68
+ "text": "Let's meet for coffee and chat about tech, coding, Cyprus and the newly formed\nCDC (Cyprus Developer Community)."
70
69
  },
71
- {
72
- "id": "location",
70
+ "location": {
71
+ "order": 1,
73
72
  "title": "Location",
74
- "text": "Cafe Nero Finikoudes, Larnaka\n"
73
+ "text": "Cafe Nero Finikoudes, Larnaka"
75
74
  },
76
- {
77
- "id": "date",
75
+ "date": {
76
+ "order": 2,
78
77
  "title": "Date",
79
- "text": "11.03.2022\n",
78
+ "text": "11.03.2022",
80
79
  "date": "2022-03-11"
81
80
  },
82
- { "id": "time", "title": "Time", "text": "16:00\n", "time": "16:00" }
83
- ]
81
+ "time": {
82
+ "order": 3,
83
+ "title": "Time",
84
+ "text": "16:00",
85
+ "time": "16:00"
86
+ }
87
+ }
84
88
  ```
85
89
 
86
90
  See more examples in [md test cases](./test/test-issue-1.md) and
@@ -88,11 +92,15 @@ See more examples in [md test cases](./test/test-issue-1.md) and
88
92
 
89
93
  ### Parsers
90
94
 
91
- - `date`: checks if the value matches a [common date format](https://github.com/zentered/issue-forms-body-parser/blob/main/src/parse.js#L14) and returns a formatted `date` field (in UTC).
92
- - `time`: checks if the value matches a [common time format](https://github.com/zentered/issue-forms-body-parser/blob/main/src/parse.js#L24) and returns a formatted `time` field.
95
+ - `date`: checks if the value matches a
96
+ [common date format](https://github.com/zentered/issue-forms-body-parser/blob/main/src/parsers/date.js#L7)
97
+ and returns a formatted `date` field (in UTC).
98
+ - `time`: checks if the value matches a
99
+ [common time format](https://github.com/zentered/issue-forms-body-parser/blob/main/src/parsers/time.js#L7)
100
+ and returns a formatted `time` field.
93
101
  - `lists`: automatically returns lists as arrays
94
- - `duration`: currently only the format `XXhYYm` is supported as duration, ie. `1h30m` returns a `duration` object with `hours` and `minutes`.
95
-
102
+ - `duration`: currently only the format `XXhYYm` is supported as duration, ie.
103
+ `1h30m` returns a `duration` object with `hours` and `minutes`.
96
104
 
97
105
  ## Installation & Usage
98
106
 
@@ -109,7 +117,7 @@ jobs:
109
117
  steps:
110
118
  - name: Issue Forms Body Parser
111
119
  id: parse
112
- uses: zentered/issue-forms-body-parser@v1.2.0
120
+ uses: zentered/issue-forms-body-parser@v2.0.0
113
121
  - run: echo "${{ JSON.stringify(steps.parse.outputs.data) }}"
114
122
  ```
115
123
 
package/dist/index.js CHANGED
@@ -51787,8 +51787,6 @@ function remarkStringify(options) {
51787
51787
 
51788
51788
  /* harmony default export */ const remark_stringify = (remarkStringify);
51789
51789
 
51790
- // EXTERNAL MODULE: ./node_modules/date-fns/index.js
51791
- var date_fns = __nccwpck_require__(3314);
51792
51790
  ;// CONCATENATED MODULE: ./node_modules/strip-final-newline/index.js
51793
51791
  function stripFinalNewline(input) {
51794
51792
  const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt();
@@ -51805,6 +51803,8 @@ function stripFinalNewline(input) {
51805
51803
  return input;
51806
51804
  }
51807
51805
 
51806
+ // EXTERNAL MODULE: ./node_modules/date-fns/index.js
51807
+ var date_fns = __nccwpck_require__(3314);
51808
51808
  // EXTERNAL MODULE: ./node_modules/date-fns/_lib/cloneObject/index.js
51809
51809
  var cloneObject = __nccwpck_require__(7934);
51810
51810
  // EXTERNAL MODULE: ./node_modules/date-fns/_lib/toInteger/index.js
@@ -52582,6 +52582,38 @@ function zonedTimeToUtc(date, timeZone, options) {
52582
52582
  return new Date(utc + offsetMilliseconds)
52583
52583
  }
52584
52584
 
52585
+ ;// CONCATENATED MODULE: ./src/parsers/date.js
52586
+
52587
+
52588
+ ;
52589
+
52590
+
52591
+ const loc = 'UTC'
52592
+ const commonDateFormats = [
52593
+ 'yyyy-MM-dd',
52594
+ 'dd/MM/yyyy',
52595
+ 'dd/MM/yy',
52596
+ 'dd-MM-yyyy',
52597
+ 'dd-MM-yy',
52598
+ 'dd.MM.yyyy',
52599
+ 'dd.MM.yy'
52600
+ ]
52601
+
52602
+ function date_parseDate(text) {
52603
+ const match = commonDateFormats.map((format) => {
52604
+ return (0,date_fns.isMatch)(text, format)
52605
+ })
52606
+ if (match.indexOf(true) > -1) {
52607
+ const date = zonedTimeToUtc(
52608
+ (0,date_fns.parse)(text, commonDateFormats[match.indexOf(true)], new Date()),
52609
+ loc
52610
+ ).toJSON()
52611
+ return date.split('T')[0]
52612
+ } else {
52613
+ return null
52614
+ }
52615
+ }
52616
+
52585
52617
  // EXTERNAL MODULE: ./node_modules/date-fns/format/index.js
52586
52618
  var format = __nccwpck_require__(2168);
52587
52619
  ;// CONCATENATED MODULE: ./node_modules/date-fns-tz/esm/_lib/tzIntlTimeZoneName/index.js
@@ -53194,33 +53226,33 @@ function formatInTimeZone(date, timeZone, formatStr, options) {
53194
53226
  return format_format(utcToZonedTime(date, timeZone), formatStr, extendedOptions)
53195
53227
  }
53196
53228
 
53197
- ;// CONCATENATED MODULE: ./src/parse.js
53229
+ ;// CONCATENATED MODULE: ./src/parsers/time.js
53198
53230
 
53199
53231
 
53200
53232
  ;
53201
53233
 
53202
53234
 
53235
+ const time_loc = 'UTC'
53236
+ const commonTimeFormats = ['HH:mm', 'HH.mm', 'hh:mm a', 'hh:mm A']
53203
53237
 
53238
+ function time_parseTime(text) {
53239
+ const match = commonTimeFormats.map((format) => {
53240
+ return (0,date_fns.isMatch)(text, format)
53241
+ })
53242
+ if (match.indexOf(true) > -1) {
53243
+ const time = zonedTimeToUtc(
53244
+ (0,date_fns.parse)(text, commonTimeFormats[match.indexOf(true)], new Date()),
53245
+ time_loc
53246
+ )
53247
+ return formatInTimeZone(time, time_loc, 'HH:mm')
53248
+ } else {
53249
+ return null
53250
+ }
53251
+ }
53204
53252
 
53253
+ ;// CONCATENATED MODULE: ./src/parsers/duration.js
53205
53254
 
53206
53255
 
53207
-
53208
- // if the system time is not UTC, we need to convert it to UTC
53209
-
53210
- const loc = 'UTC'
53211
-
53212
- const commonDateFormats = [
53213
- 'yyyy-MM-dd',
53214
- 'dd/MM/yyyy',
53215
- 'dd/MM/yy',
53216
- 'dd-MM-yyyy',
53217
- 'dd-MM-yy',
53218
- 'dd.MM.yyyy',
53219
- 'dd.MM.yy'
53220
- ]
53221
-
53222
- const commonTimeFormats = ['HH:mm', 'HH.mm', 'hh:mm a', 'hh:mm A']
53223
-
53224
53256
  function parseDuration(text) {
53225
53257
  const duration = {
53226
53258
  hours: 0,
@@ -53233,35 +53265,8 @@ function parseDuration(text) {
53233
53265
  return duration
53234
53266
  }
53235
53267
 
53236
- function parse_parseDate(text) {
53237
- const match = commonDateFormats.map((format) => {
53238
- return (0,date_fns.isMatch)(text, format)
53239
- })
53240
- if (match.indexOf(true) > -1) {
53241
- const date = zonedTimeToUtc(
53242
- (0,date_fns.parse)(text, commonDateFormats[match.indexOf(true)], new Date()),
53243
- loc
53244
- ).toJSON()
53245
- return date.split('T')[0]
53246
- } else {
53247
- return null
53248
- }
53249
- }
53268
+ ;// CONCATENATED MODULE: ./src/parsers/list.js
53250
53269
 
53251
- function parse_parseTime(text) {
53252
- const match = commonTimeFormats.map((format) => {
53253
- return (0,date_fns.isMatch)(text, format)
53254
- })
53255
- if (match.indexOf(true) > -1) {
53256
- const time = zonedTimeToUtc(
53257
- (0,date_fns.parse)(text, commonTimeFormats[match.indexOf(true)], new Date()),
53258
- loc
53259
- )
53260
- return formatInTimeZone(time, loc, 'HH:mm')
53261
- } else {
53262
- return null
53263
- }
53264
- }
53265
53270
 
53266
53271
  function parseList(list) {
53267
53272
  return list.children
@@ -53293,46 +53298,79 @@ function parseList(list) {
53293
53298
  .filter((x) => !!x)
53294
53299
  }
53295
53300
 
53301
+ ;// CONCATENATED MODULE: ./src/parsers/index.js
53302
+
53303
+
53304
+ ;
53305
+
53306
+
53307
+
53308
+
53309
+ const parsers_parseDate = date_parseDate
53310
+ const parsers_parseTime = time_parseTime
53311
+ const parsers_parseDuration = parseDuration
53312
+ const parsers_parseList = parseList
53313
+
53314
+ ;// CONCATENATED MODULE: ./src/parse.js
53315
+
53316
+
53317
+ ;
53318
+
53319
+
53320
+
53321
+
53322
+
53323
+
53324
+
53296
53325
  async function parseMD(body) {
53297
53326
  const tokens = await unified().use(remark_parse).use(remarkGfm).parse(body)
53298
53327
  if (!tokens) {
53299
53328
  return []
53300
53329
  }
53301
53330
 
53302
- const r = []
53331
+ const r = {}
53332
+ let counter = 0
53303
53333
  for (let idx = 0; idx < tokens.children.length; idx = idx + 2) {
53304
53334
  const current = tokens.children[idx]
53305
53335
  const hasNext = idx + 1 < tokens.children.length
53306
53336
 
53307
53337
  if (current.type === 'heading') {
53308
- // issue-form answers start with a h3 heading, ignore everything else
53338
+ const key = slugify(current.children[0].value)
53339
+
53340
+ // issue-form answers start with a h3 heading, ignore everything else for now
53309
53341
  const obj = {
53310
- id: slugify(current.children[0].value),
53311
- title: current.children[0].value
53342
+ title: current.children[0].value,
53343
+ order: counter++
53312
53344
  }
53345
+
53313
53346
  if (hasNext) {
53314
53347
  const next = tokens.children[idx + 1]
53315
53348
  if (next.type === 'list') {
53316
- obj.list = parseList(next).flat()
53349
+ obj.list = parsers_parseList(next).flat()
53317
53350
  }
53318
53351
  const text = await unified()
53319
53352
  .use(remarkGfm)
53320
53353
  .use(remark_stringify)
53321
53354
  .stringify(next)
53322
53355
  obj.text = stripFinalNewline(text)
53323
- const date = parse_parseDate(obj.text)
53324
- const time = parse_parseTime(obj.text)
53356
+
53357
+ const date = parsers_parseDate(obj.text)
53358
+ const time = parsers_parseTime(obj.text)
53359
+
53325
53360
  if (date) {
53326
53361
  obj.date = date
53327
53362
  }
53363
+
53328
53364
  if (time) {
53329
53365
  obj.time = time
53330
53366
  }
53331
- if (obj.id === 'duration') {
53332
- obj.duration = parseDuration(obj.text)
53367
+
53368
+ if (key === 'duration') {
53369
+ obj.duration = parsers_parseDuration(obj.text)
53333
53370
  }
53371
+
53372
+ r[key] = obj
53334
53373
  }
53335
- r.push(obj)
53336
53374
  }
53337
53375
  }
53338
53376
 
@@ -53342,6 +53380,8 @@ async function parseMD(body) {
53342
53380
  ;// CONCATENATED MODULE: ./src/index.js
53343
53381
 
53344
53382
 
53383
+ ;
53384
+
53345
53385
 
53346
53386
 
53347
53387
  async function run() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zentered/issue-forms-body-parser",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "private": false,
5
5
  "description": "Parser for GitHub Issue Form body, also available as GitHub Action",
6
6
  "keywords": [
package/src/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  import github from '@actions/github'
2
4
  import core from '@actions/core'
3
5
  import parse from './parse.js'
package/src/parse.js CHANGED
@@ -5,96 +5,13 @@ import remarkParse from 'remark-parse'
5
5
  import remarkGfm from 'remark-gfm'
6
6
  import slugify from '@sindresorhus/slugify'
7
7
  import remarkStringify from 'remark-stringify'
8
- import { parse, isMatch } from 'date-fns'
9
8
  import stripFinalNewline from 'strip-final-newline'
10
-
11
- // if the system time is not UTC, we need to convert it to UTC
12
- import { zonedTimeToUtc, formatInTimeZone } from 'date-fns-tz/esm'
13
- const loc = 'UTC'
14
-
15
- const commonDateFormats = [
16
- 'yyyy-MM-dd',
17
- 'dd/MM/yyyy',
18
- 'dd/MM/yy',
19
- 'dd-MM-yyyy',
20
- 'dd-MM-yy',
21
- 'dd.MM.yyyy',
22
- 'dd.MM.yy'
23
- ]
24
-
25
- const commonTimeFormats = ['HH:mm', 'HH.mm', 'hh:mm a', 'hh:mm A']
26
-
27
- function parseDuration(text) {
28
- const duration = {
29
- hours: 0,
30
- minutes: 0
31
- }
32
-
33
- const pieces = text.replace('m', '').split('h')
34
- duration.hours = parseInt(pieces[0]) ? parseInt(pieces[0]) : 0
35
- duration.minutes = parseInt(pieces[1]) ? parseInt(pieces[1]) : 0
36
- return duration
37
- }
38
-
39
- function parseDate(text) {
40
- const match = commonDateFormats.map((format) => {
41
- return isMatch(text, format)
42
- })
43
- if (match.indexOf(true) > -1) {
44
- const date = zonedTimeToUtc(
45
- parse(text, commonDateFormats[match.indexOf(true)], new Date()),
46
- loc
47
- ).toJSON()
48
- return date.split('T')[0]
49
- } else {
50
- return null
51
- }
52
- }
53
-
54
- function parseTime(text) {
55
- const match = commonTimeFormats.map((format) => {
56
- return isMatch(text, format)
57
- })
58
- if (match.indexOf(true) > -1) {
59
- const time = zonedTimeToUtc(
60
- parse(text, commonTimeFormats[match.indexOf(true)], new Date()),
61
- loc
62
- )
63
- return formatInTimeZone(time, loc, 'HH:mm')
64
- } else {
65
- return null
66
- }
67
- }
68
-
69
- function parseList(list) {
70
- return list.children
71
- .map((item) => {
72
- const listItem = {}
73
- if (item.type === 'list') {
74
- return parseList(list)
75
- } else if (item.type === 'listItem') {
76
- listItem.checked = item.checked
77
- return item.children
78
- .map((child) => {
79
- if (child.type === 'paragraph') {
80
- listItem.text = child.children
81
- .map((c) => {
82
- if (c.type === 'link') {
83
- return c.children[0].value
84
- } else {
85
- return c.value
86
- }
87
- })
88
- .filter((x) => !!x)
89
- .join('')
90
- return listItem
91
- }
92
- })
93
- .filter((x) => !!x)
94
- }
95
- })
96
- .filter((x) => !!x)
97
- }
9
+ import {
10
+ parseDate,
11
+ parseTime,
12
+ parseDuration,
13
+ parseList
14
+ } from './parsers/index.js'
98
15
 
99
16
  export default async function parseMD(body) {
100
17
  const tokens = await unified().use(remarkParse).use(remarkGfm).parse(body)
@@ -102,17 +19,21 @@ export default async function parseMD(body) {
102
19
  return []
103
20
  }
104
21
 
105
- const r = []
22
+ const r = {}
23
+ let counter = 0
106
24
  for (let idx = 0; idx < tokens.children.length; idx = idx + 2) {
107
25
  const current = tokens.children[idx]
108
26
  const hasNext = idx + 1 < tokens.children.length
109
27
 
110
28
  if (current.type === 'heading') {
111
- // issue-form answers start with a h3 heading, ignore everything else
29
+ const key = slugify(current.children[0].value)
30
+
31
+ // issue-form answers start with a h3 heading, ignore everything else for now
112
32
  const obj = {
113
- id: slugify(current.children[0].value),
114
- title: current.children[0].value
33
+ title: current.children[0].value,
34
+ order: counter++
115
35
  }
36
+
116
37
  if (hasNext) {
117
38
  const next = tokens.children[idx + 1]
118
39
  if (next.type === 'list') {
@@ -123,19 +44,24 @@ export default async function parseMD(body) {
123
44
  .use(remarkStringify)
124
45
  .stringify(next)
125
46
  obj.text = stripFinalNewline(text)
47
+
126
48
  const date = parseDate(obj.text)
127
49
  const time = parseTime(obj.text)
50
+
128
51
  if (date) {
129
52
  obj.date = date
130
53
  }
54
+
131
55
  if (time) {
132
56
  obj.time = time
133
57
  }
134
- if (obj.id === 'duration') {
58
+
59
+ if (key === 'duration') {
135
60
  obj.duration = parseDuration(obj.text)
136
61
  }
62
+
63
+ r[key] = obj
137
64
  }
138
- r.push(obj)
139
65
  }
140
66
  }
141
67
 
@@ -0,0 +1,30 @@
1
+ 'use strict'
2
+
3
+ import { parse, isMatch } from 'date-fns'
4
+ import { zonedTimeToUtc } from 'date-fns-tz/esm'
5
+
6
+ const loc = 'UTC'
7
+ const commonDateFormats = [
8
+ 'yyyy-MM-dd',
9
+ 'dd/MM/yyyy',
10
+ 'dd/MM/yy',
11
+ 'dd-MM-yyyy',
12
+ 'dd-MM-yy',
13
+ 'dd.MM.yyyy',
14
+ 'dd.MM.yy'
15
+ ]
16
+
17
+ export default function parseDate(text) {
18
+ const match = commonDateFormats.map((format) => {
19
+ return isMatch(text, format)
20
+ })
21
+ if (match.indexOf(true) > -1) {
22
+ const date = zonedTimeToUtc(
23
+ parse(text, commonDateFormats[match.indexOf(true)], new Date()),
24
+ loc
25
+ ).toJSON()
26
+ return date.split('T')[0]
27
+ } else {
28
+ return null
29
+ }
30
+ }
@@ -0,0 +1,13 @@
1
+ 'use strict'
2
+
3
+ export default function parseDuration(text) {
4
+ const duration = {
5
+ hours: 0,
6
+ minutes: 0
7
+ }
8
+
9
+ const pieces = text.replace('m', '').split('h')
10
+ duration.hours = parseInt(pieces[0]) ? parseInt(pieces[0]) : 0
11
+ duration.minutes = parseInt(pieces[1]) ? parseInt(pieces[1]) : 0
12
+ return duration
13
+ }
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ import date from './date.js'
4
+ import time from './time.js'
5
+ import duration from './duration.js'
6
+ import list from './list.js'
7
+
8
+ export const parseDate = date
9
+ export const parseTime = time
10
+ export const parseDuration = duration
11
+ export const parseList = list
@@ -0,0 +1,31 @@
1
+ 'use strict'
2
+
3
+ export default function parseList(list) {
4
+ return list.children
5
+ .map((item) => {
6
+ const listItem = {}
7
+ if (item.type === 'list') {
8
+ return parseList(list)
9
+ } else if (item.type === 'listItem') {
10
+ listItem.checked = item.checked
11
+ return item.children
12
+ .map((child) => {
13
+ if (child.type === 'paragraph') {
14
+ listItem.text = child.children
15
+ .map((c) => {
16
+ if (c.type === 'link') {
17
+ return c.children[0].value
18
+ } else {
19
+ return c.value
20
+ }
21
+ })
22
+ .filter((x) => !!x)
23
+ .join('')
24
+ return listItem
25
+ }
26
+ })
27
+ .filter((x) => !!x)
28
+ }
29
+ })
30
+ .filter((x) => !!x)
31
+ }
@@ -0,0 +1,22 @@
1
+ 'use strict'
2
+
3
+ import { parse, isMatch } from 'date-fns'
4
+ import { zonedTimeToUtc, formatInTimeZone } from 'date-fns-tz/esm'
5
+
6
+ const loc = 'UTC'
7
+ const commonTimeFormats = ['HH:mm', 'HH.mm', 'hh:mm a', 'hh:mm A']
8
+
9
+ export default function parseTime(text) {
10
+ const match = commonTimeFormats.map((format) => {
11
+ return isMatch(text, format)
12
+ })
13
+ if (match.indexOf(true) > -1) {
14
+ const time = zonedTimeToUtc(
15
+ parse(text, commonTimeFormats[match.indexOf(true)], new Date()),
16
+ loc
17
+ )
18
+ return formatInTimeZone(time, loc, 'HH:mm')
19
+ } else {
20
+ return null
21
+ }
22
+ }
@@ -8,32 +8,32 @@ import { join } from 'path'
8
8
  const test = t.test
9
9
 
10
10
  test('parse(md) should parse GitHub Issue Form data into useful, structured data', async (t) => {
11
- const expected = [
12
- {
13
- id: 'event-description',
11
+ const expected = {
12
+ 'event-description': {
13
+ order: 0,
14
14
  title: 'Event Description',
15
15
  text: "Let's meet for coffee and chat about tech, coding, Cyprus and the newly formed\nCDC (Cyprus Developer Community)."
16
16
  },
17
- {
18
- id: 'location',
17
+ location: {
18
+ order: 1,
19
19
  title: 'Location',
20
20
  text: '[Cafe Nero Finikoudes, Larnaka](https://goo.gl/maps/Bzjxdeat3BSdsUSVA)'
21
21
  },
22
- {
23
- id: 'date',
22
+ date: {
23
+ order: 2,
24
24
  title: 'Date',
25
25
  text: '11.03.2022',
26
26
  date: '2022-03-11'
27
27
  },
28
- { id: 'time', title: 'Time', text: '16:00', time: '16:00' },
29
- {
30
- id: 'duration',
28
+ time: { order: 3, title: 'Time', text: '16:00', time: '16:00' },
29
+ duration: {
30
+ order: 4,
31
31
  title: 'Duration',
32
32
  text: '2h',
33
33
  duration: { hours: 2, minutes: 0 }
34
34
  },
35
- {
36
- id: 'list-item-checked',
35
+ 'list-item-checked': {
36
+ order: 5,
37
37
  title: 'List Item Checked',
38
38
  list: [
39
39
  {
@@ -43,8 +43,8 @@ test('parse(md) should parse GitHub Issue Form data into useful, structured data
43
43
  ],
44
44
  text: "* [x] I agree to follow this project's\n [Code of Conduct](https://berlincodeofconduct.org)"
45
45
  },
46
- {
47
- id: 'list-item-unchecked',
46
+ 'list-item-unchecked': {
47
+ order: 6,
48
48
  title: 'List Item Unchecked',
49
49
  list: [
50
50
  {
@@ -54,8 +54,8 @@ test('parse(md) should parse GitHub Issue Form data into useful, structured data
54
54
  ],
55
55
  text: "* [ ] I agree to follow this project's\n [Code of Conduct](https://berlincodeofconduct.org)"
56
56
  },
57
- {
58
- id: 'mixed-task-list',
57
+ 'mixed-task-list': {
58
+ order: 7,
59
59
  title: 'Mixed Task List',
60
60
  list: [
61
61
  { checked: true, text: 'checked' },
@@ -66,8 +66,8 @@ test('parse(md) should parse GitHub Issue Form data into useful, structured data
66
66
  ],
67
67
  text: '* [x] checked\n* [ ] unchecked\n* [x] checked 2\n* [x] checked 3\n* [ ] unchecked 2'
68
68
  },
69
- {
70
- id: 'complex-list',
69
+ 'complex-list': {
70
+ order: 8,
71
71
  title: 'Complex List',
72
72
  list: [
73
73
  { checked: null, text: 'one' },
@@ -75,17 +75,17 @@ test('parse(md) should parse GitHub Issue Form data into useful, structured data
75
75
  ],
76
76
  text: '* one\n* two\n * three\n * four\n 1. five\n 2. six'
77
77
  },
78
- {
79
- id: 'repositories',
78
+ repositories: {
79
+ order: 9,
80
80
  title: 'Repositories',
81
81
  text: '```csv\nhttps://example.com/repository-1\nhttps://example.com/repository-2\n```'
82
82
  },
83
- {
84
- id: 'visibility',
83
+ visibility: {
84
+ order: 10,
85
85
  title: 'Visibility',
86
86
  text: 'Internal'
87
87
  }
88
- ]
88
+ }
89
89
 
90
90
  const md = await readFile(
91
91
  join(process.cwd(), 'test', 'test-issue-1.md'),
@@ -97,7 +97,7 @@ test('parse(md) should parse GitHub Issue Form data into useful, structured data
97
97
  })
98
98
 
99
99
  test('parse(md) return nothing', async (t) => {
100
- const expected = []
100
+ const expected = {}
101
101
 
102
102
  const md = await readFile(
103
103
  join(process.cwd(), 'test', 'test-issue-2.md'),