diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..053c536 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,15 @@ + + +## Contributing + +Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. + +If you have a suggestion to better our API, please fork the repo and create a pull request. Additionally, you can open an issue and offer advice. +Don't forget to give the project a star! Thanks again! + +1. Visit our Issues page to check if an issue exists and does not have an assignee. +2. Fork the Project +3. Change to your Feature Branch (`git checkout -b feature/AmazingFeature`) +4. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) +5. Push to the Branch (`git push origin feature/AmazingFeature`) +6. Open a Pull Request diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..fb48127 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 the-api-administration + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index e69de29..c6da429 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,154 @@ +# Coding-Resources-API + +
+ +[![Contributors][contributors-shield]][contributors-url] +[![Forks][forks-shield]][forks-url] +[![Stargazers][stars-shield]][stars-url] +[![Issues][issues-shield]][issues-url] +[![MIT License][license-shield]][license-url] + + +
+
+ + Logo + + +

Coding Resources API

+ +

+ Provides Coding Resources +
+ Explore the docs » +
+
+ View Demo + · + Report Bug + · + Request Feature +

+
+ + +
+ Table of Contents +
    +
  1. + About The Project + +
  2. +
  3. Getting Started
  4. +
  5. Usage
  6. +
  7. Roadmap
  8. +
  9. Contributing
  10. +
  11. License
  12. +
  13. Acknowledgments
  14. +
+
+ + + +## About The Project + +Search for coding resources by relevant keywords. This API serves educational content for a wide variety of computer science topics, languages and technologies relevant to web development. + +

(back to top)

+ +### Built With + +- EJS +- CSS +- JavaScript +- Node.js +- Express + +

(back to top)

+ + + +## Getting Started + +Simply visit: https://coding-resources-api.herokuapp.com/ and read our documentation to learn how to interact with our API! If you would like to help us out, feel free to create issues through our github repo. + +

(back to top)

+ + + +## Usage + +Access our API endpoints to recieve coding resource data in JSON format. + +

(back to top)

+ + + +## Roadmap + +- [X] Add search functionality +- [ ] Offer more resources +- [ ] Support mobile devices +- [ ] Create more endpoints + +See the [open issues](https://github.com/the-api-administration/coding-resources-api/issues) for a full list of proposed features (and known issues). + +

(back to top)

+ + + +## Contributing + +Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. + +If you have a suggestion to better our API, please fork the repo and create a pull request. Additionally, you can open an issue and offer advice. +Don't forget to give the project a star! Thanks again! + +1. Visit our Issues page to check if an issue exists and does not have an assignee. +2. Fork the Project +3. Change to your Feature Branch (`git checkout -b feature/AmazingFeature`) +4. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) +5. Push to the Branch (`git push origin feature/AmazingFeature`) +6. Open a Pull Request + +

(back to top)

+ + + +## License + +Distributed under the MIT License. See `LICENSE.md` for more information. + +

(back to top)

+ + + +## Acknowledgments + +- [@AlexisInTech](https://twitter.com/alexisintech) +- [@AlysshaLewin](https://twitter.com/AlysshaLewin) +- [@Asper_Jacob](https://twitter.com/asper_jacob) +- [@BrianSchneeDev](https://twitter.com/BrianSchneeDev) +- [@BytesByBianca](https://twitter.com/bytesbybianca) +- [@DanaMiteCoder](https://twitter.com/danamitecoder) +- [@Dev_Ethos](https://twitter.com/dev_ethos/) +- [@ErikaTeal_](https://twitter.com/erikateal_) +- [@JacobEGood](https://twitter.com/jacobegood) +- [@MoraCodes](https://twitter.com/moracodes) + +

(back to top)

+ + + +[contributors-shield]: https://img.shields.io/github/contributors/the-api-administration/coding-resources-api.svg?style=for-the-badge +[contributors-url]: https://github.com/the-api-administration/coding-resources-api/graphs/contributors +[forks-shield]: https://img.shields.io/github/forks/the-api-administration/coding-resources-api.svg?style=for-the-badge +[forks-url]: https://github.com/the-api-administration/coding-resources-api/network/members +[stars-shield]: https://img.shields.io/github/stars/the-api-administration/coding-resources-api.svg?style=for-the-badge +[stars-url]: https://github.com/the-api-administration/coding-resources-api/stargazers +[issues-shield]: https://img.shields.io/github/issues/the-api-administration/coding-resources-api.svg?style=for-the-badge +[issues-url]: https://github.com/the-api-administration/coding-resources-api/issues +[license-shield]: https://img.shields.io/github/license/the-api-administration/coding-resources-api.svg?style=for-the-badge +[license-url]: https://github.com/the-api-administration/coding-resources-api/blob/master/LICENSE.md diff --git a/index.html b/index.html deleted file mode 100644 index 4b27836..0000000 --- a/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - Resources API - - - - - - -
- -
-
-

Coding Resources API-

-

- Search for coding resources by relevant keywords. - This API serves educational content for a wide - variety of computer science topics, languages and - technologies relevant to web development. -

-
-
-
- - -
-
-
-
-
-
-

Documentation

-
-
- - - diff --git a/package-lock.json b/package-lock.json index 03e3591..f8b29e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "cors": "^2.8.5", + "ejs": "^3.1.8", "express": "^4.18.1" } }, @@ -25,11 +26,35 @@ "node": ">= 0.6" } }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -53,6 +78,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -73,6 +107,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -147,6 +217,20 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -209,6 +293,33 @@ "node": ">= 0.10.0" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -271,6 +382,14 @@ "node": ">= 0.4.0" } }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -321,6 +440,23 @@ "node": ">= 0.10" } }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -372,6 +508,17 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -565,6 +712,17 @@ "node": ">= 0.8" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -620,11 +778,29 @@ "negotiator": "0.6.3" } }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, "body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -644,6 +820,15 @@ "unpipe": "1.0.0" } }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -658,6 +843,33 @@ "get-intrinsic": "^1.0.2" } }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -713,6 +925,14 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "requires": { + "jake": "^10.8.5" + } + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -766,6 +986,32 @@ "vary": "~1.1.2" } }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -813,6 +1059,11 @@ "function-bind": "^1.1.1" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -848,6 +1099,17 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -881,6 +1143,14 @@ "mime-db": "1.52.0" } }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1020,6 +1290,14 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", diff --git a/package.json b/package.json index 0d8ae87..b4c9e0a 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,14 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" }, "author": "", "license": "ISC", "dependencies": { "cors": "^2.8.5", + "ejs": "^3.1.8", "express": "^4.18.1" } } diff --git a/public/assets/Alex.png b/public/assets/Alex.png new file mode 100644 index 0000000..f3b01f3 Binary files /dev/null and b/public/assets/Alex.png differ diff --git a/public/assets/Alondra.png b/public/assets/Alondra.png new file mode 100644 index 0000000..7a3c70d Binary files /dev/null and b/public/assets/Alondra.png differ diff --git a/public/assets/Alyssha.jpg b/public/assets/Alyssha.jpg new file mode 100644 index 0000000..8fe1cb6 Binary files /dev/null and b/public/assets/Alyssha.jpg differ diff --git a/public/assets/Bianca.jpg b/public/assets/Bianca.jpg new file mode 100644 index 0000000..6ef2fa6 Binary files /dev/null and b/public/assets/Bianca.jpg differ diff --git a/public/assets/Brian.png b/public/assets/Brian.png new file mode 100644 index 0000000..6406870 Binary files /dev/null and b/public/assets/Brian.png differ diff --git a/public/assets/Dana.jpg b/public/assets/Dana.jpg new file mode 100644 index 0000000..8ecbf19 Binary files /dev/null and b/public/assets/Dana.jpg differ diff --git a/public/assets/Erika.jpg b/public/assets/Erika.jpg new file mode 100644 index 0000000..e21da1c Binary files /dev/null and b/public/assets/Erika.jpg differ diff --git a/public/assets/Jacob.jpg b/public/assets/Jacob.jpg new file mode 100644 index 0000000..8872e78 Binary files /dev/null and b/public/assets/Jacob.jpg differ diff --git a/public/assets/JacobGood.jpg b/public/assets/JacobGood.jpg new file mode 100644 index 0000000..c77622b Binary files /dev/null and b/public/assets/JacobGood.jpg differ diff --git a/public/assets/Sebastian.png b/public/assets/Sebastian.png new file mode 100644 index 0000000..b9e1f45 Binary files /dev/null and b/public/assets/Sebastian.png differ diff --git a/public/assets/logo.svg b/public/assets/logo.svg index 0aac8d9..daeca1d 100644 --- a/public/assets/logo.svg +++ b/public/assets/logo.svg @@ -3,7 +3,7 @@ + c0-5.1,0-10.2-0.1-15.4c-0.1-2.4,0.6-3.5,3.2-3.5c6.5,0,6.4-0.1,6.3,6.4C188.2,247.2,188.3,256.1,188.3,265L188.3,265z"/> + C242.5,247,242.5,255.9,242.6,264.8L242.6,264.8z"/> + C417.3,247.2,417.2,256.1,417.3,265L417.3,265z"/> diff --git a/public/css/style.css b/public/css/style.css index 0798297..1b1e0a0 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,10 +1,42 @@ @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;800&display=swap'); +/* +================= Base Styles ================= +*/ + +ul { + margin: 1.5rem 2.5rem; + list-style: none; + padding: 0; +} + +pre { + margin: 0; +} + +a { + font-weight: 700; + text-decoration: none; + color: #4c8bf5; +} + +a:hover { + color: #3670d5; +} + +html { + scroll-behavior: smooth; +} + +/* +================= Additional Styles ================= +*/ + /* html */ html { font-family: 'Montserrat', sans-serif; - color: #141414; + color: rgb(30, 30, 30); } html * { @@ -16,7 +48,7 @@ html * { .frame { padding: 0; margin: 0; - border: solid 8px #141414; + border: solid 8px rgb(30, 30, 30); margin: 2rem; border-radius: 4rem; overflow: hidden; @@ -49,8 +81,9 @@ nav > img { /* contributors */ -.contributors { - --color: #141414; +#contributors { + --color: rgb(30, 30, 30); + background-color: #fff; position: relative; overflow: hidden; border: 3px solid var(--color); @@ -63,7 +96,7 @@ nav > img { color: var(--color); } -.contributors:before { +#contributors:before { content: ''; position: absolute; z-index: -1; @@ -76,18 +109,18 @@ nav > img { transition: all 0.4s; } -.contributors:hover { +#contributors:hover { color: #fff; cursor: pointer; } -.contributors:hover:before { +#contributors:hover:before { top: -32px; left: -30px; } -.contributors:active:before { - background: #141414; +#contributors:active:before { + background: rgb(30, 30, 30); transition: background 0s; } @@ -95,7 +128,8 @@ nav > img { main { display: flex; - padding: 2rem; + padding: 1.5rem; + margin-bottom: 2rem; } /* description */ @@ -109,18 +143,17 @@ main { } .description > h1 { - width: 70%; + width: 80%; font-size: 2.5rem; font-weight: 800; margin: 0; - display: inline; } .description > p { - font-size: 2.5rem; - width: 70%; - margin: 1rem 0; - display: inline; + font-size: 2rem; + width: 80%; + margin-top: 2rem; + margin-bottom: 0; } /* api-test */ @@ -128,10 +161,9 @@ main { .api-test { width: 50%; display: flex; - flex-wrap: wrap; flex-direction: column; - justify-content: space-between; align-items: center; + justify-content: space-around; } .api-test form { @@ -143,13 +175,12 @@ main { .api-test form input { width: 65%; - padding: 0 0; border-radius: 15px 0px 0px 15px; font-size: 0.8rem; padding-left: 1rem; transition: width 500ms ease; - border: solid 2px #141414; + border: solid 3px rgb(30, 30, 30); font-size: 1rem; font-weight: 600; } @@ -170,8 +201,8 @@ main { .api-test form button { width: 10%; - background-color: #141414; - border: solid 2px #141414; + background-color: rgb(30, 30, 30); + border: solid 2px rgb(30, 30, 30); border-radius: 0 15px 15px 0; font-size: 20px; } @@ -191,17 +222,396 @@ main { /* result */ .result { - width: 90%; - height: 70%; + width: 80%; + overflow: hidden; + border-radius: 25px; +} + +@media all and (min-width: 1280px) { + .result { + margin-top: 2rem; + } +} + +.scroll-container { + overflow-y: scroll; + overflow-x: hidden; + width: 100%; + height: 300px; border: dashed lightgray 2px; border-radius: 25px; } +.scroll-container::-webkit-scrollbar { + width: 12px; + background-color: #F5F5F5; +} + +.scroll-container::-webkit-scrollbar-thumb { + border-radius: 10px; + background-color: rgb(177, 177, 177); +} + +.scroll-container::-webkit-scrollbar-track { + border-radius: 10px; + background-color: #dbdbdb; +} + +.json { + display: block; + white-space: pre-wrap; +} + +.indent { + padding-left: 2rem; + margin-top: -2rem; + line-height: 2; +} + /* documentation */ .documentation { + padding: 3rem; + padding-bottom: 2rem; + background-color: lightgray; +} + +h4 { + font-size: 0.8rem; + margin: -1rem; + margin-bottom: 1rem; + font-weight: 500; + padding-left: 2rem; +} + +h2 { + margin: 0; + font-size: 1.8rem; + text-align: center; +} + +.object-table { + margin: 3rem 0; display: flex; + flex-direction: column; align-items: center; +} + +.object-table h3 { + font-size: 1.5rem; + font-weight: 500; + margin: 0; + margin-bottom: 3rem; +} + + + +/* table */ + +table.darkTable { + background-color: #FFFFFF; + width: 80%; + height: 200px; + text-align: center; + border-collapse: collapse; + border-radius: 15px; +} + +table.darkTable td, table.darkTable th { + padding: 2px 2px; + padding-top: 7px; +} + +table.darkTable tbody td { + font-size: 16px; + color: #1E1E1E; +} + +table.darkTable tr:nth-child(even) { + background: #e7e7e7; +} + +table.darkTable thead { + background: #1E1E1E; + border-bottom: 3px solid #1E1E1E; + +} + +table.darkTable thead th { + font-size: 17px; + font-weight: bold; + color: #E6E6E6; + text-align: center; +} + +table.darkTable thead th:first-child { + border-left: none; +} + +table.darkTable tfoot td { + font-size: 12px; +} + +table.darkTable #property { + border-radius: 15px 0 0 0; + border-right: 2px solid rgba(211, 211, 211, 0.3); +} + +table.darkTable #description{ + border-radius: 0 15px 0 0; +} + +table.darkTable #array{ + border-radius: 0 0 15px 0; +} + +table.darkTable #keywords{ + border-radius: 0 0 0 15px; +} + +#name, #url, #keywords { + border-right: 2px solid lightgray; +} + +/* Endpoints */ + +.endpoints { + margin: 3rem 0; + gap: 5rem; + display: flex; + justify-content: space-around; +} + +.endpoints h3 { + font-size: 1rem; + font-weight: 500; + margin: 0; +} + +.url, .js-fetch { + display: flex; + flex-direction: column; + gap: 2rem; + width: 50%; +} + +.js-fetch h3 { + text-align: center; +} + +.url code, .js-fetch code { + font-size: 1.2rem; + background: #fff; + padding: 0.8rem 1.2rem; + border-radius: 15px; +} + +.js-fetch code { + color: white; + font-size: 1.2rem; + background: #979797; + padding: 0.8rem 1.2rem; + border-radius: 15px; +} + +.endpoints span { + color: #F7BF50; + font-weight: 700; +} + +/* Contributor cards */ + +#contributors-title { + padding-top: 3rem; +} + +.contributors { + margin: 3rem 15rem; + display: flex; + flex-direction: row; + justify-content: center; +} + +@media all and (max-width: 1790px) { + .contributors { + margin: 3rem 11rem; + } +} + +@media all and (max-width: 1441px) { + .contributors { + margin: 3rem 3rem; + } +} + +.contributors .section { + padding: 0 2rem; + width: 435px; + display: flex; + flex-direction: column; justify-content: center; + align-items: center; +} +.card * { + margin: 0; + padding: 0; +} + +.card { + width: 100%; + height: 150px; + margin: 1.5rem; + border-radius: 12px; + box-shadow: 0.5px 0.5px 12px 0px #80808042; + display: flex; + align-items: center; + gap: 25px; + position: relative; + z-index: 2; + padding: 0 1.3rem; +} + +.card::after { + position: absolute; + content: ''; + width: 20%; + height: 100%; background-color: lightgray; + z-index: -2; + border-radius: 12px 0 0 12px; + top: 0; + left: 0; } + +.card img { + height: 109px; + width: 109px; + border-radius: 50%; + border: solid 3px lightgray; + object-fit: cover; +} + +.cont-info { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 10px; +} +.cont-info h4 { + color: #7a7a7a; + font-size: 1.7rem; + font-weight: 700; +} + +.icons { + display: flex; + gap: 1.5rem; + font-size: 1.8rem; +} + +#jacob::after { + background-color: #F37121; +} + +#jacob i { + color: #F37121; +} + +#erika::after { + background-color: #A6B4A2; +} + +#erika i { + color: #A6B4A2; +} + +#alexisintech::after { + background-color: #961711; +} + +#alexisintech i{ + color: #961711; +} + +#brian::after { + background-color: #0075bd; +} + +#brian i{ + color: #0075bd; +} + +#sebastian::after { + background-color: #0CA4BD; +} + +#sebastian i{ + color: #0CA4BD; +} + +#bianca::after { + background-color: #AE5ADB; +} + +#bianca i{ + color: #AE5ADB; +} + +#jacobg::after { + background-color: rgb(0, 85, 255); +} + +#jacobg i{ + color: rgb(0, 85, 255); +} + +#alondra::after { + background-color: #C2A08F; +} + +#alondra i{ + color: #C2A08F; +} + +#alyssha::after { + background-color: #ADB0E0; +} + +#alyssha i{ + color: #ADB0E0; +} + +#dana::after { + background-color: #2de6e2; +} + +#dana i{ + color: #2de6e2; +} + +/* Footer */ + +footer { + background-color: lightgray; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding-top: 2rem; +} + +footer h2 { + font-weight: 500; +} + +footer i { + font-size: 2rem; +} + +hr { + border: #979797 solid 1px; + width: 80% ; +} + + diff --git a/public/js/main.js b/public/js/main.js index a508f7c..3cf2323 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,12 +1,53 @@ -let resources; -fetchResources(); +const scrollBtn = document.getElementById('contributors') +const targetScroll = document.getElementById('contributors-title') +const elemRect = targetScroll.getBoundingClientRect() +scrollBtn.addEventListener("click", function () { + window.scrollTo({ + top: elemRect.top, + left: 0, + }); +}); + +const btn = document.getElementById('keyword-btn'); +btn.addEventListener('click', getMatches); -async function fetchResources() { - const response = await fetch(`/api/`); - const data = await response.json(); - resources = data; +/** + * Name: getMatches + * Description: Find resources with keywords matching the user input + */ +async function getMatches() { + //gets the input from the text box and trims white space and makes it lower case + const keyword = document.querySelector('input').value.toLowerCase().trim(); + + try { + const res = await fetch('/api'); + const data = await res.json(); + // Filters array from the API for resources with keywords containing user value + const matches = data.filter(resource => resource.keywords.some(str => str.includes(keyword))); + renderMatches(matches); + } catch (err) { + console.error(err); + } } -document.getElementById('keyword-btn').addEventListener('click', () => { - const keyword = document.querySelector('input').value; -}); +/** + * Name: renderMatches + * Description: takes an array of matches, each match represents resources that had contained a resource's keyword and renders each match to the DOM. + * @param {*} matches - accepts an array of objects had contained a resource's keyword. + */ +function renderMatches(matches) { + const list = document.getElementById('result-list'); + list.innerHTML = ''; + + // For every match found, render the objects to the DOM in JSON format + matches.forEach(match => { + const li = document.createElement('li'); + + // Create an element that looks like a JSON object for every match + li.innerHTML = ` +
{

name: '${match.name}',
url: '${match.url}',
keywords: [${match.keywords.map(keyword => `'${keyword}'`).join(", ")}]
},
+ `; + + list.appendChild(li); + }); +} \ No newline at end of file diff --git a/server.js b/server.js index af5e5c9..4f85cc3 100644 --- a/server.js +++ b/server.js @@ -2,13 +2,25 @@ const express = require('express'); const app = express(); const cors = require('cors'); const { resources } = require("./resources"); +const { response } = require('express'); +const e = require('express'); const PORT = process.env.PORT || 8000; + +app.set('view engine', 'ejs') app.use(cors()); app.use(express.static(__dirname + '/public')); app.use('/public', express.static(__dirname + '/public')); app.get('/', (req, res) => { - res.sendFile(__dirname + '/index.html'); + try { + if (resources) { + res.render('index.ejs', { resources }); + } else { + throw new Error('Resources not found.') + } + } catch (err) { + console.error(err); + } }); app.get('/api', (req, res) => { @@ -17,14 +29,18 @@ app.get('/api', (req, res) => { app.get('/api/:keyword', (req, res) => { const keyword = req.params.keyword.toLowerCase(); - + // filter resources array, return items that match query; tag. const matches = resources.filter((obj) => obj.keywords.some(str => str.includes(keyword))); - if (matches.length > 0) { + // if matches were found, respond with matches array in JSON format + if (matches.length) { res.json(matches); } else { - throw new Error('Resource not found.'); + // respond with status 404, no matches were found + res.status(404).json({ + error: `No resources were found with the ${keyword} keyword.` + }); } }); diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 0000000..6f349c9 --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,247 @@ + + + + + + + Resources API + + + + + + + + + + +
+ +
+
+

Coding Resources API

+

+ Search for coding resources by relevant keywords. + This API serves educational content for a wide + variety of computer science topics, languages and + technologies relevant to web development. +

+
+
+
+ + + +
+
+
+
    + + <% for(let i = 0; i < resources.length; i++) { %> +
  • + + +
    {

    name: '<%= resources[i].name %>',
    url: target="_blank">'<%= resources[i].url %>',
    keywords: [<%= resources[i].keywords.map(keyword => `'${keyword}'`).join(", ") %>]
    },
    +
  • + <% } %> +
+
+
+
+
+
+

Documentation

+
+

There are 3 properties/keys that come with each resource object:

+ + + + + + + + + + + + + + + + +
PROPERTYDESCRIPTION
name[String] Name or title of the document, article or website.
url[String] Link to website.
keywords[Array] Relevant keywords related to the resource's topic.
+
+

Endpoints

+
+
+

Direct link to the complete resources object or a filtered object after using a keyword:

+ https://coding-resources-api.herokuapp.com/api +

*The "/api" endpoint will return every resource object in an array.

+ https://coding-resources-api.herokuapp.com/api/<keyword> +

*The "/api/keyword" endpoint accepts a keyword that will be used to search through an array of resources by the content the resource provides.

+
+
+

Example code-block of how to fetch with JavaScript:

+ const URL = `https://coding-resources-api.herokuapp.com/api/${keyword}`;

+ fetch(URL)
+    .then(res => res.json())
+    .then(data => console.log(data))
+    .catch(err => console.error(err));
+
+
+
+

Contributors

+
+
+
+ Jacob's photo +
+

Jacob Asper

+
+ + + +
+
+
+
+ Erika's photo +
+

Erika Teal

+
+ + + +
+
+
+
+ Alexis' photo +
+

Alexisintech

+
+ + + +
+
+
+
+
+
+ Brian's photo +
+

Brian Schnee

+
+ + + +
+
+
+
+ Alondra's photo +
+

Alondra Mora

+
+ + + +
+
+
+
+ Biancas's photo +
+

Bianca T.

+
+ + + +
+
+
+
+ Jacob Good's photo +
+

Jacob Good

+
+ + + +
+
+
+
+
+
+ Sebastian's photo +
+

Sebastian O.

+
+ + + +
+
+
+
+ Alyssha's photo +
+

Alyssha L.

+
+ + + +
+
+
+
+ Dana's photo +
+

Dana Lee

+
+ + + +
+
+
+
+
+ +
+ + +