@zentered/issue-forms-body-parser 2.2.0 → 3.0.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.
- package/README.md +30 -6
- package/SECURITY.md +80 -0
- package/docs/superpowers/specs/2026-06-13-empty-field-null-design.md +92 -0
- package/eslint.config.js +42 -0
- package/package.json +24 -19
- package/pkg/parse.cjs +1 -1
- package/pkg/parse.cjs.map +1 -1
- package/pkg/parse.js +1 -1
- package/pkg/parse.js.map +1 -1
- package/pkg/parse.umd.js +1 -1
- package/pkg/parse.umd.js.map +1 -1
- package/.eslintignore +0 -5
- package/.eslintrc.json +0 -15
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -36
- package/.github/ISSUE_TEMPLATE/config.yml +0 -1
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -38
- package/.github/dependabot.yml +0 -6
- package/.github/workflows/codeql-analysis.yml +0 -59
- package/.github/workflows/end-to-end-test.yml +0 -26
- package/.github/workflows/publish.yml +0 -31
- package/.github/workflows/test.yml +0 -51
- package/.husky/commit-msg +0 -1
- package/.husky/pre-commit +0 -1
- package/.prettierignore +0 -3
- package/.prettierrc +0 -6
- package/src/index.js +0 -29
- package/src/parse.js +0 -111
- package/src/parsers/date.js +0 -30
- package/src/parsers/duration.js +0 -30
- package/src/parsers/images.js +0 -12
- package/src/parsers/index.js +0 -15
- package/src/parsers/links.js +0 -12
- package/src/parsers/list.js +0 -32
- package/src/parsers/time.js +0 -28
package/pkg/parse.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.umd.js","sources":["../src/parsers/date.js","../src/parsers/time.js","../src/parsers/index.js","../src/parsers/list.js","../src/parse.js","../src/parsers/images.js","../src/parsers/links.js","../src/parsers/duration.js"],"sourcesContent":["'use strict'\n\nimport { parse, isMatch } from 'date-fns'\nimport { zonedTimeToUtc } from 'date-fns-tz'\n\nconst loc = 'UTC'\nconst commonDateFormats = [\n 'yyyy-MM-dd',\n 'dd/MM/yyyy',\n 'dd/MM/yy',\n 'dd-MM-yyyy',\n 'dd-MM-yy',\n 'dd.MM.yyyy',\n 'dd.MM.yy'\n]\n\nexport default function parseDate(text) {\n const match = commonDateFormats.map((format) => {\n return isMatch(text, format)\n })\n if (match.indexOf(true) > -1) {\n const date = zonedTimeToUtc(\n parse(text, commonDateFormats[match.indexOf(true)], new Date()),\n loc\n ).toJSON()\n return date.split('T')[0]\n } else {\n return null\n }\n}\n","'use strict'\n\nimport { parse, isMatch } from 'date-fns'\nimport { zonedTimeToUtc, formatInTimeZone } from 'date-fns-tz'\n\nconst loc = 'UTC'\nconst commonTimeFormats = [\n 'HH:mm',\n 'HH.mm',\n 'hh:mm aaa',\n 'hh:mm a..aa',\n 'hh:mm aaaa'\n]\n\nexport default function parseTime(text) {\n const match = commonTimeFormats.map((format) => {\n return isMatch(text, format)\n })\n if (match.indexOf(true) > -1) {\n const time = zonedTimeToUtc(\n parse(text, commonTimeFormats[match.indexOf(true)], new Date()),\n loc\n )\n return formatInTimeZone(time, loc, 'HH:mm')\n } else {\n return null\n }\n}\n","'use strict'\n\nimport date from './date.js'\nimport time from './time.js'\nimport duration from './duration.js'\nimport list from './list.js'\nimport images from './images.js'\nimport links from './links.js'\n\nexport const parseDate = date\nexport const parseTime = time\nexport const parseDuration = duration\nexport const parseList = list\nexport const parseImages = images\nexport const parseLinks = links\n","'use strict'\n\nexport default function parseList(list) {\n return list.children\n .map((item) => {\n const listItem = {}\n if (item.type === 'list') {\n return parseList(list)\n } else if (item.type === 'listItem') {\n listItem.checked = item.checked\n return item.children\n .map((child) => {\n if (child.type === 'paragraph') {\n listItem.text = child.children\n .map((c) => {\n if (c.type === 'link') {\n listItem.link = c.url\n return `[${c.children[0].value}](${c.url})`\n } else {\n return c.value\n }\n })\n .filter((x) => !!x)\n .join('')\n return listItem\n }\n })\n .filter((x) => !!x)\n }\n })\n .filter((x) => !!x)\n}\n","'use strict'\n\nimport { unified } from 'unified'\nimport remarkParse from 'remark-parse'\nimport remarkGfm from 'remark-gfm'\nimport slugify from '@sindresorhus/slugify'\nimport remarkStringify from 'remark-stringify'\nimport stripFinalNewline from 'strip-final-newline'\nimport createDebug from 'debug'\nconst debug = createDebug('body-parser')\n\nimport {\n parseDate,\n parseTime,\n parseDuration,\n parseList,\n parseImages,\n parseLinks\n} from './parsers/index.js'\n\nexport default async function parseMD(body) {\n debug('parseMD()')\n const tokens = await unified().use(remarkParse).use(remarkGfm).parse(body)\n if (!tokens) {\n return []\n }\n\n const structuredResponse = {}\n let currentHeading = null\n\n for (const token of tokens.children) {\n const text = await unified()\n .use(remarkGfm)\n .use(remarkStringify)\n .stringify(token)\n let cleanText = stripFinalNewline(text)\n\n // remove `\\\\_`\n if (cleanText.indexOf('\\\\_') > -1) {\n cleanText = cleanText.replace(/\\\\_/g, '_')\n }\n\n // issue forms uses h3 as a heading\n if (token.type === 'heading') {\n currentHeading = slugify(token.children[0].value)\n structuredResponse[currentHeading] = {\n title: token.children[0].value,\n heading: token.depth,\n content: []\n }\n } else if (token.type === 'paragraph' && currentHeading) {\n const obj = structuredResponse[currentHeading]\n\n const date = parseDate(cleanText)\n const images = parseImages(token.children)\n const links = parseLinks(token.children)\n const time = parseTime(cleanText)\n const duration = parseDuration(cleanText)\n\n if (date) {\n obj.date = date\n }\n\n if (time) {\n obj.time = time\n }\n\n if (duration) {\n obj.duration = duration\n }\n\n if (links && links.length > 0) {\n obj.links = links\n }\n\n if (images && images.length > 0) {\n obj.images = images\n }\n\n obj.content.push(cleanText)\n } else if (token.type === 'list') {\n const obj = structuredResponse[currentHeading]\n obj.text = cleanText\n obj.list = parseList(token).flat()\n } else if (token.type === 'html') {\n const obj = structuredResponse[currentHeading]\n obj.content.push(token.html)\n } else if (token.type === 'code') {\n const obj = structuredResponse[currentHeading]\n obj.lang = token.lang\n obj.text = cleanText\n } else {\n debug('unhandled token type')\n debug(token)\n }\n }\n\n for (const key in structuredResponse) {\n const token = structuredResponse[key]\n const content = token.content.filter(Boolean)\n if (content && content.length > 0) {\n if (content.length === 1) {\n token.text = content[0]\n }\n token.text = content.join('\\n\\n')\n }\n token.content = content\n }\n\n return structuredResponse\n}\n","'use strict'\n\nexport default function parseImage(props) {\n return props\n .filter((p) => p.type === 'image')\n .map((p) => {\n return {\n src: p.url,\n alt: p.alt\n }\n })\n}\n","'use strict'\n\nexport default function parseLinks(props) {\n return props\n .filter((p) => p.type === 'link')\n .map((p) => {\n return {\n src: p.url,\n alt: p.children[0].value\n }\n })\n}\n","'use strict'\n\nexport default function parseDuration(text) {\n let matched = false\n const duration = {\n hours: 0,\n minutes: 0\n }\n\n const hoursAndMinutes = new RegExp(/([0-9]+)h([0-9]+)m/)\n const hours = new RegExp(/([0-9]+)h/)\n\n if (text.match(hoursAndMinutes)) {\n matched = true\n const [, h, m] = text.match(hoursAndMinutes)\n duration.hours = parseInt(h)\n duration.minutes = parseInt(m)\n } else if (text.match(hours)) {\n matched = true\n const [, h] = text.match(hours)\n duration.hours = parseInt(h)\n duration.minutes = 0\n }\n\n if (matched) {\n return duration\n } else {\n return null\n }\n}\n"],"names":["commonDateFormats","commonTimeFormats","parseList","list","children","map","item","listItem","type","checked","child","text","c","link","url","value","filter","x","join","_settle","pact","state","s","_Pact","o","bind","v","then","observer","prototype","onFulfilled","onRejected","result","this","callback","e","_this","_isSettledPact","thenable","debug","createDebug","body","_iterator","_step","token","cleanText","obj","date","images","links","time","duration","key","content","Promise","resolve","unified","use","remarkParse","remarkGfm","parse","tokens","_temp2","structuredResponse","Boolean","length","currentHeading","_createForOfIteratorHelperLoose","_temp","test","update","stage","shouldContinue","updateValue","reject","_resumeAfterTest","_resumeAfterBody","_resumeAfterUpdate","_for","done","remarkStringify","stringify","_unified$use$use$stri","match","stripFinalNewline","indexOf","replace","slugify","title","heading","depth","format","isMatch","zonedTimeToUtc","Date","toJSON","split","p","src","alt","formatInTimeZone","parseTime","matched","hours","minutes","hoursAndMinutes","RegExp","_text$match","m","parseInt","_text$match2","parseDuration","push","flat","html","lang"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parse.umd.js","sources":["../src/parsers/date.js","../src/parsers/time.js","../src/parsers/index.js","../src/parsers/list.js","../src/parse.js","../src/parsers/images.js","../src/parsers/links.js","../src/parsers/duration.js"],"sourcesContent":["'use strict'\n\nimport { parse, isMatch } from 'date-fns'\nimport { fromZonedTime } from 'date-fns-tz'\n\nconst loc = 'UTC'\nconst commonDateFormats = [\n 'yyyy-MM-dd',\n 'dd/MM/yyyy',\n 'dd/MM/yy',\n 'dd-MM-yyyy',\n 'dd-MM-yy',\n 'dd.MM.yyyy',\n 'dd.MM.yy'\n]\n\nexport default function parseDate(text) {\n const match = commonDateFormats.map((format) => {\n return isMatch(text, format)\n })\n if (match.indexOf(true) > -1) {\n const date = fromZonedTime(\n parse(text, commonDateFormats[match.indexOf(true)], new Date()),\n loc\n ).toJSON()\n return date.split('T')[0]\n } else {\n return null\n }\n}\n","'use strict'\n\nimport { parse, isMatch } from 'date-fns'\nimport { fromZonedTime, formatInTimeZone } from 'date-fns-tz'\n\nconst loc = 'UTC'\nconst commonTimeFormats = [\n 'HH:mm',\n 'HH.mm',\n 'hh:mm aaa',\n 'hh:mm a..aa',\n 'hh:mm aaaa'\n]\n\nexport default function parseTime(text) {\n const match = commonTimeFormats.map((format) => {\n return isMatch(text, format)\n })\n if (match.indexOf(true) > -1) {\n const time = fromZonedTime(\n parse(text, commonTimeFormats[match.indexOf(true)], new Date()),\n loc\n )\n return formatInTimeZone(time, loc, 'HH:mm')\n } else {\n return null\n }\n}\n","'use strict'\n\nimport date from './date.js'\nimport time from './time.js'\nimport duration from './duration.js'\nimport list from './list.js'\nimport images from './images.js'\nimport links from './links.js'\n\nexport const parseDate = date\nexport const parseTime = time\nexport const parseDuration = duration\nexport const parseList = list\nexport const parseImages = images\nexport const parseLinks = links\n","'use strict'\n\nexport default function parseList(list) {\n return list.children\n .map((item) => {\n const listItem = {}\n if (item.type === 'list') {\n return parseList(list)\n } else if (item.type === 'listItem') {\n listItem.checked = item.checked\n return item.children\n .map((child) => {\n if (child.type === 'paragraph') {\n listItem.text = child.children\n .map((c) => {\n if (c.type === 'link') {\n listItem.link = c.url\n return `[${c.children[0].value}](${c.url})`\n } else {\n return c.value\n }\n })\n .filter((x) => !!x)\n .join('')\n return listItem\n }\n })\n .filter((x) => !!x)\n }\n })\n .filter((x) => !!x)\n}\n","'use strict'\n\nimport { unified } from 'unified'\nimport remarkParse from 'remark-parse'\nimport remarkGfm from 'remark-gfm'\nimport slugify from '@sindresorhus/slugify'\nimport remarkStringify from 'remark-stringify'\nimport stripFinalNewline from 'strip-final-newline'\nimport createDebug from 'debug'\nconst debug = createDebug('body-parser')\n\nimport {\n parseDate,\n parseTime,\n parseDuration,\n parseList,\n parseImages,\n parseLinks\n} from './parsers/index.js'\n\nexport default async function parseMD(body) {\n debug('parseMD()')\n const tokens = await unified().use(remarkParse).use(remarkGfm).parse(body)\n if (!tokens) {\n return []\n }\n\n const structuredResponse = {}\n let currentHeading = null\n\n for (const token of tokens.children) {\n const text = await unified()\n .use(remarkGfm)\n .use(remarkStringify)\n .stringify(token)\n let cleanText = stripFinalNewline(text)\n\n // remove `\\\\_`\n if (cleanText.indexOf('\\\\_') > -1) {\n cleanText = cleanText.replace(/\\\\_/g, '_')\n }\n\n // issue forms uses h3 as a heading\n if (token.type === 'heading') {\n currentHeading = slugify(token.children[0].value)\n structuredResponse[currentHeading] = {\n title: token.children[0].value,\n heading: token.depth,\n content: []\n }\n } else if (token.type === 'paragraph' && currentHeading) {\n const obj = structuredResponse[currentHeading]\n\n const trimmedText = cleanText.trim()\n if (trimmedText === '*No response*' || trimmedText === '_No response_') {\n obj.text = null\n continue\n }\n\n const date = parseDate(cleanText)\n const images = parseImages(token.children)\n const links = parseLinks(token.children)\n const time = parseTime(cleanText)\n const duration = parseDuration(cleanText)\n\n if (date) {\n obj.date = date\n }\n\n if (time) {\n obj.time = time\n }\n\n if (duration) {\n obj.duration = duration\n }\n\n if (links && links.length > 0) {\n obj.links = links\n }\n\n if (images && images.length > 0) {\n obj.images = images\n }\n\n obj.content.push(cleanText)\n } else if (token.type === 'list') {\n const obj = structuredResponse[currentHeading]\n obj.text = cleanText\n obj.list = parseList(token).flat()\n } else if (token.type === 'html') {\n const obj = structuredResponse[currentHeading]\n obj.content.push(token.html)\n } else if (token.type === 'code') {\n const obj = structuredResponse[currentHeading]\n obj.lang = token.lang\n obj.text = cleanText\n } else {\n debug('unhandled token type')\n debug(token)\n }\n }\n\n for (const key in structuredResponse) {\n const token = structuredResponse[key]\n const content = token.content.filter(Boolean)\n if (content && content.length > 0) {\n if (content.length === 1) {\n token.text = content[0]\n }\n token.text = content.join('\\n\\n')\n }\n token.content = content\n }\n\n return structuredResponse\n}\n","'use strict'\n\nexport default function parseImage(props) {\n return props\n .filter((p) => p.type === 'image')\n .map((p) => {\n return {\n src: p.url,\n alt: p.alt\n }\n })\n}\n","'use strict'\n\nexport default function parseLinks(props) {\n return props\n .filter((p) => p.type === 'link')\n .map((p) => {\n return {\n src: p.url,\n alt: p.children[0].value\n }\n })\n}\n","'use strict'\n\nexport default function parseDuration(text) {\n let matched = false\n const duration = {\n hours: 0,\n minutes: 0\n }\n\n const hoursAndMinutes = new RegExp(/([0-9]+)h([0-9]+)m/)\n const hours = new RegExp(/([0-9]+)h/)\n\n if (text.match(hoursAndMinutes)) {\n matched = true\n const [, h, m] = text.match(hoursAndMinutes)\n duration.hours = parseInt(h)\n duration.minutes = parseInt(m)\n } else if (text.match(hours)) {\n matched = true\n const [, h] = text.match(hours)\n duration.hours = parseInt(h)\n duration.minutes = 0\n }\n\n if (matched) {\n return duration\n } else {\n return null\n }\n}\n"],"names":["commonDateFormats","commonTimeFormats","parseList","list","children","map","item","listItem","type","checked","child","text","c","link","url","value","filter","x","join","_settle","pact","state","s","_Pact","o","bind","v","then","observer","prototype","onFulfilled","onRejected","result","this","callback","e","_this","_isSettledPact","thenable","debug","createDebug","body","_iterator","_step","token","cleanText","obj","trimmedText","date","images","links","time","duration","key","content","Promise","resolve","unified","use","remarkParse","remarkGfm","parse","tokens","_temp2","structuredResponse","Boolean","length","currentHeading","_createForOfIteratorHelperLoose","_temp","test","update","stage","shouldContinue","updateValue","reject","_resumeAfterTest","_resumeAfterBody","_resumeAfterUpdate","_for","done","remarkStringify","stringify","_unified$use$use$stri","stripFinalNewline","indexOf","replace","slugify","title","heading","depth","trim","match","format","isMatch","fromZonedTime","Date","toJSON","split","p","src","alt","formatInTimeZone","parseTime","matched","hours","minutes","hoursAndMinutes","RegExp","_text$match","m","parseInt","_text$match2","parseDuration","push","flat","html","lang"],"mappings":"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"}
|
package/.eslintignore
DELETED
package/.eslintrc.json
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
name: Bug report
|
|
2
|
-
description: Create a report to help us improve
|
|
3
|
-
title: Bug report
|
|
4
|
-
labels: ['bug']
|
|
5
|
-
body:
|
|
6
|
-
- type: textarea
|
|
7
|
-
id: description
|
|
8
|
-
attributes:
|
|
9
|
-
label: Describe the bug
|
|
10
|
-
description: A clear and concise description of what the bug is.
|
|
11
|
-
validations:
|
|
12
|
-
required: true
|
|
13
|
-
- type: textarea
|
|
14
|
-
id: reproduction
|
|
15
|
-
attributes:
|
|
16
|
-
label: To reproduce
|
|
17
|
-
description: Steps to reproduce the behavior
|
|
18
|
-
placeholder: >
|
|
19
|
-
1. Go to ...\n 2. Click on ...\n 3. Scroll down to ...\n 4. See error
|
|
20
|
-
validations:
|
|
21
|
-
required: false
|
|
22
|
-
- type: textarea
|
|
23
|
-
id: expectation
|
|
24
|
-
attributes:
|
|
25
|
-
label: Expected behaviour
|
|
26
|
-
description:
|
|
27
|
-
A clear and concise description of what you expected to happen.
|
|
28
|
-
validations:
|
|
29
|
-
required: false
|
|
30
|
-
- type: textarea
|
|
31
|
-
id: additional
|
|
32
|
-
attributes:
|
|
33
|
-
label: Additional context
|
|
34
|
-
description: Add any other context about the problem here.
|
|
35
|
-
validations:
|
|
36
|
-
required: false
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
blank_issues_enabled: false
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
name: Feature request
|
|
2
|
-
description: Suggest an idea for this project
|
|
3
|
-
title: Feature request
|
|
4
|
-
labels: ['enhancement']
|
|
5
|
-
body:
|
|
6
|
-
- type: textarea
|
|
7
|
-
id: description
|
|
8
|
-
attributes:
|
|
9
|
-
label: Is your feature request related to a problem? Please describe.
|
|
10
|
-
description:
|
|
11
|
-
A clear and concise description of what the problem is. Ex. Im always
|
|
12
|
-
frustrated when [...]
|
|
13
|
-
validations:
|
|
14
|
-
required: true
|
|
15
|
-
- type: textarea
|
|
16
|
-
id: solution
|
|
17
|
-
attributes:
|
|
18
|
-
label: Describe the solution you would like
|
|
19
|
-
description: A clear and concise description of what you want to happen.
|
|
20
|
-
validations:
|
|
21
|
-
required: false
|
|
22
|
-
- type: textarea
|
|
23
|
-
id: alternatives
|
|
24
|
-
attributes:
|
|
25
|
-
label: Describe alternatives you have considered
|
|
26
|
-
description:
|
|
27
|
-
A clear and concise description of any alternative solutions or features
|
|
28
|
-
you have considered.
|
|
29
|
-
validations:
|
|
30
|
-
required: false
|
|
31
|
-
- type: textarea
|
|
32
|
-
id: additional
|
|
33
|
-
attributes:
|
|
34
|
-
label: Additional context
|
|
35
|
-
description:
|
|
36
|
-
Add any other context or screenshots about the feature request here.
|
|
37
|
-
validations:
|
|
38
|
-
required: false
|
package/.github/dependabot.yml
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
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@v4
|
|
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
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
name: e2e test
|
|
2
|
-
|
|
3
|
-
on: issues
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
test:
|
|
7
|
-
runs-on: ubuntu-latest
|
|
8
|
-
steps:
|
|
9
|
-
- uses: actions/checkout@v4
|
|
10
|
-
- name: Issue Forms Body Parser
|
|
11
|
-
id: parse
|
|
12
|
-
uses: ./
|
|
13
|
-
- run: echo ${{ toJSON(steps.parse.outputs.data) }}
|
|
14
|
-
|
|
15
|
-
- name: Read an issue content
|
|
16
|
-
id: read_issue
|
|
17
|
-
run: |
|
|
18
|
-
echo "body<<EOF" >> $GITHUB_OUTPUT
|
|
19
|
-
cat ./test/test-issue-3.md >> $GITHUB_OUTPUT
|
|
20
|
-
echo "EOF" >> $GITHUB_OUTPUT
|
|
21
|
-
- name: Issue Forms Body Parser With Provided Body
|
|
22
|
-
id: parse_with_body
|
|
23
|
-
uses: ./
|
|
24
|
-
with:
|
|
25
|
-
body: ${{ steps.read_issue.outputs.body }}
|
|
26
|
-
- run: echo ${{ toJSON(steps.parse_with_body.outputs.data) }}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
name: Publish
|
|
2
|
-
|
|
3
|
-
permissions:
|
|
4
|
-
contents: write
|
|
5
|
-
deployments: write
|
|
6
|
-
issues: read
|
|
7
|
-
pull-requests: write
|
|
8
|
-
|
|
9
|
-
on:
|
|
10
|
-
push:
|
|
11
|
-
branches:
|
|
12
|
-
- 'main'
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
test:
|
|
16
|
-
env:
|
|
17
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
18
|
-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
19
|
-
runs-on: ubuntu-latest
|
|
20
|
-
steps:
|
|
21
|
-
- uses: actions/checkout@v4
|
|
22
|
-
- uses: actions/setup-node@v4
|
|
23
|
-
with:
|
|
24
|
-
node-version: 20
|
|
25
|
-
cache: 'npm'
|
|
26
|
-
- run: npm ci
|
|
27
|
-
- run: npm test
|
|
28
|
-
env:
|
|
29
|
-
GITHUB_REPOSITORY: zentered/issue-forms-body-parser-test
|
|
30
|
-
- run: npm run release
|
|
31
|
-
- run: npx semantic-release
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
name: Test
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
branches:
|
|
6
|
-
- '**'
|
|
7
|
-
- '!main'
|
|
8
|
-
push:
|
|
9
|
-
branches:
|
|
10
|
-
- '**'
|
|
11
|
-
- '!main'
|
|
12
|
-
|
|
13
|
-
jobs:
|
|
14
|
-
test:
|
|
15
|
-
env:
|
|
16
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
17
|
-
runs-on: ubuntu-latest
|
|
18
|
-
steps:
|
|
19
|
-
- uses: actions/checkout@v4
|
|
20
|
-
- uses: actions/setup-node@v4
|
|
21
|
-
with:
|
|
22
|
-
node-version: 20
|
|
23
|
-
cache: 'npm'
|
|
24
|
-
- run: npm ci
|
|
25
|
-
- run: npm run lint
|
|
26
|
-
- run: npm test
|
|
27
|
-
env:
|
|
28
|
-
GITHUB_REPOSITORY: zentered/issue-forms-body-parser-test
|
|
29
|
-
|
|
30
|
-
- run: npm run build
|
|
31
|
-
|
|
32
|
-
- name: Read an issue content
|
|
33
|
-
id: read_issue
|
|
34
|
-
run: |
|
|
35
|
-
echo "body<<EOF" >> $GITHUB_OUTPUT
|
|
36
|
-
cat ./test/test-issue-3.md >> $GITHUB_OUTPUT
|
|
37
|
-
echo "EOF" >> $GITHUB_OUTPUT
|
|
38
|
-
- name: Issue Forms Body Parser With Provided Body
|
|
39
|
-
id: parse_with_body
|
|
40
|
-
uses: ./
|
|
41
|
-
with:
|
|
42
|
-
body: ${{ steps.read_issue.outputs.body }}
|
|
43
|
-
|
|
44
|
-
- name: Test input body parsed
|
|
45
|
-
run: |
|
|
46
|
-
expected="Event Description"
|
|
47
|
-
title=$(echo ${{ toJSON(steps.parse_with_body.outputs.data) }} | jq -r '.["event-description"].title')
|
|
48
|
-
if [[ $title != $expected ]]; then
|
|
49
|
-
echo "Title \"${title}\" does not match \"${expected}\""
|
|
50
|
-
exit 1
|
|
51
|
-
fi
|
package/.husky/commit-msg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
npx commitlint --edit $1
|
package/.husky/pre-commit
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
npx lint-staged
|
package/.prettierignore
DELETED
package/.prettierrc
DELETED
package/src/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import github from '@actions/github'
|
|
4
|
-
import core from '@actions/core'
|
|
5
|
-
import parse from './parse.js'
|
|
6
|
-
|
|
7
|
-
async function run() {
|
|
8
|
-
core.info('Parsing issue body ...')
|
|
9
|
-
|
|
10
|
-
let content = core.getInput('body')
|
|
11
|
-
|
|
12
|
-
if (content === '' && Object.hasOwn(github.context.payload, 'issue')) {
|
|
13
|
-
content = github.context.payload.issue.body
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
const parsedContent = await parse(content)
|
|
18
|
-
|
|
19
|
-
if (parsedContent !== undefined) {
|
|
20
|
-
core.setOutput('data', parsedContent)
|
|
21
|
-
} else {
|
|
22
|
-
core.setFailed(`There was no valid payload found in the issue.`)
|
|
23
|
-
}
|
|
24
|
-
} catch (err) {
|
|
25
|
-
core.setFailed(err)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
run()
|
package/src/parse.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { unified } from 'unified'
|
|
4
|
-
import remarkParse from 'remark-parse'
|
|
5
|
-
import remarkGfm from 'remark-gfm'
|
|
6
|
-
import slugify from '@sindresorhus/slugify'
|
|
7
|
-
import remarkStringify from 'remark-stringify'
|
|
8
|
-
import stripFinalNewline from 'strip-final-newline'
|
|
9
|
-
import createDebug from 'debug'
|
|
10
|
-
const debug = createDebug('body-parser')
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
parseDate,
|
|
14
|
-
parseTime,
|
|
15
|
-
parseDuration,
|
|
16
|
-
parseList,
|
|
17
|
-
parseImages,
|
|
18
|
-
parseLinks
|
|
19
|
-
} from './parsers/index.js'
|
|
20
|
-
|
|
21
|
-
export default async function parseMD(body) {
|
|
22
|
-
debug('parseMD()')
|
|
23
|
-
const tokens = await unified().use(remarkParse).use(remarkGfm).parse(body)
|
|
24
|
-
if (!tokens) {
|
|
25
|
-
return []
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const structuredResponse = {}
|
|
29
|
-
let currentHeading = null
|
|
30
|
-
|
|
31
|
-
for (const token of tokens.children) {
|
|
32
|
-
const text = await unified()
|
|
33
|
-
.use(remarkGfm)
|
|
34
|
-
.use(remarkStringify)
|
|
35
|
-
.stringify(token)
|
|
36
|
-
let cleanText = stripFinalNewline(text)
|
|
37
|
-
|
|
38
|
-
// remove `\\_`
|
|
39
|
-
if (cleanText.indexOf('\\_') > -1) {
|
|
40
|
-
cleanText = cleanText.replace(/\\_/g, '_')
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// issue forms uses h3 as a heading
|
|
44
|
-
if (token.type === 'heading') {
|
|
45
|
-
currentHeading = slugify(token.children[0].value)
|
|
46
|
-
structuredResponse[currentHeading] = {
|
|
47
|
-
title: token.children[0].value,
|
|
48
|
-
heading: token.depth,
|
|
49
|
-
content: []
|
|
50
|
-
}
|
|
51
|
-
} else if (token.type === 'paragraph' && currentHeading) {
|
|
52
|
-
const obj = structuredResponse[currentHeading]
|
|
53
|
-
|
|
54
|
-
const date = parseDate(cleanText)
|
|
55
|
-
const images = parseImages(token.children)
|
|
56
|
-
const links = parseLinks(token.children)
|
|
57
|
-
const time = parseTime(cleanText)
|
|
58
|
-
const duration = parseDuration(cleanText)
|
|
59
|
-
|
|
60
|
-
if (date) {
|
|
61
|
-
obj.date = date
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (time) {
|
|
65
|
-
obj.time = time
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (duration) {
|
|
69
|
-
obj.duration = duration
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (links && links.length > 0) {
|
|
73
|
-
obj.links = links
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (images && images.length > 0) {
|
|
77
|
-
obj.images = images
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
obj.content.push(cleanText)
|
|
81
|
-
} else if (token.type === 'list') {
|
|
82
|
-
const obj = structuredResponse[currentHeading]
|
|
83
|
-
obj.text = cleanText
|
|
84
|
-
obj.list = parseList(token).flat()
|
|
85
|
-
} else if (token.type === 'html') {
|
|
86
|
-
const obj = structuredResponse[currentHeading]
|
|
87
|
-
obj.content.push(token.html)
|
|
88
|
-
} else if (token.type === 'code') {
|
|
89
|
-
const obj = structuredResponse[currentHeading]
|
|
90
|
-
obj.lang = token.lang
|
|
91
|
-
obj.text = cleanText
|
|
92
|
-
} else {
|
|
93
|
-
debug('unhandled token type')
|
|
94
|
-
debug(token)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
for (const key in structuredResponse) {
|
|
99
|
-
const token = structuredResponse[key]
|
|
100
|
-
const content = token.content.filter(Boolean)
|
|
101
|
-
if (content && content.length > 0) {
|
|
102
|
-
if (content.length === 1) {
|
|
103
|
-
token.text = content[0]
|
|
104
|
-
}
|
|
105
|
-
token.text = content.join('\n\n')
|
|
106
|
-
}
|
|
107
|
-
token.content = content
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return structuredResponse
|
|
111
|
-
}
|
package/src/parsers/date.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { parse, isMatch } from 'date-fns'
|
|
4
|
-
import { zonedTimeToUtc } from 'date-fns-tz'
|
|
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
|
-
}
|
package/src/parsers/duration.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
export default function parseDuration(text) {
|
|
4
|
-
let matched = false
|
|
5
|
-
const duration = {
|
|
6
|
-
hours: 0,
|
|
7
|
-
minutes: 0
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const hoursAndMinutes = new RegExp(/([0-9]+)h([0-9]+)m/)
|
|
11
|
-
const hours = new RegExp(/([0-9]+)h/)
|
|
12
|
-
|
|
13
|
-
if (text.match(hoursAndMinutes)) {
|
|
14
|
-
matched = true
|
|
15
|
-
const [, h, m] = text.match(hoursAndMinutes)
|
|
16
|
-
duration.hours = parseInt(h)
|
|
17
|
-
duration.minutes = parseInt(m)
|
|
18
|
-
} else if (text.match(hours)) {
|
|
19
|
-
matched = true
|
|
20
|
-
const [, h] = text.match(hours)
|
|
21
|
-
duration.hours = parseInt(h)
|
|
22
|
-
duration.minutes = 0
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (matched) {
|
|
26
|
-
return duration
|
|
27
|
-
} else {
|
|
28
|
-
return null
|
|
29
|
-
}
|
|
30
|
-
}
|
package/src/parsers/images.js
DELETED
package/src/parsers/index.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
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
|
-
import images from './images.js'
|
|
8
|
-
import links from './links.js'
|
|
9
|
-
|
|
10
|
-
export const parseDate = date
|
|
11
|
-
export const parseTime = time
|
|
12
|
-
export const parseDuration = duration
|
|
13
|
-
export const parseList = list
|
|
14
|
-
export const parseImages = images
|
|
15
|
-
export const parseLinks = links
|
package/src/parsers/links.js
DELETED
package/src/parsers/list.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
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
|
-
listItem.link = c.url
|
|
18
|
-
return `[${c.children[0].value}](${c.url})`
|
|
19
|
-
} else {
|
|
20
|
-
return c.value
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
.filter((x) => !!x)
|
|
24
|
-
.join('')
|
|
25
|
-
return listItem
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
.filter((x) => !!x)
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
.filter((x) => !!x)
|
|
32
|
-
}
|