├── .github └── workflows │ └── front-end-CICD.yml ├── .vscode └── settings.json ├── README.md ├── img └── AWS-Architecture-Cloud-resume-challenge.png ├── infra ├── .gitignore ├── .terraform.lock.hcl ├── lambda │ ├── func.py │ └── func.zip ├── main.tf ├── packedlambda.zip └── provider.tf ├── lambda-function └── .gitignore └── website ├── assets ├── RishabResume.pdf ├── avatar-alt.png ├── banner.png ├── favicon.png └── work │ ├── 01.png │ ├── 02.png │ ├── 03.png │ ├── 04.png │ ├── 05.jpg │ ├── 05.png │ ├── 06.jpg │ └── 06.png ├── index.html ├── index.js ├── style.css └── vendor └── typed └── typed.min.js /.github/workflows/front-end-CICD.yml: -------------------------------------------------------------------------------- 1 | name: Upload Website 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | deploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - uses: jakejarvis/s3-sync-action@master 15 | with: 16 | args: --acl private --follow-symlinks --delete 17 | env: 18 | AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} 19 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 20 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 21 | AWS_REGION: 'us-east-1' 22 | SOURCE_DIR: 'website' 23 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS Cloud Resume Challenge 2 | [![Upload Website](https://github.com/rishabkumar7/aws-cloud-resume-challenge/actions/workflows/front-end-CICD.yml/badge.svg)](https://github.com/rishabkumar7/aws-cloud-resume-challenge/actions/workflows/front-end-CICD.yml) 3 | 4 | This is my attempt at cloud resume challenge in AWS. 5 | What is Cloud Resume Challenge? - [The Cloud Resume Challenge](https://cloudresumechallenge.dev/) is a multiple-step resume project which helps build and demonstrate skills fundamental to pursuing a career in Cloud. The project was published by Forrest Brazeal. 6 | 7 | ## Architecture 8 | 9 | ![Architecture Diagram](/img/AWS-Architecture-Cloud-resume-challenge.png) 10 | 11 | **Services Used**: 12 | 13 | - S3 14 | - AWS CloudFront 15 | - Certificate Manager 16 | - AWS Lambda 17 | - Dynamo DB 18 | - GitHub Actions 19 | - Terraform 20 | 21 | ## [Live Demo 🔗](https://resume.rishab.cloud) 22 | 23 | ## YouTube Series 24 | 25 | - Part 1 - [What is the Cloud Resume Challenge?](https://youtu.be/NNKzYhvqq5w) 26 | - Part 2 - [Setting up S3 bucket and CloudFront](https://youtu.be/P5UGhdud_ss) 27 | - Part 3 - [Setting up Dynamo DB and AWS Lambda Function](https://youtu.be/x5iTWZbOgww) 28 | - Part 4 - [Lambda and JavaScript to get viewer counter](https://youtu.be/x6TIihJSaLA) 29 | - Part 5 - [Setting up Git repo and CI/CD for frontend website](https://youtu.be/qFEf6iOo-4g) 30 | - Part 6 - [Implementing Infrastructure as Code with Terraform](https://youtu.be/rzdSuiU_TQc) 31 | 32 | 33 | ## Author 34 | - Twitter: [@rishabincloud](https://twitter.com/rishabincloud) 35 | - LinkedIn: [rishabkumar7](https://linked.com/in/rishabkumar7) 36 | 37 | ## Stars 38 | [![Stargazers over time](https://starchart.cc/rishabkumar7/aws-cloud-resume-challenge.svg?variant=adaptive)](https://starchart.cc/rishabkumar7/aws-cloud-resume-challenge) 39 | -------------------------------------------------------------------------------- /img/AWS-Architecture-Cloud-resume-challenge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rishabkumar7/aws-cloud-resume-challenge/c3465dfba5aa2807ff8b851340dbe375c811c1ae/img/AWS-Architecture-Cloud-resume-challenge.png -------------------------------------------------------------------------------- /infra/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | crash.*.log 11 | 12 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 13 | # password, private keys, and other secrets. These should not be part of version 14 | # control as they are data points which are potentially sensitive and subject 15 | # to change depending on the environment. 16 | *.tfvars 17 | *.tfvars.json 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # !example_override.tf 28 | 29 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 30 | # example: *tfplan* 31 | 32 | # Ignore CLI configuration files 33 | .terraformrc 34 | terraform.rc -------------------------------------------------------------------------------- /infra/.terraform.lock.hcl: -------------------------------------------------------------------------------- 1 | # This file is maintained automatically by "terraform init". 2 | # Manual edits may be lost in future updates. 3 | 4 | provider "registry.terraform.io/hashicorp/archive" { 5 | version = "2.3.0" 6 | hashes = [ 7 | "h1:anS1fAU2IWUABjdscCF3nexOIeJXmC3bGOKyifatSDU=", 8 | "zh:0869128d13abe12b297b0cd13b8767f10d6bf047f5afc4215615aabc39c2eb4f", 9 | "zh:481ed837d63ba3aa45dd8736da83e911e3509dee0e7961bf5c00ed2644f807b3", 10 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", 11 | "zh:9f08fe2977e2166849be24fb9f394e4d2697414d463f7996fd0d7beb4e19a29c", 12 | "zh:9fe566deeafd460d27999ca0bbfd85426a5fcfcb40007b23884deb76da127b6f", 13 | "zh:a1bd9a60925d9769e0da322e4523330ee86af9dc2e770cba1d0247a999ef29cb", 14 | "zh:bb4094c8149f74308b22a87e1ac19bcccca76e8ef021b571074d9bccf1c0c6f0", 15 | "zh:c8984c9def239041ce41ec8e19bbd76a49e74ed2024ff736dad60429dee89bcc", 16 | "zh:ea4bb5ae73db1de3a586e62f39106f5e56770804a55aa5e6b4f642df973e0e75", 17 | "zh:f44a9d596ecc3a8c5653f56ba0cd202ad93b49f76767f4608daf7260b813289e", 18 | "zh:f5c5e6cc9f7f070020ab7d95fcc9ed8e20d5cf219978295a71236e22cbb6d508", 19 | "zh:fd2273f51dcc8f43403bf1e425ba9db08a57c3ddcba5ad7a51742ccde21ca611", 20 | ] 21 | } 22 | 23 | provider "registry.terraform.io/hashicorp/aws" { 24 | version = "4.64.0" 25 | constraints = ">= 4.9.0" 26 | hashes = [ 27 | "h1:dx24DfBV5mvqY7+McvdY4oPyGOCncztP4cwCsF5Y3e0=", 28 | "zh:092614f767995140cf444cad1a97fb569885db16cb1c1dc9ee56e801232bac29", 29 | "zh:142e262fbb162c8a86493cfab4aadaf96a8572f1a3a6be444d465a4aee377dba", 30 | "zh:1c58c8cb9934dc98a2dd9dc48a8a3d94a14c2c3f2bc0136410a9344938d4ecfb", 31 | "zh:36efdf30cd52b92668cf6f912538c6e176b1a140a00e63ee0f753b85878c8b53", 32 | "zh:4c631e367fd69692b57f85564de561733380e9674e146d3a7725b781ec5db944", 33 | "zh:57ace91cb022ec944ad3af9272b78f48e7f71e9d1bf113ca56c6ce8deb4341fe", 34 | "zh:7fc9581b530ebf28fda80c62c20c6fbbb936a878c24872349eb107b7f198e64c", 35 | "zh:8280cd8f04c31af83f3e74f07704b258fbaa8bf1d70679d5ea2f0cbda2571de2", 36 | "zh:8e6217a9443b651d4349d75bdc37af9298970d854bf515d8c305919b193e4a38", 37 | "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", 38 | "zh:9c62bc4a9034a6caf15b8863da6f5a621b947d5fca161b4bd2f2e8e78eec8e3b", 39 | "zh:9d0a45cd4a031d19ee14c0a15f25df6359dcd342ccf4e2ee4751b3ee496edb57", 40 | "zh:ab47f4e300c46dc1757e2b8d8d749f34f044f219479106a00bf40572091a8999", 41 | "zh:b55119290497dda96ab9ba3dca00d648808dc99d18960ad8aa875775bfaf95db", 42 | "zh:df513941e6979f557edcac28d84bd91af9786104b0deba45b3b259a5ad215897", 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /infra/lambda/func.py: -------------------------------------------------------------------------------- 1 | import json 2 | import boto3 3 | dynamodb = boto3.resource('dynamodb') 4 | table = dynamodb.Table('resume-challenge') 5 | def lambda_handler(event, context): 6 | response = table.get_item(Key={ 7 | 'id':'0' 8 | }) 9 | views = response['Item']['views'] 10 | views = views + 1 11 | print(views) 12 | response = table.put_item(Item={ 13 | 'id':'0', 14 | 'views': views 15 | }) 16 | 17 | return views -------------------------------------------------------------------------------- /infra/lambda/func.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rishabkumar7/aws-cloud-resume-challenge/c3465dfba5aa2807ff8b851340dbe375c811c1ae/infra/lambda/func.zip -------------------------------------------------------------------------------- /infra/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_lambda_function" "myfunc" { 2 | filename = data.archive_file.zip_the_python_code.output_path 3 | source_code_hash = data.archive_file.zip_the_python_code.output_base64sha256 4 | function_name = "myfunc" 5 | role = aws_iam_role.iam_for_lambda.arn 6 | handler = "func.handler" 7 | runtime = "python3.8" 8 | } 9 | 10 | resource "aws_iam_role" "iam_for_lambda" { 11 | name = "iam_for_lambda" 12 | 13 | assume_role_policy = < 2 | 3 | 4 | 5 | 6 | 7 | Rishab Kumar 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 44 | 45 | 46 |
47 |
48 |
49 | 50 | 51 |
52 | 59 |
60 | 61 | 62 | 63 |
64 |
65 |
information
66 |

About Me

67 |
68 |
69 |
70 | profile image 71 |
72 |
73 |
About Me
74 |
I'm Rishab Kumar & a
75 |

76 | I try to create noice web experiences. I am experienced in Amazon Web Services and can 77 | help clients with several related technologies. A young technical guy with experience in 78 | creating solutions for customers. Dynamic and goal-oriented. Confident and poised in 79 | interactions with individuals at all levels. Focused and dedicated; I have a good eye 80 | for detail and put in my best effort in time management and prioritization. 81 |

82 |
83 |
84 |

Website: rishabkumar.com

86 |
87 |
88 | 90 |
91 |
92 |
93 | 94 | 95 | 96 |
97 |
98 |
Ability
99 |

My skills

100 |
101 |
102 |
103 |

104 | I am fluent with HTML/CSS and JavaScript. Have build projects with 105 | frameworks/libraries : React, Vue and Gatsby. 106 | Familiar with GIT/Source control. 107 |
108 | Also have some experience with MySQL/MSSQL and MongoDB 109 |

110 |
    111 |
  • 112 | 113 |
  • 114 |
  • 115 | 116 |
  • 117 |
  • 118 | 119 |
  • 120 |
  • 121 | 122 |
  • 123 |
124 |
125 |
126 | 127 | 128 | 129 | 130 |
131 |
132 |
What I have achieved
133 |

Awards & 134 | Certifications

135 |
136 |
137 | 138 |
    139 |
  • 140 | 141 | AWS Certified Developer Associate 142 |
  • 143 |
  • 144 | 145 | AWS Certified Solutions Architect Associate 146 |
  • 147 |
  • 148 | 149 | AWS Certified Cloud Practitioner 150 |
  • 151 |
  • 152 | 153 | Oracle Cloud Infrastructure Foundations 2020 Certified Associate 154 |
  • 155 |
  • 156 | 157 | Dean's List - Computer Networking & Technical Support 158 |
  • 159 |
160 |
161 |
162 | 163 | 176 | 177 | 178 | 179 |
180 |
181 |
Porfolio
182 |

Creative Work

183 |
184 |
185 |
186 |
187 | work1 189 |
190 |

COVID-19 Tracker

191 |

193 |

195 |
196 |
197 |
198 | work1 200 |
201 |

Weather Dashboard

202 |

204 |

205 |

207 |
208 |
209 |
210 | work1 212 |
213 |

My Blog with Gatsby

214 |

216 |

218 |
219 |
220 |
221 | work1 223 |
224 |

MyBrary

225 |

227 |

229 |
230 |
231 |
232 | work1 234 |
235 |

HackeNews Clone

236 |

238 |

239 |

241 |
242 |
243 |
244 | work1 246 |
247 |

GitFetch App

248 |

250 |

252 |
253 |
254 |
255 |
256 | 257 | 258 | 259 | 260 |
261 |
262 |
263 |
264 |
©2020 Rishab. All rights reserved 265 |
266 |
267 |
268 | 272 |
Couldn't read the counter
273 |
274 | 285 |
286 |
287 |
288 | 289 |
290 |
291 |
292 | 293 | 296 | 299 | 302 | 303 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | -------------------------------------------------------------------------------- /website/index.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function (e) { 2 | $win = $(window); 3 | $navbar = $('#header'); 4 | $toggle = $('.toggle-button'); 5 | var width = $navbar.width(); 6 | toggle_onclick($win, $navbar, width); 7 | 8 | // resize event 9 | $win.resize(function () { 10 | toggle_onclick($win, $navbar, width); 11 | }); 12 | 13 | $toggle.click(function (e) { 14 | $navbar.toggleClass("toggle-left"); 15 | }) 16 | 17 | }); 18 | 19 | function toggle_onclick($win, $navbar, width) { 20 | if ($win.width() <= 768) { 21 | $navbar.css({ left: `-${width}px` }); 22 | } else { 23 | $navbar.css({ left: '0px' }); 24 | } 25 | } 26 | 27 | var typed = new Typed('#typed', { 28 | strings: [ 29 | 'Cloud Engineer', 30 | 'Cloud Architect', 31 | 'DevOps Engineer' 32 | ], 33 | typeSpeed: 50, 34 | backSpeed: 50, 35 | loop: true 36 | }); 37 | 38 | var typed_2 = new Typed('#typed_2', { 39 | strings: [ 40 | 'Cloud Engineer', 41 | 'Cloud Architect', 42 | 'DevOps Engineer' 43 | ], 44 | typeSpeed: 50, 45 | backSpeed: 50, 46 | loop: true 47 | }); 48 | 49 | document.querySelectorAll('a[href^="#"]').forEach(anchor => { 50 | anchor.addEventListener('click', function (e) { 51 | e.preventDefault(); 52 | 53 | document.querySelector(this.getAttribute('href')).scrollIntoView({ 54 | behavior: 'smooth' 55 | }); 56 | }); 57 | }); 58 | 59 | const counter = document.querySelector(".counter-number"); 60 | async function updateCounter() { 61 | let response = await fetch( 62 | "https://wwjcx7tyxrbjmbkf3vc3teo3mu0qrvhq.lambda-url.ca-central-1.on.aws/" 63 | ); 64 | let data = await response.json(); 65 | counter.innerHTML = `👀 Views: ${data}`; 66 | } 67 | updateCounter(); -------------------------------------------------------------------------------- /website/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Oswald|Rambla|Staatliches&display=swap'); 2 | 3 | body{ 4 | margin: 0; 5 | padding: 0; 6 | } 7 | 8 | :root{ 9 | --color-black: #000000; 10 | --color-white: #ffffff; 11 | --color-border: #ffffff34; 12 | --color-blue: #6C63FF; 13 | --font-staat: 'Staatliches', cursive; 14 | --font-os: 'Oswald', sans-serif; 15 | --font-ram: 'Rambla', sans-serif; 16 | } 17 | 18 | /* global classes */ 19 | .font-staat{ 20 | font: normal 400 18px var(--font-staat); 21 | } 22 | .font-os{ 23 | font: normal 300 18px var(--font-os); 24 | } 25 | .font-ram{ 26 | font: normal bold 18px var(--font-ram); 27 | } 28 | 29 | .font-size-40{ 30 | font-size: 40px; 31 | } 32 | .font-size-34{ 33 | font-size: 34px; 34 | } 35 | .font-size-27{ 36 | font-size: 27px; 37 | } 38 | .font-size-20{ 39 | font-size: 20px; 40 | } 41 | .font-size-16{ 42 | font-size: 16px; 43 | } 44 | 45 | .bgcolor-black{ 46 | background-color: var(--color-blue); 47 | } 48 | 49 | /* #global classes */ 50 | 51 | #header{ 52 | position: fixed; 53 | top: 0; 54 | left: 0; 55 | width: 100%; 56 | z-index:1; 57 | transition: left .5s ease; 58 | } 59 | 60 | #header nav{ 61 | height: 100vh; 62 | } 63 | #header .site-title .navbar-brand{ 64 | letter-spacing: 2px; 65 | color: var(--color-white); 66 | } 67 | 68 | #header .nav-link{ 69 | margin: .7rem 1rem; 70 | border-bottom: 1px solid var(--color-border); 71 | text-transform: uppercase; 72 | } 73 | 74 | #header .nav-link:hover{ 75 | color: var(--color-white) !important; 76 | } 77 | 78 | #header .toggle-button{ 79 | background: none; 80 | color: var(--color-black); 81 | position: fixed; 82 | top: 25px; 83 | right: 20px; 84 | border: 1px solid var(--color-border); 85 | } 86 | 87 | .toggle-left{ 88 | left: 0 !important; 89 | width: 1000px !important; 90 | } 91 | 92 | /* site-main */ 93 | 94 | .site-banner .banner-area{ 95 | 96 | background-size: cover; 97 | width: 100%; 98 | height: 100vh; 99 | position: relative; 100 | } 101 | 102 | .site-banner .banner-area .author{ 103 | margin: 0; 104 | position: absolute; 105 | top: 45%; 106 | left: 50%; 107 | transform: translate(-50%, -50%); 108 | } 109 | 110 | .site-banner .banner-area .author .author-img{ 111 | width: 240px; 112 | height: 240px; 113 | border-radius: 50%; 114 | margin: auto; 115 | background: url(./assets/avatar-alt.png) no-repeat; 116 | background-size: 110%; 117 | background-position: 40% 0; 118 | } 119 | 120 | .skill .bars p, .site-content .skill .bars span{ 121 | line-height: 10px; 122 | } 123 | 124 | #footer form .row .col input[type="text"], 125 | #footer form .row .col input[type="email"], 126 | #footer form textarea{ 127 | border: none; 128 | border-radius: 0; 129 | border-bottom: 1px solid gray; 130 | padding: 1.5rem 1rem; 131 | } 132 | 133 | @media screen and (min-width: 768px){ 134 | .toggle-button{ 135 | display: none; 136 | } 137 | #header{ 138 | z-index:0; 139 | } 140 | } 141 | 142 | #typed{ 143 | color: var(--color-blue); 144 | } 145 | /* #site-main */ 146 | 147 | 148 | /*icons*/ 149 | .social-icons a{ 150 | display:inline-block;height:3.5rem; 151 | width:3.5rem; 152 | background-color: #fff; 153 | color:#343a40!important; 154 | border-radius:100%; 155 | text-align:center; 156 | font-size:1.5rem; 157 | line-height:3.5rem; 158 | margin-right:1rem 159 | } 160 | 161 | .social-icons a:last-child{ 162 | margin-right:0 163 | } 164 | 165 | .social-icons a:hover{ 166 | background-color:var(--color-blue); 167 | transform: scale(1.2) 168 | } 169 | 170 | .social-icons a:hover i { 171 | transform: scale(1.3); 172 | } 173 | 174 | .dev-icons { 175 | font-size: 5rem; 176 | } 177 | 178 | .dev-icons .list-inline-item :hover { 179 | color: var(--color-blue); 180 | } 181 | /*icons*/ 182 | 183 | 184 | 185 | /*project*/ 186 | .frame { 187 | text-align: center; 188 | position: relative; 189 | cursor: pointer; 190 | perspective: 500px; 191 | } 192 | 193 | .frame .details { 194 | width: 90%; 195 | height: 90%; 196 | padding: 5% 8%; 197 | position: absolute; 198 | content: ""; 199 | top: 50%; 200 | left: 50%; 201 | transform: translate(-50%, -50%) rotateY(90deg); 202 | transform-origin: 50%; 203 | background: var(--color-blue); 204 | opacity: 0; 205 | transition: all 0.4s ease-in; 206 | color: var(--color-white); 207 | font-family: var(--font-ram); 208 | } 209 | 210 | .frame:hover .details { 211 | transform: translate(-50%, -50%) rotateY(0deg); 212 | opacity: 1; 213 | } 214 | 215 | 216 | /*project icons- github and live site*/ 217 | .giti, .eye{ 218 | font-size: 3rem; 219 | color: var(--color-white); 220 | } 221 | 222 | .eye :hover{ 223 | color: var(--color-white); 224 | } -------------------------------------------------------------------------------- /website/vendor/typed/typed.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * 3 | * typed.js - A JavaScript Typing Animation Library 4 | * Author: Matt Boldt 5 | * Version: v2.0.11 6 | * Url: https://github.com/mattboldt/typed.js 7 | * License(s): MIT 8 | * 9 | */ 10 | (function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Typed=e():t.Typed=e()})(this,function(){return function(t){function e(n){if(s[n])return s[n].exports;var i=s[n]={exports:{},id:n,loaded:!1};return t[n].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var s={};return e.m=t,e.c=s,e.p="",e(0)}([function(t,e,s){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0});var i=function(){function t(t,e){for(var s=0;st.length)););var u=t.substring(0,e),l=t.substring(u.length+1,e+i),c=t.substring(e+i+1);t=u+l+c,i--}s.timeout=setTimeout(function(){s.toggleBlinking(!1),e>=t.length?s.doneTyping(t,e):s.keepTyping(t,e,i),s.temporaryPause&&(s.temporaryPause=!1,s.options.onTypingResumed(s.arrayPos,s))},n)},n))}},{key:"keepTyping",value:function(t,e,s){0===e&&(this.toggleBlinking(!1),this.options.preStringTyped(this.arrayPos,this)),e+=s;var n=t.substr(0,e);this.replaceText(n),this.typewrite(t,e)}},{key:"doneTyping",value:function(t,e){var s=this;this.options.onStringTyped(this.arrayPos,this),this.toggleBlinking(!0),this.arrayPos===this.strings.length-1&&(this.complete(),this.loop===!1||this.curLoop===this.loopCount)||(this.timeout=setTimeout(function(){s.backspace(t,e)},this.backDelay))}},{key:"backspace",value:function(t,e){var s=this;if(this.pause.status===!0)return void this.setPauseStatus(t,e,!0);if(this.fadeOut)return this.initFadeOut();this.toggleBlinking(!1);var n=this.humanizer(this.backSpeed);this.timeout=setTimeout(function(){e=o.htmlParser.backSpaceHtmlChars(t,e,s);var n=t.substr(0,e);if(s.replaceText(n),s.smartBackspace){var i=s.strings[s.arrayPos+1];i&&n===i.substr(0,e)?s.stopNum=e:s.stopNum=0}e>s.stopNum?(e--,s.backspace(t,e)):e<=s.stopNum&&(s.arrayPos++,s.arrayPos===s.strings.length?(s.arrayPos=0,s.options.onLastStringBackspaced(),s.shuffleStringsIfNeeded(),s.begin()):s.typewrite(s.strings[s.sequence[s.arrayPos]],e))},n)}},{key:"complete",value:function(){this.options.onComplete(this),this.loop?this.curLoop++:this.typingComplete=!0}},{key:"setPauseStatus",value:function(t,e,s){this.pause.typewrite=s,this.pause.curString=t,this.pause.curStrPos=e}},{key:"toggleBlinking",value:function(t){this.cursor&&(this.pause.status||this.cursorBlinking!==t&&(this.cursorBlinking=t,t?this.cursor.classList.add("typed-cursor--blink"):this.cursor.classList.remove("typed-cursor--blink")))}},{key:"humanizer",value:function(t){return Math.round(Math.random()*t/2)+t}},{key:"shuffleStringsIfNeeded",value:function(){this.shuffle&&(this.sequence=this.sequence.sort(function(){return Math.random()-.5}))}},{key:"initFadeOut",value:function(){var t=this;return this.el.className+=" "+this.fadeOutClass,this.cursor&&(this.cursor.className+=" "+this.fadeOutClass),setTimeout(function(){t.arrayPos++,t.replaceText(""),t.strings.length>t.arrayPos?t.typewrite(t.strings[t.sequence[t.arrayPos]],0):(t.typewrite(t.strings[0],0),t.arrayPos=0)},this.fadeOutDelay)}},{key:"replaceText",value:function(t){this.attr?this.el.setAttribute(this.attr,t):this.isInput?this.el.value=t:"html"===this.contentType?this.el.innerHTML=t:this.el.textContent=t}},{key:"bindFocusEvents",value:function(){var t=this;this.isInput&&(this.el.addEventListener("focus",function(e){t.stop()}),this.el.addEventListener("blur",function(e){t.el.value&&0!==t.el.value.length||t.start()}))}},{key:"insertCursor",value:function(){this.showCursor&&(this.cursor||(this.cursor=document.createElement("span"),this.cursor.className="typed-cursor",this.cursor.innerHTML=this.cursorChar,this.el.parentNode&&this.el.parentNode.insertBefore(this.cursor,this.el.nextSibling)))}}]),t}();e["default"]=a,t.exports=e["default"]},function(t,e,s){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0});var r=Object.assign||function(t){for(var e=1;e":";";t.substr(e+1).charAt(0)!==i&&(e++,!(e+1>t.length)););e++}return e}},{key:"backSpaceHtmlChars",value:function(t,e,s){if("html"!==s.contentType)return e;var n=t.substr(e).charAt(0);if(">"===n||";"===n){var i="";for(i=">"===n?"<":"&";t.substr(e-1).charAt(0)!==i&&(e--,!(e<0)););e--}return e}}]),t}();e["default"]=i;var r=new i;e.htmlParser=r}])}); 11 | //# sourceMappingURL=typed.min.js.map 12 | --------------------------------------------------------------------------------