diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 064f3df7..d48a1f5a 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -14,21 +14,21 @@ appearance, race, religion, or sexual identity and orientation.
Examples of behavior that contributes to creating a positive environment
include:
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
-* The use of sexualized language or imagery and unwelcome sexual attention or
+- The use of sexualized language or imagery and unwelcome sexual attention or
advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic
address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
+- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
@@ -69,10 +69,9 @@ members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
-available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+available at
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
-https://www.contributor-covenant.org/faq
-
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6b799017..22d85e20 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,7 +28,7 @@ as a new JSON object in the array.
This information includes:
- A username for your profile (used in your profile URL).
- [IE, our founder's username is `crutchcorn`, and [their page can be found here](https://unicorn-utterances.com/unicorns/crutchcorn)]
+ \[IE, our founder's username is `crutchcorn`, and [their page can be found here](https://unicorn-utterances.com/unicorns/crutchcorn)]
- Full name
@@ -74,7 +74,7 @@ Now that we have your user attribution data, we can move onto the post data itse
#### Save Location
Once you have your `.md` file, we'll need a place to put it. We place a subdirectory in our [`content/blog` folder](./content/blog) for each of the blog posts on the site. The naming of these subdirectories is integral to keep in mind, as they reflect the URL path of the article once finished. For example, the folder [`what-is-ssr-and-ssg`](./content/blog/what-is-ssr-and-ssg) will turn into the URL for the article:
-[https://unicorn-utterances.com/posts/what-is-ssr-and-ssg/](https://unicorn-utterances.com/posts/what-is-ssr-and-ssg/)
+
Once you've created a subfolder with the URI you'd like your article to have, move the `.md` file into the folder with the name `index.md`. If you have linked images or videos, you'll need to save those files in the same folder and change your markdown file to reference them locally:
@@ -121,16 +121,20 @@ The following data **must** be present:
- Title for the article
- We ask that your titles are less than 80 characters.
+
- A description of the article
- We ask that your descriptions are less than 190 characters.
- A published date
- Please follow the format as seen above
+
- An array of authors
- This array must have every value match [one of the `id`s of the `unicorns.json` file](./content/data/unicorns.json)
+
- An array of related tags
- Please try to use existing tags if possible. If you don't find any, that's alright
- We ask that you keep it to 4 tags maximum
+
- A `license` to be associated with the post
- This must match the `id` field for one of the values [in our `license.json` file](./content/data/licenses.json)
- If you're not familiar with what these licenses mean, view the `explainLink` for each of them in the `license.json` file. It'll help you understand what permissions the public has to the post
diff --git a/LICENSE.md b/LICENSE.md
index 21eff128..21ab8f0a 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -2,198 +2,208 @@ Mozilla Public License, version 2.0
1. Definitions
- 1.1. “Contributor”
- means each individual or legal entity that creates, contributes to the
- creation of, or owns Covered Software.
+ 1.1. “Contributor”
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
- 1.2. “Contributor Version”
- means the combination of the Contributions of others (if any) used by a
- Contributor and that particular Contributor’s Contribution.
+ 1.2. “Contributor Version”
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor’s Contribution.
- 1.3. “Contribution”
- means Covered Software of a particular Contributor.
+ 1.3. “Contribution”
+ means Covered Software of a particular Contributor.
- 1.4. “Covered Software”
- means Source Code Form to which the initial Contributor has attached the
- notice in Exhibit A, the Executable Form of such Source Code Form,
- and Modifications of such Source Code Form, in each case
- including portions thereof.
+ 1.4. “Covered Software”
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form,
+ and Modifications of such Source Code Form, in each case
+ including portions thereof.
- 1.5. “Incompatible With Secondary Licenses”
- means
+ 1.5. “Incompatible With Secondary Licenses”
+ means
- a. that the initial Contributor has attached the notice described
- in Exhibit B to the Covered Software; or
+ ```
+ a. that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
- b. that the Covered Software was made available under the terms of
- version 1.1 or earlier of the License, but not also under the terms
- of a Secondary License.
+ b. that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the terms
+ of a Secondary License.
+ ```
- 1.6. “Executable Form”
- means any form of the work other than Source Code Form.
+ 1.6. “Executable Form”
+ means any form of the work other than Source Code Form.
- 1.7. “Larger Work”
- means a work that combines Covered Software with other material,
- in a separate file or files, that is not Covered Software.
+ 1.7. “Larger Work”
+ means a work that combines Covered Software with other material,
+ in a separate file or files, that is not Covered Software.
- 1.8. “License”
- means this document.
+ 1.8. “License”
+ means this document.
- 1.9. “Licensable”
- means having the right to grant, to the maximum extent possible,
- whether at the time of the initial grant or subsequently,
- any and all of the rights conveyed by this License.
+ 1.9. “Licensable”
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently,
+ any and all of the rights conveyed by this License.
- 1.10. “Modifications”
- means any of the following:
+ 1.10. “Modifications”
+ means any of the following:
- a. any file in Source Code Form that results from an addition to,
- deletion from, or modification of the contents of Covered Software; or
+ ```
+ a. any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered Software; or
- b. any new file in Source Code Form that contains any Covered Software.
+ b. any new file in Source Code Form that contains any Covered Software.
+ ```
- 1.11. “Patent Claims” of a Contributor
- means any patent claim(s), including without limitation, method, process,
- and apparatus claims, in any patent Licensable by such Contributor that
- would be infringed, but for the grant of the License, by the making,
- using, selling, offering for sale, having made, import, or transfer of
- either its Contributions or its Contributor Version.
+ 1.11. “Patent Claims” of a Contributor
+ means any patent claim(s), including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by such Contributor that
+ would be infringed, but for the grant of the License, by the making,
+ using, selling, offering for sale, having made, import, or transfer of
+ either its Contributions or its Contributor Version.
- 1.12. “Secondary License”
- means either the GNU General Public License, Version 2.0, the
- GNU Lesser General Public License, Version 2.1, the GNU Affero General
- Public License, Version 3.0, or any later versions of those licenses.
+ 1.12. “Secondary License”
+ means either the GNU General Public License, Version 2.0, the
+ GNU Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those licenses.
- 1.13. “Source Code Form”
- means the form of the work preferred for making modifications.
+ 1.13. “Source Code Form”
+ means the form of the work preferred for making modifications.
- 1.14. “You” (or “Your”)
- means an individual or a legal entity exercising rights under this License.
- For legal entities, “You” includes any entity that controls,
- is controlled by, or is under common control with You. For purposes of
- this definition, “control” means (a) the power, direct or indirect,
- to cause the direction or management of such entity, whether by contract
- or otherwise, or (b) ownership of more than fifty percent (50%) of the
- outstanding shares or beneficial ownership of such entity.
+ 1.14. “You” (or “Your”)
+ means an individual or a legal entity exercising rights under this License.
+ For legal entities, “You” includes any entity that controls,
+ is controlled by, or is under common control with You. For purposes of
+ this definition, “control” means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by contract
+ or otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
2. License Grants and Conditions
- 2.1. Grants
- Each Contributor hereby grants You a world-wide, royalty-free,
- non-exclusive license:
+ 2.1. Grants
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
- a. under intellectual property rights (other than patent or trademark)
- Licensable by such Contributor to use, reproduce, make available,
- modify, display, perform, distribute, and otherwise exploit its
- Contributions, either on an unmodified basis, with Modifications,
- or as part of a Larger Work; and
+ ```
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications,
+ or as part of a Larger Work; and
- b. under Patent Claims of such Contributor to make, use, sell,
- offer for sale, have made, import, and otherwise transfer either
- its Contributions or its Contributor Version.
+ b. under Patent Claims of such Contributor to make, use, sell,
+ offer for sale, have made, import, and otherwise transfer either
+ its Contributions or its Contributor Version.
+ ```
- 2.2. Effective Date
- The licenses granted in Section 2.1 with respect to any Contribution
- become effective for each Contribution on the date the Contributor
- first distributes such Contribution.
+ 2.2. Effective Date
+ The licenses granted in Section 2.1 with respect to any Contribution
+ become effective for each Contribution on the date the Contributor
+ first distributes such Contribution.
- 2.3. Limitations on Grant Scope
- The licenses granted in this Section 2 are the only rights granted
- under this License. No additional rights or licenses will be implied
- from the distribution or licensing of Covered Software under this License.
- Notwithstanding Section 2.1(b) above, no patent license is granted
- by a Contributor:
+ 2.3. Limitations on Grant Scope
+ The licenses granted in this Section 2 are the only rights granted
+ under this License. No additional rights or licenses will be implied
+ from the distribution or licensing of Covered Software under this License.
+ Notwithstanding Section 2.1(b) above, no patent license is granted
+ by a Contributor:
- a. for any code that a Contributor has removed from
- Covered Software; or
+ ```
+ a. for any code that a Contributor has removed from
+ Covered Software; or
- b. for infringements caused by: (i) Your and any other third party’s
- modifications of Covered Software, or (ii) the combination of its
- Contributions with other software (except as part of its
- Contributor Version); or
+ b. for infringements caused by: (i) Your and any other third party’s
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its
+ Contributor Version); or
- c. under Patent Claims infringed by Covered Software in the
- absence of its Contributions.
+ c. under Patent Claims infringed by Covered Software in the
+ absence of its Contributions.
+ ```
- This License does not grant any rights in the trademarks, service marks,
- or logos of any Contributor (except as may be necessary to comply with
- the notice requirements in Section 3.4).
+ This License does not grant any rights in the trademarks, service marks,
+ or logos of any Contributor (except as may be necessary to comply with
+ the notice requirements in Section 3.4).
- 2.4. Subsequent Licenses
- No Contributor makes additional grants as a result of Your choice to
- distribute the Covered Software under a subsequent version of this
- License (see Section 10.2) or under the terms of a Secondary License
- (if permitted under the terms of Section 3.3).
+ 2.4. Subsequent Licenses
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this
+ License (see Section 10.2) or under the terms of a Secondary License
+ (if permitted under the terms of Section 3.3).
- 2.5. Representation
- Each Contributor represents that the Contributor believes its
- Contributions are its original creation(s) or it has sufficient rights
- to grant the rights to its Contributions conveyed by this License.
+ 2.5. Representation
+ Each Contributor represents that the Contributor believes its
+ Contributions are its original creation(s) or it has sufficient rights
+ to grant the rights to its Contributions conveyed by this License.
- 2.6. Fair Use
- This License is not intended to limit any rights You have under
- applicable copyright doctrines of fair use, fair dealing,
- or other equivalents.
+ 2.6. Fair Use
+ This License is not intended to limit any rights You have under
+ applicable copyright doctrines of fair use, fair dealing,
+ or other equivalents.
- 2.7. Conditions
- Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the
- licenses granted in Section 2.1.
+ 2.7. Conditions
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the
+ licenses granted in Section 2.1.
3. Responsibilities
- 3.1. Distribution of Source Form
- All distribution of Covered Software in Source Code Form, including
- any Modifications that You create or to which You contribute, must be
- under the terms of this License. You must inform recipients that the
- Source Code Form of the Covered Software is governed by the terms
- of this License, and how they can obtain a copy of this License.
- You may not attempt to alter or restrict the recipients’ rights
- in the Source Code Form.
+ 3.1. Distribution of Source Form
+ All distribution of Covered Software in Source Code Form, including
+ any Modifications that You create or to which You contribute, must be
+ under the terms of this License. You must inform recipients that the
+ Source Code Form of the Covered Software is governed by the terms
+ of this License, and how they can obtain a copy of this License.
+ You may not attempt to alter or restrict the recipients’ rights
+ in the Source Code Form.
- 3.2. Distribution of Executable Form
- If You distribute Covered Software in Executable Form then:
+ 3.2. Distribution of Executable Form
+ If You distribute Covered Software in Executable Form then:
- a. such Covered Software must also be made available in Source Code
- Form, as described in Section 3.1, and You must inform recipients of
- the Executable Form how they can obtain a copy of such Source Code
- Form by reasonable means in a timely manner, at a charge no more than
- the cost of distribution to the recipient; and
+ ```
+ a. such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more than
+ the cost of distribution to the recipient; and
- b. You may distribute such Executable Form under the terms of this
- License, or sublicense it under different terms, provided that the
- license for the Executable Form does not attempt to limit or alter
- the recipients’ rights in the Source Code Form under this License.
+ b. You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients’ rights in the Source Code Form under this License.
+ ```
- 3.3. Distribution of a Larger Work
- You may create and distribute a Larger Work under terms of Your choice,
- provided that You also comply with the requirements of this License for
- the Covered Software. If the Larger Work is a combination of
- Covered Software with a work governed by one or more Secondary Licenses,
- and the Covered Software is not Incompatible With Secondary Licenses,
- this License permits You to additionally distribute such Covered Software
- under the terms of such Secondary License(s), so that the recipient of
- the Larger Work may, at their option, further distribute the
- Covered Software under the terms of either this License or such
- Secondary License(s).
+ 3.3. Distribution of a Larger Work
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for
+ the Covered Software. If the Larger Work is a combination of
+ Covered Software with a work governed by one or more Secondary Licenses,
+ and the Covered Software is not Incompatible With Secondary Licenses,
+ this License permits You to additionally distribute such Covered Software
+ under the terms of such Secondary License(s), so that the recipient of
+ the Larger Work may, at their option, further distribute the
+ Covered Software under the terms of either this License or such
+ Secondary License(s).
- 3.4. Notices
- You may not remove or alter the substance of any license notices
- (including copyright notices, patent notices, disclaimers of warranty,
- or limitations of liability) contained within the Source Code Form of
- the Covered Software, except that You may alter any license notices to
- the extent required to remedy known factual inaccuracies.
+ 3.4. Notices
+ You may not remove or alter the substance of any license notices
+ (including copyright notices, patent notices, disclaimers of warranty,
+ or limitations of liability) contained within the Source Code Form of
+ the Covered Software, except that You may alter any license notices to
+ the extent required to remedy known factual inaccuracies.
- 3.5. Application of Additional Terms
- You may choose to offer, and to charge a fee for, warranty, support,
- indemnity or liability obligations to one or more recipients of
- Covered Software. However, You may do so only on Your own behalf,
- and not on behalf of any Contributor. You must make it absolutely clear
- that any such warranty, support, indemnity, or liability obligation is
- offered by You alone, and You hereby agree to indemnify every Contributor
- for any liability incurred by such Contributor as a result of warranty,
- support, indemnity or liability terms You offer. You may include
- additional disclaimers of warranty and limitations of liability
- specific to any jurisdiction.
+ 3.5. Application of Additional Terms
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of
+ Covered Software. However, You may do so only on Your own behalf,
+ and not on behalf of any Contributor. You must make it absolutely clear
+ that any such warranty, support, indemnity, or liability obligation is
+ offered by You alone, and You hereby agree to indemnify every Contributor
+ for any liability incurred by such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer. You may include
+ additional disclaimers of warranty and limitations of liability
+ specific to any jurisdiction.
4. Inability to Comply Due to Statute or Regulation
@@ -209,31 +219,31 @@ to be able to understand it.
5. Termination
- 5.1. The rights granted under this License will terminate automatically
- if You fail to comply with any of its terms. However, if You become
- compliant, then the rights granted under this License from a particular
- Contributor are reinstated (a) provisionally, unless and until such
- Contributor explicitly and finally terminates Your grants, and (b) on an
- ongoing basis, if such Contributor fails to notify You of the
- non-compliance by some reasonable means prior to 60 days after You have
- come back into compliance. Moreover, Your grants from a particular
- Contributor are reinstated on an ongoing basis if such Contributor
- notifies You of the non-compliance by some reasonable means,
- this is the first time You have received notice of non-compliance with
- this License from such Contributor, and You become compliant prior to
- 30 days after Your receipt of the notice.
+ 5.1. The rights granted under this License will terminate automatically
+ if You fail to comply with any of its terms. However, if You become
+ compliant, then the rights granted under this License from a particular
+ Contributor are reinstated (a) provisionally, unless and until such
+ Contributor explicitly and finally terminates Your grants, and (b) on an
+ ongoing basis, if such Contributor fails to notify You of the
+ non-compliance by some reasonable means prior to 60 days after You have
+ come back into compliance. Moreover, Your grants from a particular
+ Contributor are reinstated on an ongoing basis if such Contributor
+ notifies You of the non-compliance by some reasonable means,
+ this is the first time You have received notice of non-compliance with
+ this License from such Contributor, and You become compliant prior to
+ 30 days after Your receipt of the notice.
- 5.2. If You initiate litigation against any entity by asserting a patent
- infringement claim (excluding declaratory judgment actions,
- counter-claims, and cross-claims) alleging that a Contributor Version
- directly or indirectly infringes any patent, then the rights granted
- to You by any and all Contributors for the Covered Software under
- Section 2.1 of this License shall terminate.
+ 5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions,
+ counter-claims, and cross-claims) alleging that a Contributor Version
+ directly or indirectly infringes any patent, then the rights granted
+ to You by any and all Contributors for the Covered Software under
+ Section 2.1 of this License shall terminate.
- 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
- end user license agreements (excluding distributors and resellers) which
- have been validly granted by You or Your distributors under this License
- prior to termination shall survive termination.
+ 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+ end user license agreements (excluding distributors and resellers) which
+ have been validly granted by You or Your distributors under this License
+ prior to termination shall survive termination.
6. Disclaimer of Warranty
@@ -311,9 +321,11 @@ this License against a Contributor.
Exhibit A - Source Code Form License Notice
- This Source Code Form is subject to the terms of the
- Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed
- with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+```
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed
+with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+```
If it is not possible or desirable to put the notice in a particular file,
then You may include the notice in a location (such as a LICENSE file in a
@@ -324,6 +336,7 @@ You may add additional accurate notices of copyright ownership.
Exhibit B - “Incompatible With Secondary Licenses” Notice
- This Source Code Form is “Incompatible With Secondary Licenses”,
- as defined by the Mozilla Public License, v. 2.0.
-
+```
+This Source Code Form is “Incompatible With Secondary Licenses”,
+as defined by the Mozilla Public License, v. 2.0.
+```
diff --git a/README.es.md b/README.es.md
index 2e80fa4f..831cb3f2 100644
--- a/README.es.md
+++ b/README.es.md
@@ -16,9 +16,7 @@ Este repository actúa como la ubicación del código fuente para el [blog de Un
## Patrocinadores
-
-
-
+
[Reconocemos todos los patrocinios que compartimos abiertamente en GitHub](https://github.com/unicorn-utterances/unicorn-utterances/issues?q=is%3Aissue+label%3Adisclosure+is%3Aclosed)
diff --git a/README.md b/README.md
index dfd14747..5ccf700a 100644
--- a/README.md
+++ b/README.md
@@ -16,9 +16,7 @@ This repository acts as the source code location for [the Unicorn Utterances blo
## Sponsors
-
-
-
+
[We disclose every sponsorship we share openly on GitHub](https://github.com/unicorn-utterances/unicorn-utterances/issues?q=is%3Aissue+label%3Adisclosure+is%3Aclosed)
@@ -42,4 +40,3 @@ We highly encourage and celebrate others contributing to our site and our commun
Keep in mind that we request developers reach out [via our Discord](https://discord.gg/FMcvc6T) or [via GitHub issue](https://github.com/unicorn-utterances/unicorn-utterances/issues/new) before extensive development is pursued. If you have a feature you'd like to add to the site, let us know! We'd love to do some brainstorming before coding begins!
We extend this invitation to those who may be unfamiliar with our processes. Be sure to check out [our CONTRIBUTING.md](./CONTRIBUTING.md) file first, but don't be afraid to join in and ask questions if you're uncertain of anything
-
diff --git a/content/blog/android-studio-setup-for-ryzen-cpus/index.md b/content/blog/android-studio-setup-for-ryzen-cpus/index.md
index 930339b2..a65ec6c5 100644
--- a/content/blog/android-studio-setup-for-ryzen-cpus/index.md
+++ b/content/blog/android-studio-setup-for-ryzen-cpus/index.md
@@ -12,7 +12,7 @@
In the past, Android Studio did not support AMD's CPUs for hardware emulation of an Android device. [That all changed in 2018 when Google added Hyper-V support to the Android Emulator](https://android-developers.googleblog.com/2018/07/android-emulator-amd-processor-hyper-v.html).
-However, while working on my Ryzen CPU powered desktop, I had difficulties getting the program working on my machine.
+However, while working on my Ryzen CPU powered desktop, I had difficulties getting the program working on my machine.
# BIOS Setup {#bios}
@@ -47,15 +47,13 @@ Enabling IOMMU on a Gigabyte AMD motherboard is much easier than enabling SVM mo

-
-
Once changed, tab over to "Save & Exit" and select "Exit and save changes".
# Windows Features Setup {#windows-features}
Now that we have our BIOS (UEFI, really) configured correctly, we can enable the Windows features we need for the Android Emulator.
-To start, press Win + R, which should bring up the **"Run"** dialog. Once open, _type `OptionalFeatures` and press **"OK"**_.
+To start, press Win + R, which should bring up the **"Run"** dialog. Once open, _type `OptionalFeatures` and press **"OK"**_.

@@ -73,7 +71,7 @@ After these three settings are selected, press **"OK"** and allow the features t
# Setup Android Studio {#android-studio}
-You have a few different methods for installing Android Studio. You can choose to use [Google's installer directly](https://developer.android.com/studio/install), you can [utilize the Chocolatey CLI installer](https://chocolatey.org/packages/AndroidStudio), or even use [JetBrain's Toolbox utility to install and manage an instance of Android Studio](https://www.jetbrains.com/toolbox-app/). _Any of these methods work perfectly well_, it's down to preference, really.
+You have a few different methods for installing Android Studio. You can choose to use [Google's installer directly](https://developer.android.com/studio/install), you can [utilize the Chocolatey CLI installer](https://chocolatey.org/packages/AndroidStudio), or even use [JetBrain's Toolbox utility to install and manage an instance of Android Studio](https://www.jetbrains.com/toolbox-app/). _Any of these methods work perfectly well_, it's down to preference, really.
Once you get Android Studio installed, go ahead and _open the SDK Manager settings screen_ from the **"Configure"** dropdown.
@@ -83,15 +81,11 @@ Once you see the popup dialog, you'll want to _select the "SDK Tools" tab_. Ther

-
-
-
-
-Once you've selected it, press **"Apply"** to download the installer. _Because the "Apply" button only downloads the installer, we'll need to run it manually._
+Once you've selected it, press **"Apply"** to download the installer. _Because the "Apply" button only downloads the installer, we'll need to run it manually._
## Run the Installer {#amd-hypervisor-installer}
-To find the location of the installer, you'll want to go to the install location for your Android SDK. For me (who used the Jetbrains Toolbox to install Android Studio), that path was: `%AppData%/../Local/Android/Sdk`.
+To find the location of the installer, you'll want to go to the install location for your Android SDK. For me (who used the Jetbrains Toolbox to install Android Studio), that path was: `%AppData%/../Local/Android/Sdk`.
The hypervisor installer is located under the following subpath of that path:
@@ -125,13 +119,13 @@ You'll then see a list of the devices that you currently have setup. I, for exam
You can create a new one by _pressing **"Create Virtual Device"**_.
-Upon the dialog creation, you'll see a list of devices that you can use as a baseline for your emulator. This sets the hardware information (screen size and such). Even if you pick a device, it does not restrict the versions of Android you can use with it. I picked Pixel 2 and KitKat for my KK testing device, despite the Pixel 2 being released well after that OS release.
+Upon the dialog creation, you'll see a list of devices that you can use as a baseline for your emulator. This sets the hardware information (screen size and such). Even if you pick a device, it does not restrict the versions of Android you can use with it. I picked Pixel 2 and KitKat for my KK testing device, despite the Pixel 2 being released well after that OS release.

Once you've selected a device, you can pick the version of Android to run. You'll want to select an `x86` or `x86_64` build of Android you're looking for. I've noticed better performance from `x86_64` emulators myself, so I went with an `x86_64` build of Android Pie.
-
+
Afterward, you'll want to name your emulator. I try to keep them without strings and not too long, so if I need to run the emulator manually in the CLI, I can do so with the name of the emulator easily.
@@ -139,13 +133,12 @@ Afterward, you'll want to name your emulator. I try to keep them without strings
Finally, once you've selected **"Finish"**, it should save the emulator's settings and start the emulator itself.
-
> You may get an error such as `HAXM is not installed` when trying to set up an emulator. If you get this error, it's most likely that you have not [enabled the settings in BIOS](#bios). I know in my case, I had recently performed a BIOS upgrade, and it had reset my BIOS settings, making me go back and re-enable them.

# Conclusion
-I've had incredible success with my Ryzen powered desktop during my Android development. Not only is it cost-efficient for my usage compared to the Intel option, but it's able to run the emulator quickly. Hopefully, this article has been able to help you set up your machine as well.
+I've had incredible success with my Ryzen powered desktop during my Android development. Not only is it cost-efficient for my usage compared to the Intel option, but it's able to run the emulator quickly. Hopefully, this article has been able to help you set up your machine as well.
Let us know what your thoughts on this article were! We not only have our comments down below, but we have [a Discord community](https://discord.gg/FMcvc6T) as well that we invite you to join! We chat about all kinds of programming and CS related topics there!
diff --git a/content/blog/angular-components-control-value-accessor/index.md b/content/blog/angular-components-control-value-accessor/index.md
index d8a9fcb3..eb73dace 100644
--- a/content/blog/angular-components-control-value-accessor/index.md
+++ b/content/blog/angular-components-control-value-accessor/index.md
@@ -130,7 +130,6 @@ With this, we'll finally be able to use these methods to control our component.
> If you're wondering why you don't need to do something like this with `ngOnInit`, it's because that functionality is baked right into Angular. Angular _always_ looks for an `onInit` function and tries to call it when the respective lifecycle method is run. `implements` is just a type-safe way to ensure that you're explicitly wanting to call that method.
-
## `writeValue` {#write-value}
`writeValue` is a method that acts exactly as you'd expect it to: It simply writes a value to your component's value. As your value has more than a single write method (from your component and from the parent), it's suggested to have a setter, getter, and private internal value for your property.
@@ -302,7 +301,6 @@ Finally, you can pass these options to `ngModel` and `formControl` (or even `for
If done properly, you should see something like this:
-
# Form Control Classes
@@ -311,7 +309,6 @@ Angular CSS masters might point to [classes that's applied to inputs when variou
These classes include:
-
- `ng-pristine`
- `ng-dirty`
- `ng-untouched`
@@ -409,7 +406,6 @@ export class AppComponent {
-
Not only do you have [a wide range of Angular-built validators at your disposal](https://angular.io/api/forms/Validators), but you're even able to [make your own validator](https://angular.io/api/forms/Validator)!
# Conclusion {#conclusion}
diff --git a/content/blog/angular-extend-class/index.md b/content/blog/angular-extend-class/index.md
index b5947aaa..9fdd91a7 100644
--- a/content/blog/angular-extend-class/index.md
+++ b/content/blog/angular-extend-class/index.md
@@ -160,7 +160,7 @@ In this article we'll learn:
- [How to use a base class in Angular](#base-class-angular)
- [How to simplify Angular base class usage using an abstract class](#abstract-class)
- [Overwriting lifecycle methods in Angular extended classes](#lifecycle-methods)
-- [Using dependency injection with your extended class](#dependency injection)
+- \[Using dependency injection with your extended class]\(#dependency injection)
- [Why you don't want to use base classes with Angular](#dont-extend-base-classes)
# What is an extension class, anyway? {#base-class}
@@ -195,8 +195,6 @@ This class has a few things going on:
When we create an "instance" of this class, it will in turn call the `constructor` and give us an object with all of the properties and methods associated with `HelloMessage` as an "instance" of that class.
-
-
Now, let's say that we want to reuse the `sayHi` logic in multiple classes at a time.
> Sounds like a familiar problem, doesn't it?
@@ -584,8 +582,6 @@ class AppComponent extends BaseComponent implements OnInit, OnDestroy {
}
```
-
-
## Overwriting `constructor` behavior {#overwriting-constructors}
When working with class extension, regardless of being used in Angular or in JavaScript itself, you need to call `super()` when trying to overwrite a constructor:
@@ -837,8 +833,6 @@ class AppComponent extends BaseComponent {
}
```
-
-
# Why you don't want to extend Angular base classes {#dont-extend-base-classes}
Now that we've learned how to extend base classes in Angular to share lifecycle methods, allow me to flip the script:
@@ -995,8 +989,6 @@ class AppComponent implements OnDestroy {
}
```
-
-
# Conclusion
And that's it! I hope this has been an insightful look into how you can extend component logic.
diff --git a/content/blog/angular-npm-font-usage/index.md b/content/blog/angular-npm-font-usage/index.md
index d0d4254a..bf511734 100644
--- a/content/blog/angular-npm-font-usage/index.md
+++ b/content/blog/angular-npm-font-usage/index.md
@@ -113,7 +113,7 @@ Because we're planning on using Angular CLI, we'll want to set the `src` propert
> font-weight: 800;
> src: url("#{$base_path}/foundry_sterling_extra_bold.otf") format('opentype')
> }
->
+>
> // ... Other @font-face declarations
> }
> ```
@@ -152,7 +152,7 @@ npm i ecp-private-assets
## `angular.json` modification {#angular-json}
-Once this is done, two steps are required. First, add the following to `angular.json`'s `assets` property. This will copy the files from `ecp-private-assets` to `/assets` once you setup a build.
+Once this is done, two steps are required. First, add the following to `angular.json`'s `assets` property. This will copy the files from `ecp-private-assets` to `/assets` once you setup a build.
```json
{
@@ -201,14 +201,13 @@ This way, when we use the CSS `url('/assets/')`, it will point to our newly appo
Now that we have our assets in place, we need to import the CSS file into our app.
-
If your app utilizes `postcss`'s `import` plugin or if you're using vanilla CSS, add the following line to your `main.scss` file:
```css
@import "ecp-private-assets/fonts/foundry_sterling.css";
```
-> Remember to keep the `@import`s at the top of your file, as you will receive an error otherwise.
+> Remember to keep the `@import`s at the top of your file, as you will receive an error otherwise.
However, if you're not using `postcss` and have SCSS installed, you can use the following:
diff --git a/content/blog/angular-templates-start-to-source/index.md b/content/blog/angular-templates-start-to-source/index.md
index 876301ca..6f82bc18 100644
--- a/content/blog/angular-templates-start-to-source/index.md
+++ b/content/blog/angular-templates-start-to-source/index.md
@@ -62,7 +62,7 @@ We are then adding the [`ngIf`](https://angular.io/api/common/NgIf) structural d
- If `bool` is true, it renders `True
`, and the template containing `False
` does not
- If `bool` is false, it then checks if the [`else` condition built into `ngIf`](https://angular.io/api/common/NgIf#showing-an-alternative-template-using-else) has a value assigned to it. If there is a value assigned to the `else` condition, it renders that template.
- - In this example, it does; the template we've assigned to `templHere`. Because of this, `False
` is rendered
+ - In this example, it does; the template we've assigned to `templHere`. Because of this, `False
` is rendered
If you had forgotten to include the `ngIf`, it would never render the `False` element because **a template is not rendered to the view unless explicitly told to — this includes templates created with `ng-template`**
@@ -209,7 +209,6 @@ Fancy that.
When we want to overwrite the type of data we expect `ViewChild` to return, we can use a second property passed to the `ViewChild` decorator with the type we want to be returned. With the use-case mentioned above, we can tell Angular that we want a reference to the element of the component itself by using the `ElementRef`.
-
```typescript
/* This would replace the previous @ViewChild */
@ViewChild('myComponent', {read: ElementRef, static: false}) myComponent: ElementRef;
@@ -314,7 +313,7 @@ action-card {
}
```
-But this is often not the case. _[Angular's `ViewEncapsulation`](https://angular.io/api/core/ViewEncapsulation) prevents styles from one component from affecting the styling of another_. This is especially true if you're using a configuration that allows the native browser to handle the components under the browser's shadow DOM APIs, which restricts stylesheet sharing on a browser-level. This is why the [Angular-specific CSS selector `::ng-deep`](https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep) has been marked for depreciation (sorry old-school Angular developers [including myself, so much to migrate 😭]).
+But this is often not the case. _[Angular's `ViewEncapsulation`](https://angular.io/api/core/ViewEncapsulation) prevents styles from one component from affecting the styling of another_. This is especially true if you're using a configuration that allows the native browser to handle the components under the browser's shadow DOM APIs, which restricts stylesheet sharing on a browser-level. This is why the [Angular-specific CSS selector `::ng-deep`](https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep) has been marked for depreciation (sorry old-school Angular developers \[including myself, so much to migrate 😭]).
It's no matter, though. We have the power of `ViewChildren` on our side! Corbin already showed us how to get a reference to an element of a rendered component! Let's spin up an example:
@@ -407,7 +406,6 @@ export class AppComponent {
This is a perfect example of where you might want `@ContentChild` — not only are you unable to use `ng-content` to render this template without a template reference being passed to an outlet, but you're able to create a context that can pass information to the template being passed as a child.
-
# How Does Angular Track the UI {#understand-the-tree}
Awesome! We've been blowing through some of the real-world uses of templates like a bullet-train through a tunnel. 🚆 But I have something to admit: I feel like I've been doing a pretty bad job at explaining the "nitty-gritty" of how this stuff works. While that can often be a bit more dry of a read, I think it's very important to be able to use these APIs to their fullest. As such, let's take a step back and read through some of the more abstract concepts behind them.
@@ -516,11 +514,8 @@ Little has changed, yet there's something new! A _view container_ is just what i
```
-

-
-
_It is because Angular's view containers being able to be attached to views, templates, and elements that enable the dependency injection system to get a `ViewContainerRef` regardless of what you're requested the `ViewContainerRef` on_.
## Host Views {#components-are-directives}
@@ -566,11 +561,8 @@ export class ChildComponent {}
export class AppComponent {}
```
-

-
-
## Template Input Variable Scope
Template input variables are the variables you bind to a template when using context. ``. _These variables are defined from the context that is applied to the template_. As a result **these templates are able to be accessed by the children views of the templates, but not from a higher level** — as the context is not defined above the template:
@@ -628,8 +620,6 @@ If you look at the output of this example, you'll notice that `testingMessage` i

-
-
When the view that is trying to render `testMessage` looks for that template reference variable, it is unable to, as it is bound to the `helloThereMsg` template view. Because it cannot find a template reference variable with the id `testMessage`, it treats it like any other unfound variable: an `undefined` value. The default behavior of `undefined` being passed to `ngTemplateOutlet` is to not render anything.
In order to fix this behavior, we'd need to move the second `ng-template` into the `helloThereMsg` template view so that the `ngTemplateOutlet` is able to find the matching template reference variable within its view scope.
@@ -709,7 +699,6 @@ One of the default checks that is ran when Angular is starting the initial rende
These checks trigger the lifecycle method `DoCheck`, which you can manually handle. The `DoCheck` lifecycle method will trigger every time Angular detects data changes, regardless of if the check of that data does not decide to update the item on-screen or not.
-
So let's look at the example we had previously, but let's add some lifecycle methods to evaluate when `ViewChild` is able to give us our value.
```typescript
@@ -743,7 +732,7 @@ ngAfterViewInit | The template is present? true
ngDoCheck | The template is present? true
```
-You can see that the `testingMessageCompVar` property is not defined until the `ngAfterViewInit`. _The reason we're hitting the error is that the template is not defined in the component logic until `ngAfterViewInit`._ It is not defined until them due to timing issues:* **the template is being declared in an embedded view, which takes a portion of time to render to screen**. As a result, the `helloThereMsg` template must render first, then the `ViewChild` can get a reference to the child after the initial update.
+You can see that the `testingMessageCompVar` property is not defined until the `ngAfterViewInit`. _The reason we're hitting the error is that the template is not defined in the component logic until `ngAfterViewInit`._ It is not defined until them due to timing issues:\* **the template is being declared in an embedded view, which takes a portion of time to render to screen**. As a result, the `helloThereMsg` template must render first, then the `ViewChild` can get a reference to the child after the initial update.
When using `ViewChild` by itself, it updates the value of the `testingMessageCompVar` at the same time that the `AfterViewInit` lifecycle method is ran. This value update is then in turn reflected in the template itself.
@@ -803,9 +792,9 @@ When taking the example with the `testingMessageCompVar` prop and changing the v
Having covered views in the last section, it's important to mention an important limitation regarding them:
->Properties of elements in a view can change dynamically, in response to user actions; the structure (number and order) of elements in a view can't. You can change the structure of elements by inserting, moving, or removing nested views within their view containers.
+> Properties of elements in a view can change dynamically, in response to user actions; the structure (number and order) of elements in a view can't. You can change the structure of elements by inserting, moving, or removing nested views within their view containers.
>
->\- Angular Docs
+> \- Angular Docs
## Embed Views {#embed-views}
@@ -846,12 +835,12 @@ Starting with some small recap:
- We're creating a template with the `ng-template` tag and assigning it to a template reference variable `templ`
- We're also creating a `div` tag, assigning it to the template reference variable `viewContainerRef`
- Lastly, `ViewChild` is giving us a reference to the template on the `templ` component class property.
- - We're able to mark both of these as `static: true` as neither of them are obfuscated by non-host-view views as parents
+ - We're able to mark both of these as `static: true` as neither of them are obfuscated by non-host-view views as parents
Now the new stuff:
- We're also using `ViewChild` to assign the template reference variable `viewContainerRef` to a component class property.
- - We're using the `read` prop to give it the [`ViewContainerRef`](https://angular.io/api/core/ViewContainerRef) class, which includes some methods to help us create an embedded view.
+ - We're using the `read` prop to give it the [`ViewContainerRef`](https://angular.io/api/core/ViewContainerRef) class, which includes some methods to help us create an embedded view.
- Then, in the `ngOnInit` lifecycle, we're running the `createEmbeddedView` method present on the `ViewContainerRef` property to create an embedded view based on the template.
If you take a look at your element debugger, you'll notice that the template is injected as a sibling to the `.testing` div:
@@ -897,7 +886,6 @@ console.log(embeddIndex); // This would print `0`.
The view container keeps track of all of the embedded views in its control, and when you `createEmbeddedView`, it searches for the index to insert the view into.
-
You're also able to lookup an embedded view based on the index you're looking for using `get`. So, if you wanted to get all of the indexes being tracked by `viewContainerRef`, you'd do:
```typescript
@@ -950,7 +938,6 @@ To get around this, we can use the `ng-container` tag, which allows us to get a
```
-
#### Move/Insert Template
@@ -959,7 +946,6 @@ But oh no! You'll see that the ordering is off. The simplest (and probably most
But this is a blog post, and I needed a contrived example to showcase how we can move views programmatically:
-
```typescript
const newViewIndex = 0;
this.viewContainerRef.move(embeddRef1, newViewIndex); // This will move this view to index 1, and shift every index greater than or equal to 0 up by 1
@@ -1034,7 +1020,6 @@ You'll notice this code is almost exactly the same from some of our previous com
However, the lack of a template associated with the directive enables some fun stuff, for example, _we can use the same dependency injection trick we've been using to get the view container reference_ to get a reference to the template element that the directive is attached to and render it in the `ngOnInit` method like so:
-
```typescript
@Directive({
selector: '[renderTheTemplate]'
@@ -1162,7 +1147,6 @@ The main idea behind structural directives is that **they're directives that wil
Let's look at a basic sample to start:
-
```typescript
@Directive({
selector: '[renderThis]'
@@ -1194,7 +1178,7 @@ export class AppComponent {}
Too much CS (computer science) speak? Me too, let's rephrase that. When you add the `*` to the start of the directive that's being attached to the element, you're essentially telling Angular to wrap that element in an `ng-template` and pass the directive to the newly created template.
-From there, the directive can get a reference to that template from the constructor (as Angular is nice enough to pass the template to our directive when we ask for it [this is what the DI system does]).
+From there, the directive can get a reference to that template from the constructor (as Angular is nice enough to pass the template to our directive when we ask for it \[this is what the DI system does]).
The cool part about structural directives, though? Because they're simply directives, **you can remove the `*` and use it with an `ng-template` directly**. Want to use the `renderThis` without a structural directive? No problem! Replace the template with the following code block and you've got yourself a rendered template:
@@ -1216,7 +1200,6 @@ But rendering a template without changing it in any way isn't a very useful stru
So if we added an input with the same name as the directive ([as we did previously](#directive-same-name-input)) to accept a value to check the truthiness of, added an `if` statement to render only if the value is true, we have ourselves the start of an `ngIf` replacement that we've built ourselves!
-
```typescript
@Directive({
selector: '[renderThisIf]'
@@ -1344,16 +1327,16 @@ export class NgIfContext {
Just to recap, let's run through this line-by-line:
1. `_context` is creating a default of `{$implicit: null, ngIf: null}`
- - The object shape is defined by the `NgIfContext` class below
- - This is to be able to pass as a context to the template. While this is not required to understand how Angular implemented this directive in basic terms, it was left in to avoid editing code elsewhere
+ - The object shape is defined by the `NgIfContext` class below
+ - This is to be able to pass as a context to the template. While this is not required to understand how Angular implemented this directive in basic terms, it was left in to avoid editing code elsewhere
2. We're then defining a variable to keep track of the template reference and the view reference ([what `createEmbeddedView` returns](https://angular.io/api/core/EmbeddedViewRef)) for usage later
3. The constructor is then assigning the template reference to the variable, and getting a reference to the view container
4. We're then defining an input with the same name as a setter, as we did with our implementation
- - This setter is also calling an update function, just as were with our implementation
+ - This setter is also calling an update function, just as were with our implementation
5. The update view is then seeing if the `$implicit` value in the context is truthy (as we're assigning the value of the `ngIf` input to the `$implicit` key on the context)
6. Further checks are made to see if there is a view reference already.
- - If there is not, it will proceed to make one (checking first that there is a template to create off of)
- - If there is, it will not recreate a view, in order to avoid performance issues by recreating views over-and-over again
+ - If there is not, it will proceed to make one (checking first that there is a template to create off of)
+ - If there is, it will not recreate a view, in order to avoid performance issues by recreating views over-and-over again
## Microsyntax
@@ -1428,12 +1411,10 @@ export class MakePigLatinDirective {
export class AppComponent {}
```
-
Just as before, we would use semicolons to split the definitions, then bind the external (as in: from the directive) context value of `original` to the local (this template) variable of `ogMsg`.
-
### Additional Attribute Inputs
With a typical — non-structural — directive, you'd have inputs that you could add to your directive. For example, you could have a directive with the following inputs:
@@ -1513,7 +1494,6 @@ The magic in the syntax comes from that input name. I know in previous examples
**This is why we usually call the directive selector the structural directive prefix — it should prefix the names of any of your microsyntax inputs**. Outside of the prefix rule, there's little else that you'll need to keep in mind with these input names. Want to make it `makePiglatinCasingThingHere`? No problem, just change that part of the input syntax to read `casingThingHere: 'upper'`
-
#### Why not bind like a typical input?
Now, I remember when I was learning a lot of the structural directive stuff, I thought "well this syntax is cool, but it might be a bit ambiguous". I decided I was going to change that a bit:
@@ -1687,7 +1667,6 @@ A key expression is simply an expression that you’re able to bind to an input
- You’ll then want to **place an expression that will be passed as the input value** for the `key` you started the key expression with
- Finally, _if you’d like to save the input value_, you’re able to **use the `as` keyword**, followed by the name you’d like to save the input value to (as a template input variable)
-
```html
@@ -1702,8 +1681,8 @@ The `let` binding:
- Starts with a `let` preserved keyword
- Then lists the template input variable to save the value to
- You’ll then want to put the key of the context you want to save a value of after a `=` operator
- - It’s worth mentioning that this is optional. This is because of the `$implicit` key in context.
- EG: a context of `{$implicit: 1, namedKey: 900}` and `let smallNum; let largerNum = namedKey` would assign `1` to `smallNum` and `900` to `largerNum`
+ - It’s worth mentioning that this is optional. This is because of the `$implicit` key in context.
+ EG: a context of `{$implicit: 1, namedKey: 900}` and `let smallNum; let largerNum = namedKey` would assign `1` to `smallNum` and `900` to `largerNum`
### Combining Them Together
@@ -1821,14 +1800,16 @@ export class AppComponent {
- We're starting with enabling `uniFor` as the structural directive name
+
- Then we're defining an input to accept `of` as a key in the syntax (to match the `ngFor` structural directive syntax).
- We can then reference this value later with `this.uniForOf` just as we are in the `ngAfterViewInit`.
- In that lifecycle method, we're then creating an embedded view for each item in the array
- - This view is passed a context with an implicit value (so that `_var` in`let _var of list` will have the value of this item)
- - We also pass the index to the context to give a boolean if an item is the first in a list
- - Then we pass a `uniForOf` so that we can use `as` to capture the value passed to the `of` portion of the syntax
+ - This view is passed a context with an implicit value (so that `_var` in`let _var of list` will have the value of this item)
+ - We also pass the index to the context to give a boolean if an item is the first in a list
+ - Then we pass a `uniForOf` so that we can use `as` to capture the value passed to the `of` portion of the syntax
+
- Finally, we use the [async pipe](https://angular.io/api/common/AsyncPipe) to get the value of the array that's inside of an observable
# Conclusion
diff --git a/content/blog/basic-overview-of-packets-and-osi/index.md b/content/blog/basic-overview-of-packets-and-osi/index.md
index 898ee01c..b589df36 100644
--- a/content/blog/basic-overview-of-packets-and-osi/index.md
+++ b/content/blog/basic-overview-of-packets-and-osi/index.md
@@ -22,7 +22,8 @@ It's important to note that _"networking" is a broad, catch-all term that infers
> That said, you need the right binary data to be input into the CPU for it to process, just like our brains need the right input to find the answer of what to do. Because of this, communication with the CPU is integral
# Architecture {#network-architectures}
-There are a lot of ways that information can be connected and transferred. We use various types of architecture to connect them.
+
+There are a lot of ways that information can be connected and transferred. We use various types of architecture to connect them.
_Computers speak in `1`s and `0`s, known as binary_. These binary values come in incredibly long strings of combinations of one of the two symbols to _construct all of the data used in communication_.
@@ -44,7 +45,7 @@ Furthermore, because error-handled bi-directional cancelable subscriptions (like
## Packet Architecture {#packet-architecture}
-The weaknesses of the bus architecture led to the creation of the packet architecture. The packet architecture requires a bit more of a higher-level understanding of how data is sent and received. To explain this concept, we'll use an analogy that fits really well.
+The weaknesses of the bus architecture led to the creation of the packet architecture. The packet architecture requires a bit more of a higher-level understanding of how data is sent and received. To explain this concept, we'll use an analogy that fits really well.
Let's say you want to send a note to your friend that's hours away from you. You don't have the internet so you decide to send a letter. In a typical correspondence, you'd send off a letter, include a return address, and wait for a response back. That said, _there's nothing stopping someone from sending more than a single letter before receiving a response_. This chart is a good example of that:
@@ -56,7 +57,7 @@ Similarly, a packet is _sent from a single sender, received by a single recipien
Letters may not give you the same kind of continuous stream of consciousness as in-person communications, but they do provide something in return: structure.
-The way you might structure your thoughts when speaking is significantly different from how you might organize your thoughts on paper. For example, in this article, there is a clear beginning, end, and structured headings to each of the items in this article. Such verbose metadata (such as overall length) cannot be communicated via in-person talking. _The way you may structure data in a packet may also differ from how you might communicate data via a bus_.
+The way you might structure your thoughts when speaking is significantly different from how you might organize your thoughts on paper. For example, in this article, there is a clear beginning, end, and structured headings to each of the items in this article. Such verbose metadata (such as overall length) cannot be communicated via in-person talking. _The way you may structure data in a packet may also differ from how you might communicate data via a bus_.
That said, simply because there's a defined start and an end does not mean that you cannot _send large sequences of data through multiple packets and stitch them together_. Neither is true for the written word. This article does not contain the full set of information the series we hope to share, but rather provides a baseline and structure for how the rest of the information is to be consumed. So too can packets provide addendums to other packets, if you so wish.
diff --git a/content/blog/change-host-file-android-emulator/index.md b/content/blog/change-host-file-android-emulator/index.md
index 9ecaa8f8..3d84a269 100644
--- a/content/blog/change-host-file-android-emulator/index.md
+++ b/content/blog/change-host-file-android-emulator/index.md
@@ -23,13 +23,13 @@ In order to do this, you’ll need to install a few things first:
During installation, it will ask you if you want to setup an emulator. You’ll want to install all of the related Intel Virtualization packages, as it will greatly increase your speed of the emulator.
-- Download and install the android-platform-tools. This will include
+- Download and install the android-platform-tools. This will include
```
adb
```
- command directly on your path for you to utilize
+ command directly on your path for you to utilize
- For macOS, I suggest using [the Homebrew package manager](https://brew.sh/) and running `brew cask install android-platform-tools`
- For Windows, I suggest using [the Chocolatey package manager](https://chocolatey.org/) and running `choco install adb`
@@ -45,19 +45,19 @@ Then, press “Configure” in the bottom right corner. Then press the “AVD Ma

-You’ll see a popup window that will show you the list of virtual devices. *These are devices that will be used in order to run an emulator*. You may already have a virtual device setup from the initial setup of Android Studio. They include the version of the operating system you use when you boot up the device. While the virtual device that was setup out-of-the-box is fine for most operations, we’ll want to setup an older version of the emulator. This will allow us to change the host file in Android, which requires root (something the default images won’t allow).
+You’ll see a popup window that will show you the list of virtual devices. _These are devices that will be used in order to run an emulator_. You may already have a virtual device setup from the initial setup of Android Studio. They include the version of the operating system you use when you boot up the device. While the virtual device that was setup out-of-the-box is fine for most operations, we’ll want to setup an older version of the emulator. This will allow us to change the host file in Android, which requires root (something the default images won’t allow).
Select **Create Virtual Device**, then select a device type. In my example, I selected **Nexus 5**, but any device definition of a relatively modern phone should work.

-As mentioned before, the default images that are provided will not allow us to replace the host files. In order to do so, *we have to download an older Android image* (and one that does not include Google Play Store). To do this, I selected the **x86_64 Android 7.1.1** (non Google API version) image to download and then selected **Next**.
+As mentioned before, the default images that are provided will not allow us to replace the host files. In order to do so, _we have to download an older Android image_ (and one that does not include Google Play Store). To do this, I selected the **x86\_64 Android 7.1.1** (non Google API version) image to download and then selected **Next**.

It’s worth noting that we specifically must select a non-Google version, otherwise our future commands will not work (per Google’s restrictions on Google API images).
-After this step, proceed to name the Android Device. *I’d suggest you name it something without any spaces in order to run a command later that you’ll need to run*. In this case, I called the image **Nexus5**.
+After this step, proceed to name the Android Device. _I’d suggest you name it something without any spaces in order to run a command later that you’ll need to run_. In this case, I called the image **Nexus5**.

@@ -65,8 +65,8 @@ After this step, proceed to name the Android Device. *I’d suggest you name it
Once the AVD is initially setup, open your terminal, and find your installation path of Android Studio.
-- For MacOS, this should be under **~/Library/Android/sdk**
-- For Windows, this *should* be **C:\Users\AppData\Local\Android\sdk**
+- For MacOS, this should be under **\~/Library/Android/sdk**
+- For Windows, this _should_ be **C:\Users\AppData\Local\Android\sdk**
Once in that path, you want to run a specific emulator command:
@@ -92,9 +92,9 @@ Once you’re done with running the emulator, open a new tab and run the follow

-Upon running these commands, you’ll find a **hosts** file. *This file is the file that tells your OS what path a given domain has.* You can, for example, map `example.com` to go to a specific IP address, similar to how DNS works for most domains.
+Upon running these commands, you’ll find a **hosts** file. _This file is the file that tells your OS what path a given domain has._ You can, for example, map `example.com` to go to a specific IP address, similar to how DNS works for most domains.
-Inside the emulator, the IP address `10.0.2.2` refers to the *host* OS. For example, if you’re running a local server on your Windows/MacOS/Linux machine on `localhost:3000`, you can access it using `10.0.2.2:3000` from the Android emulator.
+Inside the emulator, the IP address `10.0.2.2` refers to the _host_ OS. For example, if you’re running a local server on your Windows/MacOS/Linux machine on `localhost:3000`, you can access it using `10.0.2.2:3000` from the Android emulator.
Knowing these two things, you can change the host file to make `example.com` refer to the host by adding the following to the host file:
diff --git a/content/blog/chess-knight-problem/index.md b/content/blog/chess-knight-problem/index.md
index c6d359a8..c9b7afd1 100644
--- a/content/blog/chess-knight-problem/index.md
+++ b/content/blog/chess-knight-problem/index.md
@@ -118,7 +118,7 @@ console.log(findPath(3, 3, 2, 1));
I correctly got 1.
-One of the spots that we can reach in 2 moves is \[4,6\].
+One of the spots that we can reach in 2 moves is \[4,6].
```javascript
console.log(findPath(3, 3, 4, 6));
diff --git a/content/blog/corbin-advice-to-technical-interviewers/index.md b/content/blog/corbin-advice-to-technical-interviewers/index.md
index 6faab4a7..ea116efa 100644
--- a/content/blog/corbin-advice-to-technical-interviewers/index.md
+++ b/content/blog/corbin-advice-to-technical-interviewers/index.md
@@ -13,36 +13,33 @@
Tech recruiting is difficult. Interviews are tricky for candidates - and for interviewers. One of the untold challenges of interviewing is knowing how to set up good candidates for success. After all, you want a process that tests the right skills, and filters out the noise that is not helpful to evaluating candidates.
-
This can be done in many ways, but let’s talk about a few today.
# Don’t Be Afraid To Help
-Something to keep in mind while interviewing candidates is that they’re just like you and me: people. People that make mistakes from time-to-time or might get stuck on a certain phrasing of a question.
+Something to keep in mind while interviewing candidates is that they’re just like you and me: people. People that make mistakes from time-to-time or might get stuck on a certain phrasing of a question.
Oftentimes, lending a gentle helping hand can be the ticket to a successful interview. It can be as simple as rephrasing the question in a way that points towards the solution, or providing a structural bit of code that needs tweaking in order to be solved.
This is particularly beneficial for junior engineers, who’s interviews should focus more on “thought process” and “ability to learn and communicate” than existing skill sets. However, even senior engineers can have the solution escape them until it finally clicks with some small assistance.
-
While this all might seem counterintuitive to assist a candidate (even in small ways) during an interview, you have to remember that they need support. In their future role with your company, they won’t (and shouldn’t) be working in isolation. Instead, they will have a team to lean on. By giving a small hint here and there, you’re able to understand how they receive feedback and when they need help.
# Allow for Resources
-As mentioned earlier, candidates are just people. Because of that, you will never find an all-knowing candidate who only ever relies solely on their existing knowledge to fix an issue (no matter what big-ego Jim says). Time-and-time again I’ve heard from seasoned developers that research and cheat-sheets are part of their daily engineering work.
+As mentioned earlier, candidates are just people. Because of that, you will never find an all-knowing candidate who only ever relies solely on their existing knowledge to fix an issue (no matter what big-ego Jim says). Time-and-time again I’ve heard from seasoned developers that research and cheat-sheets are part of their daily engineering work.
While it might not be immediately obvious, knowing how to search for and find the relevant content is incredibly important. Not only that, it’s something that’s developed gradually alongside a developer’s journey - just like any other skill.
-
After all, the point of coding interviews is to see how capable a developer is at the job they’re applying for. You want to test in real-world situations, not in an isolated environment that doesn’t represent the daily aspects of the job.
# Less Algorithms, More Demos
Speaking of representing a job in a more realistic light: think about the last time you had a ticket in your backlog that required discussion of tree reversal (or similar algorithm). Now think of the last time you asked a question like that in your interviews. See where I’m going here? I’m not implying that algorithm questions are inherently bad for every position, but in this industry they’ve been used as a stop-gap for more relevant questions.
-Many engineers can attest to being asked algorithmic questions in an interview - only to be working with styling and application state management in their day jobs. The usage of complex algorithms are far-and-few between - especially in front-end engineering.
+Many engineers can attest to being asked algorithmic questions in an interview - only to be working with styling and application state management in their day jobs. The usage of complex algorithms are far-and-few between - especially in front-end engineering.
-Even when algorithms ***are\*** relevant, there’s usually a team to discuss with, research to be done, and benchmarking to verify the usage of a given algorithm for key application logic. These discussions can take significantly longer than an hour long interview.
+Even when algorithms \***are\*** relevant, there’s usually a team to discuss with, research to be done, and benchmarking to verify the usage of a given algorithm for key application logic. These discussions can take significantly longer than an hour long interview.
Not only are these questions rarely representative of the actual job, they’re also easy to cheat with someone with enough free-time to dedicate towards algorithm memorization. Googling “interview algorithm questions” provides over 17 million results. Even the first page of results promises to teach you how to instantly solve dozens of common algorithm questions.
@@ -62,7 +59,7 @@ While real-world code samples provide many upsides, setting up a real-world exam
# Take-Homes
-We at CoderPad are ***strong\*** advocates of take-home interviews for technical assessments. While [we’ve written about many of the benefits of take-homes before](https://coderpad.io/blog/hire-better-faster-and-in-a-more-human-way-with-take-homes/), we’ll touch on some of the advantages here:
+We at CoderPad are \***strong\*** advocates of take-home interviews for technical assessments. While [we’ve written about many of the benefits of take-homes before](https://coderpad.io/blog/hire-better-faster-and-in-a-more-human-way-with-take-homes/), we’ll touch on some of the advantages here:
- Lower stress environment for candidate
- We’ve heard a lot from the autistic community and those with anxiety that this helps a lot
diff --git a/content/blog/css-fundamentals/index.md b/content/blog/css-fundamentals/index.md
index 0eb801f0..7b7d3487 100644
--- a/content/blog/css-fundamentals/index.md
+++ b/content/blog/css-fundamentals/index.md
@@ -55,7 +55,7 @@ Every element on the browser has a box model. You can inspect them using browser
Nearly every HTML element has some default browser styles. These styles are called HTML defaults. These defaults may change depending on the browsers rendering engine.
-> 🤓 Not every browser supports every CSS property! For up-to-date browser support I suggest checking out [Can I Use?](https://www.google.com/search?q=caniuse&rlz=1C1CHBF_enCA963CA963&oq=caniuse&aqs=chrome.0.69i59j69i60l3.1776j0j4&sourceid=chrome&ie=UTF-8)
+> 🤓 Not every browser supports every CSS property! For up-to-date browser support I suggest checking out [Can I Use?](https://www.google.com/search?q=caniuse\&rlz=1C1CHBF_enCA963CA963\&oq=caniuse\&aqs=chrome.0.69i59j69i60l3.1776j0j4\&sourceid=chrome\&ie=UTF-8)
Every HTML element has a place and a purpose. Some HTML elements are strictly used for grouping content and are generally referred to as containers, while other HTML elements are used for text, images and more.
@@ -203,7 +203,7 @@ justify-content: space-evenly;
> 🤓 Space your content out with justify-content
-Here is a list of CSS properties used to control flexbox properties:
+Here is a list of CSS properties used to control flexbox properties:
- [`flex-direction`](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction) - controls flexbox direction
- [`flex-grow`](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow) - controls a flex items grow factor
@@ -337,9 +337,9 @@ There are five types of element positions:
#### Flexbox:
- - Used in headers, lists, tags, or any other block or inline content with the correct flex-direction
- - Primary method to align and justify content in small components
- - Easy to use
+- Used in headers, lists, tags, or any other block or inline content with the correct flex-direction
+- Primary method to align and justify content in small components
+- Easy to use
For example, YouTube uses a flexbox to space out their headers children elements:
@@ -347,20 +347,20 @@ For example, YouTube uses a flexbox to space out their headers children elements
> 🤓 Mastering the flexbox will take you very far in CSS as it is used everywhere
-#### Gridbox:
+#### Gridbox:
- - Used in creating complex layouts that require both columns and rows
- - Provides the easiest and shortest way to center elements
- - Verbose and powerful
+- Used in creating complex layouts that require both columns and rows
+- Provides the easiest and shortest way to center elements
+- Verbose and powerful
For example, Spotify uses a gridbox to achieve their playlist player layout:

-#### Positioning:
+#### Positioning:
- - Used in lightboxes, mobile menus, modal windows, and similar overlaying elements
- - Primarily used to remove elements from document flow
+- Used in lightboxes, mobile menus, modal windows, and similar overlaying elements
+- Primarily used to remove elements from document flow
For example, the cookies modal on stackoverflow uses a fixed position to stay on your screen while hovering above other document elements:
@@ -422,7 +422,7 @@ There are five basic CSS selectors:
- **Type (`h1`)** - Targets all with the given type
- **Attribute (`[type="submit"]`)** Targets all with the given attribute
-> 🤓 I recommend using the `.class` selector over the `#id` selector as ID attributes are unique
+> 🤓 I recommend using the `.class` selector over the `#id` selector as ID attributes are unique
You can group selectors under one CSS rule using commas to share properties among multiple selectors:
@@ -532,4 +532,4 @@ CSS variables allow us to define arbitrary values for reuse across a stylesheet.
It is common to use CSS variables for repeated values such as colors, font-size, padding, etc.
-> ⚡ [Live Code Example: CSS Variables](https://codesandbox.io/s/css-variables-tx14z?file=/styles.css)
\ No newline at end of file
+> ⚡ [Live Code Example: CSS Variables](https://codesandbox.io/s/css-variables-tx14z?file=/styles.css)
diff --git a/content/blog/data-storage-options-in-react-native/index.md b/content/blog/data-storage-options-in-react-native/index.md
index 17ff9044..fbd8dd6c 100644
--- a/content/blog/data-storage-options-in-react-native/index.md
+++ b/content/blog/data-storage-options-in-react-native/index.md
@@ -62,14 +62,14 @@ While you're more than able to cache database calls manually, sometimes it's con
# Pros and Cons {#pros-and-cons}
-| Option | Pros | Cons |
-| --------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
-| [Key-Value Pair Storage](#default-preference) | - Extremely fast
- Useful for simple data storing
| - Can only store serializable data
- Not very cleanly separated
- Not very secure
|
-| [Secure Key-Value Storage](#secure-key-store) | - Fast
- A secure method of data storing
| - Can only store serializable data
- Not very cleanly separated
|
-| [SQLite without ORM](#sqlite-storage) | | - Difficult to maintain code and table migrations manually
- Not very fast compared to key-value pairs
|
-| [SQLite with ORM](#orms) | - Cleanly separated data
- Much more easy to maintain than writing SQL itself
| - Often slower than writing SQL by hand
- More work to get setup
|
-| [Serverless](#serverless) | - Simple setup
- No need to schema or migrate a database when data requirements change
| - Potentially difficult to cache
- Not on-device
|
-| [RealmDB](#realm) | - An easy-to-sync on-device and cloud storage
| - A heavier requirement of investment than something more standard
- Large migrations on the horizon
|
+| Option | Pros | Cons |
+| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
+| [Key-Value Pair Storage](#default-preference) | - Extremely fast
- Useful for simple data storing
| - Can only store serializable data
- Not very cleanly separated
- Not very secure
|
+| [Secure Key-Value Storage](#secure-key-store) | - Fast
- A secure method of data storing
| - Can only store serializable data
- Not very cleanly separated
|
+| [SQLite without ORM](#sqlite-storage) | | - Difficult to maintain code and table migrations manually
- Not very fast compared to key-value pairs
|
+| [SQLite with ORM](#orms) | - Cleanly separated data
- Much more easy to maintain than writing SQL itself
| - Often slower than writing SQL by hand
- More work to get setup
|
+| [Serverless](#serverless) | - Simple setup
- No need to schema or migrate a database when data requirements change
| - Potentially difficult to cache
- Not on-device
|
+| [RealmDB](#realm) | - An easy-to-sync on-device and cloud storage
| - A heavier requirement of investment than something more standard
- Large migrations on the horizon
|
# Conclusion
diff --git a/content/blog/debugging-nodejs-programs-using-chrome/index.md b/content/blog/debugging-nodejs-programs-using-chrome/index.md
index efdeb059..e02baeff 100644
--- a/content/blog/debugging-nodejs-programs-using-chrome/index.md
+++ b/content/blog/debugging-nodejs-programs-using-chrome/index.md
@@ -42,7 +42,7 @@ app.get('/', (req, res) => {
app.listen(3000);
```
-You'll notice that we're using the dummy endpoint http://www.mocky.io/v2/5e1a9abe3100004e004f316b. This endpoint returns an array of values with a shape much like this:
+You'll notice that we're using the dummy endpoint . This endpoint returns an array of values with a shape much like this:
```json
[
@@ -145,7 +145,7 @@ In order to access the debugger, you'll need to open up Chrome and go to the URL
Then you'll want to select `inspect` on the node instance.
-Doing so will bring up a screen of your entrypoint file with the source code in a window with line numbers.
+Doing so will bring up a screen of your entrypoint file with the source code in a window with line numbers.

@@ -155,7 +155,7 @@ Think about running your code like driving an experimental race-car. This car ha
It's similar to a debug mode of your program. You can evaluate data using `console.log`, but _to gain greater insight, you may want to pause your application_, inspect the small details in the code during a specific state, and to do so you must pause your code. This is where breakpoints come into play: they allow you to place "pause" points into your code so that when you reach the part of code that a breakpoint is present on, your code will pause and you'll be given much better insight to what your code is doing.
-To set a breakpoint from within the debugging screen, you'll want to select a code line number off to the left side of the screen. This will create a blue arrow on the line number.
+To set a breakpoint from within the debugging screen, you'll want to select a code line number off to the left side of the screen. This will create a blue arrow on the line number.
> If you accidentally select a line you didn't mean to, that's okay. Pressing this line again will disable the breakpoint you just created
@@ -163,7 +163,7 @@ To set a breakpoint from within the debugging screen, you'll want to select a co
A race-car needs to drive around the track until the point where the pit-stop is in order to be inspected; _your code needs to run through a breakpoint in order to pause and give you the expected debugging experience_. This means that, with only the above breakpoint enabled, the code will not enter into debug mode until you access `localhost:3000` in your browser to run the `app.get('/')` route.
-> Some applications may be a bit [quick-on-the-draw](https://en.wiktionary.org/wiki/quick_on_the_draw) in regards to finding an acceptable place to put a breakpoint. If you're having difficulties beating your code running, feel free to replace the `--inspect` flag with `--inspect-brk` which will automatically add in a breakpoint to the first line of code in your running file.
+> Some applications may be a bit [quick-on-the-draw](https://en.wiktionary.org/wiki/quick_on_the_draw) in regards to finding an acceptable place to put a breakpoint. If you're having difficulties beating your code running, feel free to replace the `--inspect` flag with `--inspect-brk` which will automatically add in a breakpoint to the first line of code in your running file.
>
> This way, you should have the margins to add in a breakpoint where you'd like one beforehand.
@@ -179,7 +179,7 @@ Once you do so, you're in full control of your code and its state. You can:
- _Inspect the values of variables_ (either by highlighting the variable you're interested in, looking under the "scope" tab on the right sidebar, or using the `Console` tab to run inspection commands à la [`console.table`](https://developer.mozilla.org/en-US/docs/Web/API/Console/table) or [`console.log`](https://developer.mozilla.org/en-US/docs/Web/API/Console/log)):
- 
+ 
- _Change the value of a variable:_

- _Run arbitrary JavaScript commands_, similar to how a code playground might allow you to:
@@ -199,7 +199,7 @@ So, if we want to see what happens after the `body` JSON variable is parsed into
Knowing this, let's move through the next few lines manually by pressing each item. The ran values of the variables as they're assigned should show up to the right of the code itself in a little yellow box; This should help you understand what each line of code is running and returning without `console.log`ging or otherwise manually.
-![A screenshot showing ran lines until line 12 of the "console.log". It shows that "employeeAges" is "[undefined]"](./next_few_lines.png)
+![A screenshot showing ran lines until line 12 of the "console.log". It shows that "employeeAges" is "\[undefined\]"](./next_few_lines.png)
But oh no! You can see, `employeeAges` on line `9` is the one that results in the unintended `[undefined]`. It seems to be occurring during the `map` phase, so let's add in a breakpoint to line `10` and reload the `localhost:3000` page (to re-run the function in question).
@@ -209,7 +209,7 @@ Once you hit the first breakpoint on line `7`, you can press "play" once again t
This will allow us to see the value of `employee` to see what's going wrong in our application to cause an `undefined` value.
-
+
Oh! As we can see, the name of the field we're trying to query is `employee_age`, not the mistakenly typo'd `employeeAge` property name we're currently using in our code. Let's stop our server, make the required changes, and then restart the application.
@@ -217,8 +217,6 @@ We will have to run through the breakpoints we've set by pressing the "play" but

-
-
There we go! We're able to get the expected "23"! That said, it was annoying to have to press "play" twice. Maybe there's something else we can do in similar scenarios like this?
## Disabling Breakpoints {#disabling-breakpoints}
@@ -253,7 +251,7 @@ Once inside the `map` function, there's even a button _to get you outside of tha
> }
> return ageArray;
> };
->
+>
> app.get('/', (req, res) => {
> request('http://www.mocky.io/v2/5e1a9abe3100004e004f316b', (error, response, body) => {
> const responseList = JSON.parse(body);
diff --git a/content/blog/documentation-driven-development/index.md b/content/blog/documentation-driven-development/index.md
index edabb10a..097161ef 100644
--- a/content/blog/documentation-driven-development/index.md
+++ b/content/blog/documentation-driven-development/index.md
@@ -66,7 +66,7 @@ function calculateUserScore({killsArr, deaths, assists}) {
}
```
-While we've seen the function change, remember that your game may be making this calculation in multiple parts of the codebase. On top of this, maybe your API *still* isn't perfect for this function. What if you want to display the special kills with additional points after a match?
+While we've seen the function change, remember that your game may be making this calculation in multiple parts of the codebase. On top of this, maybe your API _still_ isn't perfect for this function. What if you want to display the special kills with additional points after a match?
These drastic refactors mean that each iteration requires additional refactor work, likely delaying the time to ticket completion. This can impact releases dates or other scheduled launches.
@@ -148,19 +148,19 @@ In fact, this _includes_ tests. 😱 Tests are a good way of conveying API examp
In particular, if you're good about [writing primarily integration tests](https://kentcdodds.com/blog/write-tests), you're actually writing out usage API docs while writing testing code.
-This is particularly true when writing developer tooling or libraries. Seeing a usage example of how to do something is extremely helpful, especially with a test to validate its behavior alongside it.
+This is particularly true when writing developer tooling or libraries. Seeing a usage example of how to do something is extremely helpful, especially with a test to validate its behavior alongside it.
--------
+---
Another thing "documentation-driven development" does not prescribe is "write once and done." This idea is a myth and may be harmful to your scope and budgets - time or otherwise.
As we showed with the `calculateUserScore` example, you may need to modify your designs before moving forward for the final release: that's okay. Docs influence code influence docs. The same is true for TDD.
---------
+---
DDD isn't just useful for developing code for production, either. In interviews, some good advice to communicate your development workflow is to write code comments and **then** write the solution. This allows you to make mistakes in the documentation phase (of writing comments) that will be less time-costly than if you'd made a mistake in implementation.
-By doing this, you can communicate with your interviewer that you know how to work in a team and find well-defined goals. These will allow you to work towards an edgecase-free* implementation with those understandings.
+By doing this, you can communicate with your interviewer that you know how to work in a team and find well-defined goals. These will allow you to work towards an edgecase-free\* implementation with those understandings.
# Bring it back now y'all
@@ -173,10 +173,10 @@ Each of these refers to a form of validating the functionality of code behind us
# Conclusion
-I've been using documentation-driven development as a concept to drive my coding on some projects. Among them was my project [`CLI Testing Library`](https://github.com/crutchcorn/cli-testing-library), which allowed me to write a [myriad of documentation pages](https://github.com/crutchcorn/cli-testing-library/tree/main/docs) as well as [verbose GitHub issues](https://github.com/crutchcorn/cli-testing-library/issues/2).
+I've been using documentation-driven development as a concept to drive my coding on some projects. Among them was my project [`CLI Testing Library`](https://github.com/crutchcorn/cli-testing-library), which allowed me to write a [myriad of documentation pages](https://github.com/crutchcorn/cli-testing-library/tree/main/docs) as well as [verbose GitHub issues](https://github.com/crutchcorn/cli-testing-library/issues/2).
Both of these forced me to better refine my goals and what I was looking for. The end-product, I believe, is better as a result.
What do you think? Is "DDD" a good idea? Will you be using it for your next project?
-Let us know what you think, and [join our Discord](https://discord.gg/FMcvc6T) to talk to us more about it!
+Let us know what you think, and [join our Discord](https://discord.gg/FMcvc6T) to talk to us more about it!
diff --git a/content/blog/dom-pollution-why-i-prefer-vue-over-angular/index.md b/content/blog/dom-pollution-why-i-prefer-vue-over-angular/index.md
index 235ff906..33355967 100644
--- a/content/blog/dom-pollution-why-i-prefer-vue-over-angular/index.md
+++ b/content/blog/dom-pollution-why-i-prefer-vue-over-angular/index.md
@@ -41,6 +41,7 @@ Then if you tried the same in Angular:
What happened? Lets compare the custom components.
`MyTextCell.vue`
+
`text-cell.component.ts`
+