├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github ├── AUTHOR.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE │ └── pull_request_template.md ├── SECURITY.md ├── assets │ └── example.gif └── workflows │ ├── codeql-analysis.yml │ └── publish.yml ├── .gitignore ├── .npmignore ├── .nvmrc ├── .prettierrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── EXAMPLE-README.md ├── LICENSE ├── README.md ├── changelog.tpl.hbs ├── jest.config.babel.js ├── package.json ├── rollup.config.babel.js ├── src ├── cli.js ├── index.js ├── readme │ ├── questions │ │ ├── managers.js │ │ ├── prompt.js │ │ ├── purpose.js │ │ └── support.js │ └── templates │ │ ├── README.hbs │ │ └── partials │ │ ├── author.hbs │ │ ├── badges.hbs │ │ ├── commands.hbs │ │ ├── contributing.hbs │ │ ├── contributors.hbs │ │ ├── copyright.hbs │ │ ├── dependencies.hbs │ │ ├── description.hbs │ │ ├── dev-instructions.hbs │ │ ├── engines.hbs │ │ ├── formatters.hbs │ │ ├── installation.hbs │ │ ├── purpose.hbs │ │ ├── support.hbs │ │ └── title.hbs ├── settings │ ├── data.js │ ├── file.js │ ├── index.js │ ├── message.js │ └── path.js └── utilities │ ├── data.js │ ├── file.js │ ├── handlebar.js │ ├── index.js │ ├── question.js │ ├── system.js │ └── yaml.js └── test ├── settings ├── data.test.js ├── file.test.js ├── message.test.js └── path.test.js └── utilities ├── file.test.js ├── handlebar.test.js ├── question.test.js ├── ststem.test.js └── yaml.test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "useBuiltIns": "usage", 7 | "corejs": 3, 8 | "shippedProposals": true, 9 | "targets": { 10 | "node": "current" 11 | } 12 | } 13 | ] 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | max_line_length = off 12 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/jspm_packages 3 | **/bower_components 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "node": true, 6 | "es6": true, 7 | "jest/globals": true 8 | }, 9 | "parserOptions": { 10 | "ecmaVersion": 8, 11 | "sourceType": "module", 12 | "ecmaFeatures": { 13 | "jsx": true 14 | } 15 | }, 16 | "rules": { 17 | "no-console": "warn" 18 | }, 19 | "extends": [ 20 | "eslint:recommended", 21 | "plugin:jest/recommended", 22 | ], 23 | "plugins": [ 24 | "import", 25 | "jest", 26 | ], 27 | } 28 | -------------------------------------------------------------------------------- /.github/AUTHOR.md: -------------------------------------------------------------------------------- 1 | Dev Maurizio Battaghini | maurizio.battaghini+tech@gmail.com 2 | • Developer 3 | — — • Twitter: https://twitter.com/battago 4 | — — • GitHub: https://github.com/ibbatta 5 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at maurizio.battaghini+github@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | I love your input and I want to make contributing to this project as easy and transparent as possible, whether it's: 4 | 5 | - Reporting a bug 6 | - Discussing the current state of the code 7 | - Submitting a fix 8 | - Proposing new features 9 | - Becoming a maintainer 10 | 11 | ### How to contributing 12 | 13 | - Fork it! 14 | - Create your feature branch: `git checkout -b my-new-feature` 15 | - Commit your changes: `git commit -am 'Add some feature'` 16 | - Push to the branch: `git push origin my-new-feature` 17 | - Submit a pull request 18 | 19 | ## I Develop with Github 20 | 21 | I use github to host code, to track issues and feature requests, as well as accept pull requests. 22 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ibbatta] 4 | patreon: ibbatta 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://www.paypal.me/mauriziobattaghini 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | 34 | - Device: [e.g. iPhone6] 35 | - OS: [e.g. iOS8.1] 36 | - Browser [e.g. stock browser, safari] 37 | - Version [e.g. 22] 38 | 39 | **Additional context** 40 | Add any other context about the problem here. 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Describe your changes in detail. 4 | 5 | ## Motivation and Context 6 | 7 | Why is this change required? What problem does it solve?
8 | If it fixes an open issue, please link to the issue here. 9 | 10 | ## How Has This Been Tested? 11 | 12 | Please describe in detail how you tested your changes.
13 | Include details of your testing environment, and the tests you ran to see how your change affects other areas of the code, etc. 14 | 15 | ## Screenshots (if appropriate): 16 | 17 | ## Types of changes 18 | 19 | What types of changes does your code introduce? Put an `x` in all the boxes that apply: 20 | 21 | - [ ] Bug fix (non-breaking change which fixes an issue) 22 | - [ ] New feature (non-breaking change which adds functionality) 23 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 24 | 25 | ## Checklist: 26 | 27 | Go over all the following points, and put an `x` in all the boxes that apply.
28 | If you're unsure about any of these, don't hesitate to ask. We're here to help! 29 | 30 | - [ ] My code follows the code style of this project. 31 | - [ ] My change requires a change to the documentation. 32 | - [ ] I have updated the documentation accordingly. 33 | - [ ] I have read the **CONTRIBUTING** document. 34 | - [ ] I have added tests to cover my changes. 35 | - [ ] All new and existing tests passed. 36 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /.github/assets/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibbatta/readme-generator/24ace134de20687abfee189bf4ab3d37fdf114fd/.github/assets/example.gif -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '23 18 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'javascript' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish pkg (NPM + GITHUB) 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v1 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: 12 15 | - run: npm install 16 | - run: npm test 17 | 18 | publish-npm: 19 | needs: build 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v1 23 | - uses: actions/setup-node@v1 24 | with: 25 | node-version: 12 26 | registry-url: https://registry.npmjs.org/ 27 | scope: '@ibbatta' 28 | - run: npm install 29 | - run: npm publish 30 | env: 31 | NODE_AUTH_TOKEN: ${{secrets.npm}} 32 | 33 | publish-gpr: 34 | needs: build 35 | runs-on: ubuntu-latest 36 | steps: 37 | - uses: actions/checkout@v1 38 | - uses: actions/setup-node@v1 39 | with: 40 | node-version: 12 41 | registry-url: https://npm.pkg.github.com/ibbatta 42 | - run: npm install 43 | - run: npm publish 44 | env: 45 | NODE_AUTH_TOKEN: ${{secrets.github}} 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Node ### 2 | 3 | # Logs 4 | logs 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | 9 | # Optional npm cache directory 10 | .npm 11 | 12 | # package-lock should be ignored because users should use Yarn 13 | package-lock.json 14 | 15 | # Dependency directories 16 | **/node_modules 17 | **/jspm_packages 18 | **/bower_components 19 | 20 | # Yarn Integrity file 21 | .yarn-integrity 22 | 23 | # Optional eslint cache 24 | .eslintcache 25 | 26 | # dotenv environment variables file(s) 27 | .env 28 | .env.* 29 | 30 | #Build generated 31 | dist/ 32 | build/ 33 | .tmp/ 34 | 35 | 36 | ### SublimeText ### 37 | # cache files for sublime text 38 | *.tmlanguage.cache 39 | *.tmPreferences.cache 40 | *.stTheme.cache 41 | 42 | # workspace files are user-specific 43 | *.sublime-workspace 44 | 45 | # project files should be checked into the repository, unless a significant 46 | # proportion of contributors will probably not be using SublimeText 47 | # *.sublime-project 48 | 49 | 50 | ### VisualStudioCode ### 51 | .vscode/* 52 | !.vscode/settings.json 53 | !.vscode/tasks.json 54 | !.vscode/launch.json 55 | !.vscode/extensions.json 56 | 57 | ### WebStorm/IntelliJ ### 58 | /.idea 59 | modules.xml 60 | *.ipr 61 | 62 | 63 | ### System Files ### 64 | .DS_Store 65 | 66 | # Windows thumbnail cache files 67 | Thumbs.db 68 | ehthumbs.db 69 | ehthumbs_vista.db 70 | 71 | # Folder config file 72 | Desktop.ini 73 | 74 | # Recycle Bin used on file shares 75 | $RECYCLE.BIN/ 76 | 77 | # Thumbnails 78 | ._* 79 | 80 | # Files that might appear in the root of a volume 81 | .DocumentRevisions-V100 82 | .fseventsd 83 | .Spotlight-V100 84 | .TemporaryItems 85 | .Trashes 86 | .VolumeIcon.icns 87 | .com.apple.timemachine.donotpresent 88 | 89 | # Tests coverage 90 | **/coverage 91 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | #tests 2 | test 3 | coverage 4 | 5 | #build tools 6 | .travis.yml 7 | .jenkins.yml 8 | .codeclimate.yml 9 | 10 | #linters 11 | .jscsrc 12 | .jshintrc 13 | .eslintrc* 14 | 15 | #editor settings 16 | .idea 17 | .editorconfig 18 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "html.format.indentHandlebars": false 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased 4 | -------------------------------------------------------------------------------- /EXAMPLE-README.md: -------------------------------------------------------------------------------- 1 | # **:triangular_flag_on_post: @IBBATTA/README-GENERATOR** (version 0.1.9) 2 | 3 | ![node version](https://img.shields.io/badge/node->=10.16.x-brightgreen.svg) 4 | ![npm version](https://img.shields.io/badge/npm->=6.9.x-brightgreen.svg) 5 | 6 | > This project was born mainly to satisfy my desire for knowledge and to simplify my workflow. Being a curious (and also lazy) developer I have always wondered how avoid to waste my working time to write README.md files who fits perfectly project by project and that's why I wrote a tool to help me simplify and speed up these processes. 7 | 8 | --- 9 | 10 | ## **:package: Main tools used** 11 | 12 | - [x] boxen 13 | - [x] chalk 14 | - [x] commander 15 | - [x] figlet 16 | - [x] handlebars 17 | - [x] immer 18 | - [x] inquirer 19 | - [x] js-yaml 20 | - [x] lodash 21 | 22 | --- 23 | 24 | ## **:wrench: Developer usage** 25 | 26 | ### **Set up project** 27 | 28 | Before cloning the repo **be sure** you have installed: 29 | 30 | - [**NODE**](https://www.google.com/search?q=how+to+install+node) (version >= 10.16.x) 31 | - [**NPM**](https://www.google.com/search?q=how+to+install+npm) (version >= 6.9.x) 32 | 33 | Then: 34 | 35 | - Choose a folder project in your system and switch in `cd [folder path]` 36 | - Clone the repo in your folder path `git clone git+https://github.com/ibbatta/readme-generator.git` 37 | 38 | --- 39 | 40 | ### **Installation** 41 | 42 | In order to install the project and all dependencies, enter in the project folder and run `npm install` 43 | 44 | --- 45 | 46 | ### Start the project 47 | 48 | ```bash 49 | npm start 50 | ``` 51 | 52 | ### Test the project 53 | 54 | ```bash 55 | npm test 56 | ``` 57 | 58 | --- 59 | 60 | ### **Editor setup** 61 | 62 | To keep the style of resources consistent, I decided to stick to some shared rules that have to be applied to every 63 | project using some editors plugins. Plese be sure to disable / remove any other js/jsx linters or custom configurations. 64 | 65 | I have chosen to use 66 | 67 | - [ESLINT](https://www.google.com/search?q=eslint) 68 | - [PRETTIER](https://www.google.com/search?q=prettier) 69 | - [EDITORCONFIG](https://www.google.com/search?q=editorconfig) 70 | 71 | This 72 | works including a specific `.dotfile` in the root directory and making sure your editor has the necessary plugin. 73 | 74 | --- 75 | 76 | ## **:handshake: Contributing** 77 | 78 | - Fork it! 79 | - Create your feature branch: `git checkout -b my-new-feature` 80 | - Commit your changes: `git commit -am 'Add some feature'` 81 | - Push to the branch: `git push origin my-new-feature` 82 | - Submit a pull request 83 | 84 | --- 85 | 86 | ### **:busts_in_silhouette: Credits** 87 | 88 | - [Maurizio Battaghini](http://github.com/ibbatta) 89 | 90 | --- 91 | 92 | ### **:anger: Troubleshootings** 93 | 94 | This is just a personal project created for study / demonstration purpose and to simplify my working life, it may or may 95 | not be a good fit for your project(s). 96 | 97 | --- 98 | 99 | ### **:heart: Show your support** 100 | 101 | Please :star: this repository if you like it or this project helped you!\ 102 | Feel free to open issues or submit pull-requests to help me improving my work. 103 | 104 | 105 | Patron logo 106 | 107 | 108 | --- 109 | 110 | ### **:robot: Author** 111 | 112 | _*Maurizio Battaghini*_ 113 | 114 | > You can follow me on 115 | [twitter](https://twitter.com/battago) · [github](https://github.com/ibbatta) 116 | 117 | --- 118 | 119 | Copyright © 2020 [Maurizio Battaghini](https://twitter.com/battago). 120 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Maurizio Battaghini 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **:triangular_flag_on_post: @IBBATTA/README GENERATOR** 2 | 3 | ![Version](https://img.shields.io/npm/v/@ibbatta/readme-generator) 4 | ![Npm downloads](https://img.shields.io/npm/dt/@ibbatta/readme-generator) 5 | ![Repository size](https://img.shields.io/github/repo-size/ibbatta/readme-generator.svg) 6 | ![Release (0.1.9)](https://github.com/ibbatta/readme-generator/workflows/Publish%20pkg%20(NPM%20+%20GITHUB)/badge.svg) 7 | 8 | > This project was born to simplify my workflow and satisfy my desire for knowledge. Being a curious (and also lazy) developer, I've always wandered how to avoid wasting time writing README.md files that fit perfectly project after project. That's why I wrote this tool to help simplify and speed up this process! 9 | 10 | ![Example gif](./.github/assets/example.gif) 11 | 12 | --- 13 | 14 | ## **:clipboard: User usage** 15 | 16 | - To install globally: `npm i -g @ibbatta/readme-generator`. 17 | - To install locally: `npm i --save-dev @ibbatta/readme-generator`. 18 | 19 | Just run `readme-generator` (or `npx readme-generator`) at the root of your project and follow the prompts! 20 | 21 | You can add the following options: 22 | 23 | | Option | Description | Default | 24 | | -------------- | -------------------------------------------- | --------------------------- | 25 | | -V, --version | output the version number | | 26 | | -h, --help | output usage information | | 27 | | -E, --entry | specify the entry file | `package.json` | 28 | | -O, --output | specify the output file | `README.md` | 29 | | -T, --template | specify the path for you own README template | `internal default template` | 30 | | -D, --debug | log output readme data | `false` | 31 | 32 | The tools will look for the **name**, **version**, **description**, **respository**, **author**, **engines**, **dependencies** and **contributors** data inside you package.json and then will generate the README.md file based on that information. 33 | 34 | Due to this reason, this tool was create mainly for a node based project as it will take the package.json by default.\ 35 | If your project doesn't have a package.json, you can specify another json file. 36 | 37 | _NOTE_: To generate a complete `README.md`, make sure that the structure of your `package.json` (or you entry file) looks like this: 38 | 39 | ```js 40 | { 41 | "name": ..., 42 | "version": ..., 43 | "description": ..., 44 | "repository": { 45 | "url": ... 46 | }, 47 | "author": { 48 | "name": ..., 49 | "email": ..., 50 | "url": ... 51 | }, 52 | "contributors": [{ 53 | "name": ..., 54 | "url": ... 55 | }], 56 | "engines": { 57 | ... 58 | }, 59 | "dependencies": { 60 | ... 61 | } 62 | } 63 | 64 | ``` 65 | 66 | _If no entry file is specified, and package.json is missing, the tool will prompt you for information instead._ 67 | 68 | You can include a custom field for your social accounts simply adding a `readmeGenerator` param inside `package.json`, like in this following example: 69 | 70 | ```js 71 | { 72 | "name": ..., 73 | "version": ..., 74 | "description": ..., 75 | ..., 76 | ..., 77 | ..., 78 | "readmeGenerator": { 79 | "social": { 80 | "github": "http://github.com/...", 81 | "twitter": "http://twitter.com/...", 82 | "ADD MORE SOCIAL ACCOUNTS IF YOU WANT": "..." 83 | } 84 | } 85 | } 86 | ``` 87 | 88 | This allows the tool to create a better `README.md` with more information. 89 | 90 | Here is a generated [README example](https://github.com/ibbatta/readme-generator/blob/master/EXAMPLE-README.md). 91 | 92 | --- 93 | 94 | ## **:wrench: Developer usage** 95 | 96 | ### **Set up project** 97 | 98 | Before cloning the repo **make sure** you have installed: 99 | 100 | - [**NODE**](https://www.google.com/search?q=how+to+install+node) (version >= 8.9.x) 101 | - [**YARN**](https://www.google.com/search?q=how+to+install+yarn) (version >= 1.9.x) 102 | - [**NPM**](https://www.google.com/search?q=how+to+install+npm) (version >= 6.3.x) 103 | 104 | Then: 105 | 106 | - Choose a folder project in your system and switch in `cd [folder path]` 107 | - Clone the repo in your folder: `git clone https://github.com/ibbatta/readme-generator.git` 108 | 109 | --- 110 | 111 | ### **Installation** 112 | 113 | First, enter the project folder and run `nvm use` to check you have the right node version, then run `yarn install` to install all the dependencies. 114 | 115 | --- 116 | 117 | #### Start the project 118 | 119 | To run the cli of the project locally: 120 | 121 | ```bash 122 | npm start 123 | # or 124 | yarn start 125 | ``` 126 | 127 | #### Build the project for production 128 | 129 | This will create a folder `/lib` and compile the es6 / es7 js syntax: 130 | 131 | ```bash 132 | npm build 133 | #or 134 | yarn build 135 | ``` 136 | 137 | You can add the `--watch` flag if you want to keep watching the changes made for test files. 138 | 139 | #### Run the tests 140 | 141 | ```bash 142 | npm test 143 | #or 144 | yarn test 145 | ``` 146 | 147 | You can add the `--watch` flag if you to want keep watching the changes made for test files. 148 | 149 | --- 150 | 151 | ## **Editor setup** 152 | 153 | To keep the style of resources consistent, I decided to stick to some shared rules that have to be applied to every 154 | project using some editors plugins. Plese be sure to disable / remove any other js/jsx linters or custom configurations. 155 | 156 | ### Eslint 157 | 158 | I have chosen to use [Eslint](https://eslint.org/) to lint the Javascript / React [.js / .jsx] syntax. 159 | It includes a `.eslintrc` file in the root directory. Make sure your editor has the right plugins. 160 | 161 | ### Auto correction on save 162 | 163 | I have chosen to use [js-beautify](https://github.com/beautify-web/js-beautify/) as the beautifier for the HTML and CSS. 164 | It includes a `.jsbeautifyrc` file in the root directory. Make sure your editor has the right plugins. 165 | 166 | ### Basic Editor Configuration 167 | 168 | I have chosen to use [EditorConfig](https://editorconfig.org/) to share the basic configuration like indentation and 169 | charset. 170 | It includes a `.editorconfig` file in the root directory. Make sure your editor has the right plugins. 171 | 172 | ### Prettier 173 | 174 | I have chosen to use [Prettier](https://prettier.io/) to ensure the codebase has a consistent style. 175 | It includes a `.prettierrc` file in the root directory. Make sure your editor has the right plugin. 176 | 177 | --- 178 | 179 | ## **:handshake: Contributing** 180 | 181 | Contributions, issues and feature requests are welcome. 182 | Feel free to check the issues page if you want to contribute, and follow these simple steps: 183 | 184 | - Fork it! 185 | - Create your feature (or fix) branch: `git checkout -b my-new-feature` 186 | - Commit your changes: `git commit -am 'Add some feature'` 187 | - Push to the branch: `git push origin my-new-feature` 188 | - Submit a pull request! 189 | 190 | --- 191 | 192 | ### **:anger: Troubleshooting** 193 | 194 | This is just a personal project created for study / demonstration purposes and to simplify my working life, it may or may not be a good fit for your project! 195 | 196 | --- 197 | 198 | ### **:heart: Show your support** 199 | 200 | Please :star: this repository if you like it or this project helped you!\ 201 | Feel free to open issues or submit pull-requests to help me improve my work. 202 | 203 | 204 | Patron logo 205 | 206 | 207 | --- 208 | 209 | ### **:robot: Author** 210 | 211 | Maurizio Battaghini 212 | 213 | > GitHub [@ibbatta](https://github.com/ibbatta)  ·  214 | > Twitter [@battago](https://twitter.com/battago) 215 | 216 | --- 217 | 218 | Copyright © 2019 [Maurizio Battaghini](https://github.com/ibbatta).\ 219 | This project is covered by [MIT](https://github.com/ibbatta/readme-generator/blob/master/LICENSE) license. 220 | -------------------------------------------------------------------------------- /changelog.tpl.hbs: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | {{#each releases}} 4 | {{#if href}} 5 | ## [{{title}}]({{href}}){{#if tag}} - {{isoDate}}{{/if}} 6 | {{else}} 7 | ## {{title}}{{#if tag}} - {{isoDate}}{{/if}} 8 | {{/if}} 9 | 10 | {{#if summary}} 11 | {{summary}} 12 | {{/if}} 13 | 14 | {{#if merges}} 15 | ### Merged 16 | 17 | {{#each merges}} 18 | - {{{message}}} {{#if href}}[`#{{id}}`]({{href}}){{/if}} 19 | {{/each}} 20 | {{/if}} 21 | 22 | {{#if fixes}} 23 | ### Fixed 24 | 25 | {{#each fixes}} 26 | - {{{commit.subject}}}{{#each fixes}} {{#if href}}[`#{{id}}`]({{href}}){{/if}}{{/each}} 27 | {{/each}} 28 | {{/if}} 29 | 30 | {{#commit-list commits heading='### Commits'}} 31 | - {{#if breaking}}**Breaking change:** {{/if}}{{{subject}}} {{#if href}}[`{{shorthash}}`]({{href}}){{/if}} 32 | {{/commit-list}} 33 | 34 | {{/each}} 35 | -------------------------------------------------------------------------------- /jest.config.babel.js: -------------------------------------------------------------------------------- 1 | export default { 2 | bail: true, 3 | verbose: true, 4 | testMatch: ['./src/**/*.test.js'] 5 | }; 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ibbatta/readme-generator", 3 | "version": "0.1.9", 4 | "description": "This project was born mainly to satisfy my desire for knowledge and to simplify my workflow. Being a curious (and also lazy) developer I have always wondered how avoid to waste my working time to write README.md files who fits perfectly project by project and that's why I wrote a tool to help me simplify and speed up these processes.", 5 | "main": "./src/index.js", 6 | "bin": { 7 | "readme-generator": "./dist/index.js" 8 | }, 9 | "homepage": "https://github.com/ibbatta/readme-generator", 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/ibbatta/readme-generator.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/ibbatta/readme-generator/issues", 16 | "email": "maurizio.battaghini+tech@gmail.com" 17 | }, 18 | "author": "Maurizio Battaghini (https://twitter.com/battago)", 19 | "contributors": [ 20 | "Maurizio Battaghini (http://github.com/ibbatta)" 21 | ], 22 | "keywords": [ 23 | "readme", 24 | "readme-template", 25 | "readme-generator", 26 | "readme-md", 27 | "generator", 28 | "cli", 29 | "readme-standard", 30 | "readme-quality" 31 | ], 32 | "engines": { 33 | "node": ">= 10.16.x", 34 | "npm": ">= 6.9.x" 35 | }, 36 | "license": "MIT", 37 | "private": false, 38 | "scripts": { 39 | "start": "clear && babel-node -- ./src/index.js", 40 | "build": "rm -rf ./dist && rollup --config ./rollup.config.babel.js --environment INCLUDE_DEPS,BUILD:production", 41 | "build:watch": "rm -rf ./dist && rollup --config ./rollup.config.babel.js --watch", 42 | "test": "lint-staged && jest", 43 | "test:watch": "jest --watch", 44 | "prepare": "npm run build", 45 | "changelog": "auto-changelog", 46 | "version": "auto-changelog -p && git add CHANGELOG.md" 47 | }, 48 | "publishConfig": { 49 | "registry": "https://npm.pkg.github.com/" 50 | }, 51 | "dependencies": { 52 | "boxen": "^4.2.0", 53 | "chalk": "^4.1.0", 54 | "commander": "^5.1.0", 55 | "figlet": "^1.4.0", 56 | "handlebars": "^4.7.6", 57 | "immer": ">=8.0.1", 58 | "inquirer": "^7.1.0", 59 | "js-yaml": "^3.14.0", 60 | "lodash": "^4.17.15" 61 | }, 62 | "devDependencies": { 63 | "@babel/cli": "^7.10.1", 64 | "@babel/core": "^7.10.2", 65 | "@babel/node": "^7.10.1", 66 | "@babel/preset-env": "^7.10.2", 67 | "auto-changelog": "^2.0.0", 68 | "babel-eslint": "^10.1.0", 69 | "babel-jest": "^26.0.1", 70 | "babel-loader": "^8.1.0", 71 | "core-js": "^3.6.5", 72 | "eslint": "^7.2.0", 73 | "eslint-config-airbnb": "18.1.0", 74 | "eslint-plugin-import": "^2.21.2", 75 | "eslint-plugin-jest": "^23.13.2", 76 | "eslint-plugin-jsx-a11y": "^6.2.3", 77 | "husky": "^4.2.5", 78 | "jest": "^26.0.1", 79 | "lint-staged": "^10.2.10", 80 | "rollup": "^2.15.0", 81 | "rollup-plugin-babel": "^4.4.0", 82 | "rollup-plugin-copy-assets": "^2.0.1", 83 | "rollup-plugin-node-resolve": "^5.2.0", 84 | "rollup-plugin-terser": "^6.1.0" 85 | }, 86 | "husky": { 87 | "hooks": { 88 | "pre-commit": "npm run test && auto-changelog && git add CHANGELOG.md", 89 | "commit-msg": "echo HUSKY_GIT_PARAMS" 90 | } 91 | }, 92 | "lint-staged": { 93 | "*.js": [ 94 | "eslint --fix", 95 | "git add" 96 | ] 97 | }, 98 | "auto-changelog": { 99 | "output": "CHANGELOG.md", 100 | "template": "changelog.tpl.hbs", 101 | "unreleased": true, 102 | "commitLimit": 10, 103 | "includeBranch": [ 104 | "master", 105 | "develop", 106 | "*" 107 | ] 108 | }, 109 | "readmeGenerator": { 110 | "social": { 111 | "twitter": "https://twitter.com/battago", 112 | "github": "https://github.com/ibbatta" 113 | } 114 | }, 115 | "directories": { 116 | "test": "test" 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /rollup.config.babel.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import babel from 'rollup-plugin-babel'; 3 | import copy from 'rollup-plugin-copy-assets'; 4 | import { terser } from 'rollup-plugin-terser'; 5 | 6 | const externalDependencies = Object.keys( 7 | require('./package.json').dependencies 8 | ); 9 | 10 | export default { 11 | input: './src/index.js', 12 | output: { 13 | banner: '#!/usr/bin/env node', 14 | name: 'readme-generator', 15 | file: './dist/index.js', 16 | format: 'cjs', 17 | assetFileNames: 'src/readme' 18 | }, 19 | plugins: [ 20 | resolve({ 21 | preferBuiltins: true, 22 | customResolveOptions: { 23 | moduleDirectory: 'node_modules' 24 | } 25 | }), 26 | babel({ 27 | exclude: 'node_modules/**' // only transpile our source code 28 | }), 29 | copy({ 30 | assets: ['./src/readme'] 31 | }), 32 | terser() 33 | ], 34 | external: ['fs', 'path', externalDependencies], 35 | onwarn: warning => { 36 | if (warning.code === 'THIS_IS_UNDEFINED') return; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /src/cli.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import produce from 'immer'; 3 | const _ = require('lodash'); 4 | const inquirer = require('inquirer'); 5 | 6 | import { 7 | fileSettings, 8 | dataSettings, 9 | pathSettings, 10 | messageSettings 11 | } from './settings'; 12 | 13 | import { 14 | dataUtils, 15 | fileUtils, 16 | questionUtils, 17 | hbsUtils, 18 | systemUtils 19 | } from './utilities'; 20 | 21 | const partialDir = path.resolve(__dirname, pathSettings.readme.hbsPartials); 22 | const questionDir = path.resolve(__dirname, pathSettings.readme.questions); 23 | 24 | const readmeFile = `${fileSettings.readme.name}.${fileSettings.readme.ext}`; 25 | const supportFile = `${fileSettings.support.name}.${fileSettings.support.ext}`; 26 | 27 | const parseQuestions = async questionsPath => { 28 | const bulkQuestions = []; 29 | const extraQuestions = []; 30 | const { data } = await fileUtils.readDirectoryFiles(questionsPath); 31 | const formatters = await systemUtils.checkFormatters(fileSettings.formatters); 32 | const supports = await systemUtils.checkSupports( 33 | await fileUtils 34 | .checkExist(pathSettings.github) 35 | .then(() => path.join(pathSettings.github, supportFile)) 36 | .catch(() => path.join(pathSettings.root, supportFile)) 37 | ); 38 | 39 | const hasFormatters = !_.isNil(formatters) && !_.isEmpty(formatters); 40 | const hasSupports = !_.isNil(supports) && !_.isEmpty(supports); 41 | 42 | data.files.forEach(file => { 43 | bulkQuestions.push(...require(path.join(data.directory, file))); 44 | }); 45 | 46 | extraQuestions.push( 47 | hasFormatters && 48 | questionUtils.injectQuestion( 49 | { 50 | name: 'formatters', 51 | type: 'checkbox', 52 | message: 'What kind of formatter / linter are you using?', 53 | choices: formatters, 54 | default: formatters 55 | }, 56 | bulkQuestions 57 | ), 58 | 59 | hasSupports && 60 | questionUtils.injectQuestion( 61 | { 62 | name: 'support', 63 | default: true 64 | }, 65 | bulkQuestions 66 | ), 67 | 68 | hasSupports && 69 | !_.isNil(supports.patreon) && 70 | questionUtils.injectQuestion( 71 | { 72 | name: 'support.patreon', 73 | default: supports.patreon 74 | }, 75 | bulkQuestions 76 | ) 77 | ); 78 | 79 | messageSettings.questionTitle('\nJust few questions'); 80 | return inquirer.prompt(_.unionBy(bulkQuestions, ...extraQuestions, 'name')); 81 | }; 82 | 83 | const parseData = packageData => { 84 | const packageDataParsed = produce(packageData, draftState => { 85 | const { author, contributors, readmeGenerator } = draftState; 86 | draftState.author = _.isString(author) 87 | ? dataUtils.convertInfoToObject(author) 88 | : author; 89 | 90 | if (!_.isNil(readmeGenerator) && !_.isNil(readmeGenerator.social)) { 91 | draftState.author.social = readmeGenerator.social; 92 | delete draftState.readmeGenerator; 93 | } 94 | 95 | if (!_.isNil(contributors)) { 96 | contributors.forEach((value, index) => { 97 | contributors[index] = _.isString(value) 98 | ? dataUtils.convertInfoToObject(value) 99 | : value; 100 | }); 101 | } 102 | }); 103 | return packageDataParsed; 104 | }; 105 | 106 | const Run = async ({ entry, output, template, debug }) => { 107 | messageSettings.mainTitle('Readme\nGenerator'); 108 | 109 | const buildTemplate = {}; 110 | 111 | let entryFile = _.isNil(entry) 112 | ? fileSettings.package.path 113 | : path.resolve(pathSettings.root, entry); 114 | const outputFile = _.isNil(output) ? readmeFile : output; 115 | const templatePath = _.isNil(template) 116 | ? path.resolve(__dirname, fileSettings.template.path) 117 | : path.resolve(pathSettings.root, template); 118 | const showDebugLog = !_.isNil(debug); 119 | 120 | /** REGISTER ALL HANDLEBAR PARTIALS FOUND INSIDE THE FOLDER ./src/readme/templates/partials 121 | * 122 | */ 123 | try { 124 | await systemUtils.registerHbsPartials(partialDir); 125 | } catch ({ error }) { 126 | throw new Error(messageSettings.genericError(error)); 127 | } 128 | 129 | /** READ HANDLEBAR TEMPLATE FILE 130 | * 131 | */ 132 | 133 | try { 134 | const { data } = await fileUtils.readFile(templatePath); 135 | buildTemplate.file = data.file; 136 | } catch ({ error }) { 137 | throw new Error(messageSettings.readFileError(templatePath, error)); 138 | } 139 | 140 | let pickedData; 141 | try { 142 | await fileUtils.checkExist(entryFile); 143 | const { data } = await fileUtils.readFile(entryFile); 144 | 145 | pickedData = _.pick( 146 | JSON.parse(data.file), 147 | dataSettings.packageJsonFilterData 148 | ); 149 | } catch (error) { 150 | messageSettings.questionTitle('\nMain questions'); 151 | pickedData = await inquirer.prompt(dataSettings.fallbackQuestionData); 152 | } 153 | 154 | /** MERGE COLLECTED DATA FROM QUESTIONS AND PACKAGE.JSON 155 | * CREATE THE COLLECTION TO POPULATE HANDLEBAR TEMPLATE 156 | */ 157 | try { 158 | buildTemplate.data = _.merge( 159 | {}, 160 | parseData(pickedData), 161 | await parseQuestions(questionDir) 162 | ); 163 | } catch ({ error }) { 164 | throw new Error(messageSettings.genericError(error)); 165 | } 166 | 167 | /** PARSE AND GENERATE THE HANDLEBAR TEMPLATE 168 | * WRITE THE README.MD FILE 169 | */ 170 | try { 171 | const { file, data } = buildTemplate; 172 | const outputPath = path.resolve(pathSettings.root, outputFile); 173 | const hbsGenerated = hbsUtils.generateHandlebar(file, data, showDebugLog); 174 | await fileUtils.writeFile(outputPath, hbsGenerated); 175 | messageSettings.writeFileSuccess(outputFile); 176 | } catch ({ error }) { 177 | throw new Error(messageSettings.writeFileError(outputFile, error)); 178 | } 179 | }; 180 | 181 | export default Run; 182 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const program = require('commander'); 2 | const { version } = require('../package.json'); 3 | 4 | import Run from './cli'; 5 | 6 | program 7 | .version(version) 8 | .name('readme-generator') 9 | .option('-E, --entry ', 'specify the entry file') 10 | .option('-O, --output ', 'specify the output file') 11 | .option('-T, --template ', 'specity a custom template') 12 | .option('-D, --debug', 'log output readme data'); 13 | 14 | program.parse(process.argv); 15 | 16 | Run(program); 17 | -------------------------------------------------------------------------------- /src/readme/questions/managers.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | name: 'manager', 4 | type: 'list', 5 | message: 'What package manager are you using?', 6 | choices: ['npm', 'yarn'], 7 | default: 'npm' 8 | } 9 | ]; 10 | -------------------------------------------------------------------------------- /src/readme/questions/prompt.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | name: 'commands.start', 4 | type: 'input', 5 | message: 'What is the command to run the project?', 6 | default: 'start' 7 | }, 8 | { 9 | name: 'commands.test', 10 | type: 'input', 11 | message: 'What is the command to test the project?', 12 | default: 'test' 13 | } 14 | ]; 15 | -------------------------------------------------------------------------------- /src/readme/questions/purpose.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | name: 'purpose', 4 | type: 'confirm', 5 | message: 'Is this project a demostration / study case?', 6 | default: false 7 | } 8 | ]; 9 | -------------------------------------------------------------------------------- /src/readme/questions/support.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | name: 'support', 4 | type: 'confirm', 5 | message: 'Do you have a Patreon account?', 6 | default: false 7 | }, 8 | { 9 | name: 'support.patreon', 10 | type: 'input', 11 | message: 'Insert your Patreon username', 12 | when: answer => { 13 | return answer.support; 14 | } 15 | } 16 | ]; 17 | -------------------------------------------------------------------------------- /src/readme/templates/README.hbs: -------------------------------------------------------------------------------- 1 | {{> title}} 2 | 3 | {{> badges}} 4 | 5 | {{> description}} 6 | 7 | --- 8 | 9 | {{> dependencies}} 10 | 11 | {{> dev-instructions}} 12 | 13 | {{> installation}} 14 | 15 | {{> commands}} 16 | 17 | {{> formatters}} 18 | 19 | {{> contributing}} 20 | 21 | {{> contributors}} 22 | 23 | {{> purpose}} 24 | 25 | {{> support}} 26 | 27 | {{> author}} 28 | 29 | {{> copyright}} 30 | -------------------------------------------------------------------------------- /src/readme/templates/partials/author.hbs: -------------------------------------------------------------------------------- 1 | {{#if author.name}} 2 | ### **:robot: Author** 3 | 4 | _*{{author.name}}*_ 5 | 6 | {{#if author.social}} 7 | > You can follow me on 8 | {{#each author.social~}}{{#unless @last}}[{{@key}}]({{{this}}}) · {{/unless}}{{#if @last}}[{{@key}}]({{{this}}}){{/if}}{{~/each}} 9 | {{/if}} 10 | 11 | --- 12 | {{/if}} 13 | -------------------------------------------------------------------------------- /src/readme/templates/partials/badges.hbs: -------------------------------------------------------------------------------- 1 | {{#if engines}} 2 | {{#each engines}} 3 | ![{{@key}} version](https://img.shields.io/badge/{{@key}}-{{{removeAllSpaces this}}}-brightgreen.svg) 4 | {{/each}} 5 | {{/if}} 6 | -------------------------------------------------------------------------------- /src/readme/templates/partials/commands.hbs: -------------------------------------------------------------------------------- 1 | {{#if commands}} 2 | {{#each commands}} 3 | ### {{capitalize @key}} the project 4 | 5 | ```bash 6 | {{../manager}} {{this}} 7 | ``` 8 | 9 | {{/each}} 10 | --- 11 | {{/if}} 12 | -------------------------------------------------------------------------------- /src/readme/templates/partials/contributing.hbs: -------------------------------------------------------------------------------- 1 | ## **:handshake: Contributing** 2 | 3 | - Fork it! 4 | - Create your feature branch: `git checkout -b my-new-feature` 5 | - Commit your changes: `git commit -am 'Add some feature'` 6 | - Push to the branch: `git push origin my-new-feature` 7 | - Submit a pull request 8 | 9 | --- 10 | -------------------------------------------------------------------------------- /src/readme/templates/partials/contributors.hbs: -------------------------------------------------------------------------------- 1 | {{#if contributors}} 2 | ### **:busts_in_silhouette: Credits** 3 | 4 | {{#each contributors}} 5 | - [{{name}}]({{{url}}}) 6 | {{/each}} 7 | 8 | --- 9 | {{/if}} 10 | -------------------------------------------------------------------------------- /src/readme/templates/partials/copyright.hbs: -------------------------------------------------------------------------------- 1 | Copyright © {{getYear}} {{#if author.url}}[{{author.name}}]({{author.url}}).{{else}}{{author.name}}{{/if}} 2 | -------------------------------------------------------------------------------- /src/readme/templates/partials/dependencies.hbs: -------------------------------------------------------------------------------- 1 | {{#if dependencies}} 2 | ## **:package: Main tools used** 3 | 4 | {{#each dependencies}} 5 | - [x] {{@key}} 6 | {{/each}} 7 | {{#each frameworks}} 8 | - [x] {{this}} 9 | {{/each}} 10 | 11 | --- 12 | {{/if}} 13 | -------------------------------------------------------------------------------- /src/readme/templates/partials/description.hbs: -------------------------------------------------------------------------------- 1 | {{#if description}} 2 | > {{{description}}} 3 | {{/if}} 4 | -------------------------------------------------------------------------------- /src/readme/templates/partials/dev-instructions.hbs: -------------------------------------------------------------------------------- 1 | ## **:wrench: Developer usage** 2 | 3 | ### **Set up project** 4 | 5 | {{#if engines}} 6 | Before cloning the repo **be sure** you have installed: 7 | 8 | {{> engines}} 9 | 10 | Then: 11 | 12 | {{/if}} 13 | - Choose a folder project in your system and switch in `cd [folder path]` 14 | - Clone the repo in your folder path{{#if repository.url}} `git clone {{{repository.url}}}`{{/if}} 15 | 16 | --- 17 | -------------------------------------------------------------------------------- /src/readme/templates/partials/engines.hbs: -------------------------------------------------------------------------------- 1 | {{#each engines}} 2 | - [**{{uppercase @key}}**](https://www.google.com/search?q=how+to+install+{{lowercase @key}}) (version {{{this}}}) 3 | {{/each}} 4 | -------------------------------------------------------------------------------- /src/readme/templates/partials/formatters.hbs: -------------------------------------------------------------------------------- 1 | {{#if formatters}} 2 | ### **Editor setup** 3 | 4 | To keep the style of resources consistent, I decided to stick to some shared rules that have to be applied to every 5 | project using some editors plugins. Plese be sure to disable / remove any other js/jsx linters or custom configurations. 6 | 7 | I have chosen to use 8 | 9 | {{#each formatters}} 10 | - [{{uppercase this}}](https://www.google.com/search?q={{lowercase this}}) 11 | {{/each}} 12 | 13 | This 14 | works including a specific `.dotfile` in the root directory and making sure your editor has the necessary plugin. 15 | 16 | --- 17 | {{/if}} 18 | -------------------------------------------------------------------------------- /src/readme/templates/partials/installation.hbs: -------------------------------------------------------------------------------- 1 | ### **Installation** 2 | 3 | In order to install the project and all dependencies, enter in the project folder and run `{{manager}} install` 4 | 5 | --- 6 | -------------------------------------------------------------------------------- /src/readme/templates/partials/purpose.hbs: -------------------------------------------------------------------------------- 1 | {{#if purpose}} 2 | ### **:anger: Troubleshootings** 3 | 4 | This is just a personal project created for study / demonstration purpose and to simplify my working life, it may or may 5 | not be a good fit for your project(s). 6 | 7 | --- 8 | {{/if}} 9 | -------------------------------------------------------------------------------- /src/readme/templates/partials/support.hbs: -------------------------------------------------------------------------------- 1 | ### **:heart: Show your support** 2 | 3 | Please :star: this repository if you like it or this project helped you!\ 4 | Feel free to open issues or submit pull-requests to help me improving my work. 5 | 6 | {{#if support}} 7 | 8 | Patron logo 9 | 10 | {{/if}} 11 | 12 | --- 13 | -------------------------------------------------------------------------------- /src/readme/templates/partials/title.hbs: -------------------------------------------------------------------------------- 1 | # **:triangular_flag_on_post: {{uppercase name}}** (version {{version}}) 2 | -------------------------------------------------------------------------------- /src/settings/data.js: -------------------------------------------------------------------------------- 1 | const packageJsonFilterData = [ 2 | 'name', 3 | 'version', 4 | 'description', 5 | 'repository', 6 | 'author', 7 | 'engines', 8 | 'dependencies', 9 | 'contributors', 10 | 'readmeGenerator' 11 | ]; 12 | 13 | const fallbackQuestionData = [ 14 | { 15 | name: 'name', 16 | type: 'input', 17 | message: 'What is the name of the project?', 18 | default: 'Amazing title' 19 | }, 20 | { 21 | name: 'version', 22 | type: 'input', 23 | message: 'What is the version?', 24 | default: '0.1.0' 25 | }, 26 | { 27 | name: 'description', 28 | type: 'input', 29 | message: 'Describe your project' 30 | }, 31 | { 32 | name: 'repository.url', 33 | type: 'input', 34 | message: "Insert the url of your project's repository" 35 | }, 36 | { 37 | name: 'author.name', 38 | type: 'input', 39 | message: 'Insert the author name' 40 | } 41 | ]; 42 | 43 | export default { 44 | packageJsonFilterData, 45 | fallbackQuestionData 46 | }; 47 | -------------------------------------------------------------------------------- /src/settings/file.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import pathSettings from './path'; 3 | 4 | const settings = { 5 | package: { 6 | name: 'package', 7 | ext: 'json' 8 | }, 9 | template: { 10 | name: 'README', 11 | ext: 'hbs' 12 | }, 13 | readme: { 14 | name: 'README', 15 | ext: 'md' 16 | }, 17 | support: { 18 | name: 'FUNDING', 19 | ext: 'yml' 20 | }, 21 | formatters: [ 22 | { name: 'eslint', ext: 'rc' }, 23 | { name: 'jsbeautify', ext: 'rc' }, 24 | { name: 'editorconfig', ext: null }, 25 | { name: 'prettier', ext: 'rc' } 26 | ] 27 | }; 28 | 29 | settings.package.path = path.join( 30 | pathSettings.root, 31 | `${settings.package.name}.${settings.package.ext}` 32 | ); 33 | 34 | settings.template.path = path.join( 35 | pathSettings.readme.templates, 36 | `${settings.template.name}.${settings.template.ext}` 37 | ); 38 | 39 | settings.formatters.forEach((val, index) => { 40 | settings.formatters[index].path = path.join( 41 | pathSettings.root, 42 | `.${val.name}${val.ext ? val.ext : ''}` 43 | ); 44 | }); 45 | 46 | export default settings; 47 | -------------------------------------------------------------------------------- /src/settings/index.js: -------------------------------------------------------------------------------- 1 | export { default as fileSettings } from './file'; 2 | export { default as pathSettings } from './path'; 3 | export { default as dataSettings } from './data'; 4 | export { default as messageSettings } from './message'; 5 | -------------------------------------------------------------------------------- /src/settings/message.js: -------------------------------------------------------------------------------- 1 | const figlet = require('figlet'); 2 | const chalk = require('chalk'); 3 | const boxen = require('boxen'); 4 | 5 | const { log, clear } = console; 6 | 7 | const mainTitle = (data) => { 8 | clear(); 9 | log(chalk.magentaBright(figlet.textSync(data))); 10 | }; 11 | 12 | const questionTitle = (data) => { 13 | log(chalk.yellow(data)); 14 | }; 15 | 16 | const debugMessage = (data) => { 17 | log(data); 18 | }; 19 | 20 | const genericError = (error) => { 21 | log(chalk.red(error)); 22 | }; 23 | 24 | const readFileError = (data, error) => { 25 | log( 26 | chalk.red(`ERROR: The ${chalk.bold(data)} file is missing or not readable.`) 27 | ); 28 | log(chalk.red(error)); 29 | }; 30 | 31 | const writeFileError = (data, error) => { 32 | log(chalk.red(`ERROR: Unable to generate the ${chalk.bold(data)} file.`)); 33 | log(chalk.red(error)); 34 | }; 35 | 36 | const readFileSuccess = (data) => { 37 | log(chalk.green(`The ${data} file was successfully read`)); 38 | }; 39 | 40 | const writeFileSuccess = (data) => { 41 | log( 42 | chalk.green( 43 | boxen( 44 | `The ${chalk.bold.underline(data)} file is generated with success`, 45 | { 46 | padding: 1, 47 | margin: 1, 48 | borderStyle: 'classic', 49 | } 50 | ) 51 | ) 52 | ); 53 | }; 54 | 55 | export default { 56 | mainTitle, 57 | questionTitle, 58 | debugMessage, 59 | genericError, 60 | readFileError, 61 | writeFileError, 62 | readFileSuccess, 63 | writeFileSuccess, 64 | }; 65 | -------------------------------------------------------------------------------- /src/settings/path.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | const basePath = { 4 | root: path.resolve(process.cwd()), 5 | github: path.resolve(process.cwd(), '.github'), 6 | readme: { 7 | questions: 'readme/questions', 8 | templates: 'readme/templates', 9 | hbsPartials: 'readme/templates/partials' 10 | } 11 | }; 12 | 13 | export default basePath; 14 | -------------------------------------------------------------------------------- /src/utilities/data.js: -------------------------------------------------------------------------------- 1 | const convertInfoToObject = data => { 2 | const infoData = { 3 | name: '' 4 | }; 5 | 6 | data.split(' ').forEach(value => { 7 | if (value.includes('<' && '>')) { 8 | infoData.email = data.substring( 9 | data.lastIndexOf('<') + 1, 10 | data.lastIndexOf('>') 11 | ); 12 | } else if (value.includes('(' && ')')) { 13 | infoData.url = data.substring( 14 | data.lastIndexOf('(') + 1, 15 | data.lastIndexOf(')') 16 | ); 17 | } else { 18 | infoData.name = `${`${infoData.name} ${value}`}`.trim(); 19 | } 20 | }); 21 | 22 | return infoData; 23 | }; 24 | 25 | export default { 26 | convertInfoToObject 27 | }; 28 | -------------------------------------------------------------------------------- /src/utilities/file.js: -------------------------------------------------------------------------------- 1 | import fs, { constants } from 'fs'; 2 | 3 | const checkExist = target => 4 | new Promise((resolve, reject) => { 5 | !target && 6 | reject({ 7 | success: false, 8 | error: new Error('Path must be specified') 9 | }); 10 | fs.access(target, constants.F_OK | constants.W_OK, error => { 11 | error ? reject({ success: false, error }) : resolve({ success: true }); 12 | }); 13 | }); 14 | 15 | const readDirectoryFiles = directory => 16 | new Promise((resolve, reject) => { 17 | !directory && 18 | reject({ 19 | success: false, 20 | error: new Error('Directory must be specified') 21 | }); 22 | fs.readdir(directory, (error, files) => { 23 | error 24 | ? reject({ success: false, error }) 25 | : resolve({ success: true, data: { directory, files } }); 26 | }); 27 | }); 28 | 29 | const readFile = file => 30 | new Promise((resolve, reject) => { 31 | !file && 32 | reject({ 33 | success: false, 34 | error: new Error('File must be specified') 35 | }); 36 | fs.readFile(file, 'utf8', (error, fileData) => { 37 | error 38 | ? reject({ success: false, error }) 39 | : resolve({ success: true, data: { file: fileData } }); 40 | }); 41 | }); 42 | 43 | const writeFile = (file, data) => { 44 | new Promise((resolve, reject) => { 45 | !file && 46 | reject({ 47 | success: false, 48 | error: new Error('File must be specified') 49 | }); 50 | 51 | !data && 52 | reject({ 53 | success: false, 54 | error: new Error('Data must be specified') 55 | }); 56 | 57 | fs.writeFile(file, data, error => { 58 | error 59 | ? reject({ success: false, error }) 60 | : resolve({ 61 | success: true, 62 | data: { file } 63 | }); 64 | }); 65 | }); 66 | }; 67 | 68 | export default { 69 | checkExist, 70 | readDirectoryFiles, 71 | readFile, 72 | writeFile 73 | }; 74 | -------------------------------------------------------------------------------- /src/utilities/handlebar.js: -------------------------------------------------------------------------------- 1 | const hbs = require('handlebars'); 2 | const _ = require('lodash'); 3 | 4 | import { messageSettings } from '../settings'; 5 | 6 | hbs.registerHelper('removeAllSpaces', text => { 7 | return text.replace(/\s/g, ''); 8 | }); 9 | 10 | hbs.registerHelper('uppercase', text => { 11 | return text.toUpperCase(); 12 | }); 13 | 14 | hbs.registerHelper('lowercase', text => { 15 | return text.toLowerCase(); 16 | }); 17 | 18 | hbs.registerHelper('capitalize', text => { 19 | return `${text.charAt(0).toUpperCase()}${text.slice(1)}`; 20 | }); 21 | 22 | hbs.registerHelper('getYear', () => { 23 | return new Date().getFullYear(); 24 | }); 25 | 26 | const registerPartial = (name, partialTemplate) => { 27 | if (!name) throw new Error('Template name must be specified'); 28 | if (!partialTemplate) throw new Error('Partial data must be specified'); 29 | hbs.registerPartial(name, partialTemplate); 30 | }; 31 | 32 | const generateHandlebar = (wrapper, data, debug = false) => { 33 | for (let key of Object.keys(data)) { 34 | if ( 35 | (_.isObject(data[key]) || _.isArray(data[key])) && 36 | _.isEmpty(data[key]) 37 | ) { 38 | data[key] = null; 39 | } 40 | } 41 | const template = hbs.compile(wrapper); 42 | debug && messageSettings.debugMessage(data); 43 | return template(data); 44 | }; 45 | 46 | export default { 47 | registerPartial, 48 | generateHandlebar 49 | }; 50 | -------------------------------------------------------------------------------- /src/utilities/index.js: -------------------------------------------------------------------------------- 1 | export { default as dataUtils } from './data'; 2 | export { default as fileUtils } from './file'; 3 | export { default as hbsUtils } from './handlebar'; 4 | export { default as questionUtils } from './question'; 5 | export { default as systemUtils } from './system'; 6 | export { default as yamlUtils } from './yaml'; 7 | -------------------------------------------------------------------------------- /src/utilities/question.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | 3 | const injectQuestion = (question, bulkQuestions = []) => { 4 | let exist = false; 5 | 6 | if (_.isNil(question.name) || _.isEmpty(question.name)) 7 | throw new Error('Question name must be specified'); 8 | 9 | if (!_.isNil(bulkQuestions) && !_.isEmpty(bulkQuestions)) { 10 | bulkQuestions.map((existingQuestion, index) => { 11 | if (existingQuestion.name === question.name) { 12 | exist = true; 13 | bulkQuestions[index] = _.assign({}, existingQuestion, question); 14 | } 15 | }); 16 | } 17 | 18 | return exist ? bulkQuestions : [_.merge({}, question)]; 19 | }; 20 | 21 | export default { 22 | injectQuestion 23 | }; 24 | -------------------------------------------------------------------------------- /src/utilities/system.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fileUtils from './file'; 3 | import hbsUtils from './handlebar'; 4 | import yamlUtils from './yaml'; 5 | 6 | const registerHbsPartials = async partialsPath => { 7 | const { data } = await fileUtils.readDirectoryFiles(partialsPath); 8 | await data.files.forEach(async file => { 9 | const partialName = file.split('.')[0]; 10 | fileUtils.readFile(path.join(data.directory, file)).then(partialContent => { 11 | const { data } = partialContent; 12 | hbsUtils.registerPartial(partialName, data.file); 13 | }); 14 | }); 15 | }; 16 | 17 | const checkFormatters = async fileArray => { 18 | const formatters = []; 19 | await Promise.all( 20 | fileArray.map(async file => { 21 | await fileUtils 22 | .checkExist(file.path) 23 | .then(({ success }) => { 24 | success && formatters.push(file.name); 25 | }) 26 | .catch(() => null); 27 | }) 28 | ); 29 | 30 | return formatters; 31 | }; 32 | 33 | const checkSupports = async supportFile => { 34 | const supports = await yamlUtils.parseData( 35 | await fileUtils 36 | .readFile(supportFile) 37 | .then(({ success, data }) => { 38 | return success && data.file; 39 | }) 40 | .catch(() => null) 41 | ); 42 | return supports; 43 | }; 44 | 45 | export default { 46 | registerHbsPartials, 47 | checkFormatters, 48 | checkSupports 49 | }; 50 | -------------------------------------------------------------------------------- /src/utilities/yaml.js: -------------------------------------------------------------------------------- 1 | const yaml = require('js-yaml'); 2 | const _ = require('lodash'); 3 | 4 | const parseData = content => { 5 | return new Promise((resolve, reject) => { 6 | try { 7 | resolve(_.omitBy(yaml.safeLoad(content), _.isNil)); 8 | } catch (error) { 9 | reject(error); 10 | } 11 | }); 12 | }; 13 | 14 | export default { 15 | parseData 16 | }; 17 | -------------------------------------------------------------------------------- /test/settings/data.test.js: -------------------------------------------------------------------------------- 1 | import dataSettings from '../../src/settings/data'; 2 | 3 | const packagejsonFilterData = [ 4 | 'name', 5 | 'version', 6 | 'description', 7 | 'repository', 8 | 'author', 9 | 'engines', 10 | 'dependencies', 11 | 'contributors' 12 | ]; 13 | 14 | const fallbackQuestionData = [ 15 | { 16 | name: 'name', 17 | type: 'input', 18 | message: 'What is the name of the project?', 19 | default: 'Amazing title' 20 | }, 21 | { 22 | name: 'version', 23 | type: 'input', 24 | message: 'What is the version?', 25 | default: '0.1.0' 26 | }, 27 | { 28 | name: 'description', 29 | type: 'input', 30 | message: 'Describe your project' 31 | }, 32 | { 33 | name: 'repository.url', 34 | type: 'input', 35 | message: "Insert the url of your project's repository" 36 | }, 37 | { 38 | name: 'author.name', 39 | type: 'input', 40 | message: 'Insert the author name' 41 | } 42 | ]; 43 | 44 | test('check if packageJsonFilterData exists and is not empty', () => { 45 | expect(dataSettings.packageJsonFilterData).not.toBeNull(); 46 | expect(dataSettings.packageJsonFilterData).not.toBeUndefined(); 47 | expect(dataSettings.packageJsonFilterData.length).toBeGreaterThan(0); 48 | }); 49 | 50 | test('check if packageJsonFilterData contain all right values', () => { 51 | expect(dataSettings.packageJsonFilterData).toEqual( 52 | expect.arrayContaining(packagejsonFilterData) 53 | ); 54 | }); 55 | 56 | test('check if fallbackQuestionData exists and is not empty', () => { 57 | expect(dataSettings.fallbackQuestionData).not.toBeNull(); 58 | expect(dataSettings.fallbackQuestionData).not.toBeUndefined(); 59 | expect(dataSettings.fallbackQuestionData.length).toBeGreaterThan(0); 60 | }); 61 | 62 | test('check if fallbackQuestionData contain all right values', () => { 63 | expect(dataSettings.fallbackQuestionData).toEqual( 64 | expect.arrayContaining(fallbackQuestionData) 65 | ); 66 | }); 67 | -------------------------------------------------------------------------------- /test/settings/file.test.js: -------------------------------------------------------------------------------- 1 | import fileSettings from '../../src/settings/file'; 2 | 3 | test('check if fileSettings exists and is not empty', () => { 4 | expect(fileSettings).not.toBeNull(); 5 | expect(fileSettings).not.toBeUndefined(); 6 | expect(Object.keys(fileSettings).length).toBeGreaterThan(0); 7 | }); 8 | 9 | test('check if fileSettings has the right properties', () => { 10 | expect(fileSettings).toMatchObject({ 11 | package: { 12 | name: 'package', 13 | ext: 'json' 14 | }, 15 | template: { 16 | name: 'README', 17 | ext: 'hbs' 18 | }, 19 | readme: { 20 | name: 'README', 21 | ext: 'md' 22 | }, 23 | support: { 24 | name: 'FUNDING', 25 | ext: 'yml' 26 | }, 27 | formatters: [ 28 | { name: 'eslint', ext: 'rc' }, 29 | { name: 'jsbeautify', ext: 'rc' }, 30 | { name: 'editorconfig', ext: null }, 31 | { name: 'prettier', ext: 'rc' } 32 | ] 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/settings/message.test.js: -------------------------------------------------------------------------------- 1 | import messageSettings from '../../src/settings/message'; 2 | 3 | test('check if messageSettings exists and is not empty', () => { 4 | expect(messageSettings).not.toBeNull(); 5 | expect(messageSettings).not.toBeUndefined(); 6 | expect(Object.keys(messageSettings).length).toBeGreaterThan(0); 7 | }); 8 | -------------------------------------------------------------------------------- /test/settings/path.test.js: -------------------------------------------------------------------------------- 1 | import pathSettings from '../../src/settings/path'; 2 | import path from 'path'; 3 | 4 | test('check if pathSettings exists and is not empty', () => { 5 | expect(pathSettings).not.toBeNull(); 6 | expect(pathSettings).not.toBeUndefined(); 7 | expect(Object.keys(pathSettings).length).toBeGreaterThan(0); 8 | }); 9 | 10 | test('check if pathSettings has the right properties', () => { 11 | expect(pathSettings).toMatchObject({ 12 | root: process.cwd(), 13 | github: path.resolve(process.cwd(), '.github'), 14 | readme: { 15 | questions: 'readme/questions', 16 | templates: 'readme/templates', 17 | hbsPartials: 'readme/templates/partials' 18 | } 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/utilities/file.test.js: -------------------------------------------------------------------------------- 1 | import fileUtils from '../../src/utilities/file'; 2 | 3 | test('check if fileUtils exists and is not empty', () => { 4 | expect(fileUtils).not.toBeNull(); 5 | expect(fileUtils).not.toBeUndefined(); 6 | expect(Object.keys(fileUtils).length).toBeGreaterThan(0); 7 | }); 8 | 9 | // EXIST FILE TEST 10 | test('check if a file exist correctly', async () => { 11 | expect.assertions(1); 12 | const res = await fileUtils.checkExist('package.json'); 13 | expect(res.success).toBe(true); 14 | }); 15 | 16 | test('check if empty path throw error', async () => { 17 | expect.assertions(1); 18 | try { 19 | await fileUtils.checkExist(); 20 | } catch ({ error }) { 21 | expect(error).toEqual(new Error('Path must be specified')); 22 | } 23 | }); 24 | 25 | test('check if throw error with non-existing file', async () => { 26 | expect.assertions(1); 27 | try { 28 | await fileUtils.checkExist('test.json'); 29 | } catch ({ success }) { 30 | expect(success).toBe(false); 31 | } 32 | }); 33 | 34 | // READ DIRECTORY TEST 35 | test('check if get data from existing directory', async () => { 36 | expect.assertions(4); 37 | const res = await fileUtils.readDirectoryFiles('src/'); 38 | expect(res.success).toBe(true); 39 | expect(res.data).not.toBeNull(); 40 | expect(res.data).not.toBeUndefined(); 41 | expect(Object.keys(res.data).length).toBeGreaterThan(0); 42 | }); 43 | 44 | test('check if empty directory path throw error', async () => { 45 | expect.assertions(1); 46 | try { 47 | await fileUtils.readDirectoryFiles(); 48 | } catch ({ error }) { 49 | expect(error).toEqual(new Error('Directory must be specified')); 50 | } 51 | }); 52 | 53 | test('check if a non existing folder throw error', async () => { 54 | expect.assertions(1); 55 | try { 56 | await fileUtils.checkExist('fake/'); 57 | } catch ({ success }) { 58 | expect(success).toBe(false); 59 | } 60 | }); 61 | 62 | // READ FILE TEST 63 | test('check if can read data from existing file', async () => { 64 | expect.assertions(4); 65 | const res = await fileUtils.readFile('package.json'); 66 | expect(res.success).toBe(true); 67 | expect(res.data).not.toBeNull(); 68 | expect(res.data).not.toBeUndefined(); 69 | expect(Object.keys(res.data).length).toBeGreaterThan(0); 70 | }); 71 | 72 | test('check if empty file path throw error', async () => { 73 | expect.assertions(1); 74 | try { 75 | await fileUtils.readFile(); 76 | } catch ({ error }) { 77 | expect(error).toEqual(new Error('File must be specified')); 78 | } 79 | }); 80 | 81 | test('check if cannot read data from non existing file', async () => { 82 | expect.assertions(1); 83 | try { 84 | await fileUtils.readFile('test.json'); 85 | } catch ({ success }) { 86 | expect(success).toBe(false); 87 | } 88 | }); 89 | -------------------------------------------------------------------------------- /test/utilities/handlebar.test.js: -------------------------------------------------------------------------------- 1 | import hbsUtils from '../../src/utilities/handlebar'; 2 | 3 | test('check if fileUtils exists and is not empty', () => { 4 | expect(hbsUtils).not.toBeNull(); 5 | expect(hbsUtils).not.toBeUndefined(); 6 | expect(Object.keys(hbsUtils).length).toBeGreaterThan(0); 7 | }); 8 | 9 | test('should throw error if if try to register partial with missing name', async () => { 10 | expect.assertions(1); 11 | try { 12 | await hbsUtils.registerPartial(); 13 | } catch (error) { 14 | expect(error).toEqual(new Error('Template name must be specified')); 15 | } 16 | }); 17 | 18 | test('should throw error if try to register partial with missing template', async () => { 19 | expect.assertions(1); 20 | try { 21 | await hbsUtils.registerPartial( 22 | './src/readme/templates/partials/title.hbs' 23 | ); 24 | } catch (error) { 25 | expect(error).toEqual(new Error('Partial data must be specified')); 26 | } 27 | }); 28 | 29 | test('check if parse a handlebar template correctly', () => { 30 | const name = 'Maurizio'; 31 | const data = hbsUtils.generateHandlebar('{{name}}', { name }); 32 | expect(data).toEqual(name); 33 | }); 34 | -------------------------------------------------------------------------------- /test/utilities/question.test.js: -------------------------------------------------------------------------------- 1 | import questionUtils from '../../src/utilities/question'; 2 | 3 | test('check if fileUtils exists and is not empty', () => { 4 | expect(questionUtils).not.toBeNull(); 5 | expect(questionUtils).not.toBeUndefined(); 6 | expect(Object.keys(questionUtils).length).toBeGreaterThan(0); 7 | }); 8 | 9 | test('throw error if question name is missing', () => { 10 | const updateQuestion = { 11 | message: 'Test message' 12 | }; 13 | try { 14 | questionUtils.injectQuestion(updateQuestion); 15 | } catch (error) { 16 | expect(error).toEqual(new Error('Question name must be specified')); 17 | } 18 | }); 19 | 20 | test("check if update correctly the question's bulk", () => { 21 | const bulk = [ 22 | { 23 | name: 'commands.start', 24 | type: 'input', 25 | message: 'What is the command to run the project?', 26 | default: 'start' 27 | } 28 | ]; 29 | 30 | const updateQuestion = { 31 | name: 'commands.start', 32 | message: 'Test message' 33 | }; 34 | 35 | const data = questionUtils.injectQuestion(updateQuestion, bulk); 36 | expect(data[0]).toEqual({ 37 | name: 'commands.start', 38 | type: 'input', 39 | message: 'Test message', 40 | default: 'start' 41 | }); 42 | }); 43 | 44 | test("check if create correctly the question's bulk", () => { 45 | const createQuestion = { 46 | name: 'commands.start', 47 | type: 'input', 48 | message: 'What is the command to run the project?', 49 | default: 'start' 50 | }; 51 | 52 | const data = questionUtils.injectQuestion(createQuestion); 53 | expect(data[0]).toEqual(createQuestion); 54 | }); 55 | -------------------------------------------------------------------------------- /test/utilities/ststem.test.js: -------------------------------------------------------------------------------- 1 | import systemUtils from '../../src/utilities/system'; 2 | 3 | test('check if fileUtils exists and is not empty', () => { 4 | expect(systemUtils).not.toBeNull(); 5 | expect(systemUtils).not.toBeUndefined(); 6 | expect(Object.keys(systemUtils).length).toBeGreaterThan(0); 7 | }); 8 | -------------------------------------------------------------------------------- /test/utilities/yaml.test.js: -------------------------------------------------------------------------------- 1 | import ymlUtils from '../../src/utilities/yaml'; 2 | 3 | test('check if fileUtils exists and is not empty', () => { 4 | expect(ymlUtils).not.toBeNull(); 5 | expect(ymlUtils).not.toBeUndefined(); 6 | expect(Object.keys(ymlUtils).length).toBeGreaterThan(0); 7 | }); 8 | --------------------------------------------------------------------------------