├── .github
└── workflows
│ ├── code_health.yml
│ └── populate_feed.yml
├── .gitignore
├── .nvmrc
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── __tests__
└── utils.test.js
├── config.json
├── feed.xml
├── jest.config.cjs
├── package-lock.json
├── package.json
├── scripts
├── build.js
├── collect-discussions.js
├── collect-issues.js
├── collect-releases.js
├── format-check.js
├── format.js
└── validate.js
└── utils
└── index.js
/.github/workflows/code_health.yml:
--------------------------------------------------------------------------------
1 | on:
2 | pull_request:
3 | branches:
4 | - main
5 | push:
6 | branches:
7 | - main
8 |
9 | name: Source Code Health
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v3
16 | - uses: actions/setup-node@v3
17 | with:
18 | node-version: '18.16.1'
19 | cache: 'npm'
20 |
21 | - name: Install dependencies
22 | run: npm ci
23 |
24 | - name: Lint
25 | run: npm run lint
26 |
27 | - name: Test
28 | run: npm run rss:build
29 |
30 | - name: RSS Build
31 | run: npm run rss:build
32 |
33 | - name: RSS Check Format
34 | run: npm run rss:format-check
35 |
36 | - name: RSS Validate
37 | run: npm run rss:validate
38 |
--------------------------------------------------------------------------------
/.github/workflows/populate_feed.yml:
--------------------------------------------------------------------------------
1 | on:
2 | workflow_dispatch:
3 | schedule:
4 | - cron: '0 0 * * 0'
5 |
6 | name: Populate Feed
7 |
8 | permissions:
9 | contents: write
10 | pull-requests: write
11 | issues: read
12 | packages: none
13 |
14 | jobs:
15 | build:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v3
19 | - uses: actions/setup-node@v3
20 | with:
21 | node-version: '18.16.1'
22 | cache: 'npm'
23 |
24 | - name: Install dependencies
25 | run: npm ci
26 |
27 | - name: Collect Releases
28 | run: npm run collect:releases
29 | env:
30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31 |
32 | - name: Collect Issues (Comments)
33 | run: npm run collect:issues
34 | env:
35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36 |
37 | - name: Collect Discussions (Comments)
38 | run: npm run collect:discussions
39 | env:
40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41 |
42 | - name: RSS Build
43 | run: npm run rss:build
44 |
45 | - name: RSS Format
46 | run: npm run rss:format
47 |
48 | - name: RSS Validate
49 | run: npm run rss:validate
50 |
51 | - name: Create Pull Request
52 | uses: gr2m/create-or-update-pull-request-action@77596e3166f328b24613f7082ab30bf2d93079d5
53 | env:
54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55 | with:
56 | commit-message: 'chore: updated feed data'
57 | title: Feed Updated 🍿
58 | body: 'Feed data Updated. cc: @ulisesGascon @mhdawson'
59 | assignees: ${{ github.actor }}
60 | labels: content-update
61 | branch: feed-update
62 | update-pull-request-title-and-body: true
63 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/node,macos,linux,windows
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=node,macos,linux,windows
3 |
4 | ### Linux ###
5 | *~
6 |
7 | # temporary files which can be created if a process still has a handle open of a deleted file
8 | .fuse_hidden*
9 |
10 | # KDE directory preferences
11 | .directory
12 |
13 | # Linux trash folder which might appear on any partition or disk
14 | .Trash-*
15 |
16 | # .nfs files are created when an open file is removed but is still being accessed
17 | .nfs*
18 |
19 | ### macOS ###
20 | # General
21 | .DS_Store
22 | .AppleDouble
23 | .LSOverride
24 |
25 | # Icon must end with two \r
26 | Icon
27 |
28 |
29 | # Thumbnails
30 | ._*
31 |
32 | # Files that might appear in the root of a volume
33 | .DocumentRevisions-V100
34 | .fseventsd
35 | .Spotlight-V100
36 | .TemporaryItems
37 | .Trashes
38 | .VolumeIcon.icns
39 | .com.apple.timemachine.donotpresent
40 |
41 | # Directories potentially created on remote AFP share
42 | .AppleDB
43 | .AppleDesktop
44 | Network Trash Folder
45 | Temporary Items
46 | .apdisk
47 |
48 | ### macOS Patch ###
49 | # iCloud generated files
50 | *.icloud
51 |
52 | ### Node ###
53 | # Logs
54 | logs
55 | *.log
56 | npm-debug.log*
57 | yarn-debug.log*
58 | yarn-error.log*
59 | lerna-debug.log*
60 | .pnpm-debug.log*
61 |
62 | # Diagnostic reports (https://nodejs.org/api/report.html)
63 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
64 |
65 | # Runtime data
66 | pids
67 | *.pid
68 | *.seed
69 | *.pid.lock
70 |
71 | # Directory for instrumented libs generated by jscoverage/JSCover
72 | lib-cov
73 |
74 | # Coverage directory used by tools like istanbul
75 | coverage
76 | *.lcov
77 |
78 | # nyc test coverage
79 | .nyc_output
80 |
81 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
82 | .grunt
83 |
84 | # Bower dependency directory (https://bower.io/)
85 | bower_components
86 |
87 | # node-waf configuration
88 | .lock-wscript
89 |
90 | # Compiled binary addons (https://nodejs.org/api/addons.html)
91 | build/Release
92 |
93 | # Dependency directories
94 | node_modules/
95 | jspm_packages/
96 |
97 | # Snowpack dependency directory (https://snowpack.dev/)
98 | web_modules/
99 |
100 | # TypeScript cache
101 | *.tsbuildinfo
102 |
103 | # Optional npm cache directory
104 | .npm
105 |
106 | # Optional eslint cache
107 | .eslintcache
108 |
109 | # Optional stylelint cache
110 | .stylelintcache
111 |
112 | # Microbundle cache
113 | .rpt2_cache/
114 | .rts2_cache_cjs/
115 | .rts2_cache_es/
116 | .rts2_cache_umd/
117 |
118 | # Optional REPL history
119 | .node_repl_history
120 |
121 | # Output of 'npm pack'
122 | *.tgz
123 |
124 | # Yarn Integrity file
125 | .yarn-integrity
126 |
127 | # dotenv environment variable files
128 | .env
129 | .env.development.local
130 | .env.test.local
131 | .env.production.local
132 | .env.local
133 |
134 | # parcel-bundler cache (https://parceljs.org/)
135 | .cache
136 | .parcel-cache
137 |
138 | # Next.js build output
139 | .next
140 | out
141 |
142 | # Nuxt.js build / generate output
143 | .nuxt
144 | dist
145 |
146 | # Gatsby files
147 | .cache/
148 | # Comment in the public line in if your project uses Gatsby and not Next.js
149 | # https://nextjs.org/blog/next-9-1#public-directory-support
150 | # public
151 |
152 | # vuepress build output
153 | .vuepress/dist
154 |
155 | # vuepress v2.x temp and cache directory
156 | .temp
157 |
158 | # Docusaurus cache and generated files
159 | .docusaurus
160 |
161 | # Serverless directories
162 | .serverless/
163 |
164 | # FuseBox cache
165 | .fusebox/
166 |
167 | # DynamoDB Local files
168 | .dynamodb/
169 |
170 | # TernJS port file
171 | .tern-port
172 |
173 | # Stores VSCode versions used for testing VSCode extensions
174 | .vscode-test
175 |
176 | # yarn v2
177 | .yarn/cache
178 | .yarn/unplugged
179 | .yarn/build-state.yml
180 | .yarn/install-state.gz
181 | .pnp.*
182 |
183 | ### Node Patch ###
184 | # Serverless Webpack directories
185 | .webpack/
186 |
187 | # Optional stylelint cache
188 |
189 | # SvelteKit build / generate output
190 | .svelte-kit
191 |
192 | ### Windows ###
193 | # Windows thumbnail cache files
194 | Thumbs.db
195 | Thumbs.db:encryptable
196 | ehthumbs.db
197 | ehthumbs_vista.db
198 |
199 | # Dump file
200 | *.stackdump
201 |
202 | # Folder config file
203 | [Dd]esktop.ini
204 |
205 | # Recycle Bin used on file shares
206 | $RECYCLE.BIN/
207 |
208 | # Windows Installer files
209 | *.cab
210 | *.msi
211 | *.msix
212 | *.msm
213 | *.msp
214 |
215 | # Windows shortcuts
216 | *.lnk
217 |
218 | # End of https://www.toptal.com/developers/gitignore/api/node,macos,linux,windows
219 |
220 | IGNORE/
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 18.16.1
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | The Node.js Code of Conduct applies to this repo.
4 |
5 | The Node.js Code of Conduct document can be found at
6 | https://github.com/nodejs/admin/blob/main/CODE_OF_CONDUCT.md
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | * [Code of Conduct](#code-of-conduct)
4 | * [Issues](#issues)
5 | * [Pull Requests](#pull-requests)
6 | * [Developer's Certificate of Origin 1.1](#developers-certificate-of-origin)
7 |
8 | ## [Code of Conduct](./doc/contributing/code-of-conduct.md)
9 |
10 | The project has a
11 | [Code of Conduct](CODE_OF_CONDUCT.md)
12 | to which all contributors must adhere.
13 |
14 | See [details on our policy on Code of Conduct](CODE_OF_CONDUCT.md).
15 |
16 | ## [Issues](./doc/contributing/issues.md)
17 |
18 | You can use the issues to:
19 | - Asking for General Help
20 | - Discussing non-technical topics
21 | - Submitting a Bug Report
22 |
23 |
24 | ## [Pull Requests](./doc/contributing/pull-requests.md)
25 |
26 | Feel free to submit a pull request (PR) if you see something that can be improved. We will provide you support if you are new to open source and/or contributing to open source projects.
27 |
28 |
29 |
30 | ## Developer's Certificate of Origin 1.1
31 |
32 |
33 | By making a contribution to this project, I certify that:
34 |
35 | (a) The contribution was created in whole or in part by me and I
36 | have the right to submit it under the open source license
37 | indicated in the file; or
38 |
39 | (b) The contribution is based upon previous work that, to the best
40 | of my knowledge, is covered under an appropriate open source
41 | license and I have the right under that license to submit that
42 | work with modifications, whether created in whole or in part
43 | by me, under the same open source license (unless I am
44 | permitted to submit under a different license), as indicated
45 | in the file; or
46 |
47 | (c) The contribution was provided directly to me by some other
48 | person who certified (a), (b) or (c) and I have not modified
49 | it.
50 |
51 | (d) I understand and agree that this project and the contribution
52 | are public and that a record of the contribution (including all
53 | personal information I submit with it, including my sign-off) is
54 | maintained indefinitely and may be redistributed consistent with
55 | this project or the open source license(s) involved.
56 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Ulises Gascon and Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Official Node.js News Feeder
2 |
3 | ### Usage
4 |
5 | This project is a proof of concept of a news feeder using NodeJS. It uses the Github API to fetch the relevant information from issues, releases..and then it generates a RSS feed with the latest news.
6 |
7 | The RSS feed is available at https://raw.githubusercontent.com/nodejs/nodejs-news-feeder/main/feed.xml and https://nodejs.github.io/nodejs-news-feeder/feed.xml
8 |
9 | In order to update the RSS feed, you need to trigger the Github Action `Populate Feed` [manually](https://github.com/nodejs/nodejs-news-feeder/actions/workflows/populate_feed.yml) or wait for the CRON job.
10 |
11 | This process will generate a PR with the latest news, so we can change the content and decide when to merge it.
12 |
13 | ### Development
14 |
15 | ```bash
16 | git clone https://github.com/nodejs/nodejs-news-feeder
17 | cd nodejs-news-feeder
18 | nvm use
19 | npm install
20 | ```
21 |
22 |
23 | ### Scripts
24 |
25 | #### Code linter
26 |
27 | ```bash
28 | npm run lint
29 | npm run lint:fix
30 | ```
31 |
32 | #### Testing
33 |
34 | ```bash
35 | npm run test
36 | npm run test:watch
37 | npm run test:coverage
38 | ```
39 |
40 | #### RSS formatter
41 |
42 | Update the `feed.xml` file format
43 |
44 | ```bash
45 | npm run rss:format-check
46 | npm run rss:format
47 | ```
48 |
49 | #### RSS Build
50 |
51 | Update the `feed.xml` file with the latest news
52 |
53 | ```bash
54 | npm run rss:build
55 | ```
56 |
57 | #### RSS Validate
58 |
59 | Check the current `feed.xml` against the https://validator.w3.org/feed/check.cgi
60 |
61 | ```bash
62 | npm run rss:validate
63 | ```
64 |
65 | ### License
66 |
67 | MIT License
--------------------------------------------------------------------------------
/__tests__/utils.test.js:
--------------------------------------------------------------------------------
1 | import { buildRFC822Date } from '../utils'
2 |
3 | describe('Utils', () => {
4 | describe('buildRFC822Date', () => {
5 | it('should return a date in RFC822 format', () => {
6 | expect(buildRFC822Date('2021-11-29T00:00:00.000Z')).toBe('Mon, 29 Nov 2021 01:00:00 BST')
7 | expect(buildRFC822Date('2021-09-08T00:00:00.000+01:00')).toBe('Wed, 08 Sep 2021 01:00:00 BST')
8 | })
9 | })
10 | })
11 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lastCheckTimestamp": 1694304480111,
3 | "reposPaginationLimit": 250,
4 | "releasePaginationLimit": 10,
5 | "commentsPaginationLimit": 100,
6 | "breakDelimiter": "",
7 | "discussionsInScope": [
8 | {
9 | "team": "Node.js Core",
10 | "discussionId": "47703"
11 | }
12 | ],
13 | "issuesInScope": [
14 | {
15 | "team": "News Feeder team",
16 | "issue": "nodejs/nodejs-news-feeder/issues/4"
17 | },
18 | {
19 | "team": "Uvwasi team",
20 | "issue": "nodejs/uvwasi/issues/201"
21 | },
22 | {
23 | "team": "Node-API and node-addon-api teams",
24 | "issue": "nodejs/abi-stable-node/issues/446"
25 | },
26 | {
27 | "team": "Security WG",
28 | "issue": "nodejs/security-wg/issues/1006"
29 | },
30 | {
31 | "team": "Single Executable team",
32 | "issue": "nodejs/single-executable/issues/74"
33 | },
34 | {
35 | "team": "Performance team",
36 | "issue": "nodejs/performance/issues/98"
37 | },
38 | {
39 | "team": "Website team",
40 | "issue": "nodejs/nodejs.org/issues/5602"
41 | },
42 | {
43 | "team": "Diagnostic team",
44 | "issue": "nodejs/diagnostics/issues/619"
45 | }
46 | ]
47 | }
--------------------------------------------------------------------------------
/feed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Node.js News
5 | https://nodejs.github.io/nodejs-news-feeder/feed.xml
6 |
7 | Node.js Core most relevant news
8 | Tue, 13 Jun 2023 04:17:50 GMT
9 | en-us
10 | https://validator.w3.org/feed/docs/rss2.html
11 | Sun, 10 Sep 2023 00:08:00 GMT
12 |
13 | Node.js News
14 | https://pbs.twimg.com/profile_images/1262824892535373825/BiXDFDDp_400x400.jpg
15 | https://github.com/nodejs/nodejs-news-feeder
16 |
17 |
18 | Released nodejs/caritat v1.2.0
19 | Released nodejs/caritat v1.2.0 by github-actions[bot]. More details
20 | ]]>
21 | Sun, 03 Sep 2023 18:19:00 GMT
22 | https://github.com/nodejs/caritat/releases/tag/v1.2.0
23 | https://github.com/nodejs/caritat/releases/tag/v1.2.0
24 |
25 |
26 | Released nodejs/node v20.6.1
27 | Released nodejs/node v20.6.1 by ruyadorno. More details
28 | ]]>
29 | Fri, 08 Sep 2023 16:49:00 GMT
30 | https://github.com/nodejs/node/releases/tag/v20.6.1
31 | https://github.com/nodejs/node/releases/tag/v20.6.1
32 |
33 |
34 | Released nodejs/node v20.6.0
35 | Released nodejs/node v20.6.0 by UlisesGascon. More details
36 | ]]>
37 | Mon, 04 Sep 2023 20:30:00 GMT
38 | https://github.com/nodejs/node/releases/tag/v20.6.0
39 | https://github.com/nodejs/node/releases/tag/v20.6.0
40 |
41 |
42 | Released nodejs/node-core-utils v3.4.0
43 | Released nodejs/node-core-utils v3.4.0 by github-actions[bot]. More details
44 | ]]>
45 | Mon, 04 Sep 2023 08:04:00 GMT
46 | https://github.com/nodejs/node-core-utils/releases/tag/v3.4.0
47 | https://github.com/nodejs/node-core-utils/releases/tag/v3.4.0
48 |
49 |
50 | Released nodejs/undici v5.24.0
51 | Released nodejs/undici v5.24.0 by mcollina. More details
52 | ]]>
53 | Fri, 08 Sep 2023 14:10:00 GMT
54 | https://github.com/nodejs/undici/releases/tag/v5.24.0
55 | https://github.com/nodejs/undici/releases/tag/v5.24.0
56 |
57 |
58 | Released nodejs/corepack v0.20.0
59 | Released nodejs/corepack v0.20.0 by github-actions[bot]. More details
60 | ]]>
61 | Tue, 29 Aug 2023 15:38:00 GMT
62 | https://github.com/nodejs/corepack/releases/tag/v0.20.0
63 | https://github.com/nodejs/corepack/releases/tag/v0.20.0
64 |
65 |
66 | Released nodejs/branch-diff v2.1.4
67 | Released nodejs/branch-diff v2.1.4 by github-actions[bot]. More details
68 | ]]>
69 | Mon, 21 Aug 2023 05:15:00 GMT
70 | https://github.com/nodejs/branch-diff/releases/tag/v2.1.4
71 | https://github.com/nodejs/branch-diff/releases/tag/v2.1.4
72 |
73 |
74 | Released nodejs/llhttp release/v9.0.1
75 | Released nodejs/llhttp release/v9.0.1 by ShogunPanda. More details
76 | ]]>
77 | Mon, 21 Aug 2023 12:10:00 GMT
78 | https://github.com/nodejs/llhttp/releases/tag/release/v9.0.1
79 | https://github.com/nodejs/llhttp/releases/tag/release/v9.0.1
80 |
81 |
82 | Released nodejs/branch-diff v2.1.3
83 | Released nodejs/branch-diff v2.1.3 by github-actions[bot]. More details
84 | ]]>
85 | Tue, 15 Aug 2023 01:09:00 GMT
86 | https://github.com/nodejs/branch-diff/releases/tag/v2.1.3
87 | https://github.com/nodejs/branch-diff/releases/tag/v2.1.3
88 |
89 |
90 | Released nodejs/caritat v1.1.1
91 | Released nodejs/caritat v1.1.1 by github-actions[bot]. More details
92 | ]]>
93 | Mon, 14 Aug 2023 13:44:00 GMT
94 | https://github.com/nodejs/caritat/releases/tag/v1.1.1
95 | https://github.com/nodejs/caritat/releases/tag/v1.1.1
96 |
97 |
98 | Released nodejs/caritat v1.1.0
99 | Released nodejs/caritat v1.1.0 by github-actions[bot]. More details
100 | ]]>
101 | Mon, 14 Aug 2023 13:39:00 GMT
102 | https://github.com/nodejs/caritat/releases/tag/v1.1.0
103 | https://github.com/nodejs/caritat/releases/tag/v1.1.0
104 |
105 |
106 | Released nodejs/node v20.5.1
107 | Released nodejs/node v20.5.1 by RafaelGSS. More details
108 | ]]>
109 | Wed, 09 Aug 2023 17:58:00 GMT
110 | https://github.com/nodejs/node/releases/tag/v20.5.1
111 | https://github.com/nodejs/node/releases/tag/v20.5.1
112 |
113 |
114 | Released nodejs/node v18.17.1
115 | Released nodejs/node v18.17.1 by RafaelGSS. More details
116 | ]]>
117 | Wed, 09 Aug 2023 17:58:00 GMT
118 | https://github.com/nodejs/node/releases/tag/v18.17.1
119 | https://github.com/nodejs/node/releases/tag/v18.17.1
120 |
121 |
122 | Released nodejs/node v16.20.2
123 | Released nodejs/node v16.20.2 by RafaelGSS. More details
124 | ]]>
125 | Wed, 09 Aug 2023 17:57:00 GMT
126 | https://github.com/nodejs/node/releases/tag/v16.20.2
127 | https://github.com/nodejs/node/releases/tag/v16.20.2
128 |
129 |
130 | Node-API and node-addon-api teams update on 2023-08-05 12:18:06
131 | node-api-headers v1.1.0 has been released.
132 | ]]>
133 | Sat, 05 Aug 2023 12:18:00 GMT
134 | https://github.com/nodejs/abi-stable-node/issues/446#issuecomment-1666490129
135 | https://github.com/nodejs/abi-stable-node/issues/446#issuecomment-1666490129
136 |
137 |
138 | Released nodejs/llhttp release/v9.0.0
139 | Released nodejs/llhttp release/v9.0.0 by ShogunPanda. More details
140 | ]]>
141 | Mon, 31 Jul 2023 14:31:00 GMT
142 | https://github.com/nodejs/llhttp/releases/tag/release/v9.0.0
143 | https://github.com/nodejs/llhttp/releases/tag/release/v9.0.0
144 |
145 |
146 | Released nodejs/node-api-headers v1.1.0
147 | Released nodejs/node-api-headers v1.1.0 by NickNaso. More details
148 | ]]>
149 | Sat, 05 Aug 2023 12:09:00 GMT
150 | https://github.com/nodejs/node-api-headers/releases/tag/v1.1.0
151 | https://github.com/nodejs/node-api-headers/releases/tag/v1.1.0
152 |
153 |
154 | Released nodejs/node-core-utils v3.3.0
155 | Released nodejs/node-core-utils v3.3.0 by github-actions[bot]. More details
156 | ]]>
157 | Fri, 04 Aug 2023 20:10:00 GMT
158 | https://github.com/nodejs/node-core-utils/releases/tag/v3.3.0
159 | https://github.com/nodejs/node-core-utils/releases/tag/v3.3.0
160 |
161 |
162 | Released nodejs/undici v5.23.0
163 | Released nodejs/undici v5.23.0 by ronag. More details
164 | ]]>
165 | Thu, 03 Aug 2023 08:33:00 GMT
166 | https://github.com/nodejs/undici/releases/tag/v5.23.0
167 | https://github.com/nodejs/undici/releases/tag/v5.23.0
168 |
169 |
170 | Released nodejs/node v20.5.0
171 | Released nodejs/node v20.5.0 by juanarbol. More details
172 | ]]>
173 | Thu, 20 Jul 2023 21:41:00 GMT
174 | https://github.com/nodejs/node/releases/tag/v20.5.0
175 | https://github.com/nodejs/node/releases/tag/v20.5.0
176 |
177 |
178 | Released nodejs/node v18.17.0
179 | Released nodejs/node v18.17.0 by danielleadams. More details
180 | ]]>
181 | Tue, 18 Jul 2023 20:05:00 GMT
182 | https://github.com/nodejs/node/releases/tag/v18.17.0
183 | https://github.com/nodejs/node/releases/tag/v18.17.0
184 |
185 |
186 | Released nodejs/branch-diff v2.1.2
187 | Released nodejs/branch-diff v2.1.2 by github-actions[bot]. More details
188 | ]]>
189 | Fri, 07 Jul 2023 07:18:00 GMT
190 | https://github.com/nodejs/branch-diff/releases/tag/v2.1.2
191 | https://github.com/nodejs/branch-diff/releases/tag/v2.1.2
192 |
193 |
194 | Released nodejs/node v20.4.0
195 | Released nodejs/node v20.4.0 by RafaelGSS. More details
196 | ]]>
197 | Wed, 05 Jul 2023 15:12:00 GMT
198 | https://github.com/nodejs/node/releases/tag/v20.4.0
199 | https://github.com/nodejs/node/releases/tag/v20.4.0
200 |
201 |
202 | Released nodejs/node-core-utils v3.2.1
203 | Released nodejs/node-core-utils v3.2.1 by github-actions[bot]. More details
204 | ]]>
205 | Tue, 04 Jul 2023 15:23:00 GMT
206 | https://github.com/nodejs/node-core-utils/releases/tag/v3.2.1
207 | https://github.com/nodejs/node-core-utils/releases/tag/v3.2.1
208 |
209 |
210 | Released nodejs/readable-stream v4.4.2
211 | Released nodejs/readable-stream v4.4.2 by mcollina. More details
212 | ]]>
213 | Mon, 03 Jul 2023 12:59:00 GMT
214 | https://github.com/nodejs/readable-stream/releases/tag/v4.4.2
215 | https://github.com/nodejs/readable-stream/releases/tag/v4.4.2
216 |
217 |
218 | Released nodejs/readable-stream v4.4.1
219 | Released nodejs/readable-stream v4.4.1 by mcollina. More details
220 | ]]>
221 | Mon, 03 Jul 2023 12:59:00 GMT
222 | https://github.com/nodejs/readable-stream/releases/tag/v4.4.1
223 | https://github.com/nodejs/readable-stream/releases/tag/v4.4.1
224 |
225 |
226 | Released nodejs/caritat v1.0.1
227 | Released nodejs/caritat v1.0.1 by github-actions[bot]. More details
228 | ]]>
229 | Wed, 28 Jun 2023 23:01:00 GMT
230 | https://github.com/nodejs/caritat/releases/tag/v1.0.1
231 | https://github.com/nodejs/caritat/releases/tag/v1.0.1
232 |
233 |
234 | Released nodejs/caritat v1.0.0
235 | Released nodejs/caritat v1.0.0 by github-actions[bot]. More details
236 | ]]>
237 | Wed, 28 Jun 2023 22:44:00 GMT
238 | https://github.com/nodejs/caritat/releases/tag/v1.0.0
239 | https://github.com/nodejs/caritat/releases/tag/v1.0.0
240 |
241 |
242 | Uvwasi team update on 2023-06-07 18:05:55
243 | Node.js main branch updated to include v0.0.18 version os uvwasi
244 | ]]>
245 | Wed, 07 Jun 2023 18:05:00 GMT
246 | https://github.com/nodejs/uvwasi/issues/201#issuecomment-1581283377
247 | https://github.com/nodejs/uvwasi/issues/201#issuecomment-1581283377
248 |
249 |
250 | Node-API and node-addon-api teams update on 2023-06-02 15:09:28
251 | Node-API version 9 has been landed: https://github.com/nodejs/node/pull/48151.
252 | ]]>
253 | Fri, 02 Jun 2023 15:09:00 GMT
254 | https://github.com/nodejs/abi-stable-node/issues/446#issuecomment-1573890828
255 | https://github.com/nodejs/abi-stable-node/issues/446#issuecomment-1573890828
256 |
257 |
258 | Released nodejs/caritat v0.6.2
259 | Released nodejs/caritat v0.6.2 by github-actions[bot]. More details
260 | ]]>
261 | Tue, 13 Jun 2023 16:22:00 GMT
262 | https://github.com/nodejs/caritat/releases/tag/v0.6.2
263 | https://github.com/nodejs/caritat/releases/tag/v0.6.2
264 |
265 |
266 | Released nodejs/caritat v0.6.1
267 | Released nodejs/caritat v0.6.1 by github-actions[bot]. More details
268 | ]]>
269 | Tue, 13 Jun 2023 16:10:00 GMT
270 | https://github.com/nodejs/caritat/releases/tag/v0.6.1
271 | https://github.com/nodejs/caritat/releases/tag/v0.6.1
272 |
273 |
274 | Released nodejs/caritat v0.6.0
275 | Released nodejs/caritat v0.6.0 by github-actions[bot]. More details
276 | ]]>
277 | Tue, 13 Jun 2023 15:38:00 GMT
278 | https://github.com/nodejs/caritat/releases/tag/v0.6.0
279 | https://github.com/nodejs/caritat/releases/tag/v0.6.0
280 |
281 |
282 | Released nodejs/corepack v0.19.0
283 | Released nodejs/corepack v0.19.0 by github-actions[bot]. More details
284 | ]]>
285 | Sat, 24 Jun 2023 16:55:00 GMT
286 | https://github.com/nodejs/corepack/releases/tag/v0.19.0
287 | https://github.com/nodejs/corepack/releases/tag/v0.19.0
288 |
289 |
290 | Released nodejs/corepack v0.18.1
291 | Released nodejs/corepack v0.18.1 by github-actions[bot]. More details
292 | ]]>
293 | Tue, 13 Jun 2023 12:56:00 GMT
294 | https://github.com/nodejs/corepack/releases/tag/v0.18.1
295 | https://github.com/nodejs/corepack/releases/tag/v0.18.1
296 |
297 |
298 | Released nodejs/llhttp release/v8.1.1
299 | Released nodejs/llhttp release/v8.1.1 by ShogunPanda. More details
300 | ]]>
301 | Wed, 21 Jun 2023 08:07:00 GMT
302 | https://github.com/nodejs/llhttp/releases/tag/release/v8.1.1
303 | https://github.com/nodejs/llhttp/releases/tag/release/v8.1.1
304 |
305 |
306 | Released nodejs/llhttp release/v6.0.11
307 | Released nodejs/llhttp release/v6.0.11 by ShogunPanda. More details
308 | ]]>
309 | Wed, 21 Jun 2023 08:45:00 GMT
310 | https://github.com/nodejs/llhttp/releases/tag/release/v6.0.11
311 | https://github.com/nodejs/llhttp/releases/tag/release/v6.0.11
312 |
313 |
314 | Released nodejs/node v20.3.1
315 | Released nodejs/node v20.3.1 by RafaelGSS. More details
316 | ]]>
317 | Tue, 20 Jun 2023 20:15:00 GMT
318 | https://github.com/nodejs/node/releases/tag/v20.3.1
319 | https://github.com/nodejs/node/releases/tag/v20.3.1
320 |
321 |
322 | Released nodejs/node v18.16.1
323 | Released nodejs/node v18.16.1 by RafaelGSS. More details
324 | ]]>
325 | Tue, 20 Jun 2023 20:35:00 GMT
326 | https://github.com/nodejs/node/releases/tag/v18.16.1
327 | https://github.com/nodejs/node/releases/tag/v18.16.1
328 |
329 |
330 | Released nodejs/node v16.20.1
331 | Released nodejs/node v16.20.1 by RafaelGSS. More details
332 | ]]>
333 | Tue, 20 Jun 2023 19:29:00 GMT
334 | https://github.com/nodejs/node/releases/tag/v16.20.1
335 | https://github.com/nodejs/node/releases/tag/v16.20.1
336 |
337 |
338 | Released nodejs/node v20.3.0
339 | Released nodejs/node v20.3.0 by RafaelGSS. More details
340 | ]]>
341 | Thu, 08 Jun 2023 16:34:00 GMT
342 | https://github.com/nodejs/node/releases/tag/v20.3.0
343 | https://github.com/nodejs/node/releases/tag/v20.3.0
344 |
345 |
346 | Released nodejs/node-addon-api v7.0.0
347 | Released nodejs/node-addon-api v7.0.0 by KevinEady. More details
348 | ]]>
349 | Fri, 16 Jun 2023 21:19:00 GMT
350 | https://github.com/nodejs/node-addon-api/releases/tag/v7.0.0
351 | https://github.com/nodejs/node-addon-api/releases/tag/v7.0.0
352 |
353 |
354 | Released nodejs/node-core-utils v3.2.0
355 | Released nodejs/node-core-utils v3.2.0 by github-actions[bot]. More details
356 | ]]>
357 | Mon, 26 Jun 2023 06:12:00 GMT
358 | https://github.com/nodejs/node-core-utils/releases/tag/v3.2.0
359 | https://github.com/nodejs/node-core-utils/releases/tag/v3.2.0
360 |
361 |
362 | Released nodejs/node-core-utils v3.1.0
363 | Released nodejs/node-core-utils v3.1.0 by github-actions[bot]. More details
364 | ]]>
365 | Mon, 12 Jun 2023 06:32:00 GMT
366 | https://github.com/nodejs/node-core-utils/releases/tag/v3.1.0
367 | https://github.com/nodejs/node-core-utils/releases/tag/v3.1.0
368 |
369 |
370 | Released nodejs/node-gyp v9.4.0
371 | Released nodejs/node-gyp v9.4.0 by github-actions[bot]. More details
372 | ]]>
373 | Tue, 13 Jun 2023 04:48:00 GMT
374 | https://github.com/nodejs/node-gyp/releases/tag/v9.4.0
375 | https://github.com/nodejs/node-gyp/releases/tag/v9.4.0
376 |
377 |
378 |
--------------------------------------------------------------------------------
/jest.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'ts-jest',
3 | testEnvironment: 'jest-environment-node',
4 | transform: {},
5 | transformIgnorePatterns: ['/node_modules/']
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nodejs-news-feeder",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "private": true,
7 | "type": "module",
8 | "scripts": {
9 | "collect:releases": "node scripts/collect-releases.js",
10 | "collect:issues": "node scripts/collect-issues.js",
11 | "collect:discussions": "node scripts/collect-discussions.js",
12 | "rss:validate": "node scripts/validate.js",
13 | "rss:build": "node scripts/build.js",
14 | "rss:format": "node scripts/format.js",
15 | "rss:format-check": "node scripts/format-check.js",
16 | "lint": "standard",
17 | "lint:fix": "standard --fix",
18 | "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --detectOpenHandles --forceExit --verbose",
19 | "test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --detectOpenHandles --forceExit --verbose --coverage",
20 | "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --detectOpenHandles --forceExit --verbose --watchAll"
21 | },
22 | "standard": {
23 | "env": [
24 | "jest"
25 | ]
26 | },
27 | "repository": {
28 | "type": "git",
29 | "url": "git+https://github.com/nodejs/nodejs-news-feeder.git"
30 | },
31 | "author": "",
32 | "license": "MIT",
33 | "engines": {
34 | "node": ">=18.0.0",
35 | "npm": ">=9.0.0"
36 | },
37 | "bugs": {
38 | "url": "https://github.com/nodejs/nodejs-news-feeder/issues"
39 | },
40 | "homepage": "https://github.com/nodejs/nodejs-news-feeder#readme",
41 | "devDependencies": {
42 | "jest": "29.5.0",
43 | "standard": "17.1.0"
44 | },
45 | "dependencies": {
46 | "@octokit/graphql": "6.0.1",
47 | "gh-got": "10.0.0",
48 | "got": "13.0.0",
49 | "jsdom": "22.1.0",
50 | "remark": "14.0.3",
51 | "remark-html": "15.0.2",
52 | "xml-formatter": "3.4.1"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/build.js:
--------------------------------------------------------------------------------
1 | import { buildRFC822Date, overwriteFeedContent, getFeedContent, getConfig, overwriteConfig } from '../utils/index.js'
2 |
3 | const xml = getFeedContent()
4 | const now = new Date()
5 |
6 | // Replace lastBuildDate with current date in the feed
7 | const lastBuildDateRegex = /.*<\/lastBuildDate>/g
8 | const [before, after] = xml.split(lastBuildDateRegex)
9 | const updatedXml = `${before}${buildRFC822Date(now.toISOString())}${after}`
10 |
11 | overwriteFeedContent(updatedXml)
12 |
13 | // Overwrite config with new timestamp
14 | const config = getConfig()
15 | overwriteConfig({ ...config, lastCheckTimestamp: now.getTime() })
16 |
--------------------------------------------------------------------------------
/scripts/collect-discussions.js:
--------------------------------------------------------------------------------
1 | import { graphql } from '@octokit/graphql'
2 | import { getConfig, composeFeedItem, buildTitleDate, md2html, buildRFC822Date, getFeedContent, overwriteFeedContent } from '../utils/index.js'
3 |
4 | const { discussionsInScope, breakDelimiter, lastCheckTimestamp } = getConfig()
5 |
6 | const comments = await Promise.all(discussionsInScope.map(async ({ discussionId, team }) => {
7 | const { repository } = await graphql(
8 | `
9 | {
10 | repository(name: "node", owner: "nodejs") {
11 | discussion(number: ${discussionId}) {
12 | comments(last: 100) {
13 | edges {
14 | node {
15 | body
16 | publishedAt
17 | updatedAt
18 | databaseId
19 | }
20 | }
21 | }
22 | }
23 | }
24 | }
25 | `,
26 | {
27 | headers: {
28 | authorization: `token ${process.env.GITHUB_TOKEN}`
29 | }
30 | }
31 | )
32 |
33 | return repository.discussion.comments.edges
34 | .filter(comment => new Date(comment.node.publishedAt).getTime() > lastCheckTimestamp)
35 | .map(comment => ({ ...comment.node, team, discussionId }))
36 | }))
37 |
38 | const relevantComments = comments.flat().map(comment => composeFeedItem({
39 | title: `${comment.team} update on ${buildTitleDate(comment.publishedAt)}`,
40 | description: ``,
41 | pubDate: buildRFC822Date(comment.publishedAt),
42 | link: `https://github.com/orgs/nodejs/discussions/${comment.discussionId}#discussioncomment-${comment.databaseId}`,
43 | guid: `https://github.com/orgs/nodejs/discussions/${comment.discussionId}#discussioncomment-${comment.databaseId}`
44 | })).join('')
45 |
46 | const feedContent = getFeedContent()
47 | const [before, after] = feedContent.split(breakDelimiter)
48 | const updatedFeedContent = `${before}${breakDelimiter}${relevantComments}${after}`
49 | overwriteFeedContent(updatedFeedContent)
50 |
--------------------------------------------------------------------------------
/scripts/collect-issues.js:
--------------------------------------------------------------------------------
1 | import ghGot from 'gh-got'
2 | import { md2html, buildTitleDate, buildRFC822Date, composeFeedItem, getFeedContent, overwriteFeedContent, getConfig } from '../utils/index.js'
3 |
4 | const { lastCheckTimestamp, breakDelimiter, issuesInScope, commentsPaginationLimit } = getConfig()
5 |
6 | // Collect all the comments for the issues in scope
7 | const comments = await Promise.all(issuesInScope.map(async ({ issue, team }) => {
8 | const issueComments = await ghGot(
9 | `repos/${issue}/comments`,
10 | {
11 | token: process.env.GITHUB_TOKEN,
12 | pagination: { countLimit: commentsPaginationLimit }
13 | }
14 | ).json()
15 |
16 | // Select only comments that are newer than the last check and add issue context
17 | return issueComments
18 | .filter(comment => new Date(comment.updated_at).getTime() > lastCheckTimestamp)
19 | .map(comment => ({ ...comment, issue, team }))
20 | }))
21 |
22 | const relevantComments = comments.flat().map(comment => composeFeedItem({
23 | title: `${comment.team} update on ${buildTitleDate(comment.created_at)}`,
24 | description: ``,
25 | pubDate: buildRFC822Date(comment.created_at),
26 | link: comment.html_url,
27 | guid: comment.html_url
28 | })).join('')
29 |
30 | const feedContent = getFeedContent()
31 | const [before, after] = feedContent.split(breakDelimiter)
32 | const updatedFeedContent = `${before}${breakDelimiter}${relevantComments}${after}`
33 | overwriteFeedContent(updatedFeedContent)
34 |
--------------------------------------------------------------------------------
/scripts/collect-releases.js:
--------------------------------------------------------------------------------
1 | import ghGot from 'gh-got'
2 | import { md2html, buildRFC822Date, composeFeedItem, getFeedContent, overwriteFeedContent, getConfig } from '../utils/index.js'
3 |
4 | const { lastCheckTimestamp, releasePaginationLimit, reposPaginationLimit, breakDelimiter } = getConfig()
5 |
6 | // Collect Org Repos
7 | const repos = await ghGot.paginate.all(
8 | 'users/nodejs/repos',
9 | {
10 | token: process.env.GITHUB_TOKEN,
11 | pagination: { countLimit: reposPaginationLimit }
12 | }
13 | )
14 |
15 | // Collect New Releases
16 | const releases = await Promise.all(repos.map(async repo => {
17 | const repoReleases = await ghGot(
18 | `repos/${repo.full_name}/releases`,
19 | {
20 | token: process.env.GITHUB_TOKEN,
21 | pagination: { countLimit: releasePaginationLimit }
22 | }
23 | ).json()
24 |
25 | // Select only releases that are newer than the last check and add the repo name
26 | return repoReleases
27 | .filter(rel => new Date(rel.published_at).getTime() > lastCheckTimestamp)
28 | .map(rel => ({ ...rel, repo: repo.full_name }))
29 | }))
30 |
31 | const relevantReleases = releases.flat().map(rel => composeFeedItem({
32 | title: `Released ${rel.repo} ${rel.tag_name}`,
33 | description: ``,
34 | pubDate: buildRFC822Date(rel.published_at),
35 | link: rel.html_url,
36 | guid: rel.html_url
37 | })).join('')
38 |
39 | const feedContent = getFeedContent()
40 | const [before, after] = feedContent.split(breakDelimiter)
41 | const updatedFeedContent = `${before}${breakDelimiter}${relevantReleases}${after}`
42 | overwriteFeedContent(updatedFeedContent)
43 |
--------------------------------------------------------------------------------
/scripts/format-check.js:
--------------------------------------------------------------------------------
1 | import { execSync } from 'child_process'
2 | import { getFeedHash } from '../utils/index.js'
3 |
4 | const currentHash = getFeedHash()
5 | execSync('npm run rss:format')
6 | const newHash = getFeedHash()
7 |
8 | if (currentHash !== newHash) {
9 | console.log('The feed.xml file is not formatted.')
10 | console.log('Please run rss:format to format the feed.xml file.')
11 | process.exit(1)
12 | }
13 |
--------------------------------------------------------------------------------
/scripts/format.js:
--------------------------------------------------------------------------------
1 | import xmlFormat from 'xml-formatter'
2 | import { getFeedContent, overwriteFeedContent } from '../utils/index.js'
3 |
4 | const xml = getFeedContent()
5 | const formattedXml = xmlFormat(xml, { indentation: ' ', collapseContent: true })
6 | overwriteFeedContent(formattedXml)
7 |
--------------------------------------------------------------------------------
/scripts/validate.js:
--------------------------------------------------------------------------------
1 | import got from 'got'
2 | import jsdom from 'jsdom'
3 | import { getFeedContent } from '../utils/index.js'
4 |
5 | const { JSDOM } = jsdom
6 | const xml = getFeedContent()
7 |
8 | try {
9 | const data = await got.post('https://validator.w3.org/feed/check.cgi', {
10 | form: {
11 | rawdata: xml,
12 | manual: 1
13 | }
14 | }).text()
15 |
16 | // Avoid importing CSS in the document
17 | const dom = new JSDOM(data.replace(/@import.*/gm, ''))
18 |
19 | const title = dom.window.document.querySelector('h2').textContent
20 | const recommendations = dom.window.document.querySelector('ul').textContent
21 |
22 | console.log(recommendations)
23 |
24 | if (title === 'Sorry') {
25 | console.log('🚨 Feed is invalid!')
26 | process.exit(1)
27 | } else {
28 | console.log('✅ Feed is valid!')
29 | }
30 | } catch (error) {
31 | console.log('Service is down')
32 | console.error(error.response.statusCode)
33 | }
34 |
--------------------------------------------------------------------------------
/utils/index.js:
--------------------------------------------------------------------------------
1 | import { readFileSync, writeFileSync } from 'fs'
2 | import { join } from 'path'
3 | import { createHash } from 'crypto'
4 | import * as remark from 'remark'
5 | import remarkHtml from 'remark-html'
6 |
7 | const xmlFile = join(process.cwd(), 'feed.xml')
8 | const configFile = join(process.cwd(), 'config.json')
9 |
10 | export function md2html (md) {
11 | return remark.remark().use(remarkHtml).processSync(md).toString()
12 | }
13 |
14 | export function buildTitleDate (timestamp) {
15 | const [date, time] = new Date(timestamp).toISOString().split('T')
16 | // Format: YYYY-MM-DD HH:MM:SS
17 | return `${date} ${time.slice(0, 8)}`
18 | }
19 |
20 | export function getConfig () {
21 | return JSON.parse(readFileSync(configFile, 'utf8'))
22 | }
23 |
24 | export function overwriteConfig (config) {
25 | writeFileSync(configFile, JSON.stringify(config, null, 2))
26 | }
27 |
28 | export function composeFeedItem ({ title, description, pubDate, link, guid }) {
29 | return `
30 |
31 | ${title}
32 | ${description}
33 | ${pubDate}
34 | ${link}
35 | ${guid}
36 |
37 | `
38 | }
39 |
40 | export function getFeedContent () {
41 | return readFileSync(xmlFile, 'utf8')
42 | }
43 |
44 | export function overwriteFeedContent (content) {
45 | writeFileSync(xmlFile, content)
46 | }
47 |
48 | export function getFeedHash () {
49 | const xml = getFeedContent()
50 | return createHash('sha256').update(xml).digest('hex')
51 | }
52 |
53 | // @see: https://whitep4nth3r.com/blog/how-to-format-dates-for-rss-feeds-rfc-822/
54 | export function addLeadingZero (num) {
55 | num = num.toString()
56 | while (num.length < 2) num = '0' + num
57 | return num
58 | }
59 |
60 | export function buildRFC822Date (dateString) {
61 | const dayStrings = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
62 | const monthStrings = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
63 |
64 | const timeStamp = Date.parse(dateString)
65 | const date = new Date(timeStamp)
66 |
67 | const day = dayStrings[date.getDay()]
68 | const dayNumber = addLeadingZero(date.getDate())
69 | const month = monthStrings[date.getMonth()]
70 | const year = date.getFullYear()
71 | const time = `${addLeadingZero(date.getHours())}:${addLeadingZero(date.getMinutes())}:00`
72 | const timezone = date.getTimezoneOffset() === 0 ? 'GMT' : 'BST'
73 |
74 | // Wed, 02 Oct 2002 13:00:00 GMT
75 | return `${day}, ${dayNumber} ${month} ${year} ${time} ${timezone}`
76 | }
77 |
--------------------------------------------------------------------------------