├── .editorconfig
├── .gitignore
├── .idea
└── .gitignore
├── .nvmrc
├── .vscode
├── extensions.json
├── launch.json
└── tasks.json
├── LICENSE
├── README.md
├── angular.json
├── docs
├── devhunt_badge.png
├── dmp_1.png
├── dmp_s_1.png
├── dmp_s_2.png
├── dmp_s_3.png
├── dmp_s_4.png
└── icon.png
├── package-lock.json
├── package.json
├── src
├── app
│ ├── app-routing.module.ts
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── components
│ │ ├── background
│ │ │ ├── background.component.css
│ │ │ ├── background.component.html
│ │ │ ├── background.component.spec.ts
│ │ │ └── background.component.ts
│ │ ├── footer
│ │ │ ├── footer.component.css
│ │ │ ├── footer.component.html
│ │ │ ├── footer.component.spec.ts
│ │ │ └── footer.component.ts
│ │ ├── form-checkbox
│ │ │ ├── form-checkbox.component.css
│ │ │ ├── form-checkbox.component.html
│ │ │ ├── form-checkbox.component.spec.ts
│ │ │ └── form-checkbox.component.ts
│ │ ├── form-field
│ │ │ ├── form-field.component.css
│ │ │ ├── form-field.component.html
│ │ │ ├── form-field.component.spec.ts
│ │ │ └── form-field.component.ts
│ │ ├── form-radio
│ │ │ ├── form-radio.component.css
│ │ │ ├── form-radio.component.html
│ │ │ ├── form-radio.component.spec.ts
│ │ │ └── form-radio.component.ts
│ │ ├── form
│ │ │ ├── form.component.css
│ │ │ ├── form.component.html
│ │ │ ├── form.component.spec.ts
│ │ │ └── form.component.ts
│ │ ├── header
│ │ │ ├── header.component.css
│ │ │ ├── header.component.html
│ │ │ ├── header.component.spec.ts
│ │ │ └── header.component.ts
│ │ ├── markdown
│ │ │ ├── md-code-snippet
│ │ │ │ ├── md-code-snippet.component.css
│ │ │ │ ├── md-code-snippet.component.html
│ │ │ │ ├── md-code-snippet.component.spec.ts
│ │ │ │ └── md-code-snippet.component.ts
│ │ │ └── md-preview
│ │ │ │ ├── md-preview.component.css
│ │ │ │ ├── md-preview.component.html
│ │ │ │ ├── md-preview.component.spec.ts
│ │ │ │ └── md-preview.component.ts
│ │ ├── multi-field
│ │ │ ├── multi-field.component.css
│ │ │ ├── multi-field.component.html
│ │ │ ├── multi-field.component.spec.ts
│ │ │ └── multi-field.component.ts
│ │ ├── multi-picker
│ │ │ ├── multi-picker.component.css
│ │ │ ├── multi-picker.component.html
│ │ │ ├── multi-picker.component.spec.ts
│ │ │ └── multi-picker.component.ts
│ │ ├── raw-code-snippet
│ │ │ ├── raw-code-snippet.component.css
│ │ │ ├── raw-code-snippet.component.html
│ │ │ ├── raw-code-snippet.component.spec.ts
│ │ │ └── raw-code-snippet.component.ts
│ │ ├── repo
│ │ │ ├── repo.component.css
│ │ │ ├── repo.component.html
│ │ │ ├── repo.component.spec.ts
│ │ │ └── repo.component.ts
│ │ ├── section-title
│ │ │ ├── section-title.component.css
│ │ │ ├── section-title.component.html
│ │ │ ├── section-title.component.spec.ts
│ │ │ └── section-title.component.ts
│ │ └── svg-icon
│ │ │ ├── svg-icon.component.css
│ │ │ ├── svg-icon.component.html
│ │ │ ├── svg-icon.component.spec.ts
│ │ │ └── svg-icon.component.ts
│ ├── enums
│ │ └── license-type.enum.ts
│ ├── interfaces
│ │ ├── acknowledge-options.interface.ts
│ │ ├── author-data.interface.ts
│ │ ├── configuration-options.interface.ts
│ │ ├── contribution-options.interface.ts
│ │ ├── contributor-options.interface.ts
│ │ ├── feature-options.interface.ts
│ │ ├── github-options.interface.ts
│ │ ├── installation-options.interface.ts
│ │ ├── license-options.interface.ts
│ │ ├── npm-options.interface.ts
│ │ └── technology-options.interface.ts
│ ├── pipes
│ │ └── log.pipe.ts
│ ├── services
│ │ ├── markdown.service.ts
│ │ ├── toast.service.ts
│ │ └── utils.service.ts
│ ├── store
│ │ ├── actions
│ │ │ ├── action-types.ts
│ │ │ └── editor.actions.ts
│ │ ├── reducers
│ │ │ ├── editor.reducer.ts
│ │ │ └── index.ts
│ │ ├── selectors
│ │ │ └── editor.selectors.ts
│ │ └── state.interface.ts
│ └── toast
│ │ ├── toast.component.css
│ │ ├── toast.component.html
│ │ ├── toast.component.spec.ts
│ │ └── toast.component.ts
├── assets
│ ├── .gitkeep
│ ├── beams.jpg
│ ├── fonts
│ │ ├── IBM Plex Sans Regular.woff2
│ │ ├── PP Agrandir Bold.woff2
│ │ ├── PP Agrandir Regular.woff2
│ │ ├── TN Light.woff2
│ │ ├── TN Medium.woff2
│ │ ├── TN Regular.woff2
│ │ └── iA Writter Quattro S Regular.woff2
│ ├── github-markdown.css
│ ├── grid.svg
│ └── images
│ │ ├── devhunt_badge.png
│ │ ├── dmp_1.png
│ │ ├── dmp_2.png
│ │ ├── dmp_s_1.png
│ │ ├── dmp_s_2.png
│ │ ├── dmp_s_3.png
│ │ ├── dmp_s_4.png
│ │ ├── github_corner.png
│ │ └── icon.png
├── data
│ ├── mock.ts
│ ├── readme-demo.ts
│ ├── tech-services.ts
│ └── technologies.ts
├── favicon.ico
├── index.html
├── main.ts
└── styles.css
├── tailwind.config.js
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.ts]
12 | quote_type = single
13 |
14 | [*.md]
15 | max_line_length = off
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # Compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | /bazel-out
8 |
9 | # Node
10 | /node_modules
11 | npm-debug.log
12 | yarn-error.log
13 |
14 | # IDEs and editors
15 | .idea/
16 | .project
17 | .classpath
18 | .c9/
19 | *.launch
20 | .settings/
21 | *.sublime-workspace
22 |
23 | # Visual Studio Code
24 | .vscode/*
25 | !.vscode/settings.json
26 | !.vscode/tasks.json
27 | !.vscode/launch.json
28 | !.vscode/extensions.json
29 | .history/*
30 |
31 | # Miscellaneous
32 | /.angular/cache
33 | .sass-cache/
34 | /connect.lock
35 | /coverage
36 | /libpeerconnection.log
37 | testem.log
38 | /typings
39 |
40 | # System files
41 | .DS_Store
42 | Thumbs.db
43 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | v20.11.1
2 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
3 | "recommendations": ["angular.ng-template"]
4 | }
5 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
3 | "version": "0.2.0",
4 | "configurations": [
5 | {
6 | "name": "ng serve",
7 | "type": "chrome",
8 | "request": "launch",
9 | "preLaunchTask": "npm: start",
10 | "url": "http://localhost:4200/"
11 | },
12 | {
13 | "name": "ng test",
14 | "type": "chrome",
15 | "request": "launch",
16 | "preLaunchTask": "npm: test",
17 | "url": "http://localhost:9876/debug.html"
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
3 | "version": "2.0.0",
4 | "tasks": [
5 | {
6 | "type": "npm",
7 | "script": "start",
8 | "isBackground": true,
9 | "problemMatcher": {
10 | "owner": "typescript",
11 | "pattern": "$tsc",
12 | "background": {
13 | "activeOnStart": true,
14 | "beginsPattern": {
15 | "regexp": "(.*?)"
16 | },
17 | "endsPattern": {
18 | "regexp": "bundle generation complete"
19 | }
20 | }
21 | }
22 | },
23 | {
24 | "type": "npm",
25 | "script": "test",
26 | "isBackground": true,
27 | "problemMatcher": {
28 | "owner": "typescript",
29 | "pattern": "$tsc",
30 | "background": {
31 | "activeOnStart": true,
32 | "beginsPattern": {
33 | "regexp": "(.*?)"
34 | },
35 | "endsPattern": {
36 | "regexp": "bundle generation complete"
37 | }
38 | }
39 | }
40 | }
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Luis Ventura
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | # Document My Project
31 |
32 | Easily create markdown documentation for your project
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | ## ️Table of Contents
41 |
42 |
43 | Open Contents
44 |
45 | - [Document My Project](#document-my-project)
46 | - [ℹ️ About the Project](#-about-the-project)
47 | - [🏞 Showcase](#-showcase)
48 | - [⭐️ Features](#-features)
49 | - [🛠 Stack Tech](#-stack-tech)
50 | - [⚙ ️Setup](#-setup)
51 | - [Installation](#installation)
52 | - [Usage](#usage)
53 | - [🏆 Acknowledgements](#-acknowledgements)
54 | - [👏🏻 Contributing](#-contributing)
55 | - [Ways to Contribute](#ways-to-contribute)
56 | - [Contribution Instructions](#contribution-instructions)
57 | - [Contributors](#contributors)
58 | - [👨🏻 About the Author](#-about-the-author)
59 | - [📖 License](#-license)
60 |
61 |
62 |
63 | ## ℹ️ About the Project
64 |
65 | Tired of manually writing README files? this tool simplifies the process of creating documentation for Github projects.
66 | With just a few clicks, you can generate comprehensive documentation that enhances the visibility and usability of your
67 | repositories in seconds.
68 |
69 | ## 🏞 Showcase
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | ## ⭐️ Features
87 |
88 | 1. **Template ready**
89 |
90 | Provide a clear and concise description of your project, highlight the main features, goals, and benefits of your
91 | project
92 |
93 | 2. **Ease fo use**
94 |
95 | Easily generate a well-structured README file for your GitHub project
96 |
97 | 3. **Preview**
98 |
99 | Preview the generated README (light/dark theme) file before committing it to your repository
100 |
101 | ## 🛠 Stack Tech
102 |
103 | - [![Angular][Angular-badge]][Angular-url] - A front-end web application framework
104 |
105 | [Angular-badge]: https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular
106 |
107 | [Angular-url]: }
108 |
109 | - [![NgRx][NgRx-badge]][NgRx-url] - Angular state management based on Redux
110 |
111 | [NgRx-badge]: https://img.shields.io/badge/NgRx-B7116E?style=for-the-badge&logo=ngrx
112 |
113 | [NgRx-url]: }
114 |
115 | - [![Tailwind CSS][Tailwind CSS-badge]][Tailwind CSS-url] - Utility-first CSS framework
116 |
117 | [Tailwind CSS-badge]: https://img.shields.io/badge/Tailwind%20CSS-38B2AC?style=for-the-badge&logo=tailwindcss
118 |
119 | [Tailwind CSS-url]: }
120 |
121 | - [![TypeScript][TypeScript-badge]][TypeScript-url] - A strict syntactical superset of JavaScript
122 |
123 | [TypeScript-badge]: https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript
124 |
125 | [TypeScript-url]: }
126 |
127 | ## ⚙ ️Setup
128 |
129 | ### Installation
130 |
131 | To install this project, follow these steps:
132 |
133 | 1. Install Node.js v16 or later
134 |
135 | 2. Install the required dependencies:
136 |
137 | 3. `npm install`
138 |
139 | ### Usage
140 |
141 | After installation, you can use the project by following these steps:
142 |
143 | 1. Open the project directory in your code editor
144 |
145 | 2. Run `npm run start` to start the development server
146 |
147 | ## 🏆 Acknowledgements
148 |
149 | - [ngx-markdown](https://www.npmjs.com/package/ngx-markdown) - Angular markdown component/directive/pipe/service to
150 | parse static, dynamic or remote content to HTML with syntax highlight and more
151 | - [Flowbite](https://flowbite.com/) - Build websites even faster with components on top of Tailwind CSS
152 | - [PrismJs](https://prismjs.com/) - Prism is a lightweight, extensible syntax highlighter, built with modern web
153 | standards in mind. It’s used in millions of websites, including some of those you visit daily.
154 |
155 | ## 👏🏻 Contributing
156 |
157 | We welcome contributions from the community! If you would like to contribute to this project, please follow the
158 | guidelines below.
159 |
160 | ### Ways to Contribute
161 |
162 | - Report bugs or issues by opening a new issue on our GitHub repository.
163 | - Suggest new features or improvements by opening a new issue on our GitHub repository.
164 | - Contribute code by forking the repository, making changes, and submitting a pull request.
165 |
166 | ### Contribution Instructions
167 |
168 | 1. Fork the repository.
169 | 2. Create a new branch for your feature or bug fix: `git checkout -b my-feature-branch`.
170 | 3. Make the necessary changes and commit them: `git commit -am 'Add my new feature'`.
171 | 4. Push your branch to your forked repository: `git push origin my-feature-branch`.
172 | 5. Open a pull request against the main repository, describing the changes you made and why they should be merged.
173 |
174 | ### Contributors
175 |
176 | - Luis Ventura (@luisvent)
177 |
178 | ## 👨🏻 About the Author
179 |
180 | **Luis Ventura**
181 |
182 | This project was created by Luis Ventura. Connect with me on [GitHub](https://github.com/luisvent)
183 | and [LinkedIn](https://www.linkedin.com/in/luisvent/) to learn more about my projects and professional background.
184 |
185 | ## 📖 License
186 |
187 | This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
188 |
189 |
190 | Top ⬆️
191 |
192 | ---
193 |
194 |
195 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "document_my_project": {
7 | "projectType": "application",
8 | "schematics": {},
9 | "root": "",
10 | "sourceRoot": "src",
11 | "prefix": "app",
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 | "outputPath": "dist/document_my_project",
17 | "index": "src/index.html",
18 | "main": "src/main.ts",
19 | "polyfills": [
20 | "zone.js"
21 | ],
22 | "tsConfig": "tsconfig.app.json",
23 | "assets": [
24 | "src/favicon.ico",
25 | "src/assets"
26 | ],
27 | "styles": [
28 | "src/styles.css",
29 | "node_modules/prismjs/themes/prism-okaidia.css",
30 | "node_modules/prismjs/plugins/line-numbers/prism-line-numbers.css"
31 | ],
32 | "scripts": [
33 | "node_modules/marked/marked.min.js",
34 | "node_modules/prismjs/prism.js",
35 | "node_modules/prismjs/components/prism-css.min.js",
36 | "node_modules/prismjs/components/prism-json.min.js",
37 | "node_modules/prismjs/components/prism-shell-session.min.js",
38 | "node_modules/prismjs/components/prism-javascript.min.js",
39 | "node_modules/prismjs/components/prism-typescript.min.js",
40 | "node_modules/prismjs/plugins/line-numbers/prism-line-numbers.js"
41 | ]
42 | },
43 | "configurations": {
44 | "production": {
45 | "budgets": [
46 | {
47 | "type": "initial",
48 | "maximumWarning": "500kb",
49 | "maximumError": "1mb"
50 | },
51 | {
52 | "type": "anyComponentStyle",
53 | "maximumWarning": "2kb",
54 | "maximumError": "4kb"
55 | }
56 | ],
57 | "outputHashing": "all"
58 | },
59 | "development": {
60 | "buildOptimizer": false,
61 | "optimization": false,
62 | "vendorChunk": true,
63 | "extractLicenses": false,
64 | "sourceMap": true,
65 | "namedChunks": true
66 | }
67 | },
68 | "defaultConfiguration": "production"
69 | },
70 | "serve": {
71 | "builder": "@angular-devkit/build-angular:dev-server",
72 | "configurations": {
73 | "production": {
74 | "browserTarget": "document_my_project:build:production"
75 | },
76 | "development": {
77 | "browserTarget": "document_my_project:build:development"
78 | }
79 | },
80 | "defaultConfiguration": "development"
81 | },
82 | "extract-i18n": {
83 | "builder": "@angular-devkit/build-angular:extract-i18n",
84 | "options": {
85 | "browserTarget": "document_my_project:build"
86 | }
87 | },
88 | "test": {
89 | "builder": "@angular-devkit/build-angular:karma",
90 | "options": {
91 | "polyfills": [
92 | "zone.js",
93 | "zone.js/testing"
94 | ],
95 | "tsConfig": "tsconfig.spec.json",
96 | "assets": [
97 | "src/favicon.ico",
98 | "src/assets"
99 | ],
100 | "styles": [
101 | "src/styles.css"
102 | ],
103 | "scripts": []
104 | }
105 | }
106 | }
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/docs/devhunt_badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/docs/devhunt_badge.png
--------------------------------------------------------------------------------
/docs/dmp_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/docs/dmp_1.png
--------------------------------------------------------------------------------
/docs/dmp_s_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/docs/dmp_s_1.png
--------------------------------------------------------------------------------
/docs/dmp_s_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/docs/dmp_s_2.png
--------------------------------------------------------------------------------
/docs/dmp_s_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/docs/dmp_s_3.png
--------------------------------------------------------------------------------
/docs/dmp_s_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/docs/dmp_s_4.png
--------------------------------------------------------------------------------
/docs/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/docs/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "document-my-project",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "watch": "ng build --watch --configuration development",
9 | "test": "ng test"
10 | },
11 | "private": true,
12 | "dependencies": {
13 | "@angular/animations": "^15.2.0",
14 | "@angular/common": "^15.2.0",
15 | "@angular/compiler": "^15.2.0",
16 | "@angular/core": "^15.2.0",
17 | "@angular/forms": "^15.2.0",
18 | "@angular/platform-browser": "^15.2.0",
19 | "@angular/platform-browser-dynamic": "^15.2.0",
20 | "@angular/router": "^15.2.0",
21 | "@ngrx/store": "^15.4.0",
22 | "@ngrx/effects": "^15.4.0",
23 | "@ngrx/store-devtools": "^15.4.0",
24 | "flowbite": "^2.3.0",
25 | "marked": "^4.0.17",
26 | "ngx-markdown": "^15.1.2",
27 | "prismjs": "^1.29.0",
28 | "rxjs": "~7.8.0",
29 | "tslib": "^2.3.0",
30 | "zone.js": "~0.12.0"
31 | },
32 | "devDependencies": {
33 | "@angular-devkit/build-angular": "^15.2.11",
34 | "@angular/cli": "~15.2.11",
35 | "@angular/compiler-cli": "^15.2.0",
36 | "@tailwindcss/typography": "^0.5.12",
37 | "@types/jasmine": "~4.3.0",
38 | "@types/prismjs": "^1.26.3",
39 | "autoprefixer": "^10.4.19",
40 | "jasmine-core": "~4.5.0",
41 | "karma": "~6.4.0",
42 | "karma-chrome-launcher": "~3.1.0",
43 | "karma-coverage": "~2.2.0",
44 | "karma-jasmine": "~5.1.0",
45 | "karma-jasmine-html-reporter": "~2.0.0",
46 | "postcss": "^8.4.38",
47 | "tailwindcss": "^3.4.3",
48 | "typescript": "~4.9.4"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 |
4 | const routes: Routes = [];
5 |
6 | @NgModule({
7 | imports: [RouterModule.forRoot(routes)],
8 | exports: [RouterModule]
9 | })
10 | export class AppRoutingModule { }
11 |
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/app.component.css
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { RouterTestingModule } from '@angular/router/testing';
3 | import { AppComponent } from './app.component';
4 |
5 | describe('AppComponent', () => {
6 | beforeEach(async () => {
7 | await TestBed.configureTestingModule({
8 | imports: [
9 | RouterTestingModule
10 | ],
11 | declarations: [
12 | AppComponent
13 | ],
14 | }).compileComponents();
15 | });
16 |
17 | it('should create the app', () => {
18 | const fixture = TestBed.createComponent(AppComponent);
19 | const app = fixture.componentInstance;
20 | expect(app).toBeTruthy();
21 | });
22 |
23 | it(`should have as title 'document_my_project'`, () => {
24 | const fixture = TestBed.createComponent(AppComponent);
25 | const app = fixture.componentInstance;
26 | expect(app.title).toEqual('document_my_project');
27 | });
28 |
29 | it('should render title', () => {
30 | const fixture = TestBed.createComponent(AppComponent);
31 | fixture.detectChanges();
32 | const compiled = fixture.nativeElement as HTMLElement;
33 | expect(compiled.querySelector('.content span')?.textContent).toContain('document_my_project app is running!');
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {Store} from "@ngrx/store";
3 | import {selectGeneratedMarkdown} from "./store/selectors/editor.selectors";
4 | import {AppState} from "./store/state.interface";
5 | import {initFlowbite} from "flowbite";
6 | import {MarkdownService} from "./services/markdown.service";
7 | import {ToastService} from "./services/toast.service";
8 | import {Actions} from "./store/actions/action-types";
9 | import {testData} from "../data/mock";
10 |
11 | @Component({
12 | selector: 'app-root',
13 | templateUrl: './app.component.html',
14 | styleUrls: ['./app.component.css']
15 | })
16 | export class AppComponent implements OnInit {
17 |
18 | public generatedMarkdown$ = this.store.select(selectGeneratedMarkdown);
19 |
20 | constructor(private store: Store, private mdService: MarkdownService,
21 | public toastService: ToastService) {
22 | }
23 |
24 | ngOnInit(): void {
25 | initFlowbite();
26 | // this.markdownData = this.mdService.test();
27 | }
28 |
29 | GenerateMarkdown() {
30 | this.store.dispatch(Actions.generateMarkdown({generate: true}));
31 | window.scroll(0, 0);
32 | }
33 |
34 |
35 | LoadSample() {
36 | this.store.dispatch(Actions.setData({data: testData}));
37 | this.GenerateMarkdown();
38 | this.toastService.success('Sample data loaded');
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import {NgModule} from '@angular/core';
2 | import {BrowserModule} from '@angular/platform-browser';
3 | import {AppRoutingModule} from './app-routing.module';
4 | import {AppComponent} from './app.component';
5 | import {StoreModule} from '@ngrx/store';
6 | import {StoreDevtoolsModule} from "@ngrx/store-devtools";
7 | import {reducers} from "./store/reducers";
8 | import {MarkdownModule} from "ngx-markdown";
9 | import {BackgroundComponent} from './components/background/background.component';
10 | import {FormsModule, ReactiveFormsModule} from "@angular/forms";
11 | import {ToastComponent} from './toast/toast.component';
12 | import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
13 | import {MdPreviewComponent} from "./components/markdown/md-preview/md-preview.component";
14 | import {MultiPickerComponent} from "./components/multi-picker/multi-picker.component";
15 | import {RawCodeSnippetComponent} from "./components/raw-code-snippet/raw-code-snippet.component";
16 | import {MdCodeSnippetComponent} from "./components/markdown/md-code-snippet/md-code-snippet.component";
17 | import {FormComponent} from './components/form/form.component';
18 | import {FormCheckboxComponent} from './components/form-checkbox/form-checkbox.component';
19 | import {FormFieldComponent} from './components/form-field/form-field.component';
20 | import {SectionTitleComponent} from './components/section-title/section-title.component';
21 | import {FormRadioComponent} from './components/form-radio/form-radio.component';
22 | import {MultiFieldComponent} from './components/multi-field/multi-field.component';
23 | import {LogPipe} from "./pipes/log.pipe";
24 | import {SvgIconComponent} from './components/svg-icon/svg-icon.component';
25 | import {HeaderComponent} from './components/header/header.component';
26 | import {FooterComponent} from './components/footer/footer.component';
27 | import {RepoComponent} from './components/repo/repo.component';
28 |
29 | @NgModule({
30 | declarations: [
31 | AppComponent,
32 | MdPreviewComponent,
33 | BackgroundComponent,
34 | MultiPickerComponent,
35 | RawCodeSnippetComponent,
36 | MdCodeSnippetComponent,
37 | ToastComponent,
38 | FormComponent,
39 | FormCheckboxComponent,
40 | FormFieldComponent,
41 | SectionTitleComponent,
42 | FormRadioComponent,
43 | MultiFieldComponent,
44 | LogPipe,
45 | SvgIconComponent,
46 | HeaderComponent,
47 | FooterComponent,
48 | RepoComponent
49 | ],
50 | imports: [
51 | BrowserModule,
52 | AppRoutingModule,
53 | StoreModule.forRoot(reducers),
54 | StoreDevtoolsModule.instrument({
55 | maxAge: 25,
56 | logOnly: false,
57 | }),
58 | MarkdownModule.forRoot(),
59 | ReactiveFormsModule,
60 | BrowserAnimationsModule,
61 | FormsModule
62 | ],
63 | providers: [],
64 | bootstrap: [AppComponent]
65 | })
66 | export class AppModule {
67 | }
68 |
--------------------------------------------------------------------------------
/src/app/components/background/background.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/background/background.component.css
--------------------------------------------------------------------------------
/src/app/components/background/background.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/app/components/background/background.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { BackgroundComponent } from './background.component';
4 |
5 | describe('BackgroundComponent', () => {
6 | let component: BackgroundComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ BackgroundComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(BackgroundComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/background/background.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-background',
5 | templateUrl: './background.component.html',
6 | styleUrls: ['./background.component.css'],
7 | changeDetection: ChangeDetectionStrategy.OnPush
8 | })
9 | export class BackgroundComponent {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/components/footer/footer.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/footer/footer.component.css
--------------------------------------------------------------------------------
/src/app/components/footer/footer.component.html:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/app/components/footer/footer.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { FooterComponent } from './footer.component';
4 |
5 | describe('FooterComponent', () => {
6 | let component: FooterComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ FooterComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(FooterComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/footer/footer.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-footer',
5 | templateUrl: './footer.component.html',
6 | styleUrls: ['./footer.component.css']
7 | })
8 | export class FooterComponent {
9 |
10 | OpenProjectRepo() {
11 | window.open('https://github.com/luisvent/document_my_project', '_blank');
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/components/form-checkbox/form-checkbox.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/form-checkbox/form-checkbox.component.css
--------------------------------------------------------------------------------
/src/app/components/form-checkbox/form-checkbox.component.html:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/src/app/components/form-checkbox/form-checkbox.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { FormCheckboxComponent } from './form-checkbox.component';
4 |
5 | describe('FormCheckboxComponent', () => {
6 | let component: FormCheckboxComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ FormCheckboxComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(FormCheckboxComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/form-checkbox/form-checkbox.component.ts:
--------------------------------------------------------------------------------
1 | import {AfterViewInit, ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';
2 | import {UtilsService} from "../../services/utils.service";
3 |
4 | @Component({
5 | selector: 'app-form-checkbox',
6 | templateUrl: './form-checkbox.component.html',
7 | styleUrls: ['./form-checkbox.component.css'],
8 | changeDetection: ChangeDetectionStrategy.OnPush
9 | })
10 | export class FormCheckboxComponent implements AfterViewInit {
11 |
12 | @Input()
13 | disabled = false;
14 |
15 | @Input()
16 | toggle = true;
17 |
18 | @Input()
19 | title = '';
20 |
21 | @Output()
22 | change = new EventEmitter();
23 |
24 | @Input()
25 | value: boolean | undefined | null = false;
26 |
27 | id = '';
28 |
29 | constructor(private utilsService: UtilsService) {
30 | this.id = `checkbox-${this.utilsService.guid()}`;
31 | }
32 |
33 | ngAfterViewInit(): void {
34 | if (this.value) {
35 | const toggleInput = document.querySelector(`#${this.id}`);
36 | toggleInput?.dispatchEvent(new Event('change', {bubbles: true}))
37 | }
38 | }
39 |
40 | checkboxChange(e: Event) {
41 | this.value = (e.target as HTMLInputElement).checked;
42 | e.stopPropagation();
43 | e.preventDefault();
44 | this.change.emit(e);
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/app/components/form-field/form-field.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/form-field/form-field.component.css
--------------------------------------------------------------------------------
/src/app/components/form-field/form-field.component.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
16 |
17 |
--------------------------------------------------------------------------------
/src/app/components/form-field/form-field.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {ComponentFixture, TestBed} from '@angular/core/testing';
2 |
3 | import {FormFieldComponent} from './form-field.component';
4 |
5 | describe('FormInputComponent', () => {
6 | let component: FormFieldComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [FormFieldComponent]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(FormFieldComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/form-field/form-field.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-form-field',
5 | templateUrl: './form-field.component.html',
6 | styleUrls: ['./form-field.component.css'],
7 | changeDetection: ChangeDetectionStrategy.OnPush
8 | })
9 | export class FormFieldComponent {
10 | @Input()
11 | disabled = false;
12 |
13 | @Input()
14 | placeholder = '';
15 |
16 | @Input()
17 | textarea = false;
18 |
19 | @Output()
20 | change = new EventEmitter();
21 |
22 | @Input() value: string | null | undefined = '';
23 | @Output() valueChange = new EventEmitter();
24 |
25 | constructor() {
26 | }
27 |
28 | inputChange(e: Event) {
29 | e.stopPropagation();
30 | e.preventDefault();
31 |
32 | this.change.emit(e);
33 | this.valueChange.emit((e.target as HTMLInputElement).value);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/app/components/form-radio/form-radio.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/form-radio/form-radio.component.css
--------------------------------------------------------------------------------
/src/app/components/form-radio/form-radio.component.html:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/src/app/components/form-radio/form-radio.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { FormRadioComponent } from './form-radio.component';
4 |
5 | describe('FormRadioComponent', () => {
6 | let component: FormRadioComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ FormRadioComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(FormRadioComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/form-radio/form-radio.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-form-radio',
5 | templateUrl: './form-radio.component.html',
6 | styleUrls: ['./form-radio.component.css'],
7 | changeDetection: ChangeDetectionStrategy.OnPush
8 | })
9 | export class FormRadioComponent {
10 |
11 | @Input()
12 | options: { name: string; value: string; }[] = [];
13 |
14 | @Output()
15 | change = new EventEmitter();
16 |
17 | @Input()
18 | value: string | undefined = '';
19 |
20 | constructor() {
21 | }
22 |
23 | radioChange(e: Event) {
24 | this.value = (e.target as HTMLInputElement).value;
25 | e.stopPropagation();
26 | e.preventDefault();
27 | this.change.emit(e);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/components/form/form.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/form/form.component.css
--------------------------------------------------------------------------------
/src/app/components/form/form.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Information about your project
4 |
5 |
13 |
14 |
15 |
Short Description
16 |
22 |
23 |
24 |
25 |
Description
26 |
32 |
33 |
34 |
35 |
Documentation navigation
36 |
37 |
42 |
43 |
48 |
49 |
50 |
55 |
56 |
57 |
Source code information
58 |
59 |
60 |
Repository
61 |
67 |
68 |
69 |
76 |
77 |
78 |
NPM Package
79 |
85 |
86 |
87 |
94 |
95 |
96 |
Project showcase
97 |
98 |
99 |
Logo Url
100 |
105 |
106 |
107 |
108 |
Main Image
109 |
114 |
115 |
116 |
117 |
Screenshots Url
118 |
124 |
125 |
126 |
127 |
128 |
129 |
0"
134 | >
135 |
136 |
146 |
147 |
148 |
Add instructions to run the project...
149 |
150 |
Installation
151 |
157 |
158 |
Usage
159 |
165 |
166 |
Parameters
167 |
172 |
173 |
174 |
179 |
180 |
181 |
Who helped build the project
182 |
183 |
196 |
197 |
198 |
Add Contributors
199 |
205 |
206 |
212 |
213 |
214 |
215 |
Who is the author
216 |
217 |
218 |
Name
219 |
224 |
225 |
226 |
227 |
235 |
236 |
237 |
LinkedIn
238 |
243 |
244 |
245 |
246 |
Add your project license
247 |
248 |
254 |
255 |
262 |
263 |
269 |
270 |
271 |
Optional configuration for your readme file
272 |
273 |
279 |
280 |
286 |
287 |
288 |
294 |
296 |
299 |
300 | Generate
301 |
302 |
303 |
--------------------------------------------------------------------------------
/src/app/components/form/form.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { FormComponent } from './form.component';
4 |
5 | describe('FormComponent', () => {
6 | let component: FormComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ FormComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(FormComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/form/form.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, EventEmitter, OnInit, Output} from '@angular/core';
2 | import {technologies} from "../../../data/technologies";
3 | import {PickerItem} from "../multi-picker/multi-picker.component";
4 | import {Actions} from "../../store/actions/action-types";
5 | import {Store} from "@ngrx/store";
6 | import {AppState} from "../../store/state.interface";
7 | import {MarkdownService} from "../../services/markdown.service";
8 | import {debounceTime, distinctUntilChanged, Observable, Subject} from "rxjs";
9 | import {LicenseType} from "../../enums/license-type.enum";
10 | import {
11 | editorSelector,
12 | selectAcknowledgment,
13 | selectAuthorGithubUsername,
14 | selectAuthorLinkedinUsername,
15 | selectAuthorName,
16 | selectBackToTop,
17 | selectContentTable,
18 | selectContribution,
19 | selectContributors,
20 | selectDescription,
21 | selectFeatures,
22 | selectGeneratingMarkdown,
23 | selectInstallSteps,
24 | selectLicense,
25 | selectLogo,
26 | selectMainImage,
27 | selectNavigationLinks,
28 | selectNpmBadges,
29 | selectNpmPackage,
30 | selectParameters,
31 | selectRepository,
32 | selectRepositoryBadges,
33 | selectScreenshots,
34 | selectSectionIcons,
35 | selectShortDescription,
36 | selectStackTech,
37 | selectTitle,
38 | selectUsageSteps
39 | } from "../../store/selectors/editor.selectors";
40 | import {EditorState} from "../../store/reducers/editor.reducer";
41 | import {LicenseOptions} from "../../interfaces/license-options.interface";
42 | import {ContributorOptions} from "../../interfaces/contributor-options.interface";
43 | import {ContributionOptions} from "../../interfaces/contribution-options.interface";
44 | import {AcknowledgeOptions} from "../../interfaces/acknowledge-options.interface";
45 | import {FeatureOptions} from "../../interfaces/feature-options.interface";
46 |
47 | interface InputInteraction {
48 | type: string;
49 | value: any;
50 | }
51 |
52 | @Component({
53 | selector: 'app-form',
54 | templateUrl: './form.component.html',
55 | styleUrls: ['./form.component.css']
56 | })
57 | export class FormComponent implements OnInit {
58 | @Output()
59 | generateMarkdown = new EventEmitter();
60 |
61 | technologies = technologies;
62 | licenses: { name: string; value: string }[] = [];
63 | public debounceInput$ = new Subject();
64 | public generating$ = this.store.select(selectGeneratingMarkdown);
65 | public state$ = this.store.select(editorSelector);
66 |
67 | public title$: Observable = this.store.select(selectTitle);
68 | public description$: Observable = this.store.select(selectDescription);
69 | public shortDescription$: Observable = this.store.select(selectShortDescription);
70 | public contentTable$: Observable = this.store.select(selectContentTable);
71 | public navigationLinks$: Observable = this.store.select(selectNavigationLinks);
72 | public features$: Observable = this.store.select(selectFeatures);
73 | public repository$: Observable = this.store.select(selectRepository);
74 | public repositoryBadges$: Observable = this.store.select(selectRepositoryBadges);
75 | public npmUrl$: Observable = this.store.select(selectNpmPackage);
76 | public npmBadges$: Observable = this.store.select(selectNpmBadges);
77 | public backToTop$: Observable = this.store.select(selectBackToTop);
78 | public sectionIcons$: Observable = this.store.select(selectSectionIcons);
79 | public logo$: Observable = this.store.select(selectLogo);
80 | public mainImage$: Observable = this.store.select(selectMainImage);
81 | public screenshots$: Observable = this.store.select(selectScreenshots);
82 | public stack$: Observable = this.store.select(selectStackTech);
83 | public installSteps$: Observable = this.store.select(selectInstallSteps);
84 | public usageSteps$: Observable = this.store.select(selectUsageSteps);
85 | public parameters$: Observable<{
86 | field: string,
87 | description: string,
88 | default?: string | undefined
89 | }[]> = this.store.select(selectParameters);
90 | public acknowledgements$: Observable = this.store.select(selectAcknowledgment);
91 | public contribution$: Observable = this.store.select(selectContribution);
92 | public contributors$: Observable = this.store.select(selectContributors);
93 | public authorName$: Observable = this.store.select(selectAuthorName);
94 | public githubUsername$: Observable = this.store.select(selectAuthorGithubUsername);
95 | public linkedinUsername$: Observable = this.store.select(selectAuthorLinkedinUsername);
96 | public license$: Observable = this.store.select(selectLicense);
97 | protected readonly LicenseType = LicenseType;
98 |
99 | constructor(private store: Store, private mdService: MarkdownService) {
100 | this.getLicenses();
101 | }
102 |
103 | ngOnInit(): void {
104 | this.debounceInput$.pipe(
105 | debounceTime(500),
106 | distinctUntilChanged()).subscribe(input => {
107 | this.processInput(input);
108 | })
109 |
110 | this.state$.subscribe(state => {
111 | console.log(state)
112 | if (state.generateMarkdown) {
113 | console.log(state)
114 | this.BuildMarkdown(state);
115 | }
116 | })
117 | }
118 |
119 |
120 | BuildMarkdown(state: EditorState) {
121 | const markdown = this.mdService.Build(state);
122 | console.log(markdown)
123 | this.store.dispatch(Actions.markdownGenerated({markdown}));
124 | }
125 |
126 | selectedTechnologies(technologies: PickerItem[]) {
127 | this.processInput({type: 'technologies', value: technologies})
128 | }
129 |
130 | getLicenses() {
131 | this.licenses = Object.keys(LicenseType).map(key => {
132 | return {
133 | name: LicenseType[key as keyof typeof LicenseType], value: key
134 | }
135 | })
136 | }
137 |
138 | generate() {
139 | this.generateMarkdown.emit();
140 | }
141 |
142 | inputChange(type: string, target: EventTarget | null | boolean) {
143 | console.log('input change')
144 | this.debounceInput$.next({
145 | type,
146 | value: (target as any).type === 'checkbox' ? (target as HTMLInputElement).checked : (target as HTMLInputElement).value
147 | });
148 | }
149 |
150 | processInput(input: InputInteraction) {
151 | console.log(input)
152 | switch (input.type) {
153 |
154 | case 'title':
155 | this.store.dispatch(Actions.modifyTitle({title: input.value}));
156 | break;
157 | case 'short-description':
158 | this.store.dispatch(Actions.modifyShortDescription({shortDescription: input.value}));
159 | break;
160 | case 'description':
161 | this.store.dispatch(Actions.modifyDescription({description: input.value}));
162 | break;
163 |
164 | case 'content-table':
165 | this.store.dispatch(Actions.modifyContentTable({contentTable: input.value}));
166 | break;
167 |
168 | case 'navigation-links':
169 | this.store.dispatch(Actions.modifyNavigation({navigation: input.value}));
170 | break;
171 |
172 | case 'section-icons':
173 | this.store.dispatch(Actions.toggleSectionIcons({sectionIcons: input.value}));
174 | break;
175 |
176 | case 'back-to-top':
177 | this.store.dispatch(Actions.toggleBackToTop({backToTop: input.value}));
178 | break;
179 |
180 | case 'features':
181 | const features: any[] = [];
182 |
183 | (input.value as any[]).forEach(acknowledge => {
184 | features.push({title: acknowledge[0], description: acknowledge[1]});
185 | })
186 |
187 | this.store.dispatch(Actions.modifyFeatures({features: features}));
188 | break;
189 |
190 | case 'installation':
191 | this.store.dispatch(Actions.modifyInstallation({steps: input.value}));
192 | break;
193 |
194 | case 'usage':
195 | this.store.dispatch(Actions.modifyUsage({steps: input.value}));
196 | break;
197 |
198 | case 'repository-url':
199 | this.store.dispatch(Actions.modifyGithubUrl({url: input.value}));
200 | break;
201 |
202 | case 'repository-badges':
203 | this.store.dispatch(Actions.modifyGithubBadge({badge: input.value}));
204 | break;
205 |
206 | case 'npm-url':
207 | this.store.dispatch(Actions.modifyNpmUrl({url: input.value}));
208 | break;
209 |
210 | case 'npm-badges':
211 | this.store.dispatch(Actions.modifyNpmBadge({badge: input.value}));
212 | break;
213 |
214 | case 'logo-url':
215 | this.store.dispatch(Actions.modifyLogoUrl({logoUrl: input.value}));
216 | break;
217 |
218 | case 'main-img-url':
219 | this.store.dispatch(Actions.modifyMainImageUrl({mainImageUrl: input.value.replaceAll(' ', '')}));
220 | break;
221 |
222 | case 'screenshots-url':
223 | this.store.dispatch(Actions.modifyImages({images: input.value.replaceAll(' ', '').split(/[,\n]/)}));
224 | break;
225 |
226 | case 'technologies':
227 | this.store.dispatch(Actions.addTechnologies({technologies: [...input.value]}));
228 | break;
229 |
230 | case 'tech-stack':
231 | if (!input.value) {
232 | this.store.dispatch(Actions.removeTechnology());
233 | }
234 | break;
235 |
236 | case 'acknowledge':
237 |
238 | const acknowledgements: any[] = [];
239 |
240 | (input.value as any[]).forEach(acknowledge => {
241 | acknowledgements.push({title: acknowledge[0], url: acknowledge[1], description: acknowledge[2]});
242 | })
243 |
244 | this.store.dispatch(Actions.modifyAcknowledgement({acknowledgements: acknowledgements}));
245 | break;
246 |
247 | case 'contribution':
248 | this.store.dispatch(Actions.modifyContribution({contribution: input.value}));
249 | break;
250 |
251 | case 'contributors-img':
252 | this.store.dispatch(Actions.toggleContributorsImg({contributorsImg: input.value}));
253 | break;
254 |
255 | case 'contribution-guideline':
256 | this.store.dispatch(Actions.modifyContributionGuideline({contributionGuidelinesLink: input.value}));
257 | break;
258 |
259 | case 'author-name':
260 | this.store.dispatch(Actions.modifyAuthorName({authorName: input.value}));
261 | break;
262 |
263 | case 'author-github':
264 | this.store.dispatch(Actions.modifyAuthorGithub({authorGithub: input.value}));
265 | break;
266 |
267 | case 'license':
268 | if (!input.value) {
269 | this.store.dispatch(Actions.removeLicense());
270 | }
271 | break;
272 |
273 | case 'licenseType':
274 | this.store.dispatch(Actions.addLicense({license: {type: input.value}}));
275 | break;
276 |
277 | case 'custom-license':
278 | this.store.dispatch(Actions.modifyCustomLicense({customText: input.value}));
279 | break;
280 |
281 | }
282 | }
283 |
284 | }
285 |
--------------------------------------------------------------------------------
/src/app/components/header/header.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/header/header.component.css
--------------------------------------------------------------------------------
/src/app/components/header/header.component.html:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/src/app/components/header/header.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { HeaderComponent } from './header.component';
4 |
5 | describe('HeaderComponent', () => {
6 | let component: HeaderComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ HeaderComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(HeaderComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/header/header.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, EventEmitter, Output} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-header',
5 | templateUrl: './header.component.html',
6 | styleUrls: ['./header.component.css'],
7 | changeDetection: ChangeDetectionStrategy.OnPush
8 | })
9 | export class HeaderComponent {
10 |
11 | @Output()
12 | loadData = new EventEmitter();
13 |
14 | LoadData() {
15 | this.loadData.emit();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/components/markdown/md-code-snippet/md-code-snippet.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/markdown/md-code-snippet/md-code-snippet.component.css
--------------------------------------------------------------------------------
/src/app/components/markdown/md-code-snippet/md-code-snippet.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
20 |
21 |
23 | Toggle full view
24 |
26 |
29 |
30 |
31 |
32 |
41 |
42 |
44 | Toggle tablet view
45 |
47 |
50 |
51 |
52 |
53 |
62 |
63 |
65 | Toggle mobile view
66 |
68 |
71 |
72 |
73 |
74 |
83 |
84 |
85 |
86 |
91 |
93 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
108 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
124 |
125 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
149 | Raw
150 |
151 |
152 |
153 |
154 |
158 | Preview
159 |
160 |
161 |
162 |
163 |
164 |
169 |
171 |
172 |
173 |
174 | Copy
175 |
176 |
177 |
186 |
187 |
188 |
189 |
192 |
194 | {{ text }}
195 |
196 |
197 |
198 |
199 |
--------------------------------------------------------------------------------
/src/app/components/markdown/md-code-snippet/md-code-snippet.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { MdCodeSnippetComponent } from './md-code-snippet.component';
4 |
5 | describe('MdCodeSnippetComponent', () => {
6 | let component: MdCodeSnippetComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ MdCodeSnippetComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(MdCodeSnippetComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/markdown/md-code-snippet/md-code-snippet.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, EventEmitter, Input, Output} from '@angular/core';
2 | import {UtilsService} from "../../../services/utils.service";
3 | import {ToastService} from "../../../services/toast.service";
4 |
5 | @Component({
6 | selector: 'app-md-code-snippet',
7 | templateUrl: './md-code-snippet.component.html',
8 | styleUrls: ['./md-code-snippet.component.css']
9 | })
10 | export class MdCodeSnippetComponent {
11 | @Input()
12 | text: string = ''
13 |
14 | @Output()
15 | updateFileGenerated = new EventEmitter();
16 |
17 | tabEnabled: 'preview' | 'raw' = 'preview';
18 | theme: 'dark' | 'light' = 'light';
19 |
20 | constructor(private utilsService: UtilsService, private toastService: ToastService) {
21 | }
22 |
23 | switchTab(tab: 'preview' | 'raw') {
24 | this.tabEnabled = tab;
25 | }
26 |
27 | copyCode() {
28 | this.utilsService.copyToClipboard(this.text);
29 | this.toastService.success('Copied!');
30 | }
31 |
32 | switchTheme() {
33 | this.theme = this.theme === 'dark' ? 'light' : 'dark';
34 | }
35 |
36 | downloadReadme() {
37 | this.utilsService.saveTextAsFile(this.text);
38 | this.toastService.success('File Downloaded!');
39 | }
40 |
41 | updateFileRequest() {
42 | this.updateFileGenerated.emit();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/app/components/markdown/md-preview/md-preview.component.css:
--------------------------------------------------------------------------------
1 | img {
2 | margin: 0 !important;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/components/markdown/md-preview/md-preview.component.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/app/components/markdown/md-preview/md-preview.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { MdPreviewComponent } from './md-preview.component';
4 |
5 | describe('MdPreviewComponent', () => {
6 | let component: MdPreviewComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ MdPreviewComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(MdPreviewComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/markdown/md-preview/md-preview.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, EventEmitter, Input, Output} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-md-preview',
5 | templateUrl: './md-preview.component.html',
6 | styleUrls: ['./md-preview.component.css']
7 | })
8 | export class MdPreviewComponent {
9 |
10 | @Input() text!: string;
11 | @Input() theme: 'dark' | 'light' = 'dark';
12 | @Output() ready: EventEmitter = new EventEmitter();
13 |
14 | constructor() {
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/components/multi-field/multi-field.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/multi-field/multi-field.component.css
--------------------------------------------------------------------------------
/src/app/components/multi-field/multi-field.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
15 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
30 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/app/components/multi-field/multi-field.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { MultiFieldComponent } from './multi-field.component';
4 |
5 | describe('MultiFieldComponent', () => {
6 | let component: MultiFieldComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ MultiFieldComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(MultiFieldComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/multi-field/multi-field.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';
2 | import {UtilsService} from "../../services/utils.service";
3 |
4 | @Component({
5 | selector: 'app-multi-field',
6 | templateUrl: './multi-field.component.html',
7 | styleUrls: ['./multi-field.component.css'],
8 | changeDetection: ChangeDetectionStrategy.OnPush
9 | })
10 | export class MultiFieldComponent {
11 |
12 | @Input()
13 | fields: string[] = [];
14 |
15 | @Input()
16 | textarea: boolean = false;
17 | @Output()
18 | valueChange = new EventEmitter;
19 |
20 | entries: { id: string, name: string[] }[] = [];
21 |
22 | constructor(private utilsService: UtilsService) {
23 | }
24 |
25 | @Input()
26 | set value(values: any[] | null) {
27 | if (!values) return;
28 |
29 | this.entries = [];
30 | values.forEach(value => {
31 | console.log(typeof value)
32 | if (typeof value === 'string') {
33 | this.entries.push(this.generateFields([value]));
34 | } else if (typeof value === 'object') {
35 | this.entries.push(this.generateFields(Object.values(value)));
36 | }
37 | })
38 | }
39 |
40 | addEntry() {
41 | this.entries.push(this.generateFields());
42 | }
43 |
44 | generateFields(values: string[] = []) {
45 | const fields = [];
46 |
47 | for (let i = 0; i < this.fields.length; i++) {
48 | // const field = this.fields[i];
49 | fields.push(values[i] ?? '');
50 | }
51 | return {id: this.utilsService.guid(), name: fields};
52 | }
53 |
54 | removeEntry(id: string) {
55 | this.entries = this.entries.filter(e => e.id !== id);
56 | this.emitChange();
57 | }
58 |
59 | emitChange() {
60 | this.valueChange.emit(this.entries.map(e => e.name))
61 | }
62 |
63 | assignValue(value: string, key: number, index: number) {
64 | this.entries[index].name[key] = value;
65 | this.emitChange()
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/app/components/multi-picker/multi-picker.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/multi-picker/multi-picker.component.css
--------------------------------------------------------------------------------
/src/app/components/multi-picker/multi-picker.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ title }}
4 |
9 | Select {{ title }}
10 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
22 | {{ selected.name }}
23 |
26 |
27 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
Search {{ title }}
41 |
56 |
57 |
No items to select
58 |
60 |
62 |
63 |
64 |
70 |
72 | {{
73 | item.name
74 | }}
75 |
76 |
{{ item.description }}
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/app/components/multi-picker/multi-picker.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { MultiPickerComponent } from './multi-picker.component';
4 |
5 | describe('MultiPickerComponent', () => {
6 | let component: MultiPickerComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ MultiPickerComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(MultiPickerComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/multi-picker/multi-picker.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
2 | import {UtilsService} from "../../services/utils.service";
3 |
4 | export interface PickerItem {
5 | name: string;
6 | value: string;
7 | description: string;
8 | }
9 |
10 | @Component({
11 | selector: 'app-multi-picker',
12 | templateUrl: './multi-picker.component.html',
13 | styleUrls: ['./multi-picker.component.css']
14 | })
15 | export class MultiPickerComponent implements OnInit, OnChanges {
16 |
17 | @Input()
18 | items: PickerItem[] = [];
19 |
20 | @Input()
21 | title: string = 'items';
22 |
23 | @Input()
24 | value: string[] = [];
25 |
26 | @Output()
27 | selectedItemsChange = new EventEmitter();
28 |
29 | selectedItems: PickerItem[] = [];
30 |
31 | id = this.utilsService.guid();
32 |
33 | constructor(private utilsService: UtilsService) {
34 | }
35 |
36 | ngOnChanges(changes: SimpleChanges): void {
37 | if (this.value.length === 0) {
38 | this.selectedItems = [];
39 | }
40 | }
41 |
42 | ngOnInit(): void {
43 | if (this.value.length > 0) {
44 | const items = this.items.filter(i => this.value.includes(i.value));
45 | this.selectedItems = [...new Set(items)];
46 | }
47 | }
48 |
49 | itemChange(event: Event, item: PickerItem) {
50 | const target = event.target as HTMLInputElement;
51 | if (target.checked) {
52 | this.addItem(item);
53 | } else {
54 | this.removeItem(item)
55 | }
56 | }
57 |
58 | addItem(item: PickerItem) {
59 | if (!this.selectedItems.find(i => i.name === item.name)) {
60 | this.selectedItems.push(item);
61 | this.emitSelectedEvent();
62 | }
63 | }
64 |
65 | emitSelectedEvent() {
66 | this.selectedItemsChange.emit(this.selectedItems);
67 | }
68 |
69 | removeItem(item: PickerItem) {
70 | this.selectedItems = this.selectedItems.filter(i => i.name !== item.name);
71 | this.emitSelectedEvent();
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/app/components/raw-code-snippet/raw-code-snippet.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/raw-code-snippet/raw-code-snippet.component.css
--------------------------------------------------------------------------------
/src/app/components/raw-code-snippet/raw-code-snippet.component.html:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/src/app/components/raw-code-snippet/raw-code-snippet.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { RawCodeSnippetComponent } from './raw-code-snippet.component';
4 |
5 | describe('RawCodeSnippetComponent', () => {
6 | let component: RawCodeSnippetComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ RawCodeSnippetComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(RawCodeSnippetComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/raw-code-snippet/raw-code-snippet.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, EventEmitter, Input, Output} from '@angular/core';
2 | import {UtilsService} from "../../services/utils.service";
3 |
4 | @Component({
5 | selector: 'app-raw-code-snippet',
6 | templateUrl: './raw-code-snippet.component.html',
7 | styleUrls: ['./raw-code-snippet.component.css']
8 | })
9 | export class RawCodeSnippetComponent {
10 |
11 | @Input()
12 | code: string = ''
13 |
14 | @Output()
15 | codeCopied: EventEmitter = new EventEmitter();
16 |
17 | constructor(private utilsService: UtilsService) {
18 |
19 | }
20 |
21 | copyCode() {
22 | this.utilsService.copyToClipboard(this.code);
23 | this.codeCopied.emit(this.code);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/components/repo/repo.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/repo/repo.component.css
--------------------------------------------------------------------------------
/src/app/components/repo/repo.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/app/components/repo/repo.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { RepoComponent } from './repo.component';
4 |
5 | describe('RepoComponent', () => {
6 | let component: RepoComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ RepoComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(RepoComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/repo/repo.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-repo',
5 | templateUrl: './repo.component.html',
6 | styleUrls: ['./repo.component.css']
7 | })
8 | export class RepoComponent {
9 |
10 | OpenProjectRepo() {
11 | window.open('https://github.com/luisvent/document_my_project', '_blank');
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/components/section-title/section-title.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/section-title/section-title.component.css
--------------------------------------------------------------------------------
/src/app/components/section-title/section-title.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ title }}
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/app/components/section-title/section-title.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { SectionTitleComponent } from './section-title.component';
4 |
5 | describe('SectionTitleComponent', () => {
6 | let component: SectionTitleComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ SectionTitleComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(SectionTitleComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/section-title/section-title.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
2 | import {IconType} from "../svg-icon/svg-icon.component";
3 |
4 | @Component({
5 | selector: 'app-section-title',
6 | templateUrl: './section-title.component.html',
7 | styleUrls: ['./section-title.component.css'],
8 | changeDetection: ChangeDetectionStrategy.OnPush
9 | })
10 | export class SectionTitleComponent {
11 |
12 | @Input()
13 | title = ''
14 |
15 | @Input()
16 | iconType?: IconType;
17 |
18 | constructor() {
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/components/svg-icon/svg-icon.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/components/svg-icon/svg-icon.component.css
--------------------------------------------------------------------------------
/src/app/components/svg-icon/svg-icon.component.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
10 |
12 |
13 |
15 |
18 |
19 |
21 |
24 |
25 |
27 |
30 |
31 |
33 |
36 |
37 |
39 |
42 |
43 |
45 |
48 |
49 |
51 |
54 |
55 |
57 |
60 |
61 |
63 |
66 |
67 |
69 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/src/app/components/svg-icon/svg-icon.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { SvgIconComponent } from './svg-icon.component';
4 |
5 | describe('SvgIconComponent', () => {
6 | let component: SvgIconComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ SvgIconComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(SvgIconComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/components/svg-icon/svg-icon.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-svg-icon',
5 | templateUrl: './svg-icon.component.html',
6 | styleUrls: ['./svg-icon.component.css'],
7 | changeDetection: ChangeDetectionStrategy.OnPush
8 | })
9 | export class SvgIconComponent {
10 |
11 | @Input()
12 | type: IconType | undefined;
13 |
14 | }
15 |
16 | export type IconType =
17 | 'info' |
18 | 'list' |
19 | 'github' |
20 | 'image' |
21 | 'layers' |
22 | 'rect-list' |
23 | 'star' |
24 | 'user-group' |
25 | 'user-circle' |
26 | 'award' |
27 | 'book' |
28 | 'adjustment' |
29 | 'none'
30 |
--------------------------------------------------------------------------------
/src/app/enums/license-type.enum.ts:
--------------------------------------------------------------------------------
1 | export enum LicenseType {
2 | MIT = 'MIT',
3 | Apache2 = 'Apache-2.0',
4 | GPL3 = 'GPL-3.0',
5 | BSD3 = 'BSD-3-Clause',
6 | Custom = 'Custom'
7 | }
8 |
--------------------------------------------------------------------------------
/src/app/interfaces/acknowledge-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface AcknowledgeOptions { title: string, url: string, description: string }
2 |
--------------------------------------------------------------------------------
/src/app/interfaces/author-data.interface.ts:
--------------------------------------------------------------------------------
1 | export interface AuthorData {
2 | name: string,
3 | email: string,
4 | url: string,
5 | github: string,
6 | likedIn?: string,
7 | }
8 |
--------------------------------------------------------------------------------
/src/app/interfaces/configuration-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface ConfigurationOptions {
2 | description: string,
3 | parameters: {
4 | field: string, description: string, default?: string
5 | }[]
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/interfaces/contribution-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface ContributionOptions {
2 | add: boolean,
3 | contributorsImg: boolean,
4 | contributionGuidelinesLink?: string | undefined
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/interfaces/contributor-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface ContributorOptions {
2 | name: string,
3 | username: string
4 | }
5 |
--------------------------------------------------------------------------------
/src/app/interfaces/feature-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface FeatureOptions { title: string, description: string }
2 |
--------------------------------------------------------------------------------
/src/app/interfaces/github-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface GitHubOptions {
2 | username: string,
3 | repo: string,
4 | badges: boolean
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/interfaces/installation-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface InstallationOptions {
2 | projectName: string;
3 | packageManager: string;
4 | dependencies: string[];
5 | devDependencies: string[];
6 | installationSteps: string[];
7 | includeSetup?: boolean;
8 | setupSteps?: string[];
9 | includeUsage?: boolean;
10 | usageSteps?: string[];
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/interfaces/license-options.interface.ts:
--------------------------------------------------------------------------------
1 | import {LicenseType} from "../enums/license-type.enum";
2 |
3 | export interface LicenseOptions {
4 | type?: LicenseType,
5 | customText?: string | undefined
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/interfaces/npm-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface NPMOptions {
2 | package?: string;
3 | url: string;
4 | badges: boolean
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/interfaces/technology-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface TechnologyOptions {
2 | name: string,
3 | description: string,
4 | value: string,
5 | mainColor: string,
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/pipes/log.pipe.ts:
--------------------------------------------------------------------------------
1 | import {Pipe, PipeTransform} from '@angular/core';
2 |
3 | @Pipe({
4 | name: 'log'
5 | })
6 | export class LogPipe implements PipeTransform {
7 |
8 | transform(value: any): unknown {
9 | console.log('log pipe:', value);
10 | return value;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/app/services/markdown.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from "@angular/core";
2 | import {InstallationOptions} from "../interfaces/installation-options.interface";
3 | import {AuthorData} from "../interfaces/author-data.interface";
4 | import {GitHubOptions} from "../interfaces/github-options.interface";
5 | import {TechnologyOptions} from "../interfaces/technology-options.interface";
6 | import {FeatureOptions} from "../interfaces/feature-options.interface";
7 | import {LicenseOptions} from "../interfaces/license-options.interface";
8 | import {AcknowledgeOptions} from "../interfaces/acknowledge-options.interface";
9 | import {ContributionOptions} from "../interfaces/contribution-options.interface";
10 | import {EditorState} from "../store/reducers/editor.reducer";
11 | import {ContributorOptions} from "../interfaces/contributor-options.interface";
12 |
13 | @Injectable({
14 | providedIn: 'root'
15 | })
16 | export class MarkdownService {
17 |
18 | TABLE_CONTENT_PLACEHOLDER = '';
19 | LINKS_PLACEHOLDER = '';
20 |
21 | constructor() {
22 | }
23 |
24 | Build(state: EditorState) {
25 |
26 | const sections = [
27 | this.generateReadmeInfo(),
28 | state.github.badges && this.generateGitHubBadges({
29 | username: state.github.username,
30 | repo: state.github.repo,
31 | badges: true
32 | }),
33 | this.generateIntroductionSection(state.title, state.shortDescription,
34 | '', state.logoUrl),
35 | state.npm.badges && this.generateNpmBadges(state.npm.package!, {
36 | npmVersion: {
37 | color: '0470FF',
38 | logoColor: 'white'
39 | },
40 | npmDownloads: {
41 | color: '67ACF3'
42 | },
43 | bundleSize: {
44 | color: 'F9DBBC'
45 | }
46 | }),
47 | this.generateLinksPlaceholder(),
48 | state.mainImageUrl && this.generateCenteredImages([{url: state.mainImageUrl, alt: 'Main Image'}]),
49 | this.generateTableContentPlaceholder(),
50 | state.description && this.generateDescription([state.description], state.sectionIcons),
51 | state.images.length > 0 && this.generateShowcaseSection(state.images, state.sectionIcons),
52 | state.features.length > 0 && this.generateFeaturesSection(state.features, state.sectionIcons),
53 | state.technologies.length > 0 && this.generateTechStackSection(state.technologies, state.sectionIcons),
54 | // this.generateInstallSection({
55 | // projectName: 'My Awesome Project',
56 | // packageManager: 'npm',
57 | // dependencies: ['react', 'react-dom', 'axios'],
58 | // devDependencies: ['eslint', 'prettier'],
59 | // installationSteps: ['Run the development server with `npm run dev`'],
60 | // includeSetup: true,
61 | // setupSteps: ['Install Node.js v12 or later', 'Install a code editor (e.g., Visual Studio Code)'],
62 | // includeUsage: true,
63 | // usageSteps: ['Open the project directory in your code editor', 'Run `npm start` to start the
64 | // development server'], }),
65 | // this.generateParametersTable([
66 | // {fieldName: 'name', description: 'Name of the user', defaultValue: 'John Doe'},
67 | // {fieldName: 'age', description: 'Age of the user'},
68 | // {fieldName: 'isAdmin', description: 'Whether the user is an admin or not', defaultValue: 'false'}
69 | // ]),
70 | ...(state.installSteps.length > 0 ||
71 | state.usageSteps.length > 0 ||
72 | state.configuration.parameters.length > 0 ?
73 | [this.generateTitle(`${state.sectionIcons ? '⚙ ' : ''}️Setup`),
74 | this.generateInstallationSection(state.installSteps),
75 | this.generateUsageSection(state.usageSteps),
76 | this.generateParametersTable(state.configuration.parameters)] : []),
77 | state.acknowledgments.length > 0 && this.generateAcknowledgementsSection(state.acknowledgments, state.sectionIcons),
78 | state.contribution.add && this.generateContributionSection(state.contribution, state.contributors, state.github, state.sectionIcons),
79 | state.author.name.length > 0 && this.generateAuthorSection(state.author, state.sectionIcons),
80 | state.license.type && this.generateLicenseSection(state.license, state.sectionIcons),
81 | state.backToTop && this.generateBackToTop(state.sectionIcons),
82 | this.generateWatermark()
83 | ];
84 |
85 | let result = '';
86 |
87 | for (const section of sections) {
88 | result += section ? `${section}\n\n` : '';
89 | }
90 |
91 | if (state.contentTable) {
92 | result = this.generateTableOfContentsFromMarkdown(result);
93 | }
94 |
95 | if (state.navigationLinks) {
96 | result = this.generateLinksSection(result);
97 | }
98 |
99 | return result;
100 | }
101 |
102 | generateSetupTitle(state: EditorState) {
103 | return state.installSteps.length > 0 ||
104 | state.usageSteps.length > 0 ||
105 | state.configuration.parameters.length > 0 ?
106 | '## Setup' : '';
107 | }
108 |
109 | generateReadmeInfo() {
110 | const info = `
111 | `;
117 |
118 | return info;
119 | }
120 |
121 | generateTableContentPlaceholder() {
122 | return this.TABLE_CONTENT_PLACEHOLDER;
123 | }
124 |
125 | generateParametersTable(properties: {
126 | field: string;
127 | description: string;
128 | default?: string;
129 | }[]): string {
130 |
131 | if (properties.length === 0) {
132 | return '';
133 | }
134 |
135 | const tableHeader = '| Field Name | Description | Default Value |\n| --- | --- | --- |';
136 | let tableBody = '';
137 |
138 | for (const prop of properties) {
139 | const row = `| \`${prop.field}\` | ${prop.description} | ${prop.default || ''} |`;
140 | tableBody += `${row}\n`;
141 | }
142 |
143 | return `### Parameters\n\n${tableHeader}\n${tableBody}`;
144 | }
145 |
146 | generateNpmBadges(
147 | npmPackageName: string,
148 | options?: {
149 | npmVersion?: {
150 | logoColor?: string;
151 | color?: string;
152 | };
153 | npmDownloads?: {
154 | color?: string;
155 | };
156 | bundleSize?: {
157 | color?: string;
158 | };
159 | }
160 | ): string {
161 | const npmVersionBadge = `
162 |
163 | `;
164 |
165 | const npmDownloadsBadge = `
166 |
167 | `;
168 |
169 | const bundleSizeBadge = `
170 |
171 | `;
172 |
173 | const badges = `
174 | ${npmVersionBadge}
175 | ${npmDownloadsBadge}
176 | ${bundleSizeBadge}
177 |
`;
178 |
179 | return badges;
180 | }
181 |
182 | generateTableOfContentsFromMarkdown(markdownText: string, addTitleIcons = false): string {
183 | const headingRegex = /^(#{1,6})\s*(.*?)$/gm;
184 | const slugify = (text: string) =>
185 | text
186 | .toLowerCase()
187 | .replace(/\s+/g, '-')
188 | .replace(/[^a-z0-9-]/g, '');
189 |
190 | const headings: { text: string; level: number }[] = [];
191 | let match: RegExpExecArray | null;
192 |
193 | while ((match = headingRegex.exec(markdownText))) {
194 | const level = match[1].length;
195 | const text = match[2].trim();
196 | headings.push({text, level});
197 | }
198 |
199 | let tableOfContents = this.generateTitle(`${addTitleIcons ? '📝 ' : ''}️Table of Contents`) + '\n \nOpen Contents \n\n';
200 |
201 | headings.forEach((heading) => {
202 | const slug = slugify(heading.text);
203 | const indent = ' '.repeat(heading.level - 1);
204 | tableOfContents += `${indent}- [${heading.text}](#${slug})\n`;
205 | });
206 |
207 | tableOfContents += ' ';
208 |
209 | return markdownText.replace(this.TABLE_CONTENT_PLACEHOLDER, tableOfContents);
210 | }
211 |
212 | generateAuthorSection(author: AuthorData, addTitleIcons = false) {
213 | const aboutAuthorSection = `
214 | ${this.generateTitle(`${addTitleIcons ? '👨🏻 ' : ''}About the Author`)}
215 |
216 | **${author.name}**
217 |
218 | This project was created by ${author.name}. Connect with me on [GitHub](https://github.com/${author.github}) ${author.likedIn ? `and [LinkedIn](https://www.linkedin.com/in/${author.likedIn}/)` : ''} to learn more about my projects and professional background.
219 | `;
220 |
221 | return aboutAuthorSection;
222 | }
223 |
224 | generateGitHubBadges(
225 | github: GitHubOptions,
226 | badgeStyle: 'flat' | 'flat-square' | 'plastic' | 'for-the-badge' = 'for-the-badge'
227 | ): string {
228 |
229 | const badges = `
230 |
231 |
232 |
`;
233 |
234 | return badges;
235 | }
236 |
237 | generateBadge(
238 | label: string,
239 | url: string,
240 | color: string,
241 | logo?: string,
242 | description?: string,
243 | logoColor?: string,
244 | badgeStyle: 'flat' | 'flat-square' | 'plastic' | 'for-the-badge' = 'for-the-badge'
245 | ): string {
246 | const badgeUrl = `https://img.shields.io/badge/${encodeURIComponent(label)}-${color}?style=${badgeStyle}${
247 | logo ? `&logo=${logo}` : ''
248 | }${logoColor ? `&logoColor=${logoColor}` : ''}`;
249 |
250 | return `[![${label}][${label}-badge]][${label}-url]${description ? ` - ${description}` : ''}
251 |
252 | [${label}-badge]: ${badgeUrl}
253 | [${label}-url]: ${url}`;
254 | }
255 |
256 | generateHeading(heading: { text: string; level: number; }): string {
257 | let markdownContent = '';
258 | markdownContent += '#'.repeat(heading.level) + ' ' + heading.text + '\n\n';
259 | return markdownContent;
260 | }
261 |
262 | generateDescription(descriptions: string[], addTitleIcons = false): string {
263 | let markdownContent = this.generateTitle(`${addTitleIcons ? 'ℹ️ ' : ''}About the Project`) + '\n\n';
264 | descriptions.forEach(description => {
265 | markdownContent += description + '\n\n';
266 | });
267 | return markdownContent;
268 | }
269 |
270 | generateImages(images: { url: string; alt: string; }[]): string {
271 | let markdownContent = '';
272 | images.forEach(image => {
273 | markdownContent += `\n\n`;
274 | });
275 | return markdownContent;
276 | }
277 |
278 | generateCenteredImages(images: { url: string; alt: string; }[]): string {
279 | let markdownContent = '';
280 | images.forEach(image => {
281 | markdownContent += ` `;
282 | });
283 | return markdownContent + '
';
284 | }
285 |
286 | generateCodeBlock(codeBlocks: { language: string; code: string; }[]): string {
287 | let markdownContent = '';
288 | codeBlocks.forEach(codeBlock => {
289 | markdownContent += '```' + codeBlock.language + '\n' + codeBlock.code + '\n```\n\n';
290 | });
291 | return markdownContent;
292 | }
293 |
294 | generateContributionSection(contribution: ContributionOptions, contributors: ContributorOptions[],
295 | github: GitHubOptions, addTitleIcons = false): string {
296 | const {contributionGuidelinesLink} = contribution;
297 | let contributionSection = `${this.generateTitle(`${addTitleIcons ? '👏🏻 ' : ''}Contributing`)}\n\nWe welcome contributions from the community! If you would like to contribute to this project, please follow the guidelines below.\n`;
298 |
299 | // Generic contribution information
300 | contributionSection += `\n### Ways to Contribute\n\n- Report bugs or issues by opening a new issue on our GitHub repository.
301 | - Suggest new features or improvements by opening a new issue on our GitHub repository.
302 | - Contribute code by forking the repository, making changes, and submitting a pull request.\n`;
303 |
304 | // Contribution instructions
305 | contributionSection += `\n### Contribution Instructions\n\n1. Fork the repository.
306 | 2. Create a new branch for your feature or bug fix: \`git checkout -b my-feature-branch\`.
307 | 3. Make the necessary changes and commit them: \`git commit -am 'Add my new feature'\`.
308 | 4. Push your branch to your forked repository: \`git push origin my-feature-branch\`.
309 | 5. Open a pull request against the main repository, describing the changes you made and why they should be merged.\n`;
310 |
311 | if (contributionGuidelinesLink) {
312 | contributionSection += `\nFor more information on how to contribute, please visit [Contribution Guidelines](${contributionGuidelinesLink}).\n`;
313 | }
314 |
315 | if (contributors.length > 0 || contribution.contributorsImg) {
316 | contributionSection += `### Contributors\n\n`;
317 |
318 | if (contribution.contributorsImg) {
319 |
320 | contributionSection += `
321 |
322 | `;
323 | } else if (contributors.length > 0) {
324 |
325 | contributors.forEach(contributor => {
326 | contributionSection += `- ${contributor.name} (${contributor.username})\n`;
327 | })
328 | }
329 | }
330 |
331 | return contributionSection;
332 | }
333 |
334 | generateAcknowledgementsSection(acknowledgements: AcknowledgeOptions[], addTitleIcons = false): string {
335 | let acknowledgementsSectionContent = this.generateTitle(`${addTitleIcons ? '🏆 ' : ''}Acknowledgements`) + '\n\n';
336 |
337 | acknowledgements.forEach((item) => {
338 | const {title, url, description} = item;
339 | acknowledgementsSectionContent += `- [${title}](${url}) - ${description}\n`;
340 | });
341 |
342 | return acknowledgementsSectionContent;
343 | }
344 |
345 | generateBackToTop(addIcon = true) {
346 | return `${addIcon ? 'Top ⬆️' : '(Back to top)'}
`;
347 | }
348 |
349 | generateLicenseSection(licenseSection: LicenseOptions, addTitleIcons = false): string {
350 | const {type, customText} = licenseSection;
351 | let licenseSectionContent = this.generateTitle(`${addTitleIcons ? '📖 ' : ''}License`,) + '\n\n';
352 |
353 | switch (type) {
354 | case 'MIT':
355 | licenseSectionContent += 'This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).\n';
356 | break;
357 | case 'Apache-2.0':
358 | licenseSectionContent += 'This project is licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).\n';
359 | break;
360 | case 'GPL-3.0':
361 | licenseSectionContent += 'This project is licensed under the [GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html).\n';
362 | break;
363 | case 'BSD-3-Clause':
364 | licenseSectionContent += 'This project is licensed under the [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause).\n';
365 | break;
366 | case 'Custom':
367 | if (customText) {
368 | licenseSectionContent += `${customText}\n`;
369 | } else {
370 | licenseSectionContent += 'This project is licensed under a custom license.\n';
371 | }
372 | break;
373 | default:
374 | licenseSectionContent += 'This project is licensed under an unspecified license.\n';
375 | }
376 |
377 | return licenseSectionContent;
378 | }
379 |
380 | generateFeaturesSection(features: FeatureOptions[], addTitleIcons = false): string {
381 | let featuresSection = this.generateTitle(`${addTitleIcons ? '⭐️ ' : ''}Features`) + '\n\n';
382 |
383 | features.forEach((feature, index) => {
384 | const {title, description} = feature;
385 | featuresSection += `${index + 1}. **${title}**\n\n${description}\n\n`;
386 | });
387 |
388 | return featuresSection;
389 | }
390 |
391 | generateTitle(titleName: string) {
392 | return `## ${titleName}`;
393 | }
394 |
395 | generateIntroductionSection(title: string, description: string, url: string, imgUrl: string) {
396 | return `
397 |
398 |
399 | ${imgUrl !== '' ? `
400 |
401 | ` : ''}
402 |
403 | # ${title}
404 |
405 | ${description}
406 |
407 |
408 | `
409 | }
410 |
411 | identifyTechnologies(description: string, technologies: TechnologyOptions[]): string[] {
412 | const foundTechnologies: string[] = [];
413 |
414 | technologies.forEach(tech => {
415 | if (new RegExp(`\\b(${tech.name}|${tech.value})\\b`, 'i').test(description)) {
416 | foundTechnologies.push(tech.name);
417 | }
418 | });
419 |
420 | return foundTechnologies;
421 | }
422 |
423 | generateTechStackSection(technologies: TechnologyOptions[], addTitleIcons = false) {
424 | let stackSection = this.generateTitle(`${addTitleIcons ? '🛠 ' : ''}Stack Tech`) + '\n';
425 |
426 | technologies.forEach(tech => {
427 | stackSection += `- ${this.generateBadge(tech.name, '', tech.mainColor.replace('#', ''), tech.value, tech.description)}}\n`;
428 | });
429 |
430 | return stackSection;
431 | }
432 |
433 | /**
434 | * Generates the install section for a Markdown file.
435 | * @param options - An object containing options for generating the install section.
436 | * @returns The Markdown content for the install section.
437 | */
438 | generateInstallSection(options: InstallationOptions): string {
439 | const {
440 | projectName,
441 | packageManager,
442 | dependencies,
443 | devDependencies,
444 | installationSteps,
445 | includeSetup = false,
446 | setupSteps = [],
447 | includeUsage = false,
448 | usageSteps = [],
449 | } = options;
450 |
451 | let installSection = `${this.generateTitle('Installation')}\n\nTo install ${projectName}, follow these steps:\n\n`;
452 |
453 | // Add setup section if requested
454 | if (includeSetup && setupSteps.length > 0) {
455 | installSection += `### Setup\n\nBefore installation, make sure you have the following prerequisites set up:\n\n`;
456 | setupSteps.forEach((step, index) => {
457 | installSection += `${index + 1}. ${step}\n\n`;
458 | });
459 | }
460 |
461 | // Add step for installing dependencies
462 | if (dependencies.length > 0) {
463 | installSection += `1. Install the required dependencies:\n\n\`\`\`\n${packageManager} install ${dependencies.join(' ')}\n\`\`\`\n\n`;
464 | }
465 |
466 | // Add step for installing development dependencies
467 | if (devDependencies.length > 0) {
468 | installSection += `2. Install the development dependencies (if needed):\n\n\`\`\`\n${packageManager} install --dev ${devDependencies.join(' ')}\n\`\`\`\n\n`;
469 | }
470 |
471 | // Add additional installation steps
472 | if (installationSteps.length > 0) {
473 | installSection += `${dependencies.length > 0 || devDependencies.length > 0 ? '3. ' : '1. '}Additional steps:\n\n`;
474 | installationSteps.forEach((step, index) => {
475 | installSection += `${index + 1}. ${step}\n\n`;
476 | });
477 | }
478 |
479 | // Add usage section if requested
480 | if (includeUsage && usageSteps.length > 0) {
481 | installSection += `${this.generateTitle('Usage')}\n\nAfter installation, you can use the project by following these steps:\n\n`;
482 | usageSteps.forEach((step, index) => {
483 | installSection += `${index + 1}. ${step}\n\n`;
484 | });
485 | }
486 |
487 | return installSection;
488 | }
489 |
490 | generateInstallationSection(steps: string[]): string {
491 |
492 | if (steps.length === 0) {
493 | return '';
494 | }
495 |
496 | let installSection = `### Installation\n\nTo install this project, follow these steps:\n\n`;
497 |
498 | steps.forEach((step, index) => {
499 | installSection += `${index + 1}. ${step}\n\n`;
500 | });
501 |
502 | return installSection;
503 | }
504 |
505 | generateUsageSection(steps: string[]): string {
506 |
507 | if (steps.length === 0) {
508 | return '';
509 | }
510 |
511 | let usageSection = `### Usage\n\nAfter installation, you can use the project by following these steps:\n\n`;
512 |
513 | steps.forEach((step, index) => {
514 | usageSection += `${index + 1}. ${step}\n\n`;
515 | });
516 |
517 | return usageSection;
518 | }
519 |
520 | /**
521 | * Generates a links section for a Markdown file based on the headings.
522 | * @param markdownContent - The Markdown content of the file.
523 | * @returns The Markdown content for the links section.
524 | */
525 | generateLinksSection(markdownContent: string): string {
526 | const headings = markdownContent.match(/\n## (.+)\n/g) || [];
527 | const links = headings.map((heading) => {
528 | const label = heading.replace(/\n## (.+)\n/, '$1');
529 | const id = label.replace(/[^a-zA-Z0-9]+/g, '-').toLowerCase();
530 | return {label, id};
531 | });
532 |
533 | if (links.length === 0) {
534 | return '';
535 | }
536 |
537 | let linksSection = '';
538 |
539 | links.forEach((link, index) => {
540 | const {label, id} = link;
541 | const isLastLink = index === links.length - 1;
542 |
543 | linksSection += `${label} ${isLastLink ? '' : ' • '}`;
544 | });
545 |
546 | linksSection += ' ';
547 |
548 | return markdownContent.replace(this.LINKS_PLACEHOLDER, linksSection);
549 | }
550 |
551 | /**
552 | * Generates a showcase section with image URLs and links formatted as a table.
553 | * @param images - An array of image data objects with author and url properties.
554 | * @returns The formatted showcase section as a string.
555 | */
556 | generateShowcaseSection(images: string[], addTitleIcons = false): string {
557 | if (images.length === 0) {
558 | return '';
559 | }
560 |
561 | const columns = 2;
562 | let showcaseSection = `${this.generateTitle(`${addTitleIcons ? '🏞 ' : ''}Showcase`)}\n\n \n\n\n`;
563 |
564 | const numRows = Math.ceil(images.length / columns);
565 | for (let i = 0; i < numRows; i++) {
566 | showcaseSection += '\n';
567 |
568 | for (let j = 0; j < columns; j++) {
569 | const index = i * columns + j;
570 | if (index < images.length) {
571 | const url = images[index];
572 | showcaseSection += ` \n`;
573 | } else {
574 | showcaseSection += ' \n';
575 | }
576 | }
577 |
578 | showcaseSection += ' \n';
579 | }
580 |
581 | showcaseSection += '
\n\n ';
582 |
583 | return showcaseSection;
584 | }
585 |
586 | generateLinksPlaceholder() {
587 | return this.LINKS_PLACEHOLDER;
588 | }
589 |
590 | generateWatermark() {
591 | return '---\n ';
592 | }
593 | }
594 |
--------------------------------------------------------------------------------
/src/app/services/toast.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {BehaviorSubject} from "rxjs";
3 | import {UtilsService} from "./utils.service";
4 |
5 | export interface Toast {
6 | id: string;
7 | message: string;
8 | type: 'success' | 'error';
9 | }
10 |
11 | @Injectable({
12 | providedIn: 'root'
13 | })
14 | export class ToastService {
15 |
16 | toasts: BehaviorSubject = new BehaviorSubject([]);
17 |
18 | constructor(private utilsService: UtilsService) {
19 | }
20 |
21 | success(message: string) {
22 | this.showtoast({message, type: 'success', id: this.utilsService.guid()});
23 | }
24 |
25 | error(message: string) {
26 | this.showtoast({message, type: 'error', id: this.utilsService.guid()});
27 | }
28 |
29 | close(id: string) {
30 | this.toasts.next([...this.toasts.value.filter(t => t.id !== id)]);
31 | }
32 |
33 | private showtoast(toast: Toast) {
34 | this.toasts.next([...this.toasts.value, toast]);
35 | this.removeToast(toast); // Remove toast after 2 seconds.
36 | }
37 |
38 | private removeToast(toast: Toast) {
39 | setTimeout(() => this.close(toast.id), 2000);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/app/services/utils.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 |
3 | import {highlight, languages} from "prismjs";
4 |
5 | @Injectable({
6 | providedIn: 'root'
7 | })
8 | export class UtilsService {
9 | constructor() {
10 | }
11 |
12 | formatCode(text: string) {
13 | const html = highlight(text, languages['html'], 'html');
14 | return html;
15 | }
16 |
17 | copyToClipboard(text: string) {
18 | const selBox = document.createElement('textarea');
19 | selBox.style.position = 'fixed';
20 | selBox.style.left = '0';
21 | selBox.style.top = '0';
22 | selBox.style.opacity = '0';
23 | selBox.value = text;
24 | document.body.appendChild(selBox);
25 | selBox.focus();
26 | selBox.select();
27 | selBox.setSelectionRange(0, 99999);
28 | navigator.clipboard.writeText(selBox.value);
29 | document.body.removeChild(selBox);
30 | }
31 |
32 | guid() {
33 | return 'id-' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
34 | }
35 |
36 | /**
37 | * Saves the provided text as a file.
38 | * @param text - The text content to be saved.
39 | * @param fileName - The desired name for the file.
40 | * @param fileType - The file type or extension (e.g., '.txt', '.md', '.html').
41 | */
42 | saveTextAsFile(text: string, fileName: string = 'readme', fileType: string = 'md') {
43 | const blob = new Blob([text], {type: `text/${fileType.replace('.', '')}`});
44 | const anchor = document.createElement('a');
45 | anchor.download = `${fileName}.${fileType}`;
46 | anchor.href = window.URL.createObjectURL(blob);
47 | anchor.dataset['downloadedFilename'] = `${fileName}${fileType}`;
48 | document.body.appendChild(anchor);
49 | anchor.click();
50 | document.body.removeChild(anchor);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/app/store/actions/action-types.ts:
--------------------------------------------------------------------------------
1 | import * as Actions from './editor.actions';
2 |
3 | export {Actions}
4 |
--------------------------------------------------------------------------------
/src/app/store/actions/editor.actions.ts:
--------------------------------------------------------------------------------
1 | import {createAction, props} from '@ngrx/store';
2 | import {FeatureOptions} from "../../interfaces/feature-options.interface";
3 | import {TechnologyOptions} from "../../interfaces/technology-options.interface";
4 | import {AcknowledgeOptions} from "../../interfaces/acknowledge-options.interface";
5 | import {LicenseOptions} from "../../interfaces/license-options.interface";
6 | import {ContributorOptions} from "../../interfaces/contributor-options.interface";
7 | import {EditorState} from "../reducers/editor.reducer";
8 |
9 | export const modifyTitle = createAction(
10 | '[Form] Modify Title',
11 | props<{ title: string }>()
12 | );
13 |
14 | export const modifyShortDescription = createAction(
15 | '[Form] Modify Short Description',
16 | props<{ shortDescription: string }>()
17 | );
18 |
19 | export const modifyNavigation = createAction(
20 | '[Form] Modify Navigation Links',
21 | props<{ navigation: boolean }>()
22 | );
23 |
24 |
25 | export const modifyContentTable = createAction(
26 | '[Form] Modify Content Table',
27 | props<{ contentTable: boolean }>()
28 | );
29 |
30 | export const modifyGithubUrl = createAction(
31 | '[Form] Modify Github Url',
32 | props<{ url: string }>()
33 | );
34 |
35 | export const modifyNpmUrl = createAction(
36 | '[Form] Modify NPM Url',
37 | props<{ url: string }>()
38 | );
39 |
40 | export const modifyNpmBadge = createAction(
41 | '[Form] Modify NPM Badge',
42 | props<{ badge: boolean }>()
43 | );
44 |
45 | export const modifyGithubBadge = createAction(
46 | '[Form] Modify Github Badge',
47 | props<{ badge: boolean }>()
48 | );
49 |
50 | export const modifyLogoUrl = createAction(
51 | '[Form] Modify Logo Url',
52 | props<{ logoUrl: string }>()
53 | );
54 |
55 | export const modifyMainImageUrl = createAction(
56 | '[Form] Modify Main Image Url',
57 | props<{ mainImageUrl: string }>()
58 | );
59 |
60 | export const modifyImages = createAction(
61 | '[Form] Modify Images',
62 | props<{ images: string[] }>()
63 | );
64 |
65 | export const addTechnologies = createAction(
66 | '[Form] Add Technology',
67 | props<{ technologies: TechnologyOptions[] }>()
68 | );
69 |
70 | export const removeTechnology = createAction(
71 | '[Form] Remove Technology'
72 | );
73 |
74 |
75 | export const modifyAcknowledgement = createAction(
76 | '[Form] Modify Acknowledgement',
77 | props<{ acknowledgements: AcknowledgeOptions[] }>()
78 | );
79 |
80 | export const modifyContributors = createAction(
81 | '[Form] Modify Contributors',
82 | props<{ contributors: ContributorOptions[] }>()
83 | );
84 |
85 |
86 | export const modifyContribution = createAction(
87 | '[Form] Modify Contribution',
88 | props<{ contribution: boolean }>()
89 | );
90 |
91 | export const toggleContributorsImg = createAction(
92 | '[Form] Toggle Contributors Image',
93 | props<{ contributorsImg: boolean }>()
94 | );
95 |
96 | export const modifyContributionGuideline = createAction(
97 | '[Form] Modify Contribution Guideline',
98 | props<{ contributionGuidelinesLink: string }>()
99 | );
100 |
101 |
102 | export const modifyAuthorName = createAction(
103 | '[Form] Modify Author Name',
104 | props<{ authorName: string }>()
105 | );
106 |
107 |
108 | export const modifyAuthorGithub = createAction(
109 | '[Form] Modify Author Github',
110 | props<{ authorGithub: string }>()
111 | );
112 |
113 |
114 | export const modifyInstallation = createAction(
115 | '[Form] Modify Installation Steps',
116 | props<{ steps: string[] }>()
117 | );
118 |
119 | export const modifyUsage = createAction(
120 | '[Form] Modify Usage Steps',
121 | props<{ steps: string[] }>()
122 | );
123 |
124 | export const addLicense = createAction(
125 | '[Form] Add License',
126 | props<{ license: LicenseOptions }>()
127 | );
128 |
129 | export const modifyCustomLicense = createAction(
130 | '[Form] Modify Custom License',
131 | props<{ customText: string }>()
132 | );
133 |
134 | export const removeLicense = createAction(
135 | '[Form] Remove License'
136 | );
137 |
138 | export const modifyFeatures = createAction(
139 | '[Form] Modify Features',
140 | props<{ features: FeatureOptions[] }>()
141 | );
142 |
143 | export const modifyDescription = createAction(
144 | '[Form] Modify Description',
145 | props<{ description: string }>()
146 | );
147 |
148 | export const displayMarkdownResult = createAction(
149 | '[Form] Display Markdown'
150 | );
151 |
152 | export const hideMarkdownResult = createAction(
153 | '[Form] Hide Markdown'
154 | );
155 |
156 | export const toggleBackToTop = createAction(
157 | '[Form] Toggle Back to top',
158 | props<{ backToTop: boolean }>()
159 | );
160 |
161 | export const toggleSectionIcons = createAction(
162 | '[Form] Toggle Section Icons',
163 | props<{ sectionIcons: boolean }>()
164 | );
165 |
166 | export const generateMarkdown = createAction(
167 | '[Form] Generate Markdown',
168 | props<{ generate: boolean }>()
169 | );
170 |
171 | export const markdownGenerated = createAction(
172 | '[Form] Markdown Generated',
173 | props<{ markdown: string }>()
174 | );
175 |
176 | export const setData = createAction(
177 | '[Form] Set Data',
178 | props<{ data: EditorState }>()
179 | );
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/src/app/store/reducers/editor.reducer.ts:
--------------------------------------------------------------------------------
1 | import {createReducer, on} from '@ngrx/store';
2 | import {Actions} from "../actions/action-types";
3 | import {InstallationOptions} from "../../interfaces/installation-options.interface";
4 | import {GitHubOptions} from "../../interfaces/github-options.interface";
5 | import {NPMOptions} from "../../interfaces/npm-options.interface";
6 | import {FeatureOptions} from "../../interfaces/feature-options.interface";
7 | import {TechnologyOptions} from "../../interfaces/technology-options.interface";
8 | import {AcknowledgeOptions} from "../../interfaces/acknowledge-options.interface";
9 | import {ContributionOptions} from "../../interfaces/contribution-options.interface";
10 | import {AuthorData} from "../../interfaces/author-data.interface";
11 | import {LicenseOptions} from "../../interfaces/license-options.interface";
12 | import {ContributorOptions} from "../../interfaces/contributor-options.interface";
13 | import {ConfigurationOptions} from "../../interfaces/configuration-options.interface";
14 |
15 | export interface EditorState {
16 | title: string,
17 | shortDescription: string;
18 | description: string,
19 | github: GitHubOptions,
20 | sectionIcons: boolean,
21 | backToTop: boolean,
22 | npm: NPMOptions,
23 | logoUrl: string;
24 | navigationLinks: boolean;
25 | contentTable: boolean;
26 | mainImageUrl: string;
27 | images: string[],
28 | features: FeatureOptions[],
29 | technologies: TechnologyOptions[],
30 | installation: InstallationOptions,
31 | installSteps: string[];
32 | usageSteps: string[];
33 | configuration: ConfigurationOptions,
34 | acknowledgments: AcknowledgeOptions[],
35 | contribution: ContributionOptions,
36 | contributors: ContributorOptions[],
37 | author: AuthorData,
38 | license: LicenseOptions,
39 | watermark: boolean,
40 | displayMarkdownResult: boolean,
41 | generateMarkdown: boolean,
42 | generatedMarkdown: string
43 | }
44 |
45 | const initialState: EditorState = {
46 | title: '',
47 | shortDescription: '',
48 | description: '',
49 | navigationLinks: false,
50 | sectionIcons: false,
51 | backToTop: true,
52 | contentTable: false,
53 | github: {
54 | username: '',
55 | repo: '',
56 | badges: false
57 | },
58 | logoUrl: '',
59 | mainImageUrl: '',
60 | displayMarkdownResult: false,
61 | npm: {
62 | package: '',
63 | url: '',
64 | badges: false
65 | },
66 | images: [],
67 | features: [],
68 | technologies: [],
69 | installation: {
70 | projectName: '',
71 | packageManager: '',
72 | dependencies: [],
73 | devDependencies: [],
74 | installationSteps: [],
75 | includeSetup: false,
76 | setupSteps: [],
77 | includeUsage: false,
78 | usageSteps: [],
79 | },
80 | installSteps: [],
81 | usageSteps: [],
82 | acknowledgments: [],
83 | contribution: {add: false, contributorsImg: false, contributionGuidelinesLink: undefined},
84 | contributors: [],
85 | configuration: {
86 | description: '',
87 | parameters: []
88 | },
89 | author: {
90 | name: '',
91 | email: '',
92 | url: '',
93 | github: '',
94 | likedIn: '',
95 | },
96 | license: {type: undefined, customText: undefined},
97 | watermark: true,
98 | generateMarkdown: false,
99 | generatedMarkdown: ''
100 | };
101 |
102 | export const editorReducer = createReducer(
103 | initialState,
104 |
105 | on(Actions.modifyTitle, (state, action): EditorState => {
106 | console.log(action)
107 | return newState(state, {title: action.title})
108 | }),
109 |
110 | on(Actions.modifyDescription, (state, action): EditorState => {
111 | return newState(state, {description: action.description})
112 | }),
113 |
114 | on(Actions.modifyShortDescription, (state, action): EditorState => {
115 | return newState(state, {shortDescription: action.shortDescription})
116 | }),
117 |
118 | on(Actions.modifyGithubUrl, (state, action): EditorState => {
119 | const github = newState(state.github, {url: action.url})
120 | return newState(state, {github: github})
121 | }),
122 |
123 | on(Actions.modifyNavigation, (state, action): EditorState => {
124 | return newState(state, {navigationLinks: action.navigation})
125 | }),
126 |
127 | on(Actions.modifyContentTable, (state, action): EditorState => {
128 | return newState(state, {contentTable: action.contentTable})
129 | }),
130 |
131 | on(Actions.modifyGithubBadge, (state, action): EditorState => {
132 | const github = newState(state.github, {badges: action.badge})
133 | return newState(state, {github: github})
134 | }),
135 |
136 | on(Actions.modifyNpmUrl, (state, action): EditorState => {
137 | const npm = newState(state.npm, {url: action.url})
138 | return newState(state, {npm: npm})
139 | }),
140 |
141 | on(Actions.modifyNpmBadge, (state, action): EditorState => {
142 | const npm = newState(state.npm, {badges: action.badge})
143 | return newState(state, {npm: npm})
144 | }),
145 |
146 | on(Actions.modifyLogoUrl, (state, action): EditorState => {
147 | return newState(state, {logoUrl: action.logoUrl})
148 | }),
149 |
150 | on(Actions.modifyMainImageUrl, (state, action): EditorState => {
151 | return newState(state, {mainImageUrl: action.mainImageUrl})
152 | }),
153 |
154 | on(Actions.modifyImages, (state, action): EditorState => {
155 | return newState(state, {images: action.images})
156 | }),
157 |
158 | on(Actions.addTechnologies, (state, action): EditorState => {
159 | return newState(state, {technologies: action.technologies})
160 | }),
161 |
162 | on(Actions.removeTechnology, (state, action): EditorState => {
163 | return newState(state, {technologies: []})
164 | }),
165 |
166 | on(Actions.modifyAcknowledgement, (state, action): EditorState => {
167 | return newState(state, {acknowledgments: action.acknowledgements || []})
168 | }),
169 |
170 | on(Actions.modifyContributors, (state, action): EditorState => {
171 | return newState(state, {contributors: action.contributors || []})
172 | }),
173 |
174 | on(Actions.modifyContribution, (state, action): EditorState => {
175 | const contribution = newState(state.contribution, {add: action.contribution})
176 | return newState(state, {contribution: contribution})
177 | }),
178 |
179 | on(Actions.modifyContributionGuideline, (state, action): EditorState => {
180 | const contribution = newState(state.contribution, {contributionGuidelinesLink: action.contributionGuidelinesLink})
181 | return newState(state, {contribution: contribution})
182 | }),
183 |
184 | on(Actions.modifyAuthorName, (state, action): EditorState => {
185 | const author = newState(state.author, {name: action.authorName})
186 | return newState(state, {author: author})
187 | }),
188 |
189 | on(Actions.modifyAuthorGithub, (state, action): EditorState => {
190 | const author = newState(state.author, {github: action.authorGithub})
191 | return newState(state, {author: author})
192 | }),
193 |
194 | on(Actions.addLicense, (state, action): EditorState => {
195 | return newState(state, {license: action.license})
196 | }),
197 |
198 | on(Actions.toggleBackToTop, (state, action): EditorState => {
199 | return newState(state, {backToTop: action.backToTop})
200 | }),
201 |
202 | on(Actions.toggleContributorsImg, (state, action): EditorState => {
203 | const contribution = newState(state.contribution, {contributorsImg: action.contributorsImg})
204 | return newState(state, {contribution})
205 | }),
206 |
207 | on(Actions.toggleSectionIcons, (state, action): EditorState => {
208 | return newState(state, {sectionIcons: action.sectionIcons})
209 | }),
210 |
211 | on(Actions.removeLicense, (state, action): EditorState => {
212 | const license = {type: undefined, customText: undefined};
213 | return newState(state, {license: license})
214 | }),
215 |
216 | on(Actions.modifyCustomLicense, (state, action): EditorState => {
217 | const license = newState(state.license, {customText: action.customText})
218 | return newState(state, {license: license})
219 | }),
220 |
221 | on(Actions.modifyFeatures, (state, action): EditorState => {
222 | return newState(state, {features: action.features || []})
223 | }),
224 |
225 | on(Actions.modifyInstallation, (state, action): EditorState => {
226 | return newState(state, {installSteps: action.steps || []})
227 | }),
228 |
229 | on(Actions.modifyUsage, (state, action): EditorState => {
230 | return newState(state, {installUsage: action.steps || []})
231 | }),
232 |
233 | on(Actions.displayMarkdownResult, (state, action): EditorState => {
234 | return newState(state, {displayMarkdownResult: true})
235 | }),
236 |
237 | on(Actions.hideMarkdownResult, (state, action): EditorState => {
238 | return newState(state, {displayMarkdownResult: false})
239 | }),
240 |
241 | on(Actions.generateMarkdown, (state, action): EditorState => {
242 | return newState(state, {generateMarkdown: action.generate})
243 | }),
244 |
245 | on(Actions.markdownGenerated, (state, action): EditorState => {
246 | return newState(state, {
247 | generateMarkdown: false,
248 | generatedMarkdown: action.markdown,
249 | displayMarkdownResult: true
250 | })
251 | }),
252 |
253 | on(Actions.setData, (state, action): EditorState => {
254 | return newState(state, action.data)
255 | }),
256 | );
257 |
258 | const newState = (oldState: any, newData: any): EditorState => {
259 | const newState = {...oldState, ...newData}
260 | console.log('calculating new state', newData, newState)
261 | return newState
262 | }
263 |
--------------------------------------------------------------------------------
/src/app/store/reducers/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ActionReducerMap,
3 | } from '@ngrx/store';
4 | import {AppState} from "../state.interface";
5 | import {editorReducer} from "./editor.reducer";
6 |
7 | export const reducers: ActionReducerMap = {
8 | editor: editorReducer
9 | };
10 |
11 |
--------------------------------------------------------------------------------
/src/app/store/selectors/editor.selectors.ts:
--------------------------------------------------------------------------------
1 | import {AppState} from "../state.interface";
2 | import {createSelector} from "@ngrx/store";
3 | import {EditorState} from "../reducers/editor.reducer";
4 |
5 | export const editorSelector = (state: AppState) => state.editor;
6 |
7 | export const selectGeneratedMarkdown = createSelector(
8 | editorSelector,
9 | (state: EditorState) => state.generatedMarkdown)
10 |
11 | export const selectGeneratingMarkdown = createSelector(
12 | editorSelector,
13 | (state: EditorState) => state.generateMarkdown)
14 | export const selectDescription = createSelector(
15 | editorSelector,
16 | (state: EditorState) => state.description)
17 | export const selectTitle = createSelector(
18 | editorSelector,
19 | (state: EditorState) => state.title)
20 |
21 | export const selectShortDescription = createSelector(
22 | editorSelector,
23 | (state: EditorState) => state.shortDescription)
24 |
25 | export const selectContentTable = createSelector(
26 | editorSelector,
27 | (state: EditorState) => state.contentTable)
28 |
29 | export const selectNavigationLinks = createSelector(
30 | editorSelector,
31 | (state: EditorState) => state.navigationLinks)
32 |
33 | export const selectFeatures = createSelector(
34 | editorSelector,
35 | (state: EditorState) => state.features)
36 |
37 |
38 | export const selectRepository = createSelector(
39 | editorSelector,
40 | (state: EditorState) => state.github.repo)
41 |
42 | export const selectRepositoryBadges = createSelector(
43 | editorSelector,
44 | (state: EditorState) => state.github.badges)
45 |
46 | export const selectNpmPackage = createSelector(
47 | editorSelector,
48 | (state: EditorState) => state.npm.url)
49 |
50 | export const selectNpmBadges = createSelector(
51 | editorSelector,
52 | (state: EditorState) => state.npm.badges)
53 |
54 | export const selectBackToTop = createSelector(
55 | editorSelector,
56 | (state: EditorState) => state.backToTop)
57 |
58 | export const selectSectionIcons = createSelector(
59 | editorSelector,
60 | (state: EditorState) => state.sectionIcons)
61 |
62 | export const selectLogo = createSelector(
63 | editorSelector,
64 | (state: EditorState) => state.logoUrl)
65 |
66 | export const selectMainImage = createSelector(
67 | editorSelector,
68 | (state: EditorState) => state.mainImageUrl)
69 |
70 | export const selectScreenshots = createSelector(
71 | editorSelector,
72 | (state: EditorState) => state.images)
73 |
74 | export const selectStackTech = createSelector(
75 | editorSelector,
76 | (state: EditorState) => state.technologies.map(t => t.value))
77 |
78 | export const selectInstallSteps = createSelector(
79 | editorSelector,
80 | (state: EditorState) => state.installSteps)
81 |
82 | export const selectUsageSteps = createSelector(
83 | editorSelector,
84 | (state: EditorState) => state.usageSteps)
85 |
86 | export const selectParameters = createSelector(
87 | editorSelector,
88 | (state: EditorState) => state.configuration.parameters)
89 |
90 | export const selectAcknowledgment = createSelector(
91 | editorSelector,
92 | (state: EditorState) => state.acknowledgments)
93 |
94 | export const selectContribution = createSelector(
95 | editorSelector,
96 | (state: EditorState) => state.contribution)
97 |
98 | export const selectContributors = createSelector(
99 | editorSelector,
100 | (state: EditorState) => state.contributors)
101 |
102 | export const selectAuthorName = createSelector(
103 | editorSelector,
104 | (state: EditorState) => state.author.name)
105 |
106 | export const selectAuthorGithubUsername = createSelector(
107 | editorSelector,
108 | (state: EditorState) => state.author.github)
109 |
110 |
111 | export const selectAuthorLinkedinUsername = createSelector(
112 | editorSelector,
113 | (state: EditorState) => state.author.likedIn ?? '')
114 |
115 |
116 | export const selectLicense = createSelector(
117 | editorSelector,
118 | (state: EditorState) => state.license)
119 |
--------------------------------------------------------------------------------
/src/app/store/state.interface.ts:
--------------------------------------------------------------------------------
1 | import {EditorState} from "./reducers/editor.reducer";
2 |
3 | export interface AppState {
4 | editor: EditorState,
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/toast/toast.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/app/toast/toast.component.css
--------------------------------------------------------------------------------
/src/app/toast/toast.component.html:
--------------------------------------------------------------------------------
1 |
4 |
11 |
13 |
15 |
16 |
17 |
Warning icon
18 |
19 |
{{ toast.message }}
20 |
24 | Close
25 |
26 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/app/toast/toast.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { ToastComponent } from './toast.component';
4 |
5 | describe('ToastComponent', () => {
6 | let component: ToastComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ ToastComponent ]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(ToastComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/src/app/toast/toast.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Input} from '@angular/core';
2 | import {UtilsService} from "../services/utils.service";
3 | import {animate, style, transition, trigger} from "@angular/animations";
4 | import {Toast, ToastService} from "../services/toast.service";
5 |
6 | @Component({
7 | selector: 'app-toast',
8 | templateUrl: './toast.component.html',
9 | styleUrls: ['./toast.component.css'],
10 | animations: [
11 | trigger('fade', [
12 | transition(':enter', [
13 | style({transform: 'translateY(10%)', opacity: 0}),
14 | animate('400ms', style({transform: 'translateY(0)', opacity: 1})),
15 | ]),
16 | transition(':leave', [
17 | style({transform: 'translateY(0)', opacity: 1}),
18 | animate('200ms', style({transform: 'translateY(-5%)', opacity: 0})),
19 | ]),
20 | ]),
21 | ]
22 | })
23 | export class ToastComponent {
24 |
25 | @Input()
26 | toast!: Toast;
27 |
28 |
29 | constructor(private utilsService: UtilsService, private toastService: ToastService) {
30 | }
31 |
32 | close() {
33 | this.toastService.close(this.toast.id);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/.gitkeep
--------------------------------------------------------------------------------
/src/assets/beams.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/beams.jpg
--------------------------------------------------------------------------------
/src/assets/fonts/IBM Plex Sans Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/fonts/IBM Plex Sans Regular.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/PP Agrandir Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/fonts/PP Agrandir Bold.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/PP Agrandir Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/fonts/PP Agrandir Regular.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/TN Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/fonts/TN Light.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/TN Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/fonts/TN Medium.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/TN Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/fonts/TN Regular.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/iA Writter Quattro S Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/fonts/iA Writter Quattro S Regular.woff2
--------------------------------------------------------------------------------
/src/assets/grid.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/assets/images/devhunt_badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/devhunt_badge.png
--------------------------------------------------------------------------------
/src/assets/images/dmp_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/dmp_1.png
--------------------------------------------------------------------------------
/src/assets/images/dmp_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/dmp_2.png
--------------------------------------------------------------------------------
/src/assets/images/dmp_s_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/dmp_s_1.png
--------------------------------------------------------------------------------
/src/assets/images/dmp_s_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/dmp_s_2.png
--------------------------------------------------------------------------------
/src/assets/images/dmp_s_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/dmp_s_3.png
--------------------------------------------------------------------------------
/src/assets/images/dmp_s_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/dmp_s_4.png
--------------------------------------------------------------------------------
/src/assets/images/github_corner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/github_corner.png
--------------------------------------------------------------------------------
/src/assets/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/assets/images/icon.png
--------------------------------------------------------------------------------
/src/data/mock.ts:
--------------------------------------------------------------------------------
1 | import {EditorState} from "../app/store/reducers/editor.reducer";
2 | import {LicenseType} from "../app/enums/license-type.enum";
3 |
4 | export const testData: EditorState = {
5 | title: 'Document My Project',
6 | shortDescription: 'Easily create markdown documentation for your project',
7 | description: 'Tired of manually writing README files? this tool simplifies the process of creating documentation for Github projects. With just a few clicks, you can generate comprehensive documentation that enhances the visibility and usability of your repositories in seconds.',
8 | navigationLinks: true,
9 | sectionIcons: true,
10 | backToTop: true,
11 | installSteps: [
12 | 'Install Node.js v16 or later',
13 | 'Install the required dependencies:',
14 | '`npm install`'
15 | ],
16 | usageSteps: [
17 | 'Open the project directory in your code editor',
18 | 'Run `npm run start` to start the development server',
19 | ],
20 | contentTable: true,
21 | github: {
22 | username: 'luisvent',
23 | repo: 'document_my_project',
24 | badges: true
25 | },
26 | logoUrl: '../assets/images/icon.png',
27 | mainImageUrl: '../assets/images/dmp_1.png',
28 | displayMarkdownResult: false,
29 | npm: {
30 | package: 'http-status-utility',
31 | url: 'https://www.npmjs.com/package/http-status-utility',
32 | badges: true
33 | },
34 | images: [
35 | '../assets/images/dmp_s_1.png',
36 | '../assets/images/dmp_s_2.png',
37 | '../assets/images/dmp_s_3.png',
38 | '../assets/images/dmp_s_4.png',
39 | ],
40 | features: [
41 | {
42 | title: 'Template ready',
43 | description: 'Provide a clear and concise description of your project, highlight the main features, goals, and benefits of your project'
44 | },
45 | {
46 | title: 'Ease fo use',
47 | description: 'Easily generate a well-structured README file for your GitHub project'
48 | },
49 | {
50 | title: 'Preview',
51 | description: 'Preview the generated README (light/dark theme) file before committing it to your repository'
52 | }
53 | ],
54 | technologies: [
55 | {
56 | name: 'Angular',
57 | value: 'angular',
58 | description: "A front-end web application framework",
59 | mainColor: "#DD0031"
60 | },
61 | {name: 'NgRx', value: 'ngrx', description: "Angular state management based on Redux", mainColor: "#B7116E"},
62 | {name: 'Tailwind CSS', value: 'tailwindcss', description: 'Utility-first CSS framework', mainColor: '#38B2AC'},
63 | {
64 | name: 'TypeScript',
65 | value: 'typescript',
66 | description: "A strict syntactical superset of JavaScript",
67 | mainColor: "#3178C6"
68 | },
69 | ],
70 | installation: {
71 | projectName: '',
72 | packageManager: '',
73 | dependencies: [],
74 | devDependencies: [],
75 | installationSteps: [],
76 | includeSetup: false,
77 | setupSteps: [],
78 | includeUsage: false,
79 | usageSteps: [],
80 | },
81 | configuration: {
82 | description: 'Default values to configure',
83 | parameters: []
84 | },
85 | acknowledgments: [
86 | {
87 | title: 'ngx-markdown',
88 | url: 'https://www.npmjs.com/package/ngx-markdown',
89 | description: 'Angular markdown component/directive/pipe/service to parse static, dynamic or remote content to HTML with syntax highlight and more'
90 | },
91 | {
92 | title: 'Flowbite',
93 | url: 'https://flowbite.com/',
94 | description: 'Build websites even faster with components on top of Tailwind CSS'
95 | },
96 | {
97 | title: 'PrismJs',
98 | url: 'https://prismjs.com/',
99 | description: 'Prism is a lightweight, extensible syntax highlighter, built with modern web standards in mind. It’s used in millions of websites, including some of those you visit daily.'
100 | }
101 | ],
102 | contribution: {add: true, contributorsImg: true, contributionGuidelinesLink: undefined},
103 | contributors: [
104 | {
105 | name: 'Luis Ventura',
106 | username: 'luisvent'
107 | }
108 | ],
109 | author: {
110 | name: 'Luis Ventura',
111 | email: 'luis.ventura@email.com',
112 | url: 'luisvent.com ',
113 | github: 'luisvent',
114 | likedIn: 'luisvent',
115 | },
116 | license: {type: LicenseType.MIT, customText: undefined},
117 | watermark: true,
118 | generateMarkdown: false,
119 | generatedMarkdown: ''
120 | };
121 |
--------------------------------------------------------------------------------
/src/data/tech-services.ts:
--------------------------------------------------------------------------------
1 | export const techService = [
2 | {name: 'Continuous Integration', value: 'continuous-integration'},
3 | {name: 'Continuous Deployment', value: 'continuous-deployment'},
4 | {name: 'Continuous Delivery', value: 'continuous-delivery'},
5 | {name: 'Microservices', value: 'microservices'},
6 | {name: 'Serverless', value: 'serverless'},
7 | {name: 'Containerization', value: 'containerization'},
8 | {name: 'Virtualization', value: 'virtualization'},
9 | {name: 'Infrastructure as Code', value: 'infrastructure-as-code'},
10 | {name: 'Configuration Management', value: 'configuration-management'},
11 | {name: 'Monitoring', value: 'monitoring'},
12 | {name: 'Logging', value: 'logging'},
13 | {name: 'Alerting', value: 'alerting'},
14 | {name: 'Incident Management', value: 'incident-management'},
15 | {name: 'Collaboration', value: 'collaboration'},
16 | {name: 'Project Management', value: 'project-management'},
17 | {name: 'Task Management', value: 'task-management'},
18 | {name: 'Note-taking', value: 'note-taking'},
19 | {name: 'Time Management', value: 'time-management'},
20 | {name: 'Documentation', value: 'documentation'},
21 | {name: 'Knowledge Management', value: 'knowledge-management'},
22 | {name: 'Team Communication', value: 'team-communication'},
23 | {name: 'Video Conferencing', value: 'video-conferencing'},
24 | {name: 'Chat', value: 'chat'},
25 | {name: 'Issue Tracking', value: 'issue-tracking'},
26 | {name: 'Workflow Management', value: 'workflow-management'},
27 | {name: 'Task Automation', value: 'task-automation'},
28 | {name: 'Deployment Automation', value: 'deployment-automation'},
29 | {name: 'CI/CD Pipeline', value: 'ci-cd-pipeline'},
30 | {name: 'Observability', value: 'observability'},
31 | {name: 'Dashboards', value: 'dashboards'},
32 | {name: 'Performance Monitoring', value: 'performance-monitoring'},
33 | {name: 'Error Tracking', value: 'error-tracking'},
34 | {name: 'Event Monitoring', value: 'event-monitoring'},
35 | {name: 'Infrastructure Monitoring', value: 'infrastructure-monitoring'},
36 | {name: 'Log Management', value: 'log-management'},
37 | {name: 'Application Performance Monitoring', value: 'application-performance-monitoring'},
38 | {name: 'Transaction Monitoring', value: 'transaction-monitoring'},
39 | {name: 'User Monitoring', value: 'user-monitoring'},
40 | {name: 'Business Monitoring', value: 'business-monitoring'},
41 | {name: 'AIOps', value: 'aiops'},
42 | {name: 'Site Reliability Engineering (SRE)', value: 'sre'},
43 | {name: 'IT Operations', value: 'it-operations'},
44 | {name: 'DevSecOps', value: 'devsecops'},
45 | {name: 'GitOps', value: 'gitops'},
46 | {name: 'Cloud Computing', value: 'cloud-computing'},
47 | {name: 'Networking', value: 'networking'},
48 | {name: 'Cybersecurity', value: 'cybersecurity'},
49 | {name: 'Identity and Access Management (IAM)', value: 'iam'},
50 | {name: 'Encryption', value: 'encryption'},
51 | {name: 'Firewalls', value: 'firewalls'},
52 | {name: 'Intrusion Detection and Prevention Systems (IDPS)', value: 'idps'},
53 | {name: 'Data Loss Prevention (DLP)', value: 'dlp'},
54 | {name: 'Antivirus', value: 'antivirus'},
55 | {name: 'Security Information and Event Management (SIEM)', value: 'siem'},
56 | {name: 'Vulnerability Management', value: 'vulnerability-management'},
57 | {name: 'Penetration Testing', value: 'penetration-testing'},
58 | {name: 'Security Operations Center (SOC)', value: 'soc'},
59 | {name: 'Security Orchestration, Automation, and Response (SOAR)', value: 'soar'},
60 | {name: 'Compliance', value: 'compliance'},
61 | {name: 'GDPR', value: 'gdpr'},
62 | {name: 'HIPAA', value: 'hipaa'},
63 | {name: 'PCI DSS', value: 'pci-dss'},
64 | {name: 'ISO 27001', value: 'iso-27001'},
65 | {name: 'NIST', value: 'nist'},
66 | {name: 'CIS Controls', value: 'cis-controls'},
67 | {name: 'OWASP', value: 'owasp'},
68 | {name: 'Zero Trust', value: 'zero-trust'},
69 | {name: 'Multi-factor Authentication (MFA)', value: 'mfa'},
70 | {name: 'Single Sign-On (SSO)', value: 'sso'},
71 | {name: 'Role-based Access Control (RBAC)', value: 'rbac'},
72 | {name: 'Privileged Access Management (PAM)', value: 'pam'},
73 | {name: 'Security Information Sharing', value: 'security-information-sharing'},
74 | {name: 'Threat Intelligence', value: 'threat-intelligence'},
75 | {name: 'Security Awareness Training', value: 'security-awareness-training'},
76 | {name: 'Phishing Simulation', value: 'phishing-simulation'},
77 | {name: 'Security Policies and Procedures', value: 'security-policies-procedures'},
78 | {name: 'Incident Response Plan', value: 'incident-response-plan'},
79 | {name: 'Business Continuity Plan (BCP)', value: 'business-continuity-plan'},
80 | {name: 'Disaster Recovery Plan (DRP)', value: 'disaster-recovery-plan'},
81 | {name: 'Security Risk Assessment', value: 'security-risk-assessment'},
82 | {name: 'Security Controls', value: 'security-controls'},
83 | {name: 'Patch Management', value: 'patch-management'},
84 | {name: 'Asset Management', value: 'asset-management'},
85 | {name: 'Configuration Management', value: 'configuration-management'},
86 | {name: 'Change Management', value: 'change-management'},
87 | {name: 'Access Control', value: 'access-control'},
88 | {name: 'Network Security', value: 'network-security'},
89 | {name: 'Endpoint Security', value: 'endpoint-security'},
90 | {name: 'Data Security', value: 'data-security'},
91 | {name: 'Application Security', value: 'application-security'},
92 | {name: 'Cloud Security', value: 'cloud-security'},
93 | {name: 'Mobile Security', value: 'mobile-security'},
94 | {name: 'IoT Security', value: 'iot-security'},
95 | {name: 'Blockchain Security', value: 'blockchain-security'},
96 | {name: 'AI/ML Security', value: 'ai-ml-security'},
97 | {name: 'Deception Technology', value: 'deception-technology'},
98 | {name: 'Security Operations', value: 'security-operations'},
99 | {name: 'Forensics', value: 'forensics'},
100 | {name: 'Cyber Threat Hunting', value: 'cyber-threat-hunting'},
101 | {name: 'Cyber Threat Intelligence', value: 'cyber-threat-intelligence'},
102 | {name: 'Malware Analysis', value: 'malware-analysis'},
103 | {name: 'Digital Forensics', value: 'digital-forensics'},
104 | {name: 'Network Forensics', value: 'network-forensics'},
105 | {name: 'Incident Response', value: 'incident-response'},
106 | {name: 'Security Incident Management', value: 'security-incident-management'},
107 | {name: 'Fraud Detection', value: 'fraud-detection'},
108 | {name: 'Identity Theft Protection', value: 'identity-theft-protection'},
109 | {name: 'Data Breach Prevention', value: 'data-breach-prevention'},
110 | {name: 'Zero-Day Exploit Prevention', value: 'zero-day-exploit-prevention'},
111 | {name: 'Insider Threat Detection', value: 'insider-threat-detection'},
112 | {name: 'External Threat Intelligence', value: 'external-threat-intelligence'},
113 | {name: 'Internal Threat Intelligence', value: 'internal-threat-intelligence'},
114 | {name: 'Third-party Risk Management', value: 'third-party-risk-management'},
115 | {name: 'Compliance Management', value: 'compliance-management'},
116 | {name: 'Security Awareness', value: 'security-awareness'},
117 | {name: 'Privacy', value: 'privacy'},
118 | {name: 'Identity Management', value: 'identity-management'},
119 | {name: 'Access Management', value: 'access-management'},
120 | {name: 'Directory Services', value: 'directory-services'},
121 | {name: 'Authentication', value: 'authentication'},
122 | {name: 'Authorization', value: 'authorization'},
123 | ];
124 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luisvent/document_my_project/941ff74a3ca51797886cfd2580f4da0d563034f0/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document My Project
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
2 |
3 | import { AppModule } from './app/app.module';
4 |
5 |
6 | platformBrowserDynamic().bootstrapModule(AppModule)
7 | .catch(err => console.error(err));
8 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | @font-face {
7 | font-family: Writter;
8 | src: url('./assets/fonts/iA Writter Quattro S Regular.woff2') format("woff2");
9 | }
10 | @font-face {
11 | font-family: Agrandir;
12 | src: url('./assets/fonts/PP Agrandir Regular.woff2') format("woff2");
13 | }
14 | @font-face {
15 | font-family: TN;
16 | src: url('./assets/fonts/TN Medium.woff2') format("woff2");
17 | }
18 | }
19 |
20 | body {
21 | @apply text-slate-600 font-writter
22 | }
23 |
24 | p {
25 | @apply text-lg font-normal text-gray-500 lg:text-xl dark:text-gray-400
26 | }
27 |
28 | h1 {
29 | @apply mb-4 text-4xl font-extrabold leading-none tracking-tight text-gray-900 md:text-5xl lg:text-6xl dark:text-white text-slate-600
30 | }
31 |
32 | h2 {
33 | @apply text-5xl font-bold dark:text-white mb-2 mt-3 text-slate-600
34 | }
35 |
36 | h3 {
37 | @apply text-3xl font-bold dark:text-white mb-2 mt-3 text-slate-600
38 | }
39 |
40 | h4 {
41 | @apply text-2xl font-bold dark:text-white mb-2 mt-3 text-slate-600
42 | }
43 |
44 | h5 {
45 | @apply text-xl font-bold dark:text-white mb-2 mt-3 text-slate-600
46 | }
47 |
48 |
49 | h6 {
50 | @apply text-sm font-bold dark:text-white mb-2 mt-3 text-slate-600
51 | }
52 |
53 | small {
54 | @apply text-[12px] text-slate-500
55 | }
56 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | import defaultTheme from 'tailwindcss/defaultTheme'
3 |
4 | module.exports = {
5 | content: [
6 | "./src/**/*.{html,ts}",
7 | "./node_modules/flowbite/**/*.js"
8 | ],
9 | theme: {
10 | extend: {
11 | height: {
12 | '100vh-h-7': 'calc(100vh - 12rem)',
13 | },
14 | fontFamily: {
15 | writter: ["Writter", ...defaultTheme.fontFamily.sans],
16 | agrandir: ["Agrandir", ...defaultTheme.fontFamily.sans],
17 | tn: ["TN", ...defaultTheme.fontFamily.sans],
18 | },
19 | },
20 | },
21 | plugins: [
22 | require("@tailwindcss/typography"),
23 | require('flowbite/plugin')
24 | ],
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts"
10 | ],
11 | "include": [
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "strict": true,
9 | "noImplicitOverride": true,
10 | "noPropertyAccessFromIndexSignature": true,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "sourceMap": true,
14 | "declaration": false,
15 | "downlevelIteration": true,
16 | "experimentalDecorators": true,
17 | "moduleResolution": "node",
18 | "importHelpers": true,
19 | "target": "ES2022",
20 | "module": "ES2022",
21 | "useDefineForClassFields": false,
22 | "lib": [
23 | "ES2022",
24 | "dom"
25 | ]
26 | },
27 | "angularCompilerOptions": {
28 | "enableI18nLegacyMessageIdFormat": false,
29 | "strictInjectionParameters": true,
30 | "strictInputAccessModifiers": true,
31 | "strictTemplates": true
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/spec",
6 | "types": [
7 | "jasmine"
8 | ]
9 | },
10 | "include": [
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------