mirror of
https://github.com/avelino/awesome-go.git
synced 2024-11-07 16:33:40 +00:00
Merge branch 'main' into main
This commit is contained in:
commit
f96737cbb9
@ -18,5 +18,3 @@ engines:
|
|||||||
ratings:
|
ratings:
|
||||||
paths:
|
paths:
|
||||||
- "**.go"
|
- "**.go"
|
||||||
exclude_paths:
|
|
||||||
- vendor/
|
|
||||||
|
13
.github/ISSUE_TEMPLATE/awesome-go-com.md
vendored
13
.github/ISSUE_TEMPLATE/awesome-go-com.md
vendored
@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
name: awesome-go.com
|
|
||||||
about: website-related
|
|
||||||
title: "[awesome-go.com]: issue title here"
|
|
||||||
labels: awesome-go.com
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
before opening the issue we recommend that you read our contribution guide, there we talk about how you can contribute to awesome-go.
|
|
||||||
https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md
|
|
||||||
-->
|
|
@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
name: awesome-go related topic
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: help wanted
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
before opening the issue we recommend that you read our contribution guide, there we talk about how you can contribute to awesome-go.
|
|
||||||
https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md
|
|
||||||
-->
|
|
27
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
27
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: Report a bug encountered
|
||||||
|
labels: ["bug", "pending-review"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thank you very much for opening a bug report at awesome-go.
|
||||||
|
|
||||||
|
If you have a feature idea or need help, please go to [our Forum](https://github.com/avelino/awesome-go/discussions).
|
||||||
|
before opening the issue we recommend that you read our [contribution guide](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md), there we talk about how you can contribute to awesome-go.
|
||||||
|
- type: checkboxes
|
||||||
|
id: confirm-search
|
||||||
|
attributes:
|
||||||
|
label: Search first
|
||||||
|
description: Please search [existing issues](https://github.com/avelino/awesome-go/issues) and the [awesome-go forum](https://github.com/avelino/awesome-go/discussions) before reporting.
|
||||||
|
options:
|
||||||
|
- label: I searched and no similar issues were found
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: problem
|
||||||
|
attributes:
|
||||||
|
label: What Happened?
|
||||||
|
description: |
|
||||||
|
Please provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner.
|
||||||
|
validations:
|
||||||
|
required: true
|
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
contact_links:
|
||||||
|
- name: Feature request
|
||||||
|
url: https://github.com/avelino/awesome-go/discussions/new?category=ideas
|
||||||
|
about: Suggest an idea for awesome-go
|
||||||
|
- name: Questions & Help
|
||||||
|
url: https://github.com/avelino/awesome-go/discussions/new?category=q-a
|
||||||
|
about: Ask a question about awesome-go
|
48
.github/PULL_REQUEST_TEMPLATE.md
vendored
48
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,26 +1,40 @@
|
|||||||
> Please check if what you want to add to `awesome-go` list meets [quality standards](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#quality-standards) before sending pull request. Thanks!
|
## We want to ensure high quality of the packages. Make sure that you've checked the boxes below before sending a pull request.
|
||||||
|
|
||||||
**Please provide package links to:**
|
- [ ] I have read the [Contribution Guidelines](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#contribution-guidelines)
|
||||||
|
- [ ] I have read the [Maintainers Note](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#maintainers)
|
||||||
|
- [ ] I have read the [Quality Standards](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#quality-standards)
|
||||||
|
|
||||||
- repo link (github.com, gitlab.com, etc):
|
_Not every repository (project) will require every option, but most projects should. Check the Contribution Guidelines for details._
|
||||||
- pkg.go.dev:
|
|
||||||
- goreportcard.com:
|
|
||||||
- coverage service link ([codecov](https://codecov.io/), [coveralls](https://coveralls.io/), [gocover](http://gocover.io/) etc.):
|
|
||||||
|
|
||||||
**Note**: _that new categories can be added only when there are 3 packages or more._
|
|
||||||
|
|
||||||
**Make sure that you've checked the boxes below that apply before you submit PR.**
|
|
||||||
_Not every repository (project) will require every option, but most projects should. Check the Contribution Guidelines for detials._
|
|
||||||
|
|
||||||
- [ ] The package has been added to the list in alphabetical order.
|
|
||||||
- [ ] The package has an appropriate description with correct grammar.
|
|
||||||
- [ ] As far as I know, the package has not been listed here before.
|
|
||||||
- [ ] The repo documentation has a pkg.go.dev link.
|
- [ ] The repo documentation has a pkg.go.dev link.
|
||||||
- [ ] The repo documentation has a coverage service link.
|
- [ ] The repo documentation has a coverage service link.
|
||||||
- [ ] The repo documentation has a goreportcard link.
|
- [ ] The repo documentation has a goreportcard link.
|
||||||
- [ ] The repo has a version-numbered release and a go.mod file.
|
- [ ] The repo has a version-numbered release and a go.mod file.
|
||||||
- [ ] I have read the [Contribution Guidelines](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#contribution-guidelines), [Maintainers Note](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#maintainers) and [Quality Standards](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#quality-standards).
|
|
||||||
- [ ] The repo has a continuous integration process that automatically runs tests that must pass before new pull requests are merged.
|
- [ ] The repo has a continuous integration process that automatically runs tests that must pass before new pull requests are merged.
|
||||||
- [ ] The authors of the project do not commit directly to the repo, but rather use pull requests that run the continuous-integration process.
|
- [ ] Continuous integration is used to attempt to catch issues prior to releasing this package to end-users.
|
||||||
|
|
||||||
Thanks for your PR, you're awesome! :+1:
|
## Please provide some links to your package to ease the review
|
||||||
|
|
||||||
|
- [ ] forge link (github.com, gitlab.com, etc):
|
||||||
|
- [ ] pkg.go.dev:
|
||||||
|
- [ ] goreportcard.com:
|
||||||
|
- [ ] coverage service link ([codecov](https://codecov.io/), [coveralls](https://coveralls.io/), etc.):
|
||||||
|
|
||||||
|
## Pull Request content
|
||||||
|
|
||||||
|
- [ ] The package has been added to the list in alphabetical order.
|
||||||
|
- [ ] The package has an appropriate description with correct grammar.
|
||||||
|
- [ ] As far as I know, the package has not been listed here before.
|
||||||
|
|
||||||
|
## Category quality
|
||||||
|
|
||||||
|
_Note that new categories can be added only when there are 3 packages or more._
|
||||||
|
|
||||||
|
Packages added a long time ago might not meet the current guidelines anymore. It would be very helpful if you could check 3-5 packages above and below your submission to ensure that they also still meet the Quality Standards.
|
||||||
|
|
||||||
|
Please delete one of the following lines:
|
||||||
|
|
||||||
|
- [ ] The packages around my addition still meet the Quality Standards.
|
||||||
|
- [ ] I removed the following packages around my addition: (please give a short reason for each removal)
|
||||||
|
|
||||||
|
Thanks for your PR, you're awesome! :sunglasses:
|
||||||
|
14
.github/workflows/check-for-spammy-issues.yml
vendored
Normal file
14
.github/workflows/check-for-spammy-issues.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
name: Issues spammy check
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [opened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
mark-as-spam:
|
||||||
|
name: Remove issues with spammy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: close issue
|
||||||
|
uses: balevine/mark-as-spam@v1.0
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
31
.github/workflows/pull-request-first-comment.yaml
vendored
Normal file
31
.github/workflows/pull-request-first-comment.yaml
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
name: First comment in new pull request
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
commentCreated:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
issues: write
|
||||||
|
environment: action
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
steps:
|
||||||
|
- name: first comment
|
||||||
|
uses: peter-evans/create-or-update-comment@v3
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
issue-number: ${{ github.event.pull_request.number }}
|
||||||
|
body: |
|
||||||
|
Thank you for contributing to [awesome-go](https://awesome-go.com/). We will review your contribution as soon as possible.
|
||||||
|
|
||||||
|
Make sure you add the links in the body of the pull request that are requested in the [contribution guide](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md):
|
||||||
|
- repo link
|
||||||
|
- pkg.go.dev
|
||||||
|
- goreportcard.com
|
||||||
|
- coverage
|
||||||
|
|
||||||
|
> Your project is under review. It may take a few days to be approved.
|
8
.github/workflows/run-check.yaml
vendored
8
.github/workflows/run-check.yaml
vendored
@ -3,16 +3,20 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * 0'
|
- cron: '0 0 * * 0'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Running test
|
name: Running test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: golang:latest
|
container: golang:latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@1.0.0
|
- uses: actions/checkout@v4
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: go get -v -t -d ./...
|
run: go get -v -t -d ./...
|
||||||
- name: run script
|
- name: run script
|
||||||
run: go test stale_repositories_test.go scripts.go
|
run: go test -v -run ^TestStaleRepository$
|
||||||
env:
|
env:
|
||||||
OAUTH_TOKEN: ${{secrets.OAUTH_TOKEN}}
|
OAUTH_TOKEN: ${{secrets.OAUTH_TOKEN}}
|
||||||
|
9
.github/workflows/site-deploy.yaml
vendored
9
.github/workflows/site-deploy.yaml
vendored
@ -5,6 +5,9 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- 'main'
|
- 'main'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Make and Deploy site
|
name: Make and Deploy site
|
||||||
@ -12,15 +15,15 @@ jobs:
|
|||||||
environment: netlify
|
environment: netlify
|
||||||
container: golang:latest
|
container: golang:latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@1.0.0
|
- uses: actions/checkout@v4
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: go get -v -t -d ./...
|
run: go get -v -t -d ./...
|
||||||
- name: Make awesome-go.com
|
- name: Make awesome-go.com
|
||||||
run: go run make_site.go scripts.go
|
run: go run .
|
||||||
- name: deploy awesome-go.com
|
- name: deploy awesome-go.com
|
||||||
uses: jsmrcaga/action-netlify-deploy@v1.1.0
|
uses: jsmrcaga/action-netlify-deploy@v1.1.0
|
||||||
with:
|
with:
|
||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||||
NETLIFY_DEPLOY_TO_PROD: true
|
NETLIFY_DEPLOY_TO_PROD: true
|
||||||
build_directory: tmpl
|
build_directory: out
|
||||||
|
22
.github/workflows/stale.yml
vendored
22
.github/workflows/stale.yml
vendored
@ -1,22 +0,0 @@
|
|||||||
name: PR auto close, if you stay more than 8 days open
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v1
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
stale-pr-message: >
|
|
||||||
This PR has been automatically marked as stale because it has not had
|
|
||||||
recent activity. They will wait 15 days for your interaction, after
|
|
||||||
that the PR will be closed.
|
|
||||||
Please read more in https://github.com/avelino/awesome-go/blob/master/CONTRIBUTING.md
|
|
||||||
stale-pr-label: 'stale'
|
|
||||||
days-before-stale: 15
|
|
||||||
days-before-close: 7
|
|
7
.github/workflows/tests.yaml
vendored
7
.github/workflows/tests.yaml
vendored
@ -6,14 +6,17 @@ on:
|
|||||||
- 'main'
|
- 'main'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Running test
|
name: Running test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: golang:latest
|
container: golang:latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@1.0.0
|
- uses: actions/checkout@v4
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: go get -v -t -d ./...
|
run: go get -v -t -d ./...
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: go test repo_test.go scripts.go
|
run: go test main_test.go main.go
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,6 +1,5 @@
|
|||||||
tmpl/index.html
|
out/
|
||||||
awesome-go
|
awesome-go
|
||||||
vendor
|
|
||||||
|
|
||||||
# Folders
|
# Folders
|
||||||
.idea
|
.idea
|
||||||
@ -9,5 +8,3 @@ test_stale_repositories_log
|
|||||||
*.exe
|
*.exe
|
||||||
# Local Netlify folder
|
# Local Netlify folder
|
||||||
.netlify
|
.netlify
|
||||||
*.html
|
|
||||||
sitemap.xml
|
|
||||||
|
@ -12,7 +12,7 @@ We invite all those who participate in Awesome Go to help us create safe and pos
|
|||||||
|
|
||||||
A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
|
A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
|
||||||
|
|
||||||
Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
|
Communities mirror the societies in which they exist, and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
|
||||||
|
|
||||||
If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
|
If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
|
||||||
|
|
||||||
@ -20,28 +20,28 @@ If you see someone who is making an extra effort to ensure our community is welc
|
|||||||
|
|
||||||
The following behaviors are expected and requested of all community members:
|
The following behaviors are expected and requested of all community members:
|
||||||
|
|
||||||
* Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
|
* Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
|
||||||
* Exercise consideration and respect in your speech and actions.
|
* Exercise consideration and respect in your speech and actions.
|
||||||
* Attempt collaboration before conflict.
|
* Attempt collaboration before conflict.
|
||||||
* Refrain from demeaning, discriminatory, or harassing behavior and speech.
|
* Refrain from demeaning, discriminatory, or harassing behavior and speech.
|
||||||
* Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
|
* Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone distressed, or violations of this Code of Conduct, even if they seem inconsequential.
|
||||||
* Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
|
* Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
|
||||||
|
|
||||||
## 4. Unacceptable Behavior
|
## 4. Unacceptable Behavior
|
||||||
|
|
||||||
The following behaviors are considered harassment and are unacceptable within our community:
|
The following behaviors are considered harassment and are unacceptable within our community:
|
||||||
|
|
||||||
* Violence, threats of violence or violent language directed against another person.
|
* Violence, threats of violence or violent language directed against another person.
|
||||||
* Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
|
* Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
|
||||||
* Posting or displaying sexually explicit or violent material.
|
* Posting or displaying sexually explicit or violent material.
|
||||||
* Posting or threatening to post other people’s personally identifying information ("doxing").
|
* Posting or threatening to post other people’s personally identifying information ("doxing").
|
||||||
* Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
|
* Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
|
||||||
* Inappropriate photography or recording.
|
* Inappropriate photography or recording.
|
||||||
* Inappropriate physical contact. You should have someone’s consent before touching them.
|
* Inappropriate physical contact. You should have someone’s consent before touching them.
|
||||||
* Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
|
* Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
|
||||||
* Deliberate intimidation, stalking or following (online or in person).
|
* Deliberate intimidation, stalking or following (online or in person).
|
||||||
* Advocating for, or encouraging, any of the above behavior.
|
* Advocating for, or encouraging, any of the above behavior.
|
||||||
* Sustained disruption of community events, including talks and presentations.
|
* Sustained disruption of community events, including talks and presentations.
|
||||||
|
|
||||||
## 5. Consequences of Unacceptable Behavior
|
## 5. Consequences of Unacceptable Behavior
|
||||||
|
|
||||||
@ -49,11 +49,11 @@ Unacceptable behavior from any community member, including sponsors and those wi
|
|||||||
|
|
||||||
Anyone asked to stop unacceptable behavior is expected to comply immediately.
|
Anyone asked to stop unacceptable behavior is expected to comply immediately.
|
||||||
|
|
||||||
If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).
|
If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community unexpected (and without refund in the case of a paid event).
|
||||||
|
|
||||||
## 6. Reporting Guidelines
|
## 6. Reporting Guidelines
|
||||||
|
|
||||||
If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. t@avelino.xxx.
|
If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible.
|
||||||
|
|
||||||
[Reporting Guidelines](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#contribution-guidelines)
|
[Reporting Guidelines](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#contribution-guidelines)
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ This code of conduct and its related procedures also applies to unacceptable beh
|
|||||||
|
|
||||||
## 9. Contact info
|
## 9. Contact info
|
||||||
|
|
||||||
t@avelino.xxx
|
avelinorun AT gmail DOT com
|
||||||
|
|
||||||
## 10. License and attribution
|
## 10. License and attribution
|
||||||
|
|
||||||
@ -81,4 +81,4 @@ This Code of Conduct is distributed under a [Creative Commons Attribution-ShareA
|
|||||||
|
|
||||||
Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
|
Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
|
||||||
|
|
||||||
Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/)
|
Retrieved on November 22, 2016
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
This resource was made by the Go community and wouldn't be possible without you!
|
This resource was made by the Go community and wouldn't be possible without you!
|
||||||
We appreciate and recognize [all contributors](https://github.com/avelino/awesome-go/graphs/contributors).
|
We appreciate and recognize [all contributors](https://github.com/avelino/awesome-go/graphs/contributors).
|
||||||
|
|
||||||
|
|
||||||
# Contribution Guidelines
|
# Contribution Guidelines
|
||||||
|
|
||||||
> Please be aware that we want to accept your contribution, but we have **some rules to keep the minimum quality**
|
> Please be aware that we want to accept your contribution, but we have **some rules to keep the minimum quality** of the packages listed here. All reviews are **not personal feedback**, even if you are a _developer reviewing your contribution_. **Sorry, if we can't meet your expectations; we do our best**.
|
||||||
of the packages listed here. All reviews are **not personal feedback**,
|
|
||||||
even if you are a _developer reviewing your contribution_. **Sorry if we can't meet your expectations, we do our best**.
|
|
||||||
|
|
||||||
- **To add, remove, or change things on the list:** Submit a pull request
|
- **To add, remove, or change things on the list:** Submit a pull request
|
||||||
|
|
||||||
To set this list apart from and complement the excellent [Go wiki Projects page](https://golang.org/wiki/Projects),
|
To set this list apart from and complement the excellent [Go wiki Projects page](https://golang.org/wiki/Projects),
|
||||||
and other lists, awesome-go is a specially curated list for high-quality, actively maintained Go packages and resources.
|
and other lists, awesome-go is a specially curated list of high-quality, actively maintained Go packages and resources.
|
||||||
|
|
||||||
Please contribute links to packages/projects you have used or are familiar with. This will help ensure high-quality entries.
|
Please contribute links to packages/projects you have used or are familiar with. This will help ensure high-quality entries.
|
||||||
|
|
||||||
|
> the maintainers do not work full-time on the project, meaning that we do not have a set periodicity for reviewing contributions - rest assured that we will do our best to review and eventually accept contributions
|
||||||
|
|
||||||
|
|
||||||
## Quality standards
|
## Quality standards
|
||||||
|
|
||||||
To be on the list, project repositories should adhere to the following quality standards
|
To be on the list, project repositories should adhere to the following quality standards.
|
||||||
(https://goreportcard.com/report/github.com/ **github_user** / **github_repo**):
|
(https://goreportcard.com/report/github.com/ **github_user** / **github_repo**):
|
||||||
|
|
||||||
- have an **open source license**, [see list of allowed licenses](https://opensource.org/licenses/alphabetical);
|
- have an **open source license**, [see list of allowed licenses](https://opensource.org/licenses/alphabetical);
|
||||||
@ -26,12 +28,13 @@ To be on the list, project repositories should adhere to the following quality s
|
|||||||
- regular, recent commits;
|
- regular, recent commits;
|
||||||
- or, for finished projects, issues and pull requests are responded to generally within 2 weeks;
|
- or, for finished projects, issues and pull requests are responded to generally within 2 weeks;
|
||||||
- be stable or progressing toward stable;
|
- be stable or progressing toward stable;
|
||||||
- be thoroughly documented (README, pkg.go.dev doc comments, etc.) in the english language, so everyone is able to understand the project's intention and how it works. All public functions and types should have a Go style documentation header;
|
- be thoroughly documented (README, pkg.go.dev doc comments, etc.) in the English language, so everyone is able to understand the project's intention and how it works. All public functions and types should have a Go-style documentation header;
|
||||||
- if the library/program is testable, then coverage should be >= 80% for non-data-related packages and >=90% for data related packages. (**Note**: the tests will be reviewed too. We will check your coverage manually if your package's coverage is just a benchmark results);
|
- if the library/program is testable, then coverage should be >= 80% for non-data-related packages and >=90% for data-related packages. (**Note**: the tests will be reviewed too. We will check your coverage manually if your package's coverage is just a benchmark result);
|
||||||
- have at least one official version-numbered release that allows go.mod files to list the file by version number, of the form vX.X.X.
|
- have at least one official version-numbered release that allows go.mod files to list the file by version number of the form vX.X.X.
|
||||||
|
|
||||||
Categories must have at least 3 items.
|
Categories must have at least 3 items.
|
||||||
|
|
||||||
|
|
||||||
## Preparing for review
|
## Preparing for review
|
||||||
|
|
||||||
Projects listed must have the following in their documentation. When submitting, you will be asked
|
Projects listed must have the following in their documentation. When submitting, you will be asked
|
||||||
@ -43,9 +46,10 @@ to provide them.
|
|||||||
|
|
||||||
One way to accomplish the above is to add badges to your project's README file.
|
One way to accomplish the above is to add badges to your project's README file.
|
||||||
- Use https://pkg.go.dev/badge/ to create the pkg.go.dev link.
|
- Use https://pkg.go.dev/badge/ to create the pkg.go.dev link.
|
||||||
- Go to https://goreportcard.com/ to generate a Go Report Card report, then click on the report badge in the upper right corner to see details on how to add the badge to your README.
|
- Go to https://goreportcard.com/ to generate a Go Report Card report, then click on the report badge in the upper-right corner to see details on how to add the badge to your README.
|
||||||
- Codecov, coveralls, and gocover all offer ways to create badges for code coverage reports. Another option is to generate a badge as part of a continuous integration process. See [Code Coverage](COVERAGE.md) for an example.
|
- Codecov, coveralls, and gocover all offer ways to create badges for code coverage reports. Another option is to generate a badge as part of a continuous integration process. See [Code Coverage](COVERAGE.md) for an example.
|
||||||
|
|
||||||
|
|
||||||
## How to add an item to the list
|
## How to add an item to the list
|
||||||
|
|
||||||
Open a pull request against the README.md document that adds the repository to the list.
|
Open a pull request against the README.md document that adds the repository to the list.
|
||||||
@ -54,17 +58,17 @@ Open a pull request against the README.md document that adds the repository to t
|
|||||||
- The added item should be in alphabetical order within its category.
|
- The added item should be in alphabetical order within its category.
|
||||||
- The link should be the name of the package or project.
|
- The link should be the name of the package or project.
|
||||||
- Descriptions should be clear, concise, and non-promotional.
|
- Descriptions should be clear, concise, and non-promotional.
|
||||||
- Descriptions should follow the link, on the same line and end with a punctuation mark.
|
- Descriptions should follow the link on the same line and end with a punctuation mark.
|
||||||
- Remember to put a period `.` at end of the project description.
|
- Remember to put a period `.` at the end of the project description.
|
||||||
|
|
||||||
If you are creating a new category, move the projects that apply to the new category, ensuring
|
If you are creating a new category, move the projects that apply to the new category, ensuring
|
||||||
that the resulting list has at least 3 projects in every category and that the categories are alphabetized.
|
that the resulting list has at least 3 projects in every category, and that the categories are alphabetized.
|
||||||
|
|
||||||
Fill out the template in your PR with the links asked for. If you accidentally remove the PR template from the submission, you can find it [here](https://github.com/avelino/awesome-go/blob/main/.github/PULL_REQUEST_TEMPLATE.md).
|
Fill out the template in your PR with the links asked for. If you accidentally remove the PR template from the submission, you can find it [here](https://github.com/avelino/awesome-go/blob/main/.github/PULL_REQUEST_TEMPLATE.md).
|
||||||
|
|
||||||
|
|
||||||
## Congrats, your project got accepted - what now?
|
## Congrats, your project got accepted - what now?
|
||||||
You are an awesome project now! Feel encouraged to tell others about it by adding one of these badges:
|
You are an outstanding project now! Feel encouraged to tell others about it by adding one of these badges:
|
||||||
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
|
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
|
||||||
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go)
|
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go)
|
||||||
|
|
||||||
@ -72,43 +76,47 @@ You are an awesome project now! Feel encouraged to tell others about it by addin
|
|||||||
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
|
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
|
||||||
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go)
|
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Maintenance expectations for projects listed here
|
## Maintenance expectations for projects listed here
|
||||||
|
|
||||||
To prevent removal from awesome-go, your project must maintain the following quality standards.
|
To prevent removal from awesome-go, your project must maintain the following quality standards.
|
||||||
- Development should be on-going and maintain code quality. Official releases should be at least once a year if the project is ongoing.
|
- Development should be ongoing and maintain code quality. Official releases should be at least once a year if the project is ongoing.
|
||||||
- Or, if development has halted because the project is mature and stable, that can be demonstrated by having no bug reports in the Issues list that are older than 6 months.
|
- Or, if development has halted because the project is mature and stable, that can be demonstrated by having no bug reports in the Issues list that are older than 6 months.
|
||||||
- All links to quality reports should be to the most recent official release or current ongoing development.
|
- All links to quality reports should be to the most recent official release or current ongoing development.
|
||||||
|
|
||||||
Highly recommended but not required:
|
Highly recommended but not required:
|
||||||
- A continuous integration process be part of the ongoing development process
|
- A continuous integration process to be part of the ongoing development process
|
||||||
- That the project uses a pull-request process and the owners do not commit directly to the repository
|
- That the project uses a pull-request process, and the owners do not commit directly to the repository
|
||||||
- That the pull-request process requires the continuous-integration tests pass before a pull request can be merged
|
- That the pull-request process requires the continuous-integration tests to pass before a pull request can be merged
|
||||||
|
|
||||||
|
|
||||||
## How to remove an item from the list
|
## How to remove an item from the list
|
||||||
|
|
||||||
- Open a pull request that deletes the line of the project in question.
|
- Open a pull request that deletes the line of the project in question.
|
||||||
- Delete the submission template and substitute a description of which criteria the project is not meeting. It should be a combination of the following.
|
- Delete the submission template and substitute a description of which criteria the project is not meeting. It should be a combination of the following.
|
||||||
- The project has not made an official release within the last year and it has open issues.
|
- The project has not made an official release within the last year and has open issues.
|
||||||
- The project is not responding to bug reports issued within 6 months of submission.
|
- The project is not responding to bug reports issued within 6 months of submission.
|
||||||
- The project is not meeting quality standards as indicated by the Go Report Card or Code Coverage tests.
|
- The project is not meeting quality standards as indicated by the Go Report Card or Code Coverage tests.
|
||||||
- The quality standard links have been removed from the documentation.
|
- The quality standard links have been removed from the documentation.
|
||||||
- The project is no longer open-sourced.
|
- The project is no longer open-sourced.
|
||||||
- The project is not compatible with any Go version issued within the last year (there is hopefully an open PR about this at the project).
|
- The project is incompatible with any Go version issued within the last year (there is hopefully an open PR about this at the project).
|
||||||
|
|
||||||
If the project is hosted on Github, include a link to the project's submitter and/or author so
|
If the project is hosted on GitHub, include a link to the project's submitter and/or author so
|
||||||
that they will be notified of the desire to remove the project and have an opportunity to respond.
|
that they will be notified of the desire to remove the project and have an opportunity to respond.
|
||||||
The link should be of the form @githubID.
|
The link should be of the form @githubID.
|
||||||
|
|
||||||
If the project is not hosted on Github, open an issue at the project in question's repository linking to the PR
|
If the project is not hosted on GitHub, open an issue at the project in question's repository linking to the PR
|
||||||
and stating the following:
|
and stating the following:
|
||||||
|
|
||||||
>This project is currently listed at awesome-go at https://github.com/avelino/awesome-go.
|
>This project is currently listed at awesome-go at https://github.com/avelino/awesome-go.
|
||||||
However, it appears that the project is not maintaining the quality standards required to continue to be listed at the awesome-go project.
|
However, it appears that the project is not maintaining the quality standards required to continue to be listed at the awesome-go project.
|
||||||
This project is schedule to be removed within 2 weeks of this posting. To continue to be listed at awesome-go, please respond at:
|
This project is scheduled to be removed within 2 weeks of this posting. To continue to be listed at awesome-go, please respond at:
|
||||||
-- link to above PR --
|
-- link to above PR --
|
||||||
|
|
||||||
Then, comment on your PR at awesome-go with a link to the removal issue at the project.
|
Then, comment on your PR at awesome-go with a link to the removal issue at the project.
|
||||||
|
|
||||||
|
|
||||||
## Maintainers
|
## Maintainers
|
||||||
|
|
||||||
To make sure every PR is checked, we have [team maintainers](MAINTAINERS). Every PR MUST be reviewed by at least one maintainer before it can get merged.
|
To make sure every PR is checked, we have [team maintainers](MAINTAINERS). Every PR MUST be reviewed by at least one maintainer before it can get merged.
|
||||||
@ -120,12 +128,41 @@ that the PR will be closed.
|
|||||||
|
|
||||||
## Reporting issues
|
## Reporting issues
|
||||||
|
|
||||||
Please open an issue if you would like to discuss anything that could be improved or have suggestions for making the list a more valuable resource. We realize sometimes packages fall into abandonment or have breaking builds for extended periods of time, so if you see that, feel free to change its listing or let us know. We also realize that sometimes projects are just going through transitions or are more experimental in nature. These can still be cool, but we can indicate them as transitory or experimental.
|
Please open an issue if you would like to discuss anything that could be improved or have suggestions for making the list a more valuable resource. We realize sometimes packages fall into abandonment or have breaking builds for extended periods of time, so if you see that, feel free to change its listing, or please let us know. We also realize that sometimes projects are just going through transitions or are more experimental in nature. These can still be cool, but we can indicate them as transitory or experimental.
|
||||||
|
|
||||||
Removal changes will not be applied until they have been pending for a minimum of 1 week (7 days). This grace window benefits projects that may be going through a temporary transition but are otherwise worthy of being on the list.
|
Removal changes will not be applied until they have been pending for a minimum of 1 week (7 days). This grace window benefits projects that may be going through a temporary transition, but are otherwise worthy of being on the list.
|
||||||
|
|
||||||
Thanks everyone!
|
Thanks, everyone!
|
||||||
|
|
||||||
## How decision are made
|
|
||||||
|
## How decisions are made
|
||||||
|
|
||||||
The official group of maintainers has the final decision on what PRs are accepted. Discussions are made openly in issues. Decisions are made by consensus.
|
The official group of maintainers has the final decision on what PRs are accepted. Discussions are made openly in issues. Decisions are made by consensus.
|
||||||
|
|
||||||
|
|
||||||
|
## How to become a contributor?
|
||||||
|
|
||||||
|
awesome-go is an open source project (created and maintained by the community), we are always open to new people to help us review the contributions (pull requests), **you don't need permission** or _name on the maintainers list_ to review a contribution and mark it as **LGTM**.
|
||||||
|
|
||||||
|
> Before you do anything, please read [this topic](https://github.com/avelino/awesome-go/blob/main/CONTRIBUTING.md#quality-standards) very carefully.
|
||||||
|
|
||||||
|
Now that you've read it, let's go!
|
||||||
|
|
||||||
|
Go into the pull requests (PR) and look at the following aspects:
|
||||||
|
|
||||||
|
* **shared links in the body of the PR:** they need to be valid and follow the quality specified above
|
||||||
|
* **check that the link added to `README.md`** is the same as the link to the repository mentioned in the body of the PR.
|
||||||
|
* **is it in the correct category?**
|
||||||
|
|
||||||
|
If everything is OK, mark the PR as approved, [read this documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/reviewing-proposed-changes-in-a-pull-request#starting-a-review) on how to do it.
|
||||||
|
|
||||||
|
**Welcome to awesome-go!**
|
||||||
|
|
||||||
|
|
||||||
|
## How to become an ~~"official maintainer"~~?
|
||||||
|
|
||||||
|
We don't give this name to people who are allowed to accept the PR.
|
||||||
|
|
||||||
|
If you are a person who is constantly active in reviewing PR and contributing to the project, you will be invited by a maintainer.
|
||||||
|
|
||||||
|
> **remember:** if you stop contributing with awesome-go for a long time, you will automatically be removed from the list of maintainers.
|
||||||
|
11
COVERAGE.md
11
COVERAGE.md
@ -1,15 +1,10 @@
|
|||||||
# Code Coverage
|
# Code Coverage
|
||||||
|
|
||||||
While we recommend using one of the free websites available for monitoring code coverage
|
While we recommend using one of the free websites available for monitoring code coverage during your continuous integration process, below is an example of how you can incorporate code coverage during the continuous integration process provided by GitHub actions and generate a code coverage report without one of those services.
|
||||||
during your continuous integration process, below is an example of how you can incorporate
|
|
||||||
code coverage during the continuous integration process provided by github actions and
|
|
||||||
generate a code coverage report without one of those services.
|
|
||||||
|
|
||||||
This yaml file will run tests on multiple system configurations, but will produce
|
This `yaml` file will run tests on multiple system configurations, but will produce a code coverage report on only one of those. It will then create a code coverage badge and add it to the README file.
|
||||||
a code coverage report on only one of those. It will then create a code coverage badge
|
|
||||||
and add it to the README file.
|
|
||||||
|
|
||||||
This file should be put in the `.github/workflows` directory of your repo.
|
This file should be put in the `.github/workflows` directory of your repo:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: Go # The name of the workflow that will appear on Github
|
name: Go # The name of the workflow that will appear on Github
|
||||||
|
21
go.mod
21
go.mod
@ -1,19 +1,22 @@
|
|||||||
module github.com/avelino/awesome-go
|
module github.com/avelino/awesome-go
|
||||||
|
|
||||||
go 1.17
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/PuerkitoBio/goquery v1.8.0
|
github.com/PuerkitoBio/goquery v1.8.1
|
||||||
github.com/avelino/slugify v0.0.0-20180501145920-855f152bd774
|
github.com/avelino/slugify v0.0.0-20180501145920-855f152bd774
|
||||||
github.com/yuin/goldmark v1.4.13
|
github.com/otiai10/copy v1.14.0
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
github.com/yuin/goldmark v1.6.0
|
||||||
|
golang.org/x/oauth2 v0.15.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andybalholm/cascadia v1.3.1 // indirect
|
github.com/andybalholm/cascadia v1.3.1 // indirect
|
||||||
github.com/golang/protobuf v1.4.2 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 // indirect
|
golang.org/x/net v0.23.0 // indirect
|
||||||
golang.org/x/text v0.3.6 // indirect
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
google.golang.org/appengine v1.6.6 // indirect
|
golang.org/x/sys v0.18.0 // indirect
|
||||||
google.golang.org/protobuf v1.25.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
)
|
)
|
||||||
|
398
go.sum
398
go.sum
@ -1,376 +1,68 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
||||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
|
||||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
|
||||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
|
||||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
|
||||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
|
||||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
|
||||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
|
||||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
|
||||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
|
||||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
|
||||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
|
||||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
|
||||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
|
||||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
|
||||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
|
||||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
|
||||||
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
|
|
||||||
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
|
|
||||||
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||||
github.com/avelino/slugify v0.0.0-20180501145920-855f152bd774 h1:HrMVYtly2IVqg9EBooHsakQ256ueojP7QuG32K71X/U=
|
github.com/avelino/slugify v0.0.0-20180501145920-855f152bd774 h1:HrMVYtly2IVqg9EBooHsakQ256ueojP7QuG32K71X/U=
|
||||||
github.com/avelino/slugify v0.0.0-20180501145920-855f152bd774/go.mod h1:5wi5YYOpfuAKwL5XLFYopbgIl/v7NZxaJpa/4X6yFKE=
|
github.com/avelino/slugify v0.0.0-20180501145920-855f152bd774/go.mod h1:5wi5YYOpfuAKwL5XLFYopbgIl/v7NZxaJpa/4X6yFKE=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
|
||||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
|
||||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
|
||||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
||||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 h1:/6y1LfuqNuQdHAm0jjtPtgRcxIxjVZgm5OTu8/QhZvk=
|
|
||||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
|
||||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
|
||||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
|
||||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
|
||||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
|
||||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
|
||||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
|
||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
|
||||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
|
||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
|
||||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
|
||||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
|
||||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
|
||||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
|
||||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
|
||||||
|
365
main.go
Normal file
365
main.go
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
// Package main contains code for generate static site.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"embed"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
template2 "html/template"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/avelino/awesome-go/pkg/markdown"
|
||||||
|
cp "github.com/otiai10/copy"
|
||||||
|
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"github.com/avelino/awesome-go/pkg/slug"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Link contains info about awesome url
|
||||||
|
type Link struct {
|
||||||
|
Title string
|
||||||
|
URL string
|
||||||
|
Description string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Category describe link category
|
||||||
|
type Category struct {
|
||||||
|
Title string
|
||||||
|
Slug string
|
||||||
|
Description string
|
||||||
|
Links []Link
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source files
|
||||||
|
const readmePath = "README.md"
|
||||||
|
|
||||||
|
// This files should be copied 'as is' to outDir directory
|
||||||
|
var staticFiles = []string{
|
||||||
|
"tmpl/assets",
|
||||||
|
"tmpl/robots.txt",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Templates
|
||||||
|
//go:embed tmpl/*.tmpl.html tmpl/*.tmpl.xml
|
||||||
|
var tplFs embed.FS
|
||||||
|
|
||||||
|
var tpl = template.Must(template.ParseFS(tplFs, "tmpl/*.tmpl.html", "tmpl/*.tmpl.xml"))
|
||||||
|
|
||||||
|
// Output files
|
||||||
|
const outDir = "out/" // NOTE: trailing slash is required
|
||||||
|
|
||||||
|
var outIndexFile = filepath.Join(outDir, "index.html")
|
||||||
|
var outSitemapFile = filepath.Join(outDir, "sitemap.xml")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := buildStaticSite(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildStaticSite() error {
|
||||||
|
if err := dropCreateDir(outDir); err != nil {
|
||||||
|
return fmt.Errorf("drop-create out dir: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := renderIndex(readmePath, outIndexFile); err != nil {
|
||||||
|
return fmt.Errorf("convert markdown to html: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
input, err := os.ReadFile(outIndexFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read converted html: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(input))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create goquery instance: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
categories, err := extractCategories(doc)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("extract categories: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := renderCategories(categories); err != nil {
|
||||||
|
return fmt.Errorf("render categories: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rewriteLinksInIndex(doc, categories); err != nil {
|
||||||
|
return fmt.Errorf("rewrite links in index: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := renderSitemap(categories); err != nil {
|
||||||
|
return fmt.Errorf("render sitemap: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, srcFilename := range staticFiles {
|
||||||
|
dstFilename := filepath.Join(outDir, filepath.Base(srcFilename))
|
||||||
|
fmt.Printf("Copy static file: %s -> %s\n", srcFilename, dstFilename)
|
||||||
|
if err := cp.Copy(srcFilename, dstFilename); err != nil {
|
||||||
|
return fmt.Errorf("copy static file `%s` to `%s`: %w", srcFilename, dstFilename, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// dropCreateDir drop and create output directory
|
||||||
|
func dropCreateDir(dir string) error {
|
||||||
|
if err := os.RemoveAll(dir); err != nil {
|
||||||
|
return fmt.Errorf("remove dir: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mkdirAll(dir); err != nil {
|
||||||
|
return fmt.Errorf("create dir: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mkdirAll(path string) error {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
// directory is exists
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// unexpected error
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("unexpected result of dir stat: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// directory is not exists
|
||||||
|
if err := os.MkdirAll(path, 0755); err != nil {
|
||||||
|
return fmt.Errorf("midirAll: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderCategories(categories map[string]Category) error {
|
||||||
|
for _, category := range categories {
|
||||||
|
categoryDir := filepath.Join(outDir, category.Slug)
|
||||||
|
if err := mkdirAll(categoryDir); err != nil {
|
||||||
|
return fmt.Errorf("create category dir `%s`: %w", categoryDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: embed templates
|
||||||
|
categoryIndexFilename := filepath.Join(categoryDir, "index.html")
|
||||||
|
fmt.Printf("Write category Index file: %s\n", categoryIndexFilename)
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
if err := tpl.Lookup("category-index.tmpl.html").Execute(buf, category); err != nil {
|
||||||
|
return fmt.Errorf("render category `%s`: %w", categoryDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize HTML. This is not necessary, but allows to have content
|
||||||
|
// of all html files in same style.
|
||||||
|
{
|
||||||
|
doc, err := goquery.NewDocumentFromReader(buf)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create goquery instance for `%s`: %w", categoryDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
html, err := doc.Html()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("render goquery html for `%s`: %w", categoryDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile(categoryIndexFilename, []byte(html), 0644); err != nil {
|
||||||
|
return fmt.Errorf("write category file `%s`: %w", categoryDir, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderSitemap(categories map[string]Category) error {
|
||||||
|
f, err := os.Create(outSitemapFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create sitemap file `%s`: %w", outSitemapFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Render Sitemap to: %s\n", outSitemapFile)
|
||||||
|
|
||||||
|
if err := tpl.Lookup("sitemap.tmpl.xml").Execute(f, categories); err != nil {
|
||||||
|
return fmt.Errorf("render sitemap: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractCategories(doc *goquery.Document) (map[string]Category, error) {
|
||||||
|
categories := make(map[string]Category)
|
||||||
|
var rootErr error
|
||||||
|
|
||||||
|
doc.
|
||||||
|
Find("body #contents").
|
||||||
|
NextFiltered("ul").
|
||||||
|
Find("ul").
|
||||||
|
EachWithBreak(func(_ int, selUl *goquery.Selection) bool {
|
||||||
|
if rootErr != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
selUl.
|
||||||
|
Find("li a").
|
||||||
|
EachWithBreak(func(_ int, s *goquery.Selection) bool {
|
||||||
|
selector, exists := s.Attr("href")
|
||||||
|
if !exists {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
category, err := extractCategory(doc, selector)
|
||||||
|
if err != nil {
|
||||||
|
rootErr = fmt.Errorf("extract category: %w", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
categories[selector] = *category
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if rootErr != nil {
|
||||||
|
return nil, fmt.Errorf("extract categories: %w", rootErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractCategory(doc *goquery.Document, selector string) (*Category, error) {
|
||||||
|
var category Category
|
||||||
|
var err error
|
||||||
|
|
||||||
|
doc.Find(selector).EachWithBreak(func(_ int, selCatHeader *goquery.Selection) bool {
|
||||||
|
selDescr := selCatHeader.NextFiltered("p")
|
||||||
|
// FIXME: bug. this would select links from all neighboring
|
||||||
|
// sub-categories until the next category. To prevent this we should
|
||||||
|
// find only first ul
|
||||||
|
ul := selCatHeader.NextFilteredUntil("ul", "h2")
|
||||||
|
|
||||||
|
var links []Link
|
||||||
|
ul.Find("li").Each(func(_ int, selLi *goquery.Selection) {
|
||||||
|
selLink := selLi.Find("a")
|
||||||
|
url, _ := selLink.Attr("href")
|
||||||
|
link := Link{
|
||||||
|
Title: selLink.Text(),
|
||||||
|
// FIXME(kazhuravlev): Title contains only title but
|
||||||
|
// description contains Title + description
|
||||||
|
Description: selLi.Text(),
|
||||||
|
URL: url,
|
||||||
|
}
|
||||||
|
links = append(links, link)
|
||||||
|
})
|
||||||
|
|
||||||
|
// FIXME: In this case we would have an empty category in main index.html with link to 404 page.
|
||||||
|
if len(links) == 0 {
|
||||||
|
err = errors.New("category does not contain links")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
category = Category{
|
||||||
|
Slug: slug.Generate(selCatHeader.Text()),
|
||||||
|
Title: selCatHeader.Text(),
|
||||||
|
Description: selDescr.Text(),
|
||||||
|
Links: links,
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("build a category: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &category, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func rewriteLinksInIndex(doc *goquery.Document, categories map[string]Category) error {
|
||||||
|
var iterErr error
|
||||||
|
doc.
|
||||||
|
Find("body #content ul li ul li a").
|
||||||
|
EachWithBreak(func(_ int, s *goquery.Selection) bool {
|
||||||
|
href, hrefExists := s.Attr("href")
|
||||||
|
if !hrefExists {
|
||||||
|
// FIXME: looks like is an error. Tag `a` in our case always
|
||||||
|
// should have `href` attr.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not replace links if no page has been created for it
|
||||||
|
_, catExists := categories[href]
|
||||||
|
if !catExists {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
linkURL, err := url.Parse(href)
|
||||||
|
if err != nil {
|
||||||
|
iterErr = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if linkURL.Fragment != "" && linkURL.Fragment != "contents" {
|
||||||
|
s.SetAttr("href", linkURL.Fragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if iterErr != nil {
|
||||||
|
return iterErr
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Rewrite links in Index file: %s\n", outIndexFile)
|
||||||
|
resultHTML, err := doc.Html()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("render html: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile(outIndexFile, []byte(resultHTML), 0644); err != nil {
|
||||||
|
return fmt.Errorf("rewrite index file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// renderIndex generate site html (index.html) from markdown file
|
||||||
|
func renderIndex(srcFilename, outFilename string) error {
|
||||||
|
input, err := os.ReadFile(srcFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := markdown.ToHTML(input)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create(outFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Write Index file: %s\n", outIndexFile)
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"Body": template2.HTML(body),
|
||||||
|
}
|
||||||
|
if err := tpl.Lookup("index.tmpl.html").Execute(f, data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
return fmt.Errorf("close index file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"bytes"
|
||||||
|
"github.com/avelino/awesome-go/pkg/markdown"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -16,9 +18,38 @@ var (
|
|||||||
reLinkWithDescription = regexp.MustCompile(`\* \[.*\]\(.*\) - \S.*[\.\!]`)
|
reLinkWithDescription = regexp.MustCompile(`\* \[.*\]\(.*\) - \S.*[\.\!]`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func requireNoErr(t *testing.T, err error, msg string) {
|
||||||
|
// FIXME: replace to github.com/stretchr/testify
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
if msg == "" {
|
||||||
|
msg = "unknown error"
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Received unexpected error [%s]: %+v", msg, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func goqueryFromReadme(t *testing.T) *goquery.Document {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
input, err := os.ReadFile(readmePath)
|
||||||
|
requireNoErr(t, err, "readme file should be exists")
|
||||||
|
|
||||||
|
html, err := markdown.ToHTML(input)
|
||||||
|
requireNoErr(t, err, "markdown should be rendered to html")
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(html)
|
||||||
|
doc, err := goquery.NewDocumentFromReader(buf)
|
||||||
|
requireNoErr(t, err, "html must be valid for goquery")
|
||||||
|
|
||||||
|
return doc
|
||||||
|
}
|
||||||
|
|
||||||
func TestAlpha(t *testing.T) {
|
func TestAlpha(t *testing.T) {
|
||||||
query := startQuery()
|
doc := goqueryFromReadme(t)
|
||||||
query.Find("body > ul").Each(func(i int, s *goquery.Selection) {
|
doc.Find("body > ul").Each(func(i int, s *goquery.Selection) {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
// skip content menu
|
// skip content menu
|
||||||
// TODO: the sub items (with 3 hash marks `###`) are staying in
|
// TODO: the sub items (with 3 hash marks `###`) are staying in
|
||||||
@ -30,9 +61,9 @@ func TestAlpha(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDuplicatedLinks(t *testing.T) {
|
func TestDuplicatedLinks(t *testing.T) {
|
||||||
query := startQuery()
|
doc := goqueryFromReadme(t)
|
||||||
links := make(map[string]bool, 0)
|
links := make(map[string]bool, 0)
|
||||||
query.Find("body li > a:first-child").Each(func(_ int, s *goquery.Selection) {
|
doc.Find("body li > a:first-child").Each(func(_ int, s *goquery.Selection) {
|
||||||
t.Run(s.Text(), func(t *testing.T) {
|
t.Run(s.Text(), func(t *testing.T) {
|
||||||
href, ok := s.Attr("href")
|
href, ok := s.Attr("href")
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -49,10 +80,9 @@ func TestDuplicatedLinks(t *testing.T) {
|
|||||||
// Test if an entry has description, it must be separated from link with ` - `
|
// Test if an entry has description, it must be separated from link with ` - `
|
||||||
func TestSeparator(t *testing.T) {
|
func TestSeparator(t *testing.T) {
|
||||||
var matched, containsLink, noDescription bool
|
var matched, containsLink, noDescription bool
|
||||||
input, err := ioutil.ReadFile("./README.md")
|
input, err := os.ReadFile(readmePath)
|
||||||
if err != nil {
|
requireNoErr(t, err, "readme should be exists")
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(input), "\n")
|
lines := strings.Split(string(input), "\n")
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
line = strings.Trim(line, " ")
|
line = strings.Trim(line, " ")
|
||||||
@ -69,11 +99,12 @@ func TestSeparator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestGenerateHTML(t *testing.T) {
|
|
||||||
err := GenerateHTML()
|
func TestRenderIndex(t *testing.T) {
|
||||||
if err != nil {
|
requireNoErr(t, mkdirAll(outDir), "output dir should exists")
|
||||||
t.Errorf("html generate error '%s'", err.Error())
|
|
||||||
}
|
err := renderIndex(readmePath, outIndexFile)
|
||||||
|
requireNoErr(t, err, "html should be rendered")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testList(t *testing.T, list *goquery.Selection) {
|
func testList(t *testing.T, list *goquery.Selection) {
|
115
make_site.go
115
make_site.go
@ -1,115 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/PuerkitoBio/goquery"
|
|
||||||
"github.com/avelino/awesome-go/pkg/slug"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Link struct {
|
|
||||||
Title string
|
|
||||||
Url string
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Object struct {
|
|
||||||
Title string
|
|
||||||
Slug string
|
|
||||||
Description string
|
|
||||||
Items []Link
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
GenerateHTML()
|
|
||||||
input, err := ioutil.ReadFile("./tmpl/index.html")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
buf := bytes.NewBuffer(input)
|
|
||||||
query, err := goquery.NewDocumentFromReader(buf)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
objs := []Object{}
|
|
||||||
query.Find("body #content ul ul").First().Each(func(_ int, s *goquery.Selection) {
|
|
||||||
|
|
||||||
s.Find("li a").Each(func(_ int, s *goquery.Selection) {
|
|
||||||
selector, _ := s.Attr("href")
|
|
||||||
obj := makeObjById(selector, query.Find("body"))
|
|
||||||
objs = append(objs, obj)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
makeSiteStruct(objs)
|
|
||||||
makeSitemap(objs)
|
|
||||||
changeLinksInIndex(string(input), query)
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeSiteStruct(objs []Object) {
|
|
||||||
for _, obj := range objs {
|
|
||||||
folder := fmt.Sprintf("tmpl/%s", obj.Slug)
|
|
||||||
err := os.Mkdir(folder, 0755)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t := template.Must(template.ParseFiles("tmpl/cat-tmpl.html"))
|
|
||||||
f, _ := os.Create(fmt.Sprintf("%s/index.html", folder))
|
|
||||||
t.Execute(f, obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeSitemap(objs []Object) {
|
|
||||||
t := template.Must(template.ParseFiles("tmpl/sitemap-tmpl.xml"))
|
|
||||||
f, _ := os.Create("tmpl/sitemap.xml")
|
|
||||||
t.Execute(f, objs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeObjById(selector string, s *goquery.Selection) (obj Object) {
|
|
||||||
s.Find(selector).Each(func(_ int, s *goquery.Selection) {
|
|
||||||
desc := s.NextFiltered("p")
|
|
||||||
ul := desc.NextFiltered("ul")
|
|
||||||
|
|
||||||
links := []Link{}
|
|
||||||
ul.Find("li").Each(func(_ int, s *goquery.Selection) {
|
|
||||||
url, _ := s.Find("a").Attr("href")
|
|
||||||
link := Link{
|
|
||||||
Title: s.Find("a").Text(),
|
|
||||||
Description: s.Text(),
|
|
||||||
Url: url,
|
|
||||||
}
|
|
||||||
links = append(links, link)
|
|
||||||
})
|
|
||||||
obj = Object{
|
|
||||||
Slug: slug.Generate(s.Text()),
|
|
||||||
Title: s.Text(),
|
|
||||||
Description: desc.Text(),
|
|
||||||
Items: links,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func changeLinksInIndex(html string, query *goquery.Document) {
|
|
||||||
query.Find("body #content ul li ul li a").Each(func(_ int, s *goquery.Selection) {
|
|
||||||
|
|
||||||
href, exists := s.Attr("href")
|
|
||||||
if exists {
|
|
||||||
uri := strings.SplitAfter(href, "#")
|
|
||||||
if len(uri) >= 2 && uri[1] != "contents" {
|
|
||||||
html = strings.ReplaceAll(
|
|
||||||
html, fmt.Sprintf(`href="%s"`, href), fmt.Sprintf(`href="%s"`, uri[1]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
os.WriteFile("./tmpl/index.html", []byte(html), 0644)
|
|
||||||
}
|
|
47
netlify.toml
Normal file
47
netlify.toml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Settings in the [build] context are global and are applied to
|
||||||
|
# all contexts unless otherwise overridden by more specific contexts.
|
||||||
|
[build]
|
||||||
|
# Directory to change to before starting a build.
|
||||||
|
# This is where we will look for package.json/.nvmrc/etc.
|
||||||
|
# If not set, defaults to the root directory.
|
||||||
|
base = "./"
|
||||||
|
|
||||||
|
# Directory that contains the deploy-ready HTML files and
|
||||||
|
# assets generated by the build. This is relative to the base
|
||||||
|
# directory if one has been set, or the root directory if
|
||||||
|
# a base has not been set. This sample publishes the directory
|
||||||
|
# located at the absolute path "root/project/build-output"
|
||||||
|
|
||||||
|
publish = "out/"
|
||||||
|
|
||||||
|
# Default build command.
|
||||||
|
command = "echo 'default context'"
|
||||||
|
|
||||||
|
[[plugins]]
|
||||||
|
# Installs the Lighthouse Build Plugin for all deploy contexts
|
||||||
|
package = "@netlify/plugin-lighthouse"
|
||||||
|
|
||||||
|
# Production context: all deploys from the Production branch
|
||||||
|
# set in your site’s Branches settings in the UI will inherit
|
||||||
|
# these settings. You can define environment variables
|
||||||
|
# here but we recommend using the Netlify UI for sensitive
|
||||||
|
# values to keep them out of your source repository.
|
||||||
|
[context.production]
|
||||||
|
publish = "out/"
|
||||||
|
|
||||||
|
# Redirects and headers are GLOBAL for all builds – they do not
|
||||||
|
# get scoped to contexts no matter where you define them in the file.
|
||||||
|
# For context-specific rules, use _headers or _redirects files,
|
||||||
|
# which are PER-DEPLOY.
|
||||||
|
|
||||||
|
[[redirects]]
|
||||||
|
from = "/awesome-cloud-native"
|
||||||
|
to = "/"
|
||||||
|
status = 302
|
||||||
|
force = true
|
||||||
|
|
||||||
|
[[redirects]]
|
||||||
|
from = "/awesome-go-fork"
|
||||||
|
to = "/"
|
||||||
|
status = 302
|
||||||
|
force = true
|
@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConvertMarkdownToHTML converts markdown byte slice to a HTML byte slice
|
// ToHTML converts markdown byte slice to a HTML byte slice
|
||||||
func ConvertMarkdownToHTML(markdown []byte) ([]byte, error) {
|
func ToHTML(markdown []byte) ([]byte, error) {
|
||||||
md := goldmark.New(
|
md := goldmark.New(
|
||||||
goldmark.WithExtensions(extension.GFM),
|
goldmark.WithExtensions(extension.GFM),
|
||||||
goldmark.WithParserOptions(
|
goldmark.WithParserOptions(
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConvertMarkdownToHTML(t *testing.T) {
|
func TestToHTML(t *testing.T) {
|
||||||
input := []byte(
|
input := []byte(
|
||||||
`## some headline
|
`## some headline
|
||||||
followed by some paragraph with [a link](https://example.local)
|
followed by some paragraph with [a link](https://example.local)
|
||||||
@ -46,12 +46,12 @@ and some list:</p>
|
|||||||
<p><a href="https://example.local">embedded HTML is allowed</a></p>`,
|
<p><a href="https://example.local">embedded HTML is allowed</a></p>`,
|
||||||
)
|
)
|
||||||
|
|
||||||
got, err := ConvertMarkdownToHTML(input)
|
got, err := ToHTML(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("ConvertMarkdownToHTML() error = %v", err)
|
t.Errorf("ToHTML() error = %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(string(got)) != strings.TrimSpace(string(expected)) {
|
if strings.TrimSpace(string(got)) != strings.TrimSpace(string(expected)) {
|
||||||
t.Errorf("ConvertMarkdownToHTML() got = %v, want %v", string(got), string(expected))
|
t.Errorf("ToHTML() got = %v, want %v", string(got), string(expected))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
// Generate slugs similar to GitHub's slugs on markdown parsing
|
// Generate slugs similar to GitHub's slugs on markdown parsing
|
||||||
func Generate(text string) string {
|
func Generate(text string) string {
|
||||||
|
// FIXME: this is should be like regexp.Replace(`[^-a-zA-Z\d]+`, ``)
|
||||||
s := strings.ReplaceAll(text, "/", "")
|
s := strings.ReplaceAll(text, "/", "")
|
||||||
return slugify.Slugify(strings.TrimSpace(s))
|
return slugify.Slugify(strings.TrimSpace(s))
|
||||||
}
|
}
|
||||||
|
51
scripts.go
51
scripts.go
@ -1,51 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"html/template"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/PuerkitoBio/goquery"
|
|
||||||
"github.com/avelino/awesome-go/pkg/markdown"
|
|
||||||
)
|
|
||||||
|
|
||||||
func readme() []byte {
|
|
||||||
input, err := os.ReadFile("./README.md")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
html, err := markdown.ConvertMarkdownToHTML(input)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return html
|
|
||||||
}
|
|
||||||
|
|
||||||
func startQuery() *goquery.Document {
|
|
||||||
buf := bytes.NewBuffer(readme())
|
|
||||||
query, err := goquery.NewDocumentFromReader(buf)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return query
|
|
||||||
}
|
|
||||||
|
|
||||||
type content struct {
|
|
||||||
Body template.HTML
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateHTML generate site html (index.html) from markdown file
|
|
||||||
func GenerateHTML() (err error) {
|
|
||||||
// options
|
|
||||||
readmePath := "./README.md"
|
|
||||||
tplPath := "tmpl/tmpl.html"
|
|
||||||
idxPath := "tmpl/index.html"
|
|
||||||
input, _ := ioutil.ReadFile(readmePath)
|
|
||||||
body, _ := markdown.ConvertMarkdownToHTML(input)
|
|
||||||
c := &content{Body: template.HTML(body)}
|
|
||||||
t := template.Must(template.ParseFiles(tplPath))
|
|
||||||
f, err := os.Create(idxPath)
|
|
||||||
t.Execute(f, c)
|
|
||||||
return
|
|
||||||
}
|
|
@ -18,211 +18,250 @@ import (
|
|||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const issueTemplate = `
|
const issueTemplateContent = `
|
||||||
{{range .}}
|
{{range .}}
|
||||||
- [ ] {{.}}
|
- [ ] {{.}}
|
||||||
{{end}}
|
{{end}}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var issueTemplate = template.Must(template.New("issue").Parse(issueTemplateContent))
|
||||||
|
|
||||||
|
// FIXME: use official github client
|
||||||
var reGithubRepo = regexp.MustCompile("https://github.com/[a-zA-Z0-9-._]+/[a-zA-Z0-9-._]+$")
|
var reGithubRepo = regexp.MustCompile("https://github.com/[a-zA-Z0-9-._]+/[a-zA-Z0-9-._]+$")
|
||||||
var githubGETREPO = "https://api.github.com/repos%s"
|
var githubGETREPO = "https://api.github.com/repos%s"
|
||||||
var githubGETCOMMITS = "https://api.github.com/repos%s/commits"
|
var githubGETCOMMITS = "https://api.github.com/repos%s/commits"
|
||||||
var githubPOSTISSUES = "https://api.github.com/repos/avelino/awesome-go/issues"
|
var githubPOSTISSUES = "https://api.github.com/repos/avelino/awesome-go/issues"
|
||||||
|
|
||||||
|
// FIXME: use https
|
||||||
var awesomeGoGETISSUES = "http://api.github.com/repos/avelino/awesome-go/issues" //only returns open issues
|
var awesomeGoGETISSUES = "http://api.github.com/repos/avelino/awesome-go/issues" //only returns open issues
|
||||||
|
// FIXME: variable has type Duration, but contains a number. we should use
|
||||||
|
//
|
||||||
|
// time.Hour * ... or change type of variable
|
||||||
var numberOfYears time.Duration = 1
|
var numberOfYears time.Duration = 1
|
||||||
var timeNow = time.Now()
|
var timeNow = time.Now()
|
||||||
var issueTitle = fmt.Sprintf("Investigate repositories with more than 1 year without update - %s", timeNow.Format("2006-01-02"))
|
var issueTitle = fmt.Sprintf("Investigate repositories with more than 1 year without update - %s", timeNow.Format(time.DateOnly))
|
||||||
|
|
||||||
const deadLinkMessage = " this repository might no longer exist! (status code >= 400 returned)"
|
const deadLinkMessage = " this repository might no longer exist! (status code >= 400 returned)"
|
||||||
const movedPermanently = " status code 301 received"
|
const movedPermanently = " status code 301 received"
|
||||||
const status302 = " status code 302 received"
|
const status302 = " status code 302 received"
|
||||||
const archived = " repository has been archived"
|
const archived = " repository has been archived"
|
||||||
|
|
||||||
//LIMIT specifies the max number of repositories that are added in a single run of the script
|
// LIMIT specifies the max number of repositories that are added in a single run of the script
|
||||||
var LIMIT = 10
|
var LIMIT = 10
|
||||||
var ctr = 0
|
var ctr = 0
|
||||||
|
|
||||||
type tokenSource struct {
|
type tokenSource struct {
|
||||||
AccessToken string
|
AccessToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
type issue struct {
|
type issue struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Body string `json:"body"`
|
Body string `json:"body"`
|
||||||
}
|
}
|
||||||
type repo struct {
|
|
||||||
Archived bool `json:"archived"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *tokenSource) Token() (*oauth2.Token, error) {
|
func (t *tokenSource) Token() (*oauth2.Token, error) {
|
||||||
token := &oauth2.Token{
|
return &oauth2.Token{
|
||||||
AccessToken: t.AccessToken,
|
AccessToken: t.AccessToken,
|
||||||
}
|
}, nil
|
||||||
return token, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRepositoriesFromBody(body string) []string {
|
func getRepositoriesFromBody(body string) []string {
|
||||||
links := strings.Split(body, "- ")
|
links := strings.Split(body, "- ")
|
||||||
for idx, link := range links {
|
for i, link := range links {
|
||||||
str := strings.ReplaceAll(link, "\r", "")
|
link = strings.ReplaceAll(link, "\r", "")
|
||||||
str = strings.ReplaceAll(str, "[ ]", "")
|
link = strings.ReplaceAll(link, "[ ]", "")
|
||||||
str = strings.ReplaceAll(str, "[x]", "")
|
link = strings.ReplaceAll(link, "[x]", "")
|
||||||
str = strings.ReplaceAll(str, " ", "")
|
link = strings.ReplaceAll(link, " ", "")
|
||||||
str = strings.ReplaceAll(str, "\n", "")
|
link = strings.ReplaceAll(link, "\n", "")
|
||||||
str = strings.ReplaceAll(str, deadLinkMessage, "")
|
link = strings.ReplaceAll(link, deadLinkMessage, "")
|
||||||
str = strings.ReplaceAll(str, movedPermanently, "")
|
link = strings.ReplaceAll(link, movedPermanently, "")
|
||||||
str = strings.ReplaceAll(str, status302, "")
|
link = strings.ReplaceAll(link, status302, "")
|
||||||
str = strings.ReplaceAll(str, archived, "")
|
link = strings.ReplaceAll(link, archived, "")
|
||||||
links[idx] = str
|
links[i] = link
|
||||||
}
|
}
|
||||||
|
|
||||||
return links
|
return links
|
||||||
}
|
}
|
||||||
func generateIssueBody(repositories []string) (string, error) {
|
|
||||||
var writer bytes.Buffer
|
func generateIssueBody(t *testing.T, repositories []string) (string, error) {
|
||||||
t := template.New("issue")
|
t.Helper()
|
||||||
temp, err := t.Parse(issueTemplate)
|
|
||||||
if err != nil {
|
buf := bytes.NewBuffer(nil)
|
||||||
log.Print("Failed to generate template")
|
err := issueTemplate.Execute(buf, repositories)
|
||||||
return "", err
|
requireNoErr(t, err, "Failed to generate template")
|
||||||
}
|
|
||||||
err = temp.Execute(&writer, repositories)
|
return buf.String(), nil
|
||||||
if err != nil {
|
|
||||||
log.Print("Failed to generate template")
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
issueBody := writer.String()
|
|
||||||
return issueBody, nil
|
|
||||||
}
|
}
|
||||||
func createIssue(staleRepos []string, client *http.Client) {
|
|
||||||
|
func createIssue(t *testing.T, staleRepos []string, client *http.Client) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
if len(staleRepos) == 0 {
|
if len(staleRepos) == 0 {
|
||||||
log.Print("NO STALE REPOSITORIES")
|
log.Print("NO STALE REPOSITORIES")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
body, err := generateIssueBody(staleRepos)
|
|
||||||
if err != nil {
|
body, err := generateIssueBody(t, staleRepos)
|
||||||
log.Print("Failed at CreateIssue")
|
requireNoErr(t, err, "failed to generate issue body")
|
||||||
return
|
|
||||||
}
|
|
||||||
newIssue := &issue{
|
newIssue := &issue{
|
||||||
Title: issueTitle,
|
Title: issueTitle,
|
||||||
Body: body,
|
Body: body,
|
||||||
}
|
}
|
||||||
buf := new(bytes.Buffer)
|
buf := bytes.NewBuffer(nil)
|
||||||
json.NewEncoder(buf).Encode(newIssue)
|
requireNoErr(t, json.NewEncoder(buf).Encode(newIssue), "failed to encode json req")
|
||||||
req, err := http.NewRequest("POST", githubPOSTISSUES, buf)
|
|
||||||
if err != nil {
|
req, err := http.NewRequest(http.MethodPost, githubPOSTISSUES, buf)
|
||||||
log.Print("Failed at CreateIssue")
|
requireNoErr(t, err, "failed to create request")
|
||||||
return
|
|
||||||
}
|
_, roundTripErr := client.Do(req)
|
||||||
client.Do(req)
|
requireNoErr(t, roundTripErr, "failed to send request")
|
||||||
}
|
}
|
||||||
func getAllFlaggedRepositories(client *http.Client, flaggedRepositories *map[string]bool) error {
|
|
||||||
req, err := http.NewRequest("GET", awesomeGoGETISSUES, nil)
|
func getAllFlaggedRepositories(t *testing.T, client *http.Client) map[string]bool {
|
||||||
if err != nil {
|
t.Helper()
|
||||||
log.Print("Failed to get all issues")
|
|
||||||
return err
|
req, err := http.NewRequest(http.MethodGet, awesomeGoGETISSUES, nil)
|
||||||
}
|
requireNoErr(t, err, "failed to create request")
|
||||||
|
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
if err != nil {
|
requireNoErr(t, err, "failed to send request")
|
||||||
log.Print("Failed to get all issues")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
target := []issue{}
|
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
json.NewDecoder(res.Body).Decode(&target)
|
|
||||||
for _, i := range target {
|
var issues []issue
|
||||||
if i.Title == issueTitle {
|
requireNoErr(t, json.NewDecoder(res.Body).Decode(&issues), "failed to unmarshal response")
|
||||||
repos := getRepositoriesFromBody(i.Body)
|
|
||||||
for _, repo := range repos {
|
|
||||||
(*flaggedRepositories)[repo] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func containsOpenIssue(link string, openIssues map[string]bool) bool {
|
|
||||||
_, ok := openIssues[link]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
func testRepoState(toRun bool, href string, client *http.Client, staleRepos *[]string) bool {
|
|
||||||
if toRun {
|
|
||||||
ownerRepo := strings.ReplaceAll(href, "https://github.com", "")
|
|
||||||
apiCall := fmt.Sprintf(githubGETREPO, ownerRepo)
|
|
||||||
req, err := http.NewRequest("GET", apiCall, nil)
|
|
||||||
var repoResp repo
|
|
||||||
isRepoAdded := false
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed at repository %s\n", href)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed at repository %s\n", href)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
json.NewDecoder(resp.Body).Decode(&repoResp)
|
|
||||||
if resp.StatusCode == 301 {
|
|
||||||
*staleRepos = append(*staleRepos, href+movedPermanently)
|
|
||||||
log.Printf("%s returned 301", href)
|
|
||||||
isRepoAdded = true
|
|
||||||
}
|
|
||||||
if resp.StatusCode == 302 && !isRepoAdded {
|
|
||||||
*staleRepos = append(*staleRepos, href+status302)
|
|
||||||
log.Printf("%s returned 302", href)
|
|
||||||
isRepoAdded = true
|
|
||||||
}
|
|
||||||
if resp.StatusCode >= 400 && !isRepoAdded {
|
|
||||||
*staleRepos = append(*staleRepos, href+deadLinkMessage)
|
|
||||||
log.Printf("%s might not exist!", href)
|
|
||||||
isRepoAdded = true
|
|
||||||
}
|
|
||||||
if repoResp.Archived && !isRepoAdded {
|
|
||||||
*staleRepos = append(*staleRepos, href+archived)
|
|
||||||
log.Printf("%s is archived!", href)
|
|
||||||
isRepoAdded = true
|
|
||||||
}
|
|
||||||
return isRepoAdded
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func testCommitAge(toRun bool, href string, client *http.Client, staleRepos *[]string) bool {
|
|
||||||
if toRun {
|
|
||||||
var respObj []map[string]interface{}
|
|
||||||
since := timeNow.Add(-1 * 365 * 24 * numberOfYears * time.Hour)
|
|
||||||
sinceQuery := since.Format(time.RFC3339)
|
|
||||||
ownerRepo := strings.ReplaceAll(href, "https://github.com", "")
|
|
||||||
apiCall := fmt.Sprintf(githubGETCOMMITS, ownerRepo)
|
|
||||||
req, err := http.NewRequest("GET", apiCall, nil)
|
|
||||||
isRepoAdded := false
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed at repository %s\n", href)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
q := req.URL.Query()
|
|
||||||
q.Add("since", sinceQuery)
|
|
||||||
req.URL.RawQuery = q.Encode()
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed at repository %s\n", href)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
json.NewDecoder(resp.Body).Decode(&respObj)
|
|
||||||
isAged := len(respObj) == 0
|
|
||||||
if isAged {
|
|
||||||
log.Printf("%s has not had a commit in a while", href)
|
|
||||||
*staleRepos = append(*staleRepos, href)
|
|
||||||
isRepoAdded = true
|
|
||||||
}
|
|
||||||
return isRepoAdded
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func testStaleRepository() {
|
|
||||||
query := startQuery()
|
|
||||||
var staleRepos []string
|
|
||||||
addressedRepositories := make(map[string]bool)
|
addressedRepositories := make(map[string]bool)
|
||||||
|
for _, issue := range issues {
|
||||||
|
if issue.Title != issueTitle {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
repos := getRepositoriesFromBody(issue.Body)
|
||||||
|
for _, repo := range repos {
|
||||||
|
addressedRepositories[repo] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return addressedRepositories
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkRepoAvailability(toRun bool, href string, client *http.Client) ([]string, bool) {
|
||||||
|
if !toRun {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
ownerRepo := strings.ReplaceAll(href, "https://github.com", "")
|
||||||
|
apiCall := fmt.Sprintf(githubGETREPO, ownerRepo)
|
||||||
|
req, err := http.NewRequest(http.MethodGet, apiCall, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed at repository %s\n", href)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed at repository %s\n", href)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var repoResp struct {
|
||||||
|
Archived bool `json:"archived"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&repoResp); err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var isRepoAdded bool
|
||||||
|
|
||||||
|
var warnings []string
|
||||||
|
if resp.StatusCode == http.StatusMovedPermanently {
|
||||||
|
warnings = append(warnings, href+movedPermanently)
|
||||||
|
log.Printf("%s returned %d", href, resp.StatusCode)
|
||||||
|
isRepoAdded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusFound && !isRepoAdded {
|
||||||
|
warnings = append(warnings, href+status302)
|
||||||
|
log.Printf("%s returned %d", href, resp.StatusCode)
|
||||||
|
isRepoAdded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode >= http.StatusBadRequest && !isRepoAdded {
|
||||||
|
warnings = append(warnings, href+deadLinkMessage)
|
||||||
|
log.Printf("%s might not exist!", href)
|
||||||
|
isRepoAdded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if repoResp.Archived && !isRepoAdded {
|
||||||
|
warnings = append(warnings, href+archived)
|
||||||
|
log.Printf("%s is archived!", href)
|
||||||
|
isRepoAdded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: expression `(len(warnings) > 0) == isRepoAdded` is always true.
|
||||||
|
return warnings, isRepoAdded
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkRepoCommitActivity(toRun bool, href string, client *http.Client) ([]string, bool) {
|
||||||
|
if !toRun {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
ownerRepo := strings.ReplaceAll(href, "https://github.com", "")
|
||||||
|
apiCall := fmt.Sprintf(githubGETCOMMITS, ownerRepo)
|
||||||
|
req, err := http.NewRequest(http.MethodGet, apiCall, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed at repository %s\n", href)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
since := timeNow.Add(-1 * 365 * 24 * numberOfYears * time.Hour)
|
||||||
|
sinceQuery := since.Format(time.RFC3339)
|
||||||
|
|
||||||
|
q := req.URL.Query()
|
||||||
|
q.Add("since", sinceQuery)
|
||||||
|
req.URL.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed at repository %s\n", href)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var respObj []map[string]interface{}
|
||||||
|
// FIXME: handle error in all that cases
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&respObj); err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var warnings []string
|
||||||
|
var isRepoAdded bool
|
||||||
|
isAged := len(respObj) == 0
|
||||||
|
if isAged {
|
||||||
|
log.Printf("%s has not had a commit in a while", href)
|
||||||
|
warnings = append(warnings, href)
|
||||||
|
isRepoAdded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: expression `(len(warnings) > 0) == isRepoAdded` is always true.
|
||||||
|
return warnings, isRepoAdded
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStaleRepository(t *testing.T) {
|
||||||
|
doc := goqueryFromReadme(t)
|
||||||
|
|
||||||
oauth := os.Getenv("OAUTH_TOKEN")
|
oauth := os.Getenv("OAUTH_TOKEN")
|
||||||
client := &http.Client{}
|
client := &http.Client{
|
||||||
|
Transport: &http.Transport{},
|
||||||
|
}
|
||||||
|
|
||||||
if oauth == "" {
|
if oauth == "" {
|
||||||
log.Print("No oauth token found. Using unauthenticated client ...")
|
log.Print("No oauth token found. Using unauthenticated client ...")
|
||||||
} else {
|
} else {
|
||||||
@ -231,42 +270,47 @@ func testStaleRepository() {
|
|||||||
}
|
}
|
||||||
client = oauth2.NewClient(context.Background(), tokenSource)
|
client = oauth2.NewClient(context.Background(), tokenSource)
|
||||||
}
|
}
|
||||||
err := getAllFlaggedRepositories(client, &addressedRepositories)
|
|
||||||
|
|
||||||
if err != nil {
|
// FIXME: return addressedRepositories, no need to pass
|
||||||
log.Println("Failed to get existing issues. Exiting...")
|
addressedRepositories := getAllFlaggedRepositories(t, client)
|
||||||
return
|
|
||||||
}
|
var staleRepos []string
|
||||||
query.Find("body li > a:first-child").EachWithBreak(func(_ int, s *goquery.Selection) bool {
|
doc.
|
||||||
href, ok := s.Attr("href")
|
Find("body li > a:first-child").
|
||||||
if !ok {
|
EachWithBreak(func(_ int, s *goquery.Selection) bool {
|
||||||
log.Println("expected to have href")
|
href, ok := s.Attr("href")
|
||||||
return true
|
if !ok {
|
||||||
}
|
log.Println("expected to have href")
|
||||||
if ctr >= LIMIT && LIMIT != -1 {
|
return true
|
||||||
log.Print("Max number of issues created")
|
}
|
||||||
return false
|
|
||||||
}
|
if ctr >= LIMIT && LIMIT != -1 {
|
||||||
issueExists := containsOpenIssue(href, addressedRepositories)
|
log.Print("Max number of issues created")
|
||||||
if issueExists {
|
return false
|
||||||
log.Printf("issue already exists for %s\n", href)
|
}
|
||||||
} else {
|
|
||||||
isGithubRepo := reGithubRepo.MatchString(href)
|
if _, issueExists := addressedRepositories[href]; issueExists {
|
||||||
if isGithubRepo {
|
log.Printf("issue already exists for %s\n", href)
|
||||||
isRepoAdded := testRepoState(true, href, client, &staleRepos)
|
return true
|
||||||
isRepoAdded = testCommitAge(!isRepoAdded, href, client, &staleRepos)
|
}
|
||||||
if isRepoAdded {
|
|
||||||
ctr++
|
if !reGithubRepo.MatchString(href) {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("%s non-github repo not currently handled", href)
|
log.Printf("%s non-github repo not currently handled", href)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
createIssue(staleRepos, client)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStaleRepository(t *testing.T) {
|
// FIXME: this is `or` expres24sion. Probably we need `and`?
|
||||||
testStaleRepository()
|
warnings, isRepoAdded := checkRepoAvailability(true, href, client)
|
||||||
|
staleRepos = append(staleRepos, warnings...)
|
||||||
|
|
||||||
|
warnings, isRepoAdded = checkRepoCommitActivity(!isRepoAdded, href, client)
|
||||||
|
staleRepos = append(staleRepos, warnings...)
|
||||||
|
|
||||||
|
if isRepoAdded {
|
||||||
|
ctr++
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
createIssue(t, staleRepos, client)
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
/awesome-cloud-native/ /
|
|
||||||
/awesome-go-fork/ /
|
|
4
tmpl/assets/awesome-go.css
vendored
4
tmpl/assets/awesome-go.css
vendored
@ -114,3 +114,7 @@ h1 > a img {
|
|||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
BIN
tmpl/assets/favicon/android-chrome-192x192.png
Normal file
BIN
tmpl/assets/favicon/android-chrome-192x192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
tmpl/assets/favicon/android-chrome-512x512.png
Normal file
BIN
tmpl/assets/favicon/android-chrome-512x512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 171 KiB |
BIN
tmpl/assets/favicon/apple-touch-icon.png
Normal file
BIN
tmpl/assets/favicon/apple-touch-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
BIN
tmpl/assets/favicon/favicon.ico
Normal file
BIN
tmpl/assets/favicon/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
19
tmpl/assets/favicon/manifest.json
Normal file
19
tmpl/assets/favicon/manifest.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "Awesome Go",
|
||||||
|
"short_name": "Awesome-Go",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "./android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "./android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
109
tmpl/cat-tmpl.html
vendored
109
tmpl/cat-tmpl.html
vendored
@ -1,109 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta http-equiv="Content-Language" content="en">
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<title>{{.Title}} - Awesome Go / Golang</title>
|
|
||||||
<meta name="description" content="{{.Description}} - Awesome Go / Golang">
|
|
||||||
<meta name="keywords" content="{{.Title}}, golang, go, awesome, awesome-go, go framework, golang framework">
|
|
||||||
<meta name="twitter:card" value="summary">
|
|
||||||
<meta property="og:title" content="{{.Description}} - Awesome Go" />
|
|
||||||
<meta property="og:type" content="article" />
|
|
||||||
<meta property="og:url" content="https://awesome-go.com/{{.Slug}}" />
|
|
||||||
<meta property="og:image" content="https://awesome-go.com/assets/logo.png" />
|
|
||||||
<meta property="og:description" content="{{.Description}} - Awesome Go" />
|
|
||||||
|
|
||||||
<link rel="canonical" href="https://awesome-go.com/{{.Slug}}">
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/fonts/firasans.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/normalize.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/awesome-go.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="content">
|
|
||||||
<header>
|
|
||||||
<h1>
|
|
||||||
<a href="https://awesome-go.com/">
|
|
||||||
<img align="right" src="https://github.com/avelino/awesome-go/raw/main/tmpl/assets/logo.png" alt="awesome-go" title="awesome-go" />
|
|
||||||
</a>
|
|
||||||
{{.Title}} - <a href="https://awesome-go.com/">Awesome Go</a>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p><em>{{.Description}}</em></p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="https://github.com/avelino/awesome-go/actions/workflows/tests.yaml?query=branch%3Amain" rel="nofollow"><img src="https://github.com/avelino/awesome-go/actions/workflows/tests.yaml/badge.svg?branch=main" alt="Build Status"></a>
|
|
||||||
<a href="https://github.com/sindresorhus/awesome" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
|
|
||||||
<a href="https://gophers.slack.com/messages/awesome" rel="nofollow"><img src="https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=red" alt="Slack Widget"></a>
|
|
||||||
<a href="https://app.netlify.com/sites/awesome-go/deploys" rel="nofollow"><img src="https://api.netlify.com/api/v1/badges/83a6dcbe-0da6-433e-b586-f68109286bd5/deploy-status" alt="Netlify Status"></a>
|
|
||||||
<a href="https://www.trackawesomelist.com/avelino/awesome-go/" rel="nofollow"><img src="https://www.trackawesomelist.com/badge.svg" alt="Track Awesome List"></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="https://www.producthunt.com/posts/awesome-go?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-awesome-go" rel="nofollow"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=291535&theme=light" width="250" height="54" /></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</header>
|
|
||||||
<div>
|
|
||||||
<h3 id="sponsorships">Sponsorships</h3>
|
|
||||||
<p>
|
|
||||||
<div id="amzn-assoc-ad-ce1dd292-c6f0-4062-ac99-55bc005bbbf9"></div>
|
|
||||||
<script async src="//z-na.amazon-adsystem.com/widgets/onejs?MarketPlace=US&adInstanceId=ce1dd292-c6f0-4062-ac99-55bc005bbbf9"></script>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="https://www.doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=awesomego&utm_source=github">
|
|
||||||
<img src="https://github.com/avelino/awesome-go/raw/main/tmpl/assets/sponsors/doppler.png" alt="Doppler">
|
|
||||||
<br />
|
|
||||||
<b>Quit struggling with scattered API keys and access controls.</b>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="https://bit.ly/awesome-go-xteam">
|
|
||||||
<img src="https://avelino.run/sponsors/xteam-logo.png" width="200" alt="x-team">
|
|
||||||
<br />
|
|
||||||
<b>Work from anywhere in the world with top tech companies like Riot Games, Coinbase, and Google.</b>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="https://m.do.co/c/bd3b723c0a36?utm_medium=opensource&utm_source=awesome-go"><img src="https://avelino.run/sponsors/do_logo_horizontal_blue-210.png" alt="Digital Ocean"></a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<i><a href="/#contents" alt="back to content menu" title="back to content menu">🗺️ back to content menu</a></i>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{{range .Items}}
|
|
||||||
<li><a href="{{.Url}}?utm_campaign=awesomego&utm_medium=referral&utm_source=awesomego" alt="Go to {{.Title}} link" title="Go to {{.Title}} link">{{.Description}}</a></li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a href="https://bit.ly/awesome-go-netlify">
|
|
||||||
<img src="https://www.netlify.com/img/global/badges/netlify-dark.svg" alt="Deploys by Netlify" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/1.1.0/marked.min.js" integrity="sha512-uggp1jOpxGjqTeS8Fit5x6+lqyJoIuXXn/VziVPlxBRnqZ0FhCaxsUnQsPL5PKylHr0KIoMtNbBIiU6n31dDTg==" crossorigin="anonymous"></script>
|
|
||||||
<script>
|
|
||||||
(function(i, s, o, g, r, a, m) {
|
|
||||||
i['GoogleAnalyticsObject'] = r;
|
|
||||||
i[r] = i[r] || function() {
|
|
||||||
(i[r].q = i[r].q || []).push(arguments)
|
|
||||||
}, i[r].l = 1 * new Date();
|
|
||||||
a = s.createElement(o),
|
|
||||||
m = s.getElementsByTagName(o)[0];
|
|
||||||
a.async = 1;
|
|
||||||
a.src = g;
|
|
||||||
m.parentNode.insertBefore(a, m)
|
|
||||||
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
|
||||||
|
|
||||||
ga('create', 'UA-85465107-1', 'auto');
|
|
||||||
ga('send', 'pageview');
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
113
tmpl/category-index.tmpl.html
vendored
Normal file
113
tmpl/category-index.tmpl.html
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<title>{{.Title}} - Awesome Go / Golang</title>
|
||||||
|
<meta name="description" content=
|
||||||
|
"{{.Description}} - Awesome Go / Golang">
|
||||||
|
<meta name="keywords" content=
|
||||||
|
"{{.Title}}, golang, go, awesome, awesome-go, go framework, golang framework">
|
||||||
|
<meta name="twitter:card" value="summary">
|
||||||
|
<meta property="og:title" content=
|
||||||
|
"{{.Description}} - Awesome Go">
|
||||||
|
<meta property="og:type" content="article">
|
||||||
|
<meta property="og:url" content=
|
||||||
|
"https://awesome-go.com/{{.Slug}}">
|
||||||
|
<meta property="og:image" content=
|
||||||
|
"https://awesome-go.com/assets/logo.png">
|
||||||
|
<meta property="og:description" content=
|
||||||
|
"{{.Description}} - Awesome Go">
|
||||||
|
<link rel="canonical" href="https://awesome-go.com/{{.Slug}}">
|
||||||
|
<link rel="stylesheet" type="text/css" href=
|
||||||
|
"/assets/fonts/firasans.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href=
|
||||||
|
"/assets/normalize.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href=
|
||||||
|
"/assets/awesome-go.css"><!--ICONS-->
|
||||||
|
<link rel="icon" href="/assets/favicon/favicon.ico" type=
|
||||||
|
"image/x-icon">
|
||||||
|
<link rel="apple-touch-icon" href=
|
||||||
|
"/assets/favicon/apple-touch-icon.png">
|
||||||
|
<link rel="manifest" href="/assets/favicon/manifest.json">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="content">
|
||||||
|
<header>
|
||||||
|
<h1><a href="https://awesome-go.com/"><img align=
|
||||||
|
"right" src=
|
||||||
|
"https://github.com/avelino/awesome-go/raw/main/tmpl/assets/logo.png"
|
||||||
|
alt="awesome-go" title="awesome-go"></a> {{.Title}} -
|
||||||
|
<a href="https://awesome-go.com/">Awesome Go</a></h1>
|
||||||
|
<p><em>{{.Description}}</em></p>
|
||||||
|
<p><a href=
|
||||||
|
"https://github.com/avelino/awesome-go/actions/workflows/tests.yaml?query=branch%3Amain"
|
||||||
|
rel="nofollow"><img src=
|
||||||
|
"https://github.com/avelino/awesome-go/actions/workflows/tests.yaml/badge.svg?branch=main"
|
||||||
|
alt="Build Status"></a> <a href=
|
||||||
|
"https://github.com/sindresorhus/awesome" rel=
|
||||||
|
"nofollow"><img src=
|
||||||
|
"https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg"
|
||||||
|
alt="Awesome"></a> <a href=
|
||||||
|
"https://gophers.slack.com/messages/awesome" rel=
|
||||||
|
"nofollow"><img src=
|
||||||
|
"https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=red"
|
||||||
|
alt="Slack Widget"></a> <a href=
|
||||||
|
"https://app.netlify.com/sites/awesome-go/deploys" rel=
|
||||||
|
"nofollow"><img src=
|
||||||
|
"https://api.netlify.com/api/v1/badges/83a6dcbe-0da6-433e-b586-f68109286bd5/deploy-status"
|
||||||
|
alt="Netlify Status"></a> <a href=
|
||||||
|
"https://www.trackawesomelist.com/avelino/awesome-go/"
|
||||||
|
rel="nofollow"><img src=
|
||||||
|
"https://www.trackawesomelist.com/badge.svg" alt=
|
||||||
|
"Track Awesome List"></a></p>
|
||||||
|
<p><a href=
|
||||||
|
"https://www.producthunt.com/posts/awesome-go?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-awesome-go"
|
||||||
|
rel="nofollow"><img src=
|
||||||
|
"https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=291535&theme=light"
|
||||||
|
width="250" height="54"></a></p>
|
||||||
|
</header><i><a href="/#contents" alt="back to content menu"
|
||||||
|
title="back to content menu">🗺️ back to content
|
||||||
|
menu</a></i>
|
||||||
|
<ul>
|
||||||
|
{{range .Links}}
|
||||||
|
<li>
|
||||||
|
<a href=
|
||||||
|
"{{.URL}}?utm_campaign=awesomego&utm_medium=referral&utm_source=awesomego"
|
||||||
|
alt="Go to {{.Title}} link" title=
|
||||||
|
"Go to {{.Title}} link">{{.Description}}</a>
|
||||||
|
</li>{{end}}
|
||||||
|
</ul><a href="https://bit.ly/awesome-go-netlify"><img src=
|
||||||
|
"https://www.netlify.com/img/global/badges/netlify-dark.svg"
|
||||||
|
alt="Deploys by Netlify"></a>
|
||||||
|
</div>
|
||||||
|
<script src=
|
||||||
|
"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
|
||||||
|
integrity=
|
||||||
|
"sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg=="
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src=
|
||||||
|
"https://cdnjs.cloudflare.com/ajax/libs/marked/1.1.0/marked.min.js"
|
||||||
|
integrity=
|
||||||
|
"sha512-uggp1jOpxGjqTeS8Fit5x6+lqyJoIuXXn/VziVPlxBRnqZ0FhCaxsUnQsPL5PKylHr0KIoMtNbBIiU6n31dDTg=="
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
(function(i, s, o, g, r, a, m) {
|
||||||
|
i['GoogleAnalyticsObject'] = r;
|
||||||
|
i[r] = i[r] || function() {
|
||||||
|
(i[r].q = i[r].q || []).push(arguments)
|
||||||
|
}, i[r].l = 1 * new Date();
|
||||||
|
a = s.createElement(o),
|
||||||
|
m = s.getElementsByTagName(o)[0];
|
||||||
|
a.async = 1;
|
||||||
|
a.src = g;
|
||||||
|
m.parentNode.insertBefore(a, m)
|
||||||
|
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
||||||
|
|
||||||
|
ga('create', 'UA-85465107-1', 'auto');
|
||||||
|
ga('send', 'pageview');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
33
tmpl/tmpl.html → tmpl/index.tmpl.html
vendored
33
tmpl/tmpl.html → tmpl/index.tmpl.html
vendored
@ -1,34 +1,39 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta http-equiv="Content-Language" content="en">
|
<meta name="viewport" content="width=device-width" />
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<title>A curated list of awesome Go frameworks, libraries and software - Awesome Go / Golang</title>
|
<title>A curated list of awesome Go frameworks, libraries and software - Awesome Go / Golang</title>
|
||||||
<meta name="description" content="A curated list of awesome Go / Golang frameworks, libraries and software">
|
<meta name="description" content="A curated list of awesome Go / Golang frameworks, libraries and software" />
|
||||||
<meta name="keywords" content="golang, go, awesome, awesome-go, go framework, golang framework">
|
<meta name="keywords" content="golang, go, awesome, awesome-go, go framework, golang framework" />
|
||||||
<meta name="twitter:card" value="summary">
|
<meta name="twitter:card" value="summary" />
|
||||||
<meta property="og:title" content="A curated list of awesome Go frameworks, libraries and software - Awesome Go" />
|
<meta property="og:title" content="A curated list of awesome Go frameworks, libraries and software - Awesome Go" />
|
||||||
<meta property="og:type" content="article" />
|
<meta property="og:type" content="article" />
|
||||||
<meta property="og:url" content="https://awesome-go.com/" />
|
<meta property="og:url" content="https://awesome-go.com/" />
|
||||||
<meta property="og:image" content="https://awesome-go.com/assets/logo.png" />
|
<meta property="og:image" content="https://awesome-go.com/assets/logo.png" />
|
||||||
<meta property="og:description" content="A curated list of awesome #Golang frameworks, libraries and software" />
|
<meta property="og:description" content="A curated list of awesome #Golang frameworks, libraries and software" />
|
||||||
|
|
||||||
<link rel="canonical" href="https://awesome-go.com/">
|
<link rel="canonical" href="https://awesome-go.com/" />
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/fonts/firasans.css">
|
<link rel="stylesheet" type="text/css" href="/assets/fonts/firasans.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/normalize.css">
|
<link rel="stylesheet" type="text/css" href="/assets/normalize.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/awesome-go.css">
|
<link rel="stylesheet" type="text/css" href="/assets/awesome-go.css" />
|
||||||
|
|
||||||
|
<!--ICONS-->
|
||||||
|
<link rel="icon" href="/assets/favicon/favicon.ico" type="image/x-icon" />
|
||||||
|
<link rel="apple-touch-icon" href="/assets/favicon/apple-touch-icon.png" />
|
||||||
|
<link rel="manifest" href="/assets/favicon/manifest.json" />
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<p>
|
<div>
|
||||||
<div id="amzn-assoc-ad-ce1dd292-c6f0-4062-ac99-55bc005bbbf9"></div>
|
<div id="amzn-assoc-ad-ce1dd292-c6f0-4062-ac99-55bc005bbbf9"></div>
|
||||||
<script async src="//z-na.amazon-adsystem.com/widgets/onejs?MarketPlace=US&adInstanceId=ce1dd292-c6f0-4062-ac99-55bc005bbbf9"></script>
|
<script async src="//z-na.amazon-adsystem.com/widgets/onejs?MarketPlace=US&adInstanceId=ce1dd292-c6f0-4062-ac99-55bc005bbbf9"></script>
|
||||||
</p>
|
</div>
|
||||||
|
|
||||||
{{.Body}}
|
{{.Body}}
|
||||||
|
|
@ -1 +1,2 @@
|
|||||||
User-Agent: *
|
User-Agent: *
|
||||||
|
Allow: /
|
||||||
|
Loading…
Reference in New Issue
Block a user