Home Page
Zola
2024-03-11T00:00:00+00:00
https://williamhuey.github.io/atom.xml
Tsx - Use TypeScript in NPM Scripts
2024-03-11T00:00:00+00:00
2024-03-11T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/tsx-use-typescript-in-npm-scripts/
<h3 id="execute-esm-script-on-nodejs-command-line-without-compilation">Execute ESM script on Nodejs Command Line without Compilation</h3>
<p>When executing NPM scripts you can use node to run JavaScript files.</p>
<p>If you want step up the type safety of your JavaScript you would switch to using TypeScript, but then you then need something to help compile your
TypeScript on demand such as <a href="https://github.com/TypeStrong/ts-node">ts-node</a>.</p>
<span id="continue-reading"></span>
<p>However, now when supplying the <code>--esm</code> flag script ts-node, it might error out with this issue:</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">bad</span><span> option:</span><span style="color:#f29718;"> --esm
</span></code></pre>
<p>One of things that you can do to correct for this issue is by using another TypeScript on demand compiler tool, <a href="https://github.com/privatenumber/tsx">tsx</a>.
This alternative aims to be more compatible with ESM scripts. You can also use tsx for JavaScript files.</p>
Typst - LaTeX Alternative
2024-02-21T00:00:00+00:00
2024-02-21T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/typst-latex-alternative/
<h3 id="typesetting-documents-with-rust">Typesetting Documents with Rust</h3>
<p>LaTeX is a time-honored typesetting application that has developed a large
community. With age, comes accumulation of the wealth of packages for general document creation. Although it is tool that is well-developed, it tends to be slower and
is burden with a legacy design that is not as performant as newer tools.
Since its use is so pervasive, it has become entrenched in the document
creation community preventing new competing application has come forth. However, there is an alternative that is worth considering and that one is Typst.</p>
<span id="continue-reading"></span><h2 id="install">Install</h2>
<p>To install the Typst application, note the <a href="https://github.com/typst/typst?tab=readme-ov-file#installation">instructions</a>. If you happen have <code>node</code> installed on your machine, you can install it readily from <a href="https://typst.community/typst.js/">npm</a>.</p>
<p>Typst is a small self-contained binary (10mb) that allows you to quickly get started. LateX on the other hand is a very large installation size.</p>
<h2 id="example">Example</h2>
<p>A Typst document starts with a plain text file that ends with the <code>typ</code> file extension.</p>
<p>Navigate to a location and create the document file.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">touch</span><span> sample.typ
</span></code></pre>
<p>Add some sample content into the sample.typ.</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>This is some content.
</span></code></pre>
<p>To make Typst compile this automatically,</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">typst</span><span> watch sample.typ
</span></code></pre>
<p>Typst will monitor this document and automatically compiles your file to a pdf.</p>
<p>If you have installed Typst with NPM, you can use Typst <a href="https://typst.community/typst.js/#md:installation">programmatically</a> within nodejs.</p>
<p>The compilation process takes less than 5ms from the example above.
Typst promises fast rendering through <a href="https://laurmaedje.github.io/posts/comemo/">incremental compilation</a>.</p>
<p>There is also thorough <a href="https://typst.app/docs/">documentation</a> on how to use Typst. Typst was designed to offer the flexibility and power of LaTeX in an easier to use concise syntax of markdown.</p>
Oclif and Vite
2024-01-14T00:00:00+00:00
2024-01-14T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/oclif-and-vite/
<h3 id="incompatbility-with-cli-build">Incompatbility with CLI Build</h3>
<p>If you intend to build out an Oclif typescript CLI app that is to be consumed by Vitejs, you might experience an issue with integrating the two. The Oclif CLI builds properly, but when executing the CLI through vite, this errors comes up.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">[ERR_UNKNOWN_FILE_EXTENSION]</span><span> TypeError Plugin: ... </span><span style="color:#ff7733;">[</span><span>ERR_UNKNOWN_FILE_EXTENSION</span><span style="color:#ff7733;">]</span><span>: Unknown file extension </span><span style="color:#c2d94c;">".ts"</span><span> ...
</span></code></pre>
<span id="continue-reading"></span>
<p>There is an <a href="https://github.com/oclif/oclif/issues/1151">Oclif issue</a> raised that suggests that Vite doesn't work with Oclif.</p>
<p>Since the issue hasn't been resolved as of January 2024, one can switch to using <a href="https://parceljs.org/">parceljs</a> as the alternative. Parcel has a programmatic API for <a href="https://parceljs.org/features/parcel-api/#watching">watching</a> and <a href="https://parceljs.org/features/parcel-api/#dev-server">serving content</a> functionalities similar to Vite.</p>
<p>For additional file watching capabilities, look into the <a href="https://www.npmjs.com/package/@parcel/watcher">@parcel/ watcher</a> package.</p>
Superqt - Distributing QCollapsible Containers
2023-12-21T00:00:00+00:00
2023-12-21T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/superqt-distributing-qcollapsible-containers/
<h3 id="spacing-display-issues">Spacing Display Issues</h3>
<p>By itself, the QCollapsible element placed in a QVBoxLayout or QHBoxLayout
will not offer an out-of-the-box solution for a refined display of distributing containers or the containers contents predicatabley.</p>
<span id="continue-reading"></span><h4 id="problems">Problems</h4>
<ol>
<li>QCollapsible grows taller than the current's window size when expanding a container that has a lot of content.</li>
</ol>
<video controls="" name="media">
<source src="/images/posts/exceeds-original-window-height.webm" alt="demo of qcollapsible container exceeding original window height">
</video>
<ol start="2">
<li>The QCollapsible containers become evenly distributed when the window is sized vertically. The vertical shifting of content is disorientating. This might make sense in a mobile type of application, but not well suited for a desktop application.</li>
</ol>
<video controls="" name="media">
<source src="/images/posts/unwanted-qcollapsible-container-distribution.webm" alt="demo of qcollapsible containers with unwanted vertical space distribution">
</video>
<p>To remedy these problems, you need to place the QCollapsible containers in a QScrollArea to solve the first problem. Then the QVBoxLayout or QHBoxLayout layouts needs a call to the <code>addStretch</code> method which acts as a buffer to fill in the empty space to prevent the container space redistribution.</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">import </span><span>sys
</span><span style="color:#ff7733;">from </span><span>PyQt6</span><span style="color:#f29668;">.</span><span>QtWidgets </span><span style="color:#ff7733;">import </span><span>(QWidget</span><span style="color:#bfbab0cc;">, </span><span>QScrollArea</span><span style="color:#bfbab0cc;">, </span><span>QVBoxLayout</span><span style="color:#bfbab0cc;">, </span><span>QMainWindow</span><span style="color:#bfbab0cc;">, </span><span>QApplication</span><span style="color:#bfbab0cc;">, </span><span>QLabel</span><span style="color:#bfbab0cc;">, </span><span>QPushButton)
</span><span style="color:#ff7733;">from </span><span>superqt </span><span style="color:#ff7733;">import </span><span>QCollapsible
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">MainWindow</span><span>(</span><span style="text-decoration:underline;color:#59c2ff;">QMainWindow</span><span>):
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#f29718;">self</span><span>):
</span><span> </span><span style="color:#f07178;">super</span><span>()</span><span style="color:#f29668;">.</span><span style="color:#f07178;">__init__</span><span>()
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">initUI</span><span>()
</span><span>
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#ffb454;">initUI</span><span>(</span><span style="color:#f29718;">self</span><span>):
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create layout and widgets
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>scroll </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QScrollArea</span><span>()
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>widget </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QWidget</span><span>()
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>vbox </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QVBoxLayout</span><span>()
</span><span>
</span><span> collapsible </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QCollapsible</span><span>(</span><span style="color:#c2d94c;">"Advanced analysis"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">collapsedIcon</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"►"</span><span>)
</span><span> collapsible2 </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QCollapsible</span><span>(</span><span style="color:#c2d94c;">"Some other analysis"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">collapsedIcon</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"►"</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Add contents to the collapsible containers
</span><span> collapsible</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(</span><span style="color:#ffb454;">QLabel</span><span>(</span><span style="color:#c2d94c;">"This is the inside of the collapsible frame"</span><span>))
</span><span> </span><span style="color:#ff7733;">for </span><span>i </span><span style="color:#ff7733;">in </span><span style="color:#f07178;">range</span><span>(</span><span style="color:#f29718;">10</span><span>):
</span><span> collapsible</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(</span><span style="color:#ffb454;">QPushButton</span><span>(</span><span style="color:#ff7733;">f</span><span style="color:#c2d94c;">"Content button </span><span>{i </span><span style="color:#f29668;">+ </span><span style="color:#f29718;">1</span><span>}</span><span style="color:#c2d94c;">"</span><span>))
</span><span>
</span><span> collapsible2</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(</span><span style="color:#ffb454;">QLabel</span><span>(</span><span style="color:#c2d94c;">"Another note"</span><span>))
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Add collapsible containers to the layout
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>vbox</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(collapsible)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>vbox</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(collapsible2)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Prevent the collapsible containers from distributing space evenly
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>vbox</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addStretch</span><span>()
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Scrollarea settings
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>scroll</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setWidgetResizable</span><span>(</span><span style="color:#f29718;">True</span><span>)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>scroll</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setWidget</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>widget)
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>widget</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setLayout</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>vbox)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setCentralWidget</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>scroll)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Initially resize window for better visibility
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setGeometry</span><span>(</span><span style="color:#f29718;">600</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">100</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">500</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">200</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()
</span><span>
</span><span style="color:#ff7733;">if </span><span>__name__ </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">'__main__'</span><span>:
</span><span> app </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QApplication</span><span>([])
</span><span> mainWindow </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">MainWindow</span><span>()
</span><span> sys</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exit</span><span>(app</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exec</span><span>())
</span><span>
</span></code></pre>
<p>Improved display results</p>
<video controls="" name="media">
<source src="/images/posts/refined-qcollapsible-containers.webm" alt="demo of refined qcollapsible containers display">
</video>
Oclif v3 - Module Load Error
2023-11-05T00:00:00+00:00
2023-11-05T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/oclif-typescript-import-module-aliases/
<h3 id="typescript-import-aliases">Typescript Import Aliases</h3>
<p>To simplify the referencing of module import paths, one can configure the <code>ts.config.json</code> like so.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"compilerOptions"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#ff3333;">...
</span><span> </span><span style="color:#c2d94c;">"paths"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"@src/*"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#c2d94c;">"src/*"
</span><span> ]
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"rootDir"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"src"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"baseUrl"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"."</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"include"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#c2d94c;">"src/**/*"
</span><span> ]
</span><span>}
</span></code></pre>
<span id="continue-reading"></span>
<p>To be able to use this import</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ typeCheck</span><span style="color:#bfbab0cc;">, </span><span>stringTypes } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@src/utilities/type-check'</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>over something like this</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ typeCheck</span><span style="color:#bfbab0cc;">, </span><span>stringTypes } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'../utilities/type-check'</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Using aliases makes for more intuitive file path referencing if you decide to rearrange certain files.</p>
<p>However, when using TypeScript with Oclif, the TypeScript custom import aliases
might produce this error when executing </p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span>[MODULE_NOT_FOUND] ModuleLoadError </span><span style="color:#59c2ff;">Plugin</span><span style="color:#bfbab0cc;">:
</span></code></pre>
<p>To remedy this problem, install <a href="https://www.npmjs.com/package/tsconfig-paths">tsconfig-paths</a> and add the below changes into the "bin/dev" file and execute the "bin/dev" file as you normally would.</p>
<p>Configure the "bin/dev" file.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">#!/usr/bin/env node
</span><span>
</span><span style="color:#ff7733;">const </span><span>oclif </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'@oclif/core'</span><span>)
</span><span style="color:#ff7733;">const </span><span>path </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'path'</span><span>)
</span><span>
</span><span style="color:#ff7733;">const </span><span>tsConfigPaths </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'tsconfig-paths'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>project </span><span style="color:#f29668;">= </span><span>path</span><span style="color:#f29668;">.</span><span style="color:#f07178;">join</span><span>(__dirname</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'..'</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'tsconfig.json'</span><span>)
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// In dev mode -> use ts-node and dev plugins
</span><span>process</span><span style="color:#f29668;">.</span><span>env</span><span style="color:#f29668;">.</span><span>NODE_ENV </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'development'
</span><span>
</span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'ts-node'</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">register</span><span>({project})
</span><span>tsConfigPaths</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">register</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// In dev mode, always show stack traces
</span><span>oclif</span><span style="color:#f29668;">.</span><span>settings</span><span style="color:#f29668;">.</span><span>debug </span><span style="color:#f29668;">= </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Start the CLI
</span><span>oclif</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">run</span><span>()</span><span style="color:#f29668;">.</span><span style="color:#f07178;">then</span><span>(oclif</span><span style="color:#f29668;">.</span><span>flush)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">catch</span><span>(oclif</span><span style="color:#f29668;">.</span><span>Errors</span><span style="color:#f29668;">.</span><span>handle)
</span></code></pre>
<p>Then execute the "dev" file to run the cli.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">./bin/dev </span><span style="color:#f29668;"><</span><span>your-command</span><span style="color:#f29668;">>
</span></code></pre>
PyQT - Collapsible Sections
2023-10-15T00:00:00+00:00
2023-10-15T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/pyqt-collapsible-sections/
<h3 id="pyqt-accordion-equivalent">PyQt - Accordion Equivalent</h3>
<p>When there are groups of related information that are to be made available for viewing, but is too visually cluttering when shown all at once, one can use the grouping behavior of an accordion or collapsible section to selectively show
information.</p>
<p>One native Qt widget that can be used in PyQT is the <a href="https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QToolBox.html#qtoolbox">QtToolBox</a>.
This widget offers a vertical list of collapsible containers where
only one can be viewed at a time. It behaves similar to a tab view except the the tab and its associated content are bunched together.</p>
<span id="continue-reading"></span><pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">import </span><span>sys
</span><span>
</span><span style="color:#ff7733;">from </span><span>PyQt6</span><span style="color:#f29668;">.</span><span>QtWidgets </span><span style="color:#ff7733;">import </span><span>QApplication</span><span style="color:#bfbab0cc;">, </span><span>QLabel</span><span style="color:#bfbab0cc;">, </span><span>QMainWindow</span><span style="color:#bfbab0cc;">, </span><span>QToolBox</span><span style="color:#bfbab0cc;">, </span><span>QGridLayout</span><span style="color:#bfbab0cc;">, </span><span>QLabel</span><span style="color:#bfbab0cc;">, </span><span>QPushButton</span><span style="color:#bfbab0cc;">, </span><span>QWidget
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">MainWindow</span><span>(</span><span style="text-decoration:underline;color:#59c2ff;">QMainWindow</span><span>):
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#f29718;">self</span><span>):
</span><span> </span><span style="color:#f07178;">super</span><span>()</span><span style="color:#f29668;">.</span><span style="color:#f07178;">__init__</span><span>()
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">resize</span><span>(</span><span style="color:#f29718;">500</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">300</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create layouts
</span><span> layout </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QGridLayout</span><span>()
</span><span> bees_layout </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QGridLayout</span><span>()
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create toolbox widget
</span><span> toolbox </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QToolBox</span><span>()
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Add the labels to the toolbox
</span><span> </span><span style="font-style:italic;color:#5c6773;"># to create each section
</span><span> toolbox</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addItem</span><span>(</span><span style="color:#ffb454;">QLabel</span><span>(</span><span style="color:#c2d94c;">"Some information about ants."</span><span>)</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"Ants"</span><span>)
</span><span>
</span><span> btn </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QPushButton</span><span>(</span><span style="color:#c2d94c;">'A button for bees'</span><span>)
</span><span> widget </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QWidget</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span>)
</span><span> widget</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setLayout</span><span>(bees_layout)
</span><span> bees_layout</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(btn)
</span><span> toolbox</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addItem</span><span>(widget</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"Bees"</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Set the widget to the layout
</span><span> layout</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(toolbox)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setCentralWidget</span><span>(toolbox)
</span><span>
</span><span style="color:#ff7733;">if </span><span>__name__ </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">'__main__'</span><span>:
</span><span> app </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QApplication</span><span>(sys</span><span style="color:#f29668;">.</span><span>argv)
</span><span> window </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">MainWindow</span><span>()
</span><span> window</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()
</span><span> sys</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exit</span><span>(app</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exec</span><span>())
</span></code></pre>
<img src="/images/posts/qtoolbox.png" alt="example of qtoolbox">
<p>One limitation of the QtToolBox is that only one group can be visible at once, but one might want to show multiple groups at once. To remedy this problem, use the superqt <a href="https://pyapp-kit.github.io/superqt/widgets/qcollapsible/">QCollapsible component </a>.</p>
<p>Below example adapted from superqt's documentation page.</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">import </span><span>sys
</span><span>
</span><span style="color:#ff7733;">from </span><span>PyQt6</span><span style="color:#f29668;">.</span><span>QtWidgets </span><span style="color:#ff7733;">import </span><span>QApplication</span><span style="color:#bfbab0cc;">, </span><span>QLabel</span><span style="color:#bfbab0cc;">, </span><span>QPushButton</span><span style="color:#bfbab0cc;">, </span><span>QLabel</span><span style="color:#bfbab0cc;">, </span><span>QPushButton</span><span style="color:#bfbab0cc;">, </span><span>QWidget</span><span style="color:#bfbab0cc;">, </span><span>QVBoxLayout</span><span style="color:#bfbab0cc;">, </span><span>QMainWindow
</span><span>
</span><span style="color:#ff7733;">from </span><span>superqt </span><span style="color:#ff7733;">import </span><span>QCollapsible
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">MainWindow</span><span>(</span><span style="text-decoration:underline;color:#59c2ff;">QWidget</span><span>):
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#f29718;">self</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">parent</span><span style="color:#f29668;">=</span><span style="color:#f29718;">None</span><span>):
</span><span> </span><span style="color:#f07178;">super</span><span>(MainWindow</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">self</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">__init__</span><span>(parent)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">initUI</span><span>()
</span><span>
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#ffb454;">initUI</span><span>(</span><span style="color:#f29718;">self</span><span>):
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create layouts
</span><span> </span><span style="color:#ffb454;">QMainWindow</span><span>()</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setCentralWidget</span><span>(</span><span style="color:#ffb454;">QWidget</span><span>())
</span><span> layout </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QVBoxLayout</span><span>()
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create the collapsible sections
</span><span> collapsible </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QCollapsible</span><span>(</span><span style="color:#c2d94c;">"Advanced analysis"</span><span>)
</span><span> collapsible2 </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QCollapsible</span><span>(</span><span style="color:#c2d94c;">"Some other analysis"</span><span>)
</span><span>
</span><span> layout</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(collapsible)
</span><span> layout</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(collapsible2)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Add contents to the collapsible sections
</span><span> collapsible</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(
</span><span> </span><span style="color:#ffb454;">QLabel</span><span>(</span><span style="color:#c2d94c;">"This is the inside of the collapsible frame"</span><span>))
</span><span> </span><span style="color:#ff7733;">for </span><span>i </span><span style="color:#ff7733;">in </span><span style="color:#f07178;">range</span><span>(</span><span style="color:#f29718;">10</span><span>):
</span><span> collapsible</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(</span><span style="color:#ffb454;">QPushButton</span><span>(</span><span style="color:#ff7733;">f</span><span style="color:#c2d94c;">"Content button </span><span>{i </span><span style="color:#f29668;">+ </span><span style="color:#f29718;">1</span><span>}</span><span style="color:#c2d94c;">"</span><span>))
</span><span>
</span><span> collapsible2</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(</span><span style="color:#ffb454;">QLabel</span><span>(</span><span style="color:#c2d94c;">"Another note"</span><span>))
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Show the collapsible sections
</span><span> collapsible</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">expand</span><span>(</span><span style="color:#f29718;">animate</span><span style="color:#f29668;">=</span><span style="color:#f29718;">True</span><span>)
</span><span> collapsible</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()
</span><span> collapsible2</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">expand</span><span>(</span><span style="color:#f29718;">animate</span><span style="color:#f29668;">=</span><span style="color:#f29718;">True</span><span>)
</span><span> collapsible2</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Display layouts
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setLayout</span><span>(layout)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()
</span><span>
</span><span style="color:#ff7733;">if </span><span>__name__ </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">'__main__'</span><span>:
</span><span> app </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QApplication</span><span>([])
</span><span> mainWindow </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">MainWindow</span><span>()
</span><span> mainWindow</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()
</span><span> sys</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exit</span><span>(app</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exec</span><span>())
</span></code></pre>
<img src="/images/posts/superqt-qcollapsible.png" alt="example of superqt qcollapsible">
Dev Tools - Searching Elements in the DOM Elements Tab
2023-09-09T00:00:00+00:00
2023-09-09T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/devtools-searching-for-elements-in-dom-elements-tab/
<h3 id="jump-to-specific-elements-in-the-dom-viewer">Jump to Specific Elements in the Dom Viewer</h3>
<p>Within the "Inspector" or "Elements" (depending if you are using Firefox or Chrome) Html node viewer tab's input search field, you can use a xpath selector to select a group of elements with the following.</p>
<pre data-lang="xml" style="background-color:#0f1419;color:#bfbab0;" class="language-xml "><code class="language-xml" data-lang="xml"><span>//element-type
</span></code></pre>
<p>This will search for all <code>a</code> tags.</p>
<pre data-lang="xml" style="background-color:#0f1419;color:#bfbab0;" class="language-xml "><code class="language-xml" data-lang="xml"><span>//a
</span></code></pre>
<span id="continue-reading"></span>
<p>To narrow down the elements based on their type and attribute, prefix the attribute with the <code>@</code> character along with the attribute value.
Then place the attribute and value into square brackets.</p>
<pre data-lang="xml" style="background-color:#0f1419;color:#bfbab0;" class="language-xml "><code class="language-xml" data-lang="xml"><span>//div[@id='container']
</span></code></pre>
PyQtgraph - Graphing with a Ui File
2023-08-12T00:00:00+00:00
2023-08-12T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/pyqtgraph-graphing-with-a-ui-file/
<h3 id="pyqtgraph-graph-in-native-window">PyQtgraph Graph in Native Window</h3>
<p>Dedicating a UI file to store the application layout will make for a more organized process when working with PyQt. The Python code will be cleaner if it focuses on creating the dynamic data that will be inserted into the ui file.</p>
<p>To demonstrate this, create a <code>window.ui</code> file.</p>
<pre data-lang="xml" style="background-color:#0f1419;color:#bfbab0;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#39bae690;"><?</span><span style="color:#59c2ff;">xml </span><span style="color:#ffb454;">version</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"1.0" </span><span style="color:#ffb454;">encoding</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8"</span><span style="color:#39bae690;">?>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">ui </span><span style="color:#ffb454;">version</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"4.0"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">class</span><span style="color:#39bae690;">></span><span>MainWindow</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">class</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">widget </span><span style="color:#ffb454;">class</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"QMainWindow" </span><span style="color:#ffb454;">name</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"MainWindow"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">property </span><span style="color:#ffb454;">name</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"windowTitle"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">string</span><span style="color:#39bae690;">></span><span>MainWindow</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">string</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">property</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">widget </span><span style="color:#ffb454;">class</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"QWidget" </span><span style="color:#ffb454;">name</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"centralwidget"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">layout </span><span style="color:#ffb454;">class</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"QVBoxLayout" </span><span style="color:#ffb454;">name</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"verticalLayout"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">layout</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">widget</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">widget</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">ui</span><span style="color:#39bae690;">>
</span></code></pre>
<span id="continue-reading"></span>
<p>Now create a <code>main.py</code> file loading the graphing dependencies and <code>window.ui</code> file.</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">from </span><span>PyQt6 </span><span style="color:#ff7733;">import </span><span>QtWidgets</span><span style="color:#bfbab0cc;">, </span><span>uic
</span><span style="color:#ff7733;">from </span><span>PyQt6</span><span style="color:#f29668;">.</span><span>QtWidgets </span><span style="color:#ff7733;">import </span><span>QMainWindow
</span><span style="color:#ff7733;">import </span><span>pyqtgraph </span><span style="color:#ff7733;">as </span><span>pg
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">Main</span><span>(</span><span style="text-decoration:underline;color:#59c2ff;">QMainWindow</span><span>):
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#f29718;">self</span><span>):
</span><span> QMainWindow</span><span style="color:#f29668;">.</span><span style="color:#f07178;">__init__</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Load the UI file and make a variable reference
</span><span> </span><span style="font-style:italic;color:#5c6773;"># for later graph placement
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>ui </span><span style="color:#f29668;">= </span><span>uic</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">loadUi</span><span>(</span><span style="color:#c2d94c;">"window.ui"</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">self</span><span>)
</span></code></pre>
<p>Create the PyQtgraph plot area and graph.</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">from </span><span>PyQt6 </span><span style="color:#ff7733;">import </span><span>QtWidgets</span><span style="color:#bfbab0cc;">, </span><span>uic
</span><span style="color:#ff7733;">from </span><span>PyQt6</span><span style="color:#f29668;">.</span><span>QtWidgets </span><span style="color:#ff7733;">import </span><span>QMainWindow
</span><span style="color:#ff7733;">import </span><span>pyqtgraph </span><span style="color:#ff7733;">as </span><span>pg
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">Main</span><span>(</span><span style="text-decoration:underline;color:#59c2ff;">QMainWindow</span><span>):
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#f29718;">self</span><span>):
</span><span> QMainWindow</span><span style="color:#f29668;">.</span><span style="color:#f07178;">__init__</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Load the UI file and make a variable reference
</span><span> </span><span style="font-style:italic;color:#5c6773;"># for later graph placement
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>ui </span><span style="color:#f29668;">= </span><span>uic</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">loadUi</span><span>(</span><span style="color:#c2d94c;">"window.ui"</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">self</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create the pyqtgraph plot area
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Bar Graph Configuration: https://pyqtgraph.readthedocs.io/en/latest/api_reference/graphicsItems/bargraphitem.html
</span><span> plot </span><span style="color:#f29668;">= </span><span>pg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">PlotWidget</span><span>()
</span><span> x1 </span><span style="color:#f29668;">= </span><span>[</span><span style="color:#f29718;">5</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">4</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">1</span><span>]
</span><span> y </span><span style="color:#f29668;">= </span><span>[</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">4</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">5</span><span>]
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create the bar graph
</span><span> bargraph </span><span style="color:#f29668;">= </span><span>pg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">BarGraphItem</span><span>(</span><span style="color:#f29718;">x0</span><span style="color:#f29668;">=</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">y</span><span style="color:#f29668;">=</span><span>y</span><span style="color:#bfbab0cc;">,</span><span style="color:#f29718;">width</span><span style="color:#f29668;">=</span><span>x1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">height</span><span style="color:#f29668;">=</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">.</span><span style="color:#f29718;">7</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Place the bar graph into the plot area
</span><span> plot</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addItem</span><span>(bargraph)
</span></code></pre>
<p>Finally, reference the widget layout in the UI file and insert the PyQtgraph plot area into the layout.</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">from </span><span>PyQt6 </span><span style="color:#ff7733;">import </span><span>QtWidgets</span><span style="color:#bfbab0cc;">, </span><span>uic
</span><span style="color:#ff7733;">from </span><span>PyQt6</span><span style="color:#f29668;">.</span><span>QtWidgets </span><span style="color:#ff7733;">import </span><span>QMainWindow
</span><span style="color:#ff7733;">import </span><span>pyqtgraph </span><span style="color:#ff7733;">as </span><span>pg
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">Main</span><span>(</span><span style="text-decoration:underline;color:#59c2ff;">QMainWindow</span><span>):
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#f29718;">self</span><span>):
</span><span> QMainWindow</span><span style="color:#f29668;">.</span><span style="color:#f07178;">__init__</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Load the UI file and make a variable reference
</span><span> </span><span style="font-style:italic;color:#5c6773;"># for later graph placement
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>ui </span><span style="color:#f29668;">= </span><span>uic</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">loadUi</span><span>(</span><span style="color:#c2d94c;">"window.ui"</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">self</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create the pyqtgraph plot area
</span><span> plot </span><span style="color:#f29668;">= </span><span>pg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">PlotWidget</span><span>()
</span><span> x1 </span><span style="color:#f29668;">= </span><span>[</span><span style="color:#f29718;">5</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">4</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">1</span><span>]
</span><span> y </span><span style="color:#f29668;">= </span><span>[</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">4</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">5</span><span>]
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create the bar graph
</span><span> bargraph </span><span style="color:#f29668;">= </span><span>pg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">BarGraphItem</span><span>(</span><span style="color:#f29718;">x0</span><span style="color:#f29668;">=</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">y</span><span style="color:#f29668;">=</span><span>y</span><span style="color:#bfbab0cc;">,</span><span style="color:#f29718;">width</span><span style="color:#f29668;">=</span><span>x1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">height</span><span style="color:#f29668;">=</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">.</span><span style="color:#f29718;">7</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Place the bar graph into the plot area
</span><span> plot</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addItem</span><span>(bargraph)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Programmatic insertion of graph into native window
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>ui</span><span style="color:#f29668;">.</span><span>verticalLayout</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(plot)
</span><span>
</span><span style="color:#ff7733;">def </span><span style="color:#ffb454;">main</span><span>():
</span><span> app </span><span style="color:#f29668;">= </span><span>QtWidgets</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">QApplication</span><span>([])
</span><span> win </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">Main</span><span>()
</span><span> win</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()
</span><span> app</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exec</span><span>()
</span><span>
</span><span style="color:#ff7733;">if </span><span>__name__ </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">'__main__'</span><span>:
</span><span> </span><span style="color:#ffb454;">main</span><span>()
</span><span> </span><span style="color:#ffb454;">exit</span><span>()
</span><span>
</span></code></pre>
fzf - Integrate with Jq for JSON Search
2023-07-16T00:00:00+00:00
2023-07-16T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/fzf-integrate-jq/
<h3 id="fzf-search-json-data">Fzf Search JSON Data</h3>
<p>JSON is a ubiquitous data format and searching for content in JSON will come up often enough to warrant a real-time search functionality. <a href="https://github.com/jqlang/jq">jq</a> can be used to query json and fzf can be combined with this tool to fulfill our JSON search capabilities.</p>
<p>Start fzf with jq</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#f07178;">echo </span><span style="color:#c2d94c;">'' </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">fzf</span><span style="color:#f29718;"> --preview </span><span style="color:#c2d94c;">"jq {q} < us-data.json.json"
</span></code></pre>
<span id="continue-reading"></span>
<p>The <code>us-data.json</code> data is pulled from
<a href="https://datausa.io/api/data?drilldowns=Nation&measures=Population">https://datausa.io/api/data?drilldowns=Nation&measures=Population</a></p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"data"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2020</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2020"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">326569308</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2019</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2019"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">324697795</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2018</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2018"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">322903030</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2017</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2017"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">321004407</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2016</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2016"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">318558162</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2015</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2015"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">316515021</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2014</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2014"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">314107084</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2013</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2013"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">311536594</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"source"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"measures"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#c2d94c;">"Population"
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"annotations"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"source_name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"Census Bureau"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"source_description"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"The American Community Survey (ACS) is conducted by the US Census and sent to a portion of the population every year."</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"dataset_name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"ACS 5-year Estimate"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"dataset_link"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"http://www.census.gov/programs-surveys/acs/"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"table_id"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"B01003"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"topic"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"Diversity"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"subtopic"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"Demographics"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"acs_yg_total_population_5"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"substitutions"</span><span style="color:#bfbab0cc;">: </span><span>[]
</span><span> }
</span><span> ]
</span><span>}
</span></code></pre>
<p>Here we have the search for 'ID Year'</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">.data[].</span><span style="color:#c2d94c;">"ID Year"
</span></code></pre>
<p>This will yield all the values of the "ID Year" keys</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>2020
</span><span>2019
</span><span>2018
</span><span>2017
</span><span>2016
</span><span>2015
</span><span>2014
</span><span>2013
</span></code></pre>
<p>Now to get the reverse, by using the value to find its parent object, we will use the following</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">.data[] </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">paths</span><span> as $p </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">select</span><span>(getpath($p) </span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">= "2013"</span><span>)
</span></code></pre>
<p>will provide this result</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"ID Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"01000US"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"United States"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ID Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2013</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Year"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"2013"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Population"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">311536594</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"Slug Nation"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"united-states"
</span><span>}
</span></code></pre>
DITA - Structured Documentation with XML
2023-06-11T00:00:00+00:00
2023-06-11T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/dita-structured-documentation-with-xml/
<h3 id="dita-setup">DITA Setup</h3>
<p>DITA stands for Darwin Information Typing Architecture, it is an XML specification that prescribes tags for organizing your documentation content.
For Dita to be able to generate a well-defined structure, it suggests a rather prescriptive methods of tag use. The intention of Dita is to promote content reuse so that your documentation project will be more manageable as it scales up in size and complexity.</p>
<p>Getting started with Dita begins with having these prerequisites.</p>
<ul>
<li>Java</li>
<li>Text editor</li>
<li>DITA-OT</li>
</ul>
<span id="continue-reading"></span>
<p>Alternatively, there are xml editors out there that bundle Dita together with Dita which offers you the convenience of an integrated DITA authoring experience.
These editors tend to be in the family of WYSIWYG editors. Most of these solutions are paid software, but <a href="https://xmlmind.com/xmleditor/">XMLmind XML Editor</a> is a free alternative.</p>
<p>However, the rest of this article will focus on using more developer centric tools for better learning when working with the raw xml markup.</p>
<h4 id="installing-prerequisites">Installing Prerequisites</h4>
<h5 id="java">Java</h5>
<p>The version of Java that DITA-OT version 4.0.2 supports is version 17.
To make managing the versions of Java easier, using a general tools installer version manager such as <a href="https://github.com/asdf-vm/asdf">asdf</a>.
Asdf is commonly used to install different programmming languages onto your machine.</p>
<p>After installing asdf with the <a href="https://asdf-vm.com/guide/getting-started.html#official-download">official installation instructions</a>, you are ready to use it to install Java.</p>
<p>Asdf requires that you add plugins to manage the many different tools that out there for installation. You install a plugin for a particular tool that you would want to use.</p>
<p>Add the Java plugin for asdf.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">asdf</span><span> plugin add java
</span></code></pre>
<p>List all Java versions to find the latest version 17 of Java.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">asdf</span><span> list-all java
</span></code></pre>
<p>Install the Java version. Pick a version that is up-to-date, the version of Java shown below is shown for demonstration purposes.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">asdf</span><span> install java oracle-17.0.6
</span></code></pre>
<p>Set the installed Java version as global.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">asdf</span><span> global java oracle-17.0.6
</span></code></pre>
<p>Additional Java configuration information can be found from the <a href="https://github.com/halcyon/asdf-java">asdf java plugin page</a>.</p>
<h5 id="dita-ot">DITA-OT</h5>
<p>The DITA-OT binary will provide the actual DITA functionality. This will put <code>dita</code> into the command line for processing our DITA xml documents.</p>
<p>Download Dita from github located at <a href="https://github.com/dita-ot/dita-ot/releases">https://github.com/dita-ot/dita-ot/releases</a>.
Extract the zip file into a location where you can reference the dita binary.</p>
<p>Put the DITA binary into your path by adding this line into your .bashrc file. Substitute with your location of the DITA folder.</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>export PATH=$PATH:/the/path/to/your/Dita/dita-ot-4.0.2/bin/
</span></code></pre>
<h5 id="text-editor">Text Editor</h5>
<p>A text editor with xml highlighting support is recommended.</p>
<h3 id="basic-example">Basic Example</h3>
<p>The following will be a minimal DITA example. Create a <code>dita-example</code> folder with the associated DITA files.</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>dita-example/
</span><span>├── map.ditamap
</span><span>└── concept.dita
</span></code></pre>
<p>The <code>map.ditamap</code> serves as the entry point file that DITA reads to determine references to topic type and other ditamap files. This file indicates which files will be build for the final output. These referencing files have the extension of <code>.ditamap</code>.</p>
<p>With DITA, the two file extension types you will frequently encounter will be <code>.ditamap</code> and <code>.dita</code>. The <code>.dita</code> file are for storing the topic information content.</p>
<p>The <code>map.ditmap</code> file uses a <code><topicref></code> tag to reference the <code>concept.dita</code> file.</p>
<pre data-lang="xml" style="background-color:#0f1419;color:#bfbab0;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#39bae690;"><?</span><span style="color:#59c2ff;">xml </span><span style="color:#ffb454;">version</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"1.0" </span><span style="color:#ffb454;">encoding</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8"</span><span style="color:#39bae690;">?>
</span><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span>map </span><span style="color:#ff7733;">PUBLIC </span><span style="color:#c2d94c;">"-//OASIS//DTD DITA Map//EN" "map.dtd"</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">map </span><span style="color:#ffb454;">chunk</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"by-topic"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">></span><span>DITA Topic Map</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">topicref </span><span style="color:#ffb454;">keys</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"concepts" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"concept.dita" </span><span style="color:#ffb454;">toc</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"yes" </span><span style="color:#39bae690;">/>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">map</span><span style="color:#39bae690;">>
</span></code></pre>
<p>DITA's authoring strategy involves writing for "topics" which serve as discrete cohesive units of information. The three more commonly used topic types are the <code><concept></code>, <code><task></code>, and <code><reference></code>.
The type of topic you use will be determined by what that pieces of information is intended to convey to the audience.</p>
<p>The <code><concept></code> explains the background information of the subject that you are trying to illustrate. It will provide the general purpose of the subject.</p>
<p>The <code><task></code> topic will list out the specific instructional steps that are carried out when attempting to perform a 'task'. This topic type is suited for use with something that is found in a cooking recipe or assembly instruction manual where mechanical steps are listed in a bulleted list.</p>
<p>The <code><reference></code> topic is used for providing supporting information. This can be complementary information for the <code><concept></code>.</p>
<p>As for our example, we will focus on using the <code><concept></code> topic.
To define a <code><concept></code> document, these first two lines are needed. The first line declares that it is a xml file, while the second is to help DITA identify it as a concept document.</p>
<pre data-lang="xml" style="background-color:#0f1419;color:#bfbab0;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#39bae690;"><?</span><span style="color:#59c2ff;">xml </span><span style="color:#ffb454;">version</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"1.0" </span><span style="color:#ffb454;">encoding</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8"</span><span style="color:#39bae690;">?>
</span><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span>concept </span><span style="color:#ff7733;">PUBLIC </span><span style="color:#c2d94c;">"-//OASIS//DTD DITA Concept//EN" "concept.dtd"</span><span style="color:#39bae690;">>
</span></code></pre>
<p>Next, the <code><concept></code> tag is added along with the <code><title></code> and <code><shortdesc></code> tags. The <code><title></code> states the subject that will be discussed and the <code><shortdesc></code> offers a brief description of the topic.</p>
<pre data-lang="xml" style="background-color:#0f1419;color:#bfbab0;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#39bae690;"><?</span><span style="color:#59c2ff;">xml </span><span style="color:#ffb454;">version</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"1.0" </span><span style="color:#ffb454;">encoding</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8"</span><span style="color:#39bae690;">?>
</span><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span>concept </span><span style="color:#ff7733;">PUBLIC </span><span style="color:#c2d94c;">"-//OASIS//DTD DITA Concept//EN" "concept.dtd"</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">concept </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"concept"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">></span><span>Painting a Wall</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">shortdesc</span><span style="color:#39bae690;">></span><span>Periodic painting of a wall will ensure that moisture does not damage the material underneath. It also ensures that you living environment is visually pleasant to look at.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">shortdesc</span><span style="color:#39bae690;">>
</span><span> ...
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">concept</span><span style="color:#39bae690;">>
</span></code></pre>
<p>Add the <code><conbody></code> below the <code><shortdesc></code> along with the <code><section></code> information to describe the topic in detail. You can add additional sections for further details.</p>
<pre data-lang="xml" style="background-color:#0f1419;color:#bfbab0;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#39bae690;"><?</span><span style="color:#59c2ff;">xml </span><span style="color:#ffb454;">version</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"1.0" </span><span style="color:#ffb454;">encoding</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8"</span><span style="color:#39bae690;">?>
</span><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span>concept </span><span style="color:#ff7733;">PUBLIC </span><span style="color:#c2d94c;">"-//OASIS//DTD DITA Concept//EN" "concept.dtd"</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">concept </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"concept"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">></span><span>Painting a Wall</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">shortdesc</span><span style="color:#39bae690;">></span><span>Periodic painting of a wall will ensure that moisture does not damage the material underneath. It also ensures that you living environment is visually pleasant to look at.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">shortdesc</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">conbody</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">section</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">></span><span>Clearing the Area for Painting</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">></span><span>Remove obstructing items from the wall that is painted. You will need room to manuever you painting equipment.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">section</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">conbody</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">concept</span><span style="color:#39bae690;">>
</span></code></pre>
<p>Run the DITA command to generate the output in html.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">dita</span><span style="color:#f29718;"> --input</span><span style="color:#f29668;">=</span><span>map.ditamap</span><span style="color:#f29718;"> --format</span><span style="color:#f29668;">=</span><span>html5
</span></code></pre>
<p>The <code>dita</code> command will create an <code>out</code> folder with these files.</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>out/
</span><span>├── commonltr.css
</span><span>├── commonrtl.css
</span><span>├── concept.html
</span><span>└── index.html
</span></code></pre>
<p>The map.ditamap outputs to the <code>index.html</code> file and the <code>concept.html</code>. The css files are auto-generated to support styling the generated html. View the html files in your browser.</p>
Nuitka and PyQtgraph - Bundle a Python Application into a Standalone Binary
2023-05-01T00:00:00+00:00
2023-05-01T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nuitka-pyqtgraph-bundle-standalone-executable/
<h3 id="pyqtgraph-standalone-application">PyQtgraph Standalone Application</h3>
<p>Nuitka is a Python compiler that supports the conversion of a Python application to compiled code. It enables you to create a single file executable for convenient distribution.</p>
<h4 id="prerequisites">Prerequisites</h4>
<p>You will need a C compiler and a Python version specified in the Nuitka <a href="https://github.com/Nuitka/Nuitka#requirements">README.md</a>.</p>
<h4 id="installing-nuitka">Installing Nuitka</h4>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">python3</span><span style="color:#f29718;"> -m</span><span> pip install nuitka
</span></code></pre>
<span id="continue-reading"></span><h4 id="compilation-options">Compilation Options</h4>
<h5 id="simple-bundle-command">Simple bundle command</h5>
<p>Once nuitka is installed, you will navigate to your Python project folder and run this minimal command to get an application compiled. By default, this basic command will not output a single executable file. </p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">nuitka</span><span> main.py
</span></code></pre>
<h5 id="dynamic-imports">Dynamic imports</h5>
<p>Since PyQtGraph uses dynamic imports, you will need to tell nuitka to include these dependencies for the </p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">nuitka</span><span style="color:#f29718;"> --follow-imports --include-plugin-directory</span><span style="color:#f29668;">=</span><span>mods main.py
</span></code></pre>
<h5 id="pyqtgraph-bundling-options">PyQtgraph Bundling Options</h5>
<p>PyQtgraph uses dynamic imports and requires the '--follow-imports' graph.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">python3</span><span style="color:#f29718;"> -m</span><span> nuitka main.py</span><span style="color:#f29718;"> --follow-imports --onefile --enable-plugin</span><span style="color:#f29668;">=</span><span>pyqt6
</span></code></pre>
<p>Here is the command and options if you are using poetry with nuitka.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">poetry</span><span> run python</span><span style="color:#f29718;"> -m</span><span> nuitka main.py</span><span style="color:#f29718;"> --follow-imports --onefile --enable-plugin</span><span style="color:#f29668;">=</span><span>pyqt6
</span></code></pre>
<p>You might have to install some other python modules to speed up performance based on the warnings that nuitka outputs when using poetry.</p>
<h4 id="result">Result</h4>
<p>This will create a standalone binary, main.bin, that is about 52 megabytes.</p>
Creating an AppImage from a Binary Executable
2023-04-07T00:00:00+00:00
2023-04-07T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/creating-an-appimage-for-binary-application/
<h3 id="make-a-portable-desktop-application-without-the-need-for-installation">Make a Portable Desktop Application without the need for Installation</h3>
<p>To create a binary which can be run on many Linux machines, an <a href="https://en.wikipedia.org/wiki/AppImage">AppImage</a> can be generated. An AppImage wraps around the files needed to run the application and when executed, doesn't require modifications to your operating system as it is self-contained.</p>
<p>Download the appimage tool executable file from
<a href="https://github.com/AppImage/AppImageKit/releases">here</a>.</p>
<span id="continue-reading"></span>
<p>Make the app image tool executable</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">chmod</span><span> +x /path/to/the/appimagetool-x86_64.AppImage
</span></code></pre>
<p>Create an <code>AppDir</code> folder and place all your application files into this folder. In my case, I have to rename my <code>main.bin</code> file to AppRun.
See <a href="https://docs.appimage.org/reference/appdir.html#id2%5D">AppDir Specifications</a>.</p>
<p>Create a <appname>.desktop file inside the <code>AppDir</code> folder with the following minimum keys.
For the filename key, leaving out the image extension is allowed.</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>[Desktop Entry]
</span><span>Name=<your_app_name>
</span><span>Type=Application
</span><span>Icon=<name of your imagefile>
</span></code></pre>
<p>Run the following to tell the appimage tool to create an appimage executable.
The <code>source_folder</code> is <code>AppDir</code> in my case, but this is folder where you have placed your executable application and .desktop file.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">appimagetool-x86_64.AppImage </span><span style="color:#f29668;"><</span><span>source_folder</span><span style="color:#f29668;">>
</span></code></pre>
Dearpygui - Menu Bar
2023-03-25T00:00:00+00:00
2023-03-25T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/dearpygui-menu-bar/
<p>With dearpygui, there are two ways to create a menu bar that displays within your main application window. One method of creating a menu bar is to use the "Viewport Menu Bar" which is the traditional menu bar with the fixed horizontal row of menu entries found near the top of your main applications window and the other is the "Menu Bar" which is a floating menu window inside your main application window.</p>
<span id="continue-reading"></span>
<p>The 'Menu Bar' contains 'Menu' entries, and the 'Menu' entries contain the 'Menu Items'. The 'Menu Items' can reside directly underneath the 'Menu Bar'.</p>
<h3 id="viewport-menu-bar">Viewport Menu Bar</h3>
<p>Below is the annotated code sample from the main <a href="https://dearpygui.readthedocs.io/en/latest/documentation/menus.html">documentation page</a>.</p>
<img src="/images/posts/viewport-menubar.png" alt="viewport-menubar-example">
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="font-style:italic;color:#5c6773;"># Viewport Menu Bar
</span><span>
</span><span style="color:#ff7733;">import </span><span>dearpygui</span><span style="color:#f29668;">.</span><span>dearpygui </span><span style="color:#ff7733;">as </span><span>dpg
</span><span>
</span><span style="color:#ff7733;">def </span><span style="color:#ffb454;">print_me</span><span>(</span><span style="color:#f29718;">sender</span><span>):
</span><span> </span><span style="color:#f07178;">print</span><span>(</span><span style="color:#ff7733;">f</span><span style="color:#c2d94c;">"Menu Item: </span><span>{sender}</span><span style="color:#c2d94c;">"</span><span>)
</span><span>
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">create_context</span><span>()
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">create_viewport</span><span>(</span><span style="color:#f29718;">title</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">'Custom Title'</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">width</span><span style="color:#f29668;">=</span><span style="color:#f29718;">600</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">height</span><span style="color:#f29668;">=</span><span style="color:#f29718;">200</span><span>)
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Create the menu bar
</span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">viewport_menu_bar</span><span>():
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># A top-level 'File' menu entry
</span><span> </span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">menu</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"File"</span><span>):
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Save"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Save As"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Nested 'Settings' menu entry under 'File' with further nested
</span><span> </span><span style="font-style:italic;color:#5c6773;"># 'Setting 1' and 'Setting 2' entries
</span><span> </span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">menu</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Settings"</span><span>):
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Setting 1"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">check</span><span style="color:#f29668;">=</span><span style="color:#f29718;">True</span><span>)
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Setting 2"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># A top-level 'Help' menu item entry that triggers a callback upon clicking
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Help"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># A top-level 'Widget Items' menu entry with items that can be added which
</span><span> </span><span style="font-style:italic;color:#5c6773;"># are not a direct 'menu item'
</span><span> </span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">menu</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Widget Items"</span><span>):
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_checkbox</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Pick Me"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_button</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Press Me"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_color_picker</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Color Me"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Application setup
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setup_dearpygui</span><span>()
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show_viewport</span><span>()
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">start_dearpygui</span><span>()
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">destroy_context</span><span>()
</span></code></pre>
<h3 id="menu-bar-example">Menu Bar Example</h3>
<p>The 'Menu Bar' example below is nearly identical to the example shown above except that the call to create the menu bar is now switched to a <code>dpg.window</code> call. This 'window' appears as a floating widget element within your main application window.</p>
<img src="/images/posts/menubar.png" alt="menubar-example">
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="font-style:italic;color:#5c6773;"># Menu Bar Example
</span><span>
</span><span style="color:#ff7733;">import </span><span>dearpygui</span><span style="color:#f29668;">.</span><span>dearpygui </span><span style="color:#ff7733;">as </span><span>dpg
</span><span>
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">create_context</span><span>()
</span><span>
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">create_viewport</span><span>(</span><span style="color:#f29718;">title</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">'Custom Title'</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">width</span><span style="color:#f29668;">=</span><span style="color:#f29718;">600</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">height</span><span style="color:#f29668;">=</span><span style="color:#f29718;">200</span><span>)
</span><span>
</span><span style="color:#ff7733;">def </span><span style="color:#ffb454;">print_me</span><span>(</span><span style="color:#f29718;">sender</span><span>):
</span><span> </span><span style="color:#f07178;">print</span><span>(</span><span style="color:#ff7733;">f</span><span style="color:#c2d94c;">"Menu Item: </span><span>{sender}</span><span style="color:#c2d94c;">"</span><span>)
</span><span>
</span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">window</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Tutorial"</span><span>):
</span><span> </span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">menu_bar</span><span>():
</span><span> </span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">menu</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"File"</span><span>):
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Save"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Save As"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span>
</span><span> </span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">menu</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Settings"</span><span>):
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Setting 1"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">check</span><span style="color:#f29668;">=</span><span style="color:#f29718;">True</span><span>)
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Setting 2"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span>
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_menu_item</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Help"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span>
</span><span> </span><span style="color:#ff7733;">with </span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">menu</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Widget Items"</span><span>):
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_checkbox</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Pick Me"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_button</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Press Me"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span> dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_color_picker</span><span>(</span><span style="color:#f29718;">label</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"Color Me"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">callback</span><span style="color:#f29668;">=</span><span>print_me)
</span><span>
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setup_dearpygui</span><span>()
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show_viewport</span><span>()
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">start_dearpygui</span><span>()
</span><span>dpg</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">destroy_context</span><span>()
</span></code></pre>
Word Proximity Search
2023-02-04T00:00:00+00:00
2023-02-04T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/word-proximity-search/
<p>When you search for related words in a general area that are not in strict sequential order, you will have to resort to use a regex pattern that search across multiple words at a time.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#c2d94c;">"firstword someword anotherword someotherword secondword"</span><span style="color:#f29668;">.</span><span style="color:#f07178;">match</span><span>(</span><span style="color:#95e6cb;">/</span><span style="color:#ff7733;">\b</span><span style="color:#95e6cb;">(?:firstword(?:</span><span style="color:#f29718;">\W</span><span style="color:#f29668;">+</span><span style="color:#f29718;">\w</span><span style="color:#f29668;">+</span><span style="color:#95e6cb;">)</span><span style="color:#f29668;">{1,3}?</span><span style="color:#f29718;">\W</span><span style="color:#f29668;">+</span><span style="color:#95e6cb;">secondword)</span><span style="color:#ff7733;">\b</span><span style="color:#95e6cb;">/</span><span style="color:#ff7733;">g</span><span>)
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Returns
</span><span style="font-style:italic;color:#5c6773;">// ["firstword someword anotherword someotherword secondword"]
</span></code></pre>
<span id="continue-reading"></span>
<p>This will only look at the actual word distance, and this will match across sentences. The above example will match the separated words if there are three or fewer words between them and will fail to match if greater than four words between them. This will return the whole string as the result.</p>
<p>If there is a need to match the words in the reverse order, add the second regex pattern branch with the words in the flipped locations.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#c2d94c;">"secondword someword anotherword someotherword firstword"</span><span style="color:#f29668;">.</span><span style="color:#f07178;">match</span><span>(</span><span style="color:#95e6cb;">/</span><span style="color:#ff7733;">\b</span><span style="color:#95e6cb;">(?:firstword(?:</span><span style="color:#f29718;">\W</span><span style="color:#f29668;">+</span><span style="color:#f29718;">\w</span><span style="color:#f29668;">+</span><span style="color:#95e6cb;">)</span><span style="color:#f29668;">{1,3}?</span><span style="color:#f29718;">\W</span><span style="color:#f29668;">+</span><span style="color:#95e6cb;">secondword</span><span style="color:#f29668;">|</span><span style="color:#95e6cb;">secondword(?:</span><span style="color:#f29718;">\W</span><span style="color:#f29668;">+</span><span style="color:#f29718;">\w</span><span style="color:#f29668;">+</span><span style="color:#95e6cb;">)</span><span style="color:#f29668;">{1,3}?</span><span style="color:#f29718;">\W</span><span style="color:#f29668;">+</span><span style="color:#95e6cb;">firstword)</span><span style="color:#ff7733;">\b</span><span style="color:#95e6cb;">/</span><span style="color:#ff7733;">g</span><span>)
</span></code></pre>
<p>To use this in the VSCode code editor, use this regex pattern</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>(?:firstword(?:\W+\w+){1,3}?\W+secondword|secondword(?:\W+\w+){1,3}?\W+firstword)
</span></code></pre>
fzf - Find CLI Application and Execute
2023-01-01T00:00:00+00:00
2023-01-01T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/fzf-find-application-and-execute/
<h3 id="run-the-application-when-found">Run the Application when Found</h3>
<p>When you have an application you wish to search for that you know starts with a certain letter, you type the letter into your Bash shell and press tab to display all the suggestions. Most likely, there will be more applications than one would be able to identify readily by eye. </p>
<p>To make the task of finding your application easier, one can use <code>fzf</code> to perform real-time filtering of your application search.</p>
<span id="continue-reading"></span>
<p>First, we need to display all the applications on your system with the following.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#f07178;">echo </span><span style="color:#f29718;">-n </span><span>$PATH </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">xargs</span><span style="color:#f29718;"> -d</span><span> :</span><span style="color:#f29718;"> -I </span><span>{} find {}</span><span style="color:#f29718;"> -maxdepth</span><span> 1</span><span style="color:#f29718;"> -executable -type</span><span> f</span><span style="color:#f29718;"> -printf </span><span style="color:#c2d94c;">'%P\n' </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">sort</span><span style="color:#f29718;"> -u
</span></code></pre>
<p>Next, the output of all the applications will be piped to fzf.
Upon typing enough characters to narrow down to the entry of your choice,
execute the command by pressing <code>ctrl+x</code>.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#f07178;">echo </span><span style="color:#f29718;">-n </span><span>$PATH </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">xargs</span><span style="color:#f29718;"> -d</span><span> :</span><span style="color:#f29718;"> -I </span><span>{} find {}</span><span style="color:#f29718;"> -maxdepth</span><span> 1</span><span style="color:#f29718;"> -executable -type</span><span> f</span><span style="color:#f29718;"> -printf </span><span style="color:#c2d94c;">'%P\n' </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">sort</span><span style="color:#f29718;"> -u </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">fzf </span><span style="color:#c2d94c;">'--bind=enter:accept,ctrl-x:execute({})+accept'
</span></code></pre>
<p>To make entering all this into the shell with less hassle, create a Bash function which also takes in arguments to provide the application arguments or options for checking if is the application that you are after.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">findapp</span><span>() {
</span><span> </span><span style="color:#f07178;">echo </span><span style="color:#f29718;">-n </span><span>$PATH </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">xargs</span><span style="color:#f29718;"> -d</span><span> :</span><span style="color:#f29718;"> -I </span><span>{} find {}</span><span style="color:#f29718;"> -maxdepth</span><span> 1</span><span style="color:#f29718;"> -executable -type</span><span> f</span><span style="color:#f29718;"> -printf </span><span style="color:#c2d94c;">'%P\n' </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">sort</span><span style="color:#f29718;"> -u </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">fzf </span><span style="color:#c2d94c;">"--bind=enter:accept,ctrl-x:execute({} $</span><span>1</span><span style="color:#c2d94c;">)+accept"
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Displays the 'help' information of the application
</span><span style="font-style:italic;color:#5c6773;"># findapp --help
</span></code></pre>
PySide6 and Matplotlib - Simple Line Plot
2022-12-01T00:00:00+00:00
2022-12-01T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/pyside-matplotlib-simple-graph/
<h3 id="fill-a-window-with-a-graph">Fill a Window with a Graph</h3>
<p>The <a href="https://pypi.org/project/PySide6/">PySide6</a> library offers Python bindings for <a href="https://doc.qt.io/qt-6/index.html">Qt</a> which is a C++ cross-platform UI library. Qt has been in development for a long time and this will give a stable and mature platform for developing desktop applications.
PySide enables one to leverage all the packages from the Python community while using QT. The Python graphing library, <a href="https://matplotlib.org/stable/gallery/user_interfaces/embedding_in_qt_sgskip.html">Matplotlib</a>, becomes a naturally pairing with the QT library because Matplotlib provides integration options.</p>
<span id="continue-reading"></span>
<p>To show how Matplotlib can be used with PySide, the below example will demonstrate a plot that scales to the full width and height of a desktop window.
We start off by importing the PySide and Matplotlib dependencies along with the
native packages to generate data for our graph.</p>
<p>The <code>__init__</code> function will define a couple of properties to provide the desktop values for window size and title while the <code>PlotCanvas</code> function will be defined later to set up the Matplotlib graph details.</p>
<p>The Qt <code>QVBoxLayout</code> is defined for storing the graph canvas to scale inside the window.</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">import </span><span>sys
</span><span style="color:#ff7733;">import </span><span>random
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># PySide dependency
</span><span style="color:#ff7733;">from </span><span>PySide6</span><span style="color:#f29668;">.</span><span>QtWidgets </span><span style="color:#ff7733;">import </span><span>QApplication</span><span style="color:#bfbab0cc;">, </span><span>QWidget</span><span style="color:#bfbab0cc;">, </span><span>QVBoxLayout
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Matplotlib dependencies
</span><span style="color:#ff7733;">from </span><span>matplotlib</span><span style="color:#f29668;">.</span><span>backends</span><span style="color:#f29668;">.</span><span>backend_qtagg </span><span style="color:#ff7733;">import </span><span>FigureCanvas
</span><span style="color:#ff7733;">from </span><span>matplotlib</span><span style="color:#f29668;">.</span><span>figure </span><span style="color:#ff7733;">import </span><span>Figure
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">App</span><span>(</span><span style="text-decoration:underline;color:#59c2ff;">QWidget</span><span>):
</span><span>
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#f29718;">self</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">parent</span><span style="color:#f29668;">=</span><span style="color:#f29718;">None</span><span>):
</span><span> </span><span style="color:#f07178;">super</span><span>(App</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">self</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">__init__</span><span>(parent)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Set properties of the window
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">resize</span><span>(</span><span style="color:#f29718;">600</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">490</span><span>)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>title </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'The Window Title'
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setWindowTitle</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>title)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create the matplotlib canvas
</span><span> canvas </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">PlotCanvas</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Add the plot canvas to the horizontal box layout
</span><span> layout </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QVBoxLayout</span><span>()
</span><span> layout</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addWidget</span><span>(canvas)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setLayout</span><span>(layout)
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># ...
</span></code></pre>
<p>Now the <code>PlotCanvas</code> function creates the graph canvas and figure before setting the properties for the graph. Most of the manipulation of the graph
involves calling on functions on the <code>self.axes</code> object.</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">PlotCanvas</span><span>(</span><span style="text-decoration:underline;color:#59c2ff;">FigureCanvas</span><span>):
</span><span> </span><span style="color:#ff7733;">def </span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#f29718;">self</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">parent</span><span style="color:#f29668;">=</span><span style="color:#f29718;">None</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">dpi</span><span style="color:#f29668;">=</span><span style="color:#f29718;">100</span><span>):
</span><span> </span><span style="color:#f07178;">super</span><span>(PlotCanvas</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">self</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">__init__</span><span>(</span><span style="color:#ffb454;">Figure</span><span>())
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setParent</span><span>(parent)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create the figure and figure canvas
</span><span> fig </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">Figure</span><span>(</span><span style="color:#f29718;">dpi</span><span style="color:#f29668;">=</span><span>dpi)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>figure </span><span style="color:#f29668;">= </span><span>fig
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>canvas </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">FigureCanvas</span><span>(</span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>figure)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>axes </span><span style="color:#f29668;">= </span><span>fig</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">add_subplot</span><span>()
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Create data for the graph
</span><span> data </span><span style="color:#f29668;">= </span><span>[random</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">random</span><span>() </span><span style="color:#ff7733;">for </span><span>i </span><span style="color:#ff7733;">in </span><span style="color:#f07178;">range</span><span>(</span><span style="color:#f29718;">25</span><span>)]
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Line style
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>axes</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">plot</span><span>(data</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">linestyle</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">'dashed'</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Graph title text
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>axes</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">set_title</span><span>(</span><span style="color:#c2d94c;">'The Graph Title'</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Axes labels text
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>axes</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">set_ylabel</span><span>(</span><span style="color:#c2d94c;">'Y Label'</span><span>)
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>axes</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">set_xlabel</span><span>(</span><span style="color:#c2d94c;">'X Label'</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># X-axis color change
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>axes</span><span style="color:#f29668;">.</span><span>xaxis</span><span style="color:#f29668;">.</span><span>label</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">set_color</span><span>(</span><span style="color:#c2d94c;">'blue'</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Set the x-axis ticks and labels
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>axes</span><span style="color:#f29668;">.</span><span>xaxis</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">set_tick_params</span><span>(</span><span style="color:#f29718;">colors</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">'red'</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Set y-axis label line color
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span>axes</span><span style="color:#f29668;">.</span><span>spines[</span><span style="color:#c2d94c;">'left'</span><span>]</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">set_color</span><span>(</span><span style="color:#c2d94c;">'orange'</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">self</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">draw</span><span>()
</span><span>
</span><span style="color:#ff7733;">if </span><span>__name__ </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">'__main__'</span><span>:
</span><span> app </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">QApplication</span><span>(sys</span><span style="color:#f29668;">.</span><span>argv)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"># Additional styling for the widget which houses
</span><span> </span><span style="font-style:italic;color:#5c6773;"># the chart
</span><span> app</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setStyleSheet</span><span>(</span><span style="color:#c2d94c;">"""
</span><span style="color:#c2d94c;"> QWidget {
</span><span style="color:#c2d94c;"> background-color: "green";
</span><span style="color:#c2d94c;"> padding: 20px;
</span><span style="color:#c2d94c;"> }
</span><span style="color:#c2d94c;"> """</span><span>)
</span><span>
</span><span> widget </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">App</span><span>()
</span><span> widget</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">show</span><span>()
</span><span> sys</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exit</span><span>(app</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">exec</span><span>())
</span><span>
</span></code></pre>
<p>The outcome of all this will result in the graph below.</p>
<video controls="" name="media">
<source src="/images/posts/pyside-matplotlib-simple-graph-qwidget-resize.webm" type="video/webm">
</video>
Coqui STT - Extract Words from Audio Files
2022-11-02T00:00:00+00:00
2022-11-02T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/coqui-stt-extract-words-from-audio-file/
<h3 id="speech-to-text-cli-tool">Speech to Text CLI Tool</h3>
<p>There could be a time when you were listening to a podcast, but you can not make out the spelling of a word that you would like to understand.
If there was a way to add a 'live-caption' feature to your podcast, this will inform you of the vocabulary that you are missing. To get remedy this problem, you can use a <a href="https://en.wikipedia.org/wiki/Speech-to-text_reporter">Speech-to-Text</a> tool to output the transcript of the audio.</p>
<p>You might also want to convert an audio file to text if you are able to read quicker than you can listen to the audio file.</p>
<span id="continue-reading"></span>
<p>The following will show you how to use <a href="https://stt.readthedocs.io/en/latest/#quickstart">coqui STT</a> to perform a transcribing of an audio file to text in the terminal.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">docker</span><span> pull ghcr.io/coqui-ai/stt-train
</span></code></pre>
<p>Download the docker container.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">docker</span><span> run</span><span style="color:#f29718;"> -it --net</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">"host"</span><span> ghcr.io/coqui-ai/stt-train:latest
</span></code></pre>
<p>Add the host directory to docker for access inside the docker container when running the docker container.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">docker</span><span> run</span><span style="color:#f29718;"> -v</span><span> /folder/for/host:/folder/for/docker</span><span style="color:#f29718;"> -it</span><span> ghcr.io/coqui-ai/stt-train:latest
</span></code></pre>
<p>Download a version of the pre-trained data from</p>
<p><a href="https://github.com/coqui-ai/STT/releases/tag/v1.4.0">https://github.com/coqui-ai/STT/releases/tag/v1.4.0</a></p>
<p>Navigate to the host directory of where the folder 'coqui-stt-1.4.0-checkpoint' is stored.</p>
<p>In the same directory, create the directory for the 'checkpoint' folder.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">mkdir</span><span> coqui-stt-1.0.0-checkpoint
</span></code></pre>
<p>and download the huge-vocabulary.scorer
from <a href="https://coqui.ai/english/coqui/v1.0.0-huge-vocab">https://coqui.ai/english/coqui/v1.0.0-huge-vocab</a></p>
<p>Acquire a mp3 audio file for STT to process. You will most likely have to convert the audio file because STT will only take a 16-bit wav file format for input.</p>
<p>The following ffmpeg media converter command shows an example of a conversion.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">ffmpeg</span><span style="color:#f29718;"> -i </span><span style="color:#c2d94c;">"Gettysburg Address.mp3"</span><span style="color:#f29718;"> -acodec</span><span> pcm_u8</span><span style="color:#f29718;"> -ar</span><span> 22050 </span><span style="color:#c2d94c;">"Gettysburg Address.wav"
</span></code></pre>
<p>Run the <a href="https://stt.readthedocs.io/en/latest/Checkpoint-Inference.html?highlight=audio%20file#transcribing-a-single-file">'Single file (aka one-shot) inference'</a> command to perform a basic conversion of an audio to text.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">python</span><span style="color:#f29718;"> -m</span><span> coqui_stt_training.training_graph_inference</span><span style="color:#f29718;"> --checkpoint_dir</span><span> coqui-stt-1.4.0-checkpoint</span><span style="color:#f29718;"> --scorer_path</span><span> huge-vocabulary.scorer</span><span style="color:#f29718;"> --n_hidden</span><span> 2048</span><span style="color:#f29718;"> --one_shot_infer </span><span style="color:#c2d94c;">'Gettysburg Address.wav'
</span></code></pre>
<p>The output will be displayed on the console.</p>
forgit - Git with fzf
2022-10-15T00:00:00+00:00
2022-10-15T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/forgit-git-with-fzf/
<h3 id="fuzzy-finder-for-git-commands">Fuzzy Finder for Git Commands</h3>
<p>The real time fuzzy finder tool fzf is a good tool to perform searches for files as well as filtering output from other command line tools. This tool complements Git really well due to the fact git has a <a href="https://developers.apple.com/library/archive/documentation/Cocoa/Conceptual/CocoaBindings/Tasks/masterdetail.html">master-detail</a> workflow view. When you are looking at a commit log (master), you want to look at the file changes (details) for that commit.</p>
<span id="continue-reading"></span>
<p>As a complete git viewing experience, <a href="https://github.com/wfxr/forgit#custom-options">forgit</a>, is able to provide the split view interface when interacting with the git subcommands (diff, branch, stash, etc.).</p>
<p>Forgit can be used in the namespace format, or the shorthand alias form can be used. The following commands are for using git's show with forgit.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">forgit::stash::show
</span></code></pre>
<p>or</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">gss
</span></code></pre>
Docusaurus - Basic Config
2022-09-10T00:00:00+00:00
2022-09-10T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/docusaurus-basic-config/
<h3 id="documentation-centric-changes">Documentation-centric Changes</h3>
<p>Docusaurus is a JavaScript framework documentation generator. This tool provides many useful conveniences such as documentation versioning and search integration. Docusaurus gives you the ability to quickly get a working documentation site running by using a config-based means of manipulating your settings for the site. Even though it is config-based, one can drop to a lower level by changing JavaScript and styles files in the <code>src</code> source to make custom changes to your site.</p>
<span id="continue-reading"></span><h4 id="docs-mode">Docs Mode</h4>
<p>By default, the basic generator will also create blog pages when you run the following command.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npx</span><span> create-docusaurus@latest my-website classic
</span></code></pre>
<p>However, one can <a href="https://docusaurus.io/docs/docs-introduction#docs-only-mode">prioritize the viewing of the docs pages</a> by removing the <code>/doc</code> prefixing URl scheme.</p>
<p>In additional to performing the steps needed to prioritize the docs pages, the <code>_categories.json</code> should also be updated by removing the <code>link</code> key. </p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>{
</span><span> "label": "Tutorial - Basics",
</span><span> "position": 2
</span><span>}
</span></code></pre>
<p>From</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>http://localhost:3000/docs/tutorial-extras/manage-docs-versions
</span></code></pre>
<p>To</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>http://localhost:3000/tutorial-extras/manage-docs-versions
</span></code></pre>
<p>Doing this will also remove the page for original category link.</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>http://localhost:3000/docs/category/tutorial---basics
</span></code></pre>
<h4 id="versioning">Versioning</h4>
<p>Keeping track of the versions of your documentation is also an essential part of maintaining your documentation when you have a major release of product that
significantly changes your API. You still would want the old version of the documentation around for people who have not yet migrated to the new version.</p>
<p>Very few documentation generators out there I see possess the ability to perform
versioning which is rather unfortunate. With versioning in Docusaurus, you can keep historical versions of your documentation around. One downside in using versioning is that it cause more complexity in maintenance of your documentation.</p>
<p>Creating a new version can be done be using this command</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>npm run docusaurus docs:version 1.1.0
</span></code></pre>
<p>Then add the version list dropdown in the navbar by updating <code>docusaurus.config.js</code></p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>module.exports = {
</span><span> //...
</span><span> themeConfig: {
</span><span> navbar: {
</span><span> //...
</span><span> items: [
</span><span> {
</span><span> type: 'docsVersionDropdown',
</span><span> position: 'left',
</span><span> dropdownItemsAfter: [{to: '/versions', label: 'All versions'}],
</span><span> dropdownActiveClassDisabled: true,
</span><span> },
</span><span> ],
</span><span> //...
</span><span> },
</span><span> },
</span><span> //...
</span><span>};
</span></code></pre>
<p><a href="https://docusaurus.io/docs/versioning">More information for versioning</a>.</p>
Using Ava with Testdouble
2022-08-05T00:00:00+00:00
2022-08-05T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/ava-with-testdouble/
<h3 id="example-of-a-simple-test-case">Example of a Simple Test Case</h3>
<p><a href="https://github.com/avajs/ava">Ava</a> is a unique testing framework in that it is one of the few testing frameworks out there that recognizes observable resolution.
It also makes asynchronous testing the default option when you write tests ensuring better performance.
Another nice feature of Ava is that it has a <a href="https://github.com/avajs/ava#magic-assert">nicer assertion output display</a>.</p>
<p><a href="https://github.com/testdouble/testdouble.js">Testdouble</a> is an assertion library which specializes in create 'doubles'. Testdouble is different from Sinon because Testdouble will replace the function outright for which it is substituting when mocking out a function or object. It also makes it easier to track using a 'sandbox' API to alleviate the user from having to restore an original replaced function.</p>
<span id="continue-reading"></span>
<p>To demonstrate the usage of this testing framework and assertion library, the following modified example taken from <a href="https://testdouble.github.io/testdouble.js/3-getting-started.html#getting-started">Testdouble's Readme</a> will be shown.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// Import the libraries Ava and Testdouble
</span><span style="color:#ff7733;">import </span><span>test </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'ava'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span style="color:#f29718;">* </span><span style="color:#ff7733;">as </span><span>td </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'testdouble'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Example adapted from https://testdouble.github.io/testdouble.js/3-getting-started.html#getting-started
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Functions that are defined on the top level will be
</span><span style="font-style:italic;color:#5c6773;">// mocked by Testdouble. The functions will be used to build
</span><span style="font-style:italic;color:#5c6773;">// up the two classes.
</span><span style="color:#ff7733;">let </span><span>subject</span><span style="color:#bfbab0cc;">, </span><span>createRandomProblem</span><span style="color:#bfbab0cc;">, </span><span>savesProblem</span><span style="color:#bfbab0cc;">, </span><span>submitProblem</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">MathProblem </span><span>{
</span><span> </span><span style="color:#ff7733;">constructor</span><span>(</span><span style="color:#f29718;">createRandomProblem</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">savesProblem</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">submitProblem</span><span>) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>createRandomProblem </span><span style="color:#f29668;">= </span><span>createRandomProblem</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>savesProblem </span><span style="color:#f29668;">= </span><span>savesProblem</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>submitProblem </span><span style="color:#f29668;">= </span><span>submitProblem</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="color:#ffb454;">generate</span><span>() {
</span><span> </span><span style="color:#ff7733;">const </span><span>problem </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">createRandomProblem</span><span>()</span><span style="color:#bfbab0cc;">,
</span><span> savedProblem </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>savesProblem</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">save</span><span>(problem)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">submitProblem</span><span>(savedProblem)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">SavesProblem </span><span>{
</span><span> </span><span style="color:#ffb454;">save</span><span>() {
</span><span> }
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">//...
</span></code></pre>
<p>Continuing in the same file, there will be two blocks. One of which will be for
defining the variables for comparison, while the second will be used
for making assertions.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">//...
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">SavesProblem </span><span>{
</span><span> </span><span style="color:#ffb454;">save</span><span>() {
</span><span> }
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Ava's test blocks which will contain the testdouble assertions.
</span><span style="font-style:italic;color:#5c6773;">// Testdouble creates a 'double' for two functions and an object.
</span><span style="font-style:italic;color:#5c6773;">// This is the preparatory block for creating the class instances for
</span><span style="font-style:italic;color:#5c6773;">// asserting in the block below.
</span><span>test</span><span style="color:#f29668;">.</span><span style="color:#f07178;">before</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> createRandomProblem </span><span style="color:#f29668;">= </span><span>td</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">func</span><span>(</span><span style="color:#c2d94c;">'createRandomProblem'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> savesProblem </span><span style="color:#f29668;">= </span><span>td</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">object</span><span>(</span><span style="color:#f29668;">new </span><span style="color:#59c2ff;">SavesProblem</span><span>())</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Use td.func and not td.function
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Issue - https://github.com/testdouble/testdouble.js/issues/214
</span><span> submitProblem </span><span style="color:#f29668;">= </span><span>td</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">func</span><span>(</span><span style="color:#c2d94c;">'submitProblem'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> subject </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">MathProblem</span><span>(createRandomProblem</span><span style="color:#bfbab0cc;">, </span><span>savesProblem</span><span style="color:#bfbab0cc;">, </span><span>submitProblem)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Testdouble's assertion are primarily used in this block and they
</span><span style="font-style:italic;color:#5c6773;">// checked against the output of the 'double' function.
</span><span style="color:#ffb454;">test</span><span>(</span><span style="color:#c2d94c;">'test double'</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">t </span><span style="color:#ff7733;">=> </span><span>{
</span><span> td</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">when</span><span>(</span><span style="color:#ffb454;">createRandomProblem</span><span>())</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">thenReturn</span><span>(</span><span style="color:#c2d94c;">'some problem'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> td</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">when</span><span>(savesProblem</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">save</span><span>(</span><span style="color:#c2d94c;">'some problem'</span><span>))</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">thenReturn</span><span>(</span><span style="color:#c2d94c;">'saved problem'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> subject</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">generate</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Wrap with an Ava assertion to state that there will not be an error when using
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Testdouble's verify assertion. This prevents the Ava test from failing.
</span><span> t</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">notThrows</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{ td</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">verify</span><span>(</span><span style="color:#ffb454;">submitProblem</span><span>(</span><span style="color:#c2d94c;">'saved problem'</span><span>)) })</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
JavaScript - Querying Objects
2022-07-10T00:00:00+00:00
2022-07-10T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/javascript-querying-objects/
<h3 id="data-querying">Data Querying</h3>
<p>As JSON/JavaScript objects are heavily relied upon means of accessing data, it is crucial to quickly retrieve certain pieces of information within the object quickly. For simple objects, a couple of loops will suffice in honing in to the exact detail, but most likely, the general object will be more complex.</p>
<span id="continue-reading"></span>
<p>A general querying library can alleviate the difficulty of getting a specific key or value within deeply nested objects. Ideally, the library of choice should have the following features:</p>
<ul>
<li>Operate on any JavaScript object.
<ul>
<li>Avoid having to wrap your object around any special library object, or avoid the need to structure your object in a certain way.</li>
</ul>
</li>
<li>Provide dot notation access.</li>
<li>Provide comparison functionality.</li>
</ul>
<p>These are some evaluations for a select group of libraries that I have researched to fit the criteria defined above:</p>
<ul>
<li>
<p><a href="https://www.npmjs.com/package/alasql">alasql</a>
Provides a really close SQL querying engine equivalent, but this library is too large for my liking.</p>
</li>
<li>
<p><a href="https://www.npmjs.com/package/jsonpath">jsonpath</a>
Operate on a single object at a time. This lacks the ability to perform comparisons between different objects.</p>
</li>
<li>
<p><a href="https://www.npmjs.com/package/@nano-sql/core">nanosql</a>
Has SQL-Like querying capabilities. It even has observable querying support.
Does not appear to be a maintained library.</p>
</li>
<li>
<p><a href="https://www.npmjs.com/package/mingo">mingo</a>
Provides Mongodb querying capabilities well suited for object access.</p>
</li>
</ul>
<p>Ultimately, mingo was my choice for the query library because it offers a balance between size and functionality while also being maintained.</p>
Zola - Include Template
2022-06-26T00:00:00+00:00
2022-06-26T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/zola-include-template/
<h3 id="common-template">Common Template</h3>
<p>Common content that belongs on multiple pages should be situated in a template which should be shared globally. An example of would be a footer, the bottom of the page content that persists across pages. Looking at Tera, the template engine for Zola, the <a href="https://tera.netlify.app/docs/#include">include</a> feature within a template offers the capability to reference other templates.</p>
<span id="continue-reading"></span>
<p>In other template languages, a shared template is also known as a partial.</p>
<p>Here is an index template that references a shared <code>footer.html</code> template
on the bottom of the 'main' container:</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span style="color:#f29718;">html</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">html </span><span style="color:#ffb454;">lang</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"en"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> ...
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"main"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">class</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"section footer"</span><span style="color:#39bae690;">>
</span><span> {% include "footer.html" %}
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span></code></pre>
<p>Within the <code>templates/footer.html</code> file is the footer template:</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">span</span><span style="color:#39bae690;">>
</span><span> Copyright © {{ now() | date(format="%Y") }}
</span><span> Github.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">a</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">span</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">>
</span></code></pre>
<p>The footer contains a copyright notice which uses the current year.</p>
Visual Studio Code Extensions - Quick Picks #6
2022-06-12T00:00:00+00:00
2022-06-12T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/visual-studio-code-extensions-quick-picks-6/
<h3 id="markdown-table-formatter"><a href="https://marketplace.visualstudio.com/items?itemName=darkriszty.markdown-table-prettify">Markdown Table Formatter</a></h3>
<p>A markdown table's formatting often tends to go awry when there is a need to change the words in the headers which affects the width of columns. It is a laborious process to have to realign all the column content that fall underneath the changed header.</p>
<p>To solve this issue, use the Markdown Table Formatter extension to format markdown tables. This extension will format the 'basic markdown tables' such as the following:</p>
<pre data-lang="md" style="background-color:#0f1419;color:#bfbab0;" class="language-md "><code class="language-md" data-lang="md"><span style="color:#bfbab0cc;">|</span><span> Food Item </span><span style="color:#bfbab0cc;">|</span><span> Items Bought </span><span style="color:#bfbab0cc;">|
</span><span style="color:#bfbab0cc;">|</span><span>------------</span><span style="color:#bfbab0cc;">|</span><span>--------------</span><span style="color:#bfbab0cc;">|
</span><span style="color:#bfbab0cc;">|</span><span> Pineapples </span><span style="color:#bfbab0cc;">|</span><span> 4 </span><span style="color:#bfbab0cc;">|
</span><span style="color:#bfbab0cc;">|</span><span> Tomatoes </span><span style="color:#bfbab0cc;">|</span><span> 3 </span><span style="color:#bfbab0cc;">|
</span></code></pre>
<p>However, it does not work with Pandoc's <a href="https://pandoc.org/MANUAL.html#extension-grid_tables">grid table</a> markdown output.</p>
<span id="continue-reading"></span><h3 id="filename-search"><a href="https://marketplace.visualstudio.com/items?itemName=potatoqualitee.filename-search">Filename Search</a></h3>
<video title="vscode extension - filename search demo" controls>
<source src='https://user-images.githubusercontent.com/8278033/124448117-5f57ab00-dd82-11eb-8929-a830a885c9d7.mp4' type='video/mp4' />
</video>
<p>By default, VsCode comes with a file name search which is brought up using the ctrl + shift + p key combination. However, this search provides only a temporary overlay element for files, that disappears if you click on the outside area of that element.
Use this extension to keep a persistent view of the file names being searched.</p>
<p>After opening up this panel with the ctrl + shift + q combination, you can drag this panel's tab into the Search panel to keep it accessible on the bottom panel.
The default view of this plugin will show up in the additional vertical sidebar.</p>
<img src="/images/posts/vscode-filename-search.png" alt="vscode extension file search in tab">
Bash - Display all Aliases Defined in Shell
2022-06-04T00:00:00+00:00
2022-06-04T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/createpost/
<h3 id="check-on-aliases-defined-in-bashrc">Check on Aliases Defined in .bashrc</h3>
<p>If you so happen to have many alias commands in your .bashrc file and want to be reminded of them, you can list them out using the following</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#f07178;">alias
</span></code></pre>
<span id="continue-reading"></span>
<p>The output will be a list of aliases in alphabetical order.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Example
</span><span style="color:#f07178;">alias </span><span style="color:#ffb454;">gst</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">'git status'
</span><span style="color:#f07178;">alias </span><span style="color:#ffb454;">lsla</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">'ls -la'
</span></code></pre>
Vite - Quick Tips #1
2022-05-01T00:00:00+00:00
2022-05-01T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/vite-quick-tips-1/
<h3 id="more-log-information-when-vite-server-runs">More Log Information when Vite Server Runs</h3>
<p>Using the <code>-d</code> option with the Vite command in the npm script to have
more verbose output for debugging.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span style="font-style:italic;color:#5c6773;">// ...
</span><span> </span><span style="color:#c2d94c;">"scripts"</span><span>: {
</span><span> </span><span style="color:#c2d94c;">"dev"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"vite -d"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"build"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"vite build"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"preview"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"vite preview"
</span><span> }
</span><span style="font-style:italic;color:#5c6773;">// ...
</span></code></pre>
<span id="continue-reading"></span><h3 id="launch-the-vite-server-programmatically">Launch the Vite Server Programmatically</h3>
<p>Using the JavaScript API, the Vite server can be dynamically configured with custom options.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">const </span><span>{ createServer } </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'vite'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>(</span><span style="color:#ff7733;">async </span><span>() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">const </span><span>server </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">await </span><span style="color:#ffb454;">createServer</span><span>({
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// any valid user config options, plus `mode` and `configFile`
</span><span> configFile</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">,
</span><span> root</span><span style="color:#bfbab0cc;">: </span><span>__dirname</span><span style="color:#bfbab0cc;">,
</span><span> server</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> port</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">8080
</span><span> }
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">await </span><span>server</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">listen</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>server</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">printUrls</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>})()</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Vite - Before the Server Starts
2022-04-14T00:00:00+00:00
2022-04-14T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/vite-before-the-server-starts/
<h3 id="use-the-configure-server">Use the 'configure-server'</h3>
<p>Create a Vite application from the new project command with a template option.
This command will create a simple TypeScript project.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> create vite@latest a-vite-test</span><span style="color:#f29668;"> --</span><span> --template vanilla-ts
</span></code></pre>
<span id="continue-reading"></span>
<p>While the Vite specific hook, <a href="https://vitejs.dev/guide/api-plugin.html#configureserver">configureServer</a>, is intended for configuring the Vite dev server middleware, it also allows for early stage task configuration that
might run on the command line prior to the Vite dev server starts up.</p>
<p>It is useful because it can also replicate the behavior of a 'before' callback.</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="color:#ff7733;">import </span><span>{ defineConfig } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"vite"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">export default </span><span style="color:#ffb454;">defineConfig</span><span>({
</span><span> plugins</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> (() </span><span style="color:#ff7733;">=> </span><span>({
</span><span> name</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'configure-server'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">configureServer</span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Do something early before the dev server starts up.'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> server</span><span style="color:#f29668;">.</span><span>middlewares</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">use</span><span>((</span><span style="color:#f29718;">req</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">res</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">next</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// custom handle request...
</span><span> })
</span><span> }
</span><span> }))()
</span><span> ]
</span><span>})
</span></code></pre>
Git - Custom SSH Keys Per Repository
2022-03-30T00:00:00+00:00
2022-03-30T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/git-custom-ssh-key-per-repository/
<h3 id="assign-git-profiles-for-different-repositories">Assign Git Profiles for Different Repositories</h3>
<p>On occasions where you wish to associate different Git profiles to different repositories, such as when you have a work account and a personal account, one can achieve this by running a Git config command on repository level basis.</p>
<span id="continue-reading"></span>
<p>Assuming that you have already created two ssh keys within your <code>.ssh</code> folder to separate your work vs personal Git repositories activities, and you want to pin a repository for work related activities, navigate into the Git repository of where you perform your work and run this command:</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">git</span><span> config core.sshCommand </span><span style="color:#c2d94c;">"ssh -i ~/.ssh/your_select_ssh_key_name_for_work -F /dev/null"
</span></code></pre>
<p>Now suppose you have another Git folder which you only want to interact with your personal Git account, you will need to navigate to the personal repo and run this command:</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">git</span><span> config core.sshCommand </span><span style="color:#c2d94c;">"ssh -i ~/.ssh/your_select_ssh_key_name_for_personal -F /dev/null"
</span></code></pre>
Lit Element - Constrain Global Styles in a Web Component
2022-03-19T00:00:00+00:00
2022-03-19T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/lit-element-constrain-global-styles-in-a-web-component/
<h3 id="linking-stylesheet-in-the-template">Linking Stylesheet in the Template</h3>
<p>To use even a basic css library will cause some styles to be applied globally to the entire page, but you wish to localize the styling to just the web component which you are defining.</p>
<p>Importing the third party css library in the static style definition will not bring in the styles.</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span>static styles </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">css</span><span style="color:#c2d94c;">`
</span><span style="color:#c2d94c;">
</span><span style="color:#c2d94c;">// This won't work
</span><span style="color:#c2d94c;">@import 'bulma/css/bulma.css';
</span><span style="color:#c2d94c;">
</span><span style="color:#c2d94c;">...
</span><span style="color:#c2d94c;">`
</span></code></pre>
<span id="continue-reading"></span>
<p>Instead, add the link tag which references another stylesheet within the template. That stylesheet will be the one which will provide the import
of the css library.</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"./stuff.css"</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"my-custom-element"</span><span style="color:#39bae690;">>
</span><span> Stuff
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span></code></pre>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* stuff.css */
</span><span>
</span><span>// This will work
</span><span style="color:#ff7733;">@import </span><span style="color:#c2d94c;">'bulma/css/bulma.css'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>...
</span></code></pre>
Git - Cherry Picking Changes but Avoid Taking the Exact Commit Log
2022-03-10T00:00:00+00:00
2022-03-10T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/git-cherry-pick-pick-custom-commit-message/
<h3 id="customize-the-cherry-picked-commit-message">Customize the cherry-picked Commit Message</h3>
<p>You are working on a branch focusing on a certain feature, but you end up adding in commit messages that are not presentable enough to be applied to your <code>main</code> branch. To fix this problem, you can rebase to squash the commits and then cherry-pick the changes onto the <code>main</code> branch.</p>
<span id="continue-reading"></span>
<p>First, squash the commits in the feature branch and then switch to your <code>main</code> branch.</p>
<p>Cherry-pick the changes, but use the <code>n</code> option when selecting the hash
from the feature branch to apply the changes.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">git</span><span> cherry-pick</span><span style="color:#f29718;"> -n </span><span style="color:#f29668;"><</span><span>HASH</span><span style="color:#f29668;">>
</span></code></pre>
<p>Now you can add a commit message of your choice for a cleaner commit log.</p>
Lit Element - After Attribute Change
2022-02-27T00:00:00+00:00
2022-02-27T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/lit-element-attribute-change/
<h3 id="wait-for-dom-change-before-taking-action">Wait for DOM Change before Taking Action</h3>
<p>Assume that we have a button which sets up with a click event listener to call upon a toggling of state to display an associated container:</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="color:#ff7733;">import </span><span>{ LitElement</span><span style="color:#bfbab0cc;">, </span><span>html } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"lit-element"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">MyElement </span><span style="color:#ff7733;">extends </span><span style="text-decoration:underline;color:#59c2ff;">LitElement </span><span>{
</span><span>
</span><span> </span><span style="color:#ffb454;">render</span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">html</span><span style="color:#c2d94c;">`
</span><span style="color:#c2d94c;"> <button @click="${</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>_handleClick</span><span style="color:#c2d94c;">}">click</button>
</span><span style="color:#c2d94c;"> <div id="container" class=${</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>open </span><span style="color:#f29668;">? </span><span style="color:#c2d94c;">'expanded' </span><span style="color:#f29668;">: </span><span style="color:#c2d94c;">'collapsed'}>
</span><span style="color:#c2d94c;"> The contents.
</span><span style="color:#c2d94c;"> </div>
</span><span style="color:#c2d94c;"> `</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="color:#ffb454;">_handleClick</span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">_toggleContainer</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">//...
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">//...
</span></code></pre>
<span id="continue-reading"></span>
<p>The <code>toggleContainer</code> function will flip the attribute boolean value to change the class name for the container, but it is necessary to wait for the attribute change to propagate to the DOM before any further action can be taken by converting the operating function to be an await function.</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="font-style:italic;color:#5c6773;">// Add the async label for the function
</span><span>async </span><span style="color:#ffb454;">_toggleContainer</span><span>() {
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Change the property of the element
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>open </span><span style="color:#f29668;">= !</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>open</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Wait for the DOM change to complete.
</span><span> </span><span style="font-style:italic;color:#5c6773;">// The 'updateComplete' is a special built-in promise
</span><span> </span><span style="font-style:italic;color:#5c6773;">// that you will need to use for signaling completion.
</span><span> </span><span style="color:#ff7733;">await </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>updateComplete</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Perform other operations
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">doOtherThings</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
Emotion Css with Linaria
2022-02-17T00:00:00+00:00
2022-02-17T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/emotion-css-with-linaria/
<h3 id="share-global-styles-on-compile-and-runtime">Share Global Styles on Compile and Runtime</h3>
<p>Linaria is able to achieve zero-runtime css-in-js because it compiles the js to css before the local dev server startup, however one might wish to share and modify styles used by Linaria during development.</p>
<p>Since one can't use Linaria when the dev server is running for client css-in-js, the base styles will need to be handed over to another css-in-js library for modification.</p>
<span id="continue-reading"></span>
<p>To avoid redundancy in redefining the css-in-js styles that Linaria uses to a more suitable format for another css-in-js library, a shared 'global-styles.js' in css file will need to be compatible for reading by both css-in-js libraries.</p>
<p>Emotion css happens to be another library that can read the css in the template string format that Linaria relies on.</p>
<p>Create a 'global-styles.js' file which will be the base styles that will be used by both libraries:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// global.js
</span><span>
</span><span style="color:#ff7733;">export default </span><span style="color:#c2d94c;">`
</span><span style="color:#c2d94c;"> html {
</span><span style="color:#c2d94c;"> background-color: gray;
</span><span style="color:#c2d94c;"> }
</span><span style="color:#c2d94c;">
</span><span style="color:#c2d94c;"> body {
</span><span style="color:#c2d94c;"> width: 100%;
</span><span style="color:#c2d94c;"> max-width: 100%;
</span><span style="color:#c2d94c;"> margin: 0;
</span><span style="color:#c2d94c;"> }
</span><span style="color:#c2d94c;">`
</span></code></pre>
<p>The Linaria run definition which references the 'global-styles.js' for building
before the local dev server is to start up in your package.json.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#ff3333;">...,
</span><span> </span><span style="color:#c2d94c;">"scripts"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"start"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"npx linaria -o 'src/build/' -r './src/' './src/styles/global-styles.js' && <your dev server start command>"
</span><span> }
</span><span>}
</span><span>
</span></code></pre>
<p>Use Emotion to reference the 'global-styles.js' file for local development:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// index.js
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Emotion reads from the same 'global-styles.js'
</span><span style="font-style:italic;color:#5c6773;">// as Linaria
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ injectGlobal } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@emotion/css'
</span><span style="color:#ff7733;">import </span><span>{ </span><span style="color:#ff7733;">default as </span><span>globalStyles } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"../styles/global-styles.js"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Global styles attached to the body
</span><span style="color:#ff7733;">const </span><span>myStyle </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">injectGlobal</span><span style="color:#c2d94c;">`${</span><span>globalStyles</span><span style="color:#c2d94c;">}`</span><span style="color:#bfbab0cc;">;
</span><span>document</span><span style="color:#f29668;">.</span><span>body</span><span style="color:#f29668;">.</span><span>classList</span><span style="color:#f29668;">.</span><span style="color:#f07178;">add</span><span>(myStyle)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Redefined a Web Component
2022-02-05T00:00:00+00:00
2022-02-05T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/redefined-a-web-component/
<h3 id="hmr-with-web-components">HMR with Web Components</h3>
<p>Say that you are using HMR in conjunction with web components for your layouts, you would expect a change in the component's JavaScript logic to trigger the HMR code to re-register the component.</p>
<p>However, there isn't a way to redefine a web component once it has already been defined and registered onto the page, an error will be thrown if you tried to redefine the web component again.</p>
<span id="continue-reading"></span>
<p>As of this writing on Feb 2022, there also isn't a method for web components for removal, such that the option to remove and redefine is not possible. (<a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry">https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry</a>)</p>
<p>Alternatively, it is possible to check for an existence of a web component, and once it is
found to be already defined, one can force a refresh of the entire page instead.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">!</span><span>window</span><span style="color:#f29668;">.</span><span>customElements</span><span style="color:#f29668;">.</span><span style="color:#f07178;">get</span><span>(</span><span style="color:#c2d94c;">'my-web-component'</span><span>)) {
</span><span> location</span><span style="color:#f29668;">.</span><span style="color:#f07178;">reload</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<p>Through the basic APIs for interacting with web components, there isn't a way for web components to work with HMR, but there is a way to do "limited HMR" with web components if you use a specific implementation of <a href="https://open-wc.org/docs/development/hot-module-replacement/#how-it-works">"@open-wc/dev-server-hmr"</a>.</p>
Snowpack - HMR - Compare Old and New Value
2022-01-29T00:00:00+00:00
2022-01-29T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/snowpack-hmr-compare-old-and-new-value/
<h3 id="export-value-for-comparison">Export Value for Comparison</h3>
<p>HMR is a convenient tool to have when one wishes to perform updates to a page without fully reloading the whole page. When using Snowpack's HMR, one can compare a variable's value prior to it being changed.</p>
<p>This feature might come in handy when you want to perform resets after a set amount of time has passed for a user session, but there also might be a requirement to restore certain pieces of old information back into a new session.
For example, in a privacy-sensitive form area, a notice can come up in area that does not require a full refresh as a top status bar after a time-out period.</p>
<span id="continue-reading"></span>
<p>While there might be other cases that HMR will come into play, the
following example below will illustrate the saving and retrieval of
a variable value which that could be used later for comparison and manipulation.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// Sample variable to watch for changes
</span><span style="font-style:italic;color:#5c6773;">// must be exported
</span><span style="color:#ff7733;">export let </span><span>myVar </span><span style="color:#f29668;">= </span><span style="color:#f29718;">5</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Add the following your entry point .js file
</span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#ff7733;">import</span><span style="color:#f29668;">.</span><span>meta</span><span style="color:#f29668;">.</span><span>hot) {
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Area to compare old with the new changed value
</span><span> </span><span style="color:#ff7733;">import</span><span style="color:#f29668;">.</span><span>meta</span><span style="color:#f29668;">.</span><span>hot</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">accept</span><span>(({</span><span style="color:#f29718;">module</span><span>}) </span><span style="color:#ff7733;">=> </span><span>{
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Recently changed state value
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'module.myVar'</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">module</span><span style="color:#f29668;">.</span><span>myVar)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Prior value before the changed state value
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#ff7733;">import</span><span style="color:#f29668;">.</span><span>meta</span><span style="color:#f29668;">.</span><span>hot</span><span style="color:#f29668;">.</span><span>data</span><span style="color:#f29668;">.</span><span>myVar)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Current myVar value will become the old variable value
</span><span> myVar </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">module</span><span style="color:#f29668;">.</span><span>myVar</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Area to save prior variable value for comparison later
</span><span> </span><span style="color:#ff7733;">import</span><span style="color:#f29668;">.</span><span>meta</span><span style="color:#f29668;">.</span><span>hot</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">dispose</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Save state before destroying the current module.
</span><span> </span><span style="color:#ff7733;">import</span><span style="color:#f29668;">.</span><span>meta</span><span style="color:#f29668;">.</span><span>hot</span><span style="color:#f29668;">.</span><span>data </span><span style="color:#f29668;">= </span><span>{ myVar }</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span>}
</span></code></pre>
<p>More details from the official snowpack esm-hmr <a href="https://github.com/withastro/esm-hmr">repository</a>.</p>
Snowpack - Dev Server - Compile Css on Server Start
2022-01-22T00:00:00+00:00
2022-01-22T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/snowpack-dev-server-compile-css-on-server-start/
<h3 id="linaria-cli">Linaria CLI</h3>
<p>CSS-in-Js styles are quite modular given their ability to be associated with components, but it is also helpful to have the option to compile some styles ahead of time for a html page to use. This behavior is desired if there are common global styles that referenced by all pages. Having minimum styles on the page in a css file also helps to prevent the flash of unstyled content.</p>
<p>In the following example, <a href="https://github.com/callstack/linaria">Linaria</a> will be shown as the CSS-in-Js of choice since this library supports compilation during build.</p>
<p>Create a new project and install the project dependencies:</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> install snowpack @snowpack/plugin-run-script @linaria/cli @linaria/shaker
</span></code></pre>
<span id="continue-reading"></span>
<p>For this example, the build folder will reside in the content folder. Create a gitignore rule to ignore the build folder.</p>
<p>Configure the "snowpack" config file to use the "@snowpack/plugin-run-script" to run the build of the conversion of js styles to css styles file.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// snowpack.config.js
</span><span style="font-style:italic;color:#39bae6;">module</span><span style="color:#f29668;">.</span><span style="font-style:italic;color:#39bae6;">exports </span><span style="color:#f29668;">= </span><span>{
</span><span> mount</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"content"</span><span style="color:#bfbab0cc;">: </span><span>{ url</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'/' </span><span>}
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> plugins</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> [
</span><span> </span><span style="color:#c2d94c;">"@snowpack/plugin-run-script"</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"cmd"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"npx linaria -o 'content/build/' -r './content/' './content/styles/project.js'"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"watch"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"npx linaria -o 'content/build/' -r './content/' './content/styles/project.js'"
</span><span> }
</span><span> ]
</span><span> ]
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Create the main "index.html" for displaying the sample styles content and "project.js" for the global page styles. The "project.js" will have the Linaria CSS-in-Js content which will output a "project.css" which the "index.html" will refer to.</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span style="color:#f29718;">html</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">html </span><span style="color:#ffb454;">lang</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"en"</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">meta </span><span style="color:#ffb454;">charset</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">meta </span><span style="color:#ffb454;">http-equiv</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"X-UA-Compatible" </span><span style="color:#ffb454;">content</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"IE=edge"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">meta </span><span style="color:#ffb454;">name</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"viewport" </span><span style="color:#ffb454;">content</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"width=device-width, initial-scale=1.0"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">></span><span>Document</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet" </span><span style="color:#ffb454;">type</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"text/css" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"./build/styles/project.css"</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span> Some content.
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span></code></pre>
<p>Add a general gray background color for all pages.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// project.js
</span><span style="color:#ff7733;">import </span><span>{ css } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@linaria/core'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">export const </span><span>globals </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">css</span><span style="color:#c2d94c;">`
</span><span style="color:#c2d94c;"> :global() {
</span><span style="color:#c2d94c;"> html {
</span><span style="color:#c2d94c;"> background-color: gray;
</span><span style="color:#c2d94c;"> color: white;
</span><span style="color:#c2d94c;"> }
</span><span style="color:#c2d94c;"> }
</span><span style="color:#c2d94c;">`</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Start the snowpack dev and the "project.css" file will be generated.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">snowpack</span><span> dev
</span></code></pre>
<p>The project file structure should look like this after setup and compilation:</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>├── content
</span><span>│ ├── build
</span><span>│ │ └── styles
</span><span>│ │ └── project.css
</span><span>│ ├── index.html
</span><span>│ └── styles
</span><span>│ └── project.js
</span><span>├── package.json
</span><span>├── package-lock.json
</span><span>└── snowpack.config.js
</span></code></pre>
Document Fragment with Kor UI
2022-01-15T00:00:00+00:00
2022-01-15T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/document-fragment-kor-ui/
<h3 id="dynamically-adding-lit-elements-into-page">Dynamically Adding Lit Elements into Page</h3>
<p><a href="https://lit.dev/">Lit elements</a> are an implementation of <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components">web components</a>. Lit elements are useful because it encourages component reuse across different JavaScript frameworks, which leads to reduced development time.</p>
<p>The traditional usage of Lit elements / web components involves defining the component inside your html page, however there might be instances where you do not wish to modify the html page by introducing the web component markup. The introduced web components might serve only as an assistive means for using the page, but the html export of the page must remain immaculate.</p>
<span id="continue-reading"></span>
<p>Since the page can not be modified during the initial definition, it will not be initially rendered. This will mean that dom manipulation will need to be employed after the fact and a way to achieve this is to use a document fragment.</p>
<p>If we were to use a web component library that is built on top of the default Lit elements, such as the <a href="https://kor-ui.com/introduction/welcome">Kor UI library</a>, the Lit element library will also need to be used because the Kor UI library does not offer low-level dynamic page manipulation capabilities.</p>
<p>The Lit element library will allow for the creation of a new wrapper web component that renders the Kor UI element inside a document fragment using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/range/createContextualFragment">Range.createContextualFragment()</a> method. The <code>createContextualFragment</code> method will take in a raw string and render it as live html.</p>
<p>After this, when a new custom Lit element is defined and registered, it can be inserted into a dom element of your choice.</p>
<p>The below example shows the complete usage:</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link
</span><span> </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet"
</span><span> </span><span style="color:#ffb454;">type</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"text/css"
</span><span> </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"https://unpkg.com/@kor-ui/kor@1.9.1/kor-styles.css"
</span><span style="color:#39bae690;">/>
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script </span><span style="color:#ffb454;">type</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"module"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#ff7733;">import </span><span>{ LitElement</span><span style="color:#bfbab0cc;">, </span><span>html } </span><span style="color:#ff7733;">from
</span><span> </span><span style="color:#c2d94c;">'https://unpkg.com/lit@2.1.1/index.js?module'</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">import </span><span style="color:#c2d94c;">'https://unpkg.com/@kor-ui/kor@1.9.1/components/button/index.js?module'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Wrap the Kor Button component
</span><span> </span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">KorButtonWrap </span><span style="color:#ff7733;">extends </span><span style="text-decoration:underline;color:#59c2ff;">LitElement </span><span>{
</span><span>
</span><span> </span><span style="color:#ffb454;">render</span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">html </span><span style="color:#c2d94c;">`</span><span>${
</span><span> </span><span style="font-style:italic;color:#39bae6;">document
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">createRange</span><span>()
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">createContextualFragment</span><span>(</span><span style="color:#c2d94c;">`
</span><span style="color:#c2d94c;"> <kor-button label='</span><span>${</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>label}</span><span style="color:#c2d94c;">' color='primary'></kor-button>
</span><span style="color:#c2d94c;"> `</span><span>)
</span><span> }</span><span style="color:#c2d94c;">`</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Register the Kor button into a custom wrapper element
</span><span> customElements</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">define</span><span>(</span><span style="color:#c2d94c;">'kor-button-wrap'</span><span style="color:#bfbab0cc;">, </span><span>KorButtonWrap)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Create the custom wrapper element for the button
</span><span> </span><span style="color:#ff7733;">let </span><span>korButtonWrap </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">document</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">createElement</span><span>(</span><span style="color:#c2d94c;">'kor-button-wrap'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Define text dynamically after the creation of the wrapped kor button
</span><span> korButtonWrap</span><span style="color:#f29668;">.</span><span>label </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'some text'
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Get div container for appending the element
</span><span> </span><span style="color:#ff7733;">let </span><span>container </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">document</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">getElementById</span><span>(</span><span style="color:#c2d94c;">'container'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Insert the wrapped kor button into a div container
</span><span> container</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">appendChild</span><span>(korButtonWrap)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"container"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span></code></pre>
<p>Online example:
<a href="https://jsfiddle.net/1vczbamp/">https://jsfiddle.net/1vczbamp/</a></p>
Ramda - Quick Tips #1
2022-01-04T00:00:00+00:00
2022-01-04T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/ramda-quick-tips-1/
<h3 id="remove-falsey-values-from-an-array">Remove Falsey Values from an Array</h3>
<p>Use <a href="https://ramdajs.com/docs/#without"><code>without</code></a> as a means to remove falsey values from your arrays. The first argument to the <code>without</code> method takes in an array which will represent the elements which are to be removed when found in the second argument array. You can include any values in the first argument array which you deem to be a "falsey" value.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">without</span><span>([</span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">null</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">''</span><span>]</span><span style="color:#bfbab0cc;">, </span><span>[</span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">null</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">''</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">null</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">4</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">5</span><span>])</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Outputs
</span><span style="font-style:italic;color:#5c6773;">// [1, 2, 3, 4, 5]
</span></code></pre>
<span id="continue-reading"></span><h3 id="pattern-matching-cond-compact-if-statements-matching">Pattern Matching (Cond) / Compact If Statements Matching</h3>
<p>From the official documentation <a href="https://ramdajs.com/docs/#cond">cond example</a> on the use of <code>cond</code>, this method can mimic the behavior of pattern matching by encapsulating multiple conditions into one function which you then pass in a value for comparison:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">const </span><span>fn </span><span style="color:#f29668;">= </span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">cond</span><span>([
</span><span> [R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">equals</span><span>(</span><span style="color:#f29718;">0</span><span>)</span><span style="color:#bfbab0cc;">, </span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">always</span><span>(</span><span style="color:#c2d94c;">'water freezes at 0°C'</span><span>)]</span><span style="color:#bfbab0cc;">,
</span><span> [R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">equals</span><span>(</span><span style="color:#f29718;">100</span><span>)</span><span style="color:#bfbab0cc;">, </span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">always</span><span>(</span><span style="color:#c2d94c;">'water boils at 100°C'</span><span>)]</span><span style="color:#bfbab0cc;">,
</span><span> [R</span><span style="color:#f29668;">.</span><span>T</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">temp </span><span style="color:#ff7733;">=> </span><span style="color:#c2d94c;">'nothing special happens at ' </span><span style="color:#f29668;">+ </span><span>temp </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">'°C'</span><span>]
</span><span>])</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">fn</span><span>(</span><span style="color:#f29718;">0</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="font-style:italic;color:#5c6773;">// Outputs: 'water freezes at 0°C'
</span><span>
</span><span style="color:#ffb454;">fn</span><span>(</span><span style="color:#f29718;">50</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="font-style:italic;color:#5c6773;">// Outputs: 'nothing special happens at 50°C'
</span><span>
</span><span style="color:#ffb454;">fn</span><span>(</span><span style="color:#f29718;">100</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="font-style:italic;color:#5c6773;">// Outputs: 'water boils at 100°C'
</span></code></pre>
SuperTest - Testing a Server
2021-12-26T00:00:00+00:00
2021-12-26T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/supertest-testing-a-server/
<h3 id="check-content-type">Check Content-Type</h3>
<p>Testing a simple static file server is made simple when using <a href="https://github.com/visionmedia/supertest">SuperTest</a>.
It permits for the testing of HTTP methods, content-type, response body and many <a href="https://visionmedia.github.io/superagent/">more options</a>.</p>
<p>Supposedly you wish to test a basic http server which serves the common zip, jpg, and html files. This server example uses only the native Nodejs modules: <code>http</code>, <code>fs</code>, and <code>path</code>:</p>
<span id="continue-reading"></span><pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="font-style:italic;color:#5c6773;">// server.js
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Adapted from https://stackoverflow.com/questions/16333790/node-js-quick-file-server-static-files-over-http/59088331#59088331
</span><span>
</span><span style="color:#ff7733;">import </span><span style="color:#f29718;">* </span><span style="color:#ff7733;">as </span><span>http </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'http'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ IncomingMessage</span><span style="color:#bfbab0cc;">, </span><span>ServerResponse } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'http'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span style="color:#f29718;">* </span><span style="color:#ff7733;">as </span><span>fs </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'fs'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span style="color:#f29718;">* </span><span style="color:#ff7733;">as </span><span>path </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'path'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">interface </span><span style="color:#59c2ff;">CreateServer </span><span>{
</span><span> fileName</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">string</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span>process</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">'uncaughtException'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">err </span><span style="color:#ff7733;">=> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">error</span><span>(</span><span style="color:#c2d94c;">'uncaughtException'</span><span style="color:#bfbab0cc;">, </span><span>err))</span><span style="color:#bfbab0cc;">;
</span><span>process</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">'unhandledRejection'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">err </span><span style="color:#ff7733;">=> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">error</span><span>(</span><span style="color:#c2d94c;">'unhandledRejection'</span><span style="color:#bfbab0cc;">, </span><span>err))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>mediaTypes</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">Record</span><span><</span><span style="font-style:italic;color:#39bae6;">string</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">string</span><span>> </span><span style="color:#f29668;">= </span><span>{
</span><span> zip</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'application/zip'</span><span style="color:#bfbab0cc;">,
</span><span> jpg</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'image/jpeg'</span><span style="color:#bfbab0cc;">,
</span><span> html</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'text/html'</span><span style="color:#bfbab0cc;">,
</span><span>}
</span><span>
</span><span style="color:#ff7733;">const </span><span style="color:#ffb454;">createServer </span><span style="color:#f29668;">= </span><span>({ </span><span style="color:#f29718;">fileName </span><span>}</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">CreateServer</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">const </span><span>server </span><span style="color:#f29668;">= </span><span>http</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">createServer</span><span>(</span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">_request</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">IncomingMessage</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">response</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">ServerResponse</span><span>) {
</span><span> fs</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">readFile</span><span>(fileName</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">err</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">NodeJS</span><span style="color:#f29668;">.</span><span style="color:#59c2ff;">ErrnoException </span><span style="color:#f29668;">| </span><span style="font-style:italic;color:#39bae6;">null</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">data</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">Buffer</span><span>) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(err) {
</span><span> response</span><span style="color:#f29668;">.</span><span>statusCode </span><span style="color:#f29668;">= </span><span style="color:#f29718;">404</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span>response</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">end</span><span>(</span><span style="color:#c2d94c;">'File not found or invalid request made.'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="color:#ff7733;">let </span><span>mediaType </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'text/html'</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">const </span><span>ext </span><span style="color:#f29668;">= </span><span>path</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">extname</span><span>(fileName)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">if </span><span>(ext</span><span style="color:#f29668;">.</span><span>length </span><span style="color:#f29668;">> </span><span style="color:#f29718;">0 </span><span style="color:#f29668;">&& </span><span>mediaTypes</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">hasOwnProperty</span><span>(ext</span><span style="color:#f29668;">.</span><span style="color:#f07178;">slice</span><span>(</span><span style="color:#f29718;">1</span><span>))) {
</span><span> mediaType </span><span style="color:#f29668;">= </span><span>mediaTypes[ext</span><span style="color:#f29668;">.</span><span style="color:#f07178;">slice</span><span>(</span><span style="color:#f29718;">1</span><span>)]</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> response</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setHeader</span><span>(</span><span style="color:#c2d94c;">'Content-Type'</span><span style="color:#bfbab0cc;">, </span><span>mediaType)</span><span style="color:#bfbab0cc;">;
</span><span> response</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">end</span><span>(data)</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">return </span><span>server</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#ff7733;">export </span><span>{
</span><span> createServer
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>We wish to verify that the index.html file can be served with this test:</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="font-style:italic;color:#5c6773;">// Test
</span><span>
</span><span style="color:#ff7733;">const </span><span>request </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'supertest'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">describe</span><span>(</span><span style="color:#c2d94c;">'/'</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function</span><span>() {
</span><span> </span><span style="color:#ffb454;">it</span><span>(</span><span style="color:#c2d94c;">'responds with html'</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function</span><span>(</span><span style="color:#f29718;">done</span><span>) {
</span><span> </span><span style="color:#ffb454;">request</span><span>(server)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#f07178;">get</span><span>(</span><span style="color:#c2d94c;">'/'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">expect</span><span>(</span><span style="color:#c2d94c;">'Content-Type'</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'text/html'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">expect</span><span>(</span><span style="color:#f29718;">200</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">end</span><span>(</span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">err</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">any</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">_res</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">any</span><span>) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(err) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Error in the serving of the static html file.'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">done</span><span>(err)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">done</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>This example uses mocha as the testing framework, where it checks for the presence of a html file on the root url, '/', to be successful with a 200 response when accessed.</p>
<p>SuperTest will also take care of assigning a random port for you when you pass in the server object, so you don't need to worry about assigning a port that is not available.</p>
Visual Studio Code Extensions - Quick Picks #5
2021-12-19T00:00:00+00:00
2021-12-19T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/visual-studio-code-extensions-quick-picks-5/
<h3 id="lorem-ipsum"><a href="https://marketplace.visualstudio.com/items?itemName=Tyriar.lorem-ipsum">Lorem Ipsum</a></h3>
<p>Use this plugin to fill out placeholder paragraphs. Helpful to see how content flows in html in a layout template or to check for text overflows.</p>
<span id="continue-reading"></span><img src="https://github.com/Tyriar/vscode-lorem-ipsum/raw/HEAD/images/usage-animation.gif" alt="lorem-ipsum">
<h3 id="vscode-pdf"><a href="https://marketplace.visualstudio.com/items?itemName=tomoki1207.pdf">vscode-pdf</a></h3>
<p>Quickly view pdf documents within Vscode without the help of an external pdf reader.</p>
<img src="https://user-images.githubusercontent.com/3643499/84454816-98fcd600-ac96-11ea-822c-3ae1e1599a13.gif" alt="vscode-pdf">
CBOR - JSON Encoding
2021-12-12T00:00:00+00:00
2021-12-12T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/cbor-json-encoding/
<h3 id="compact-binary-format-for-json-data-transfer">Compact Binary Format for JSON Data Transfer</h3>
<p>When you wish to use JSON for its convenience, but also want to send the JSON using a more compact representation to save data that needs to be transfer, you will need to use an information encoder for JSON. These encoders tend to represent the JSON data in binary format for transfer and there are many <a href="https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats">out there</a>.</p>
<span id="continue-reading"></span>
<p>While other encoders out there are general purpose, there are encoders which focus on encoding JSON, but we will pick CBOR as an example.</p>
<p>CBOR is a binary data serialization format which can process a JSON object by encoding for transferring and decoding for reading. Not only is the data representation smaller, the serializing and deserializing is also faster than the native JSON functions.</p>
<p>Here is how it can be used in the <a href="https://github.com/kriszyp/cbor-x">cbor-x</a> npm package:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ decode</span><span style="color:#bfbab0cc;">, </span><span>encode } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'cbor-x'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// On the client
</span><span style="color:#ff7733;">let </span><span>serializedAsBuffer </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">encode</span><span>(value)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Send serializedAsBuffer over to the server
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// On the server
</span><span style="color:#ff7733;">let </span><span>data </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">decode</span><span>(serializedAsBuffer)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Nodejs - Quick Picks #3
2021-12-05T00:00:00+00:00
2021-12-05T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-quick-picks-3/
<h3 id="get-port"><a href="https://www.npmjs.com/package/get-port">Get Port</a></h3>
<p>Getting an open TCP port is useful when you wish to run a server on a port without knowing which ports are currently available.</p>
<span id="continue-reading"></span><h3 id="look-path"><a href="https://www.npmjs.com/package/lookpath">Look Path</a></h3>
<p>Check if a terminal command exists and for the location of the executable file.</p>
Pdf Generation with Playwright
2021-11-28T00:00:00+00:00
2021-11-28T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/pdf-generation-with-playwright/
<h3 id="alternative-to-puppeteer-for-pdf-generation">Alternative to Puppeteer for PDF Generation</h3>
<p>While puppeteer is a popular option used for testing as well as pdf generation for webpages, playwright is also another option that can perform these tasks and <a href="https://www.infoq.com/news/2020/01/playwright-browser-automation/">more</a>.</p>
<span id="continue-reading"></span>
<p>To simplify the configuration of pdf generation with playwright, the <a href="https://github.com/raminjafary/sura">'@raminjafary/sura'</a> module will be used as an example to show how to generate a pdf from an url. This module will require you to use <a href="https://flaviocopes.com/es-modules/">ESM</a>.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ generateFile } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@raminjafary/sura'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>(</span><span style="color:#ff7733;">async </span><span>() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">await </span><span style="color:#ffb454;">generateFile</span><span>({
</span><span> type</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'pdf'</span><span style="color:#bfbab0cc;">,
</span><span> htmlPath</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'https://github.com/raminjafary/sura'</span><span style="color:#bfbab0cc;">,
</span><span> pageLoad</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> waitUntil</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'networkidle'</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> pdf</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> path</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'/path/to/file.pdf'</span><span style="color:#bfbab0cc;">,
</span><span> format</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'A4'</span><span style="color:#bfbab0cc;">,
</span><span> printBackground</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> })
</span><span>})()</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>This module will only generate html files from a server url, and it is also capable of generating screenshots from pages.</p>
<p>If you do have control over the html page contents, then it is helpful to add in the following css to the html elements for which you do not want to clip off between a page break as to avoid the 'cutting' of the element when the element can not fit completely on the bottom of the page.</p>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="color:#ffb454;">.my-element-which-should-not-break</span><span>{
</span><span> </span><span style="color:#39bae6;">break-inside</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">avoid</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
gitignore - Exclusions for Ignore
2021-11-21T00:00:00+00:00
2021-11-21T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/gitignore-exclusions-for-ignore/
<h3 id="avoid-ignoring-folders-that-has-files-within-them-to-ignore">Avoid Ignoring Folders that has Files Within them to Ignore</h3>
<p>Supposedly, there is a need to ignore generated content within a folder called "temp":</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span># .gitignore
</span><span>
</span><span>test/temp/*
</span></code></pre>
<span id="continue-reading"></span>
<p>You will want this behavior when you are creating a folder in your test suite where you want to have this folder when starting the test for storing the generated files, but do not want to keep the generated files around after the testing has completed.</p>
<p>However, this will totally ignore the folder from being tracked in git even though there is a ".gitkeep" file within "temp". The solution to this problem is to use an exclusion rule where you specify that the .gitkeep file should be kept around for tracking:</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span># .gitignore
</span><span>
</span><span>test/temp/*
</span><span>!test/temp/.gitkeep
</span></code></pre>
TypeScript - String Enum for Checking Value Type
2021-11-14T00:00:00+00:00
2021-11-14T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/typescript-string-enum-for-checking-value-type/
<h3 id="ramda-s-type-check">Ramda's Type Check</h3>
<p>Ramda's type checking returns a string, but in order for this to be useful, one needs to know if the returned value matches your intended assertion.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>({})</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "Object"
</span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#f29718;">1</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "Number"
</span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#f29718;">false</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "Boolean"
</span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#c2d94c;">'s'</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "String"
</span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#f29718;">null</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "Null"
</span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>([])</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "Array"
</span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#95e6cb;">/</span><span style="color:#f29718;">[A-z]</span><span style="color:#95e6cb;">/</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "RegExp"
</span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{})</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "Function"
</span><span>R</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#f29718;">undefined</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//=> "Undefined"
</span></code></pre>
<span id="continue-reading"></span>
<p>Although there is a <a href="https://ramdajs.com/docs/#is"><code>is</code></a> function in Ramda that replicates the behavior of the example, the following will describe how a string enum will be used to replicate the <code>is</code> function (do use Ramda's built-in <code>is</code> function as it is more succinct).</p>
<p>The goal is to wrap Ramda's type check in a comparison function to perform the assertion for us. Create a string enum which will be used inside the function to check against Ramda's string return from the type check.</p>
<pre data-lang="ts" style="background-color:#0f1419;color:#bfbab0;" class="language-ts "><code class="language-ts" data-lang="ts"><span style="font-style:italic;color:#5c6773;">// typeCheck.ts
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ type </span><span style="color:#ff7733;">as </span><span>checkType } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'ramda'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// String enum
</span><span style="color:#ff7733;">export enum </span><span style="color:#59c2ff;">stringTypes </span><span>{
</span><span> </span><span style="color:#c2d94c;">'Object'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'Number'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'Boolean'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'String'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'Null'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'Array'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'RegExp'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'Function'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'Undefined'
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// checkType is R.type which returns a string to explain the checked value type that will be compared against the enum string
</span><span style="color:#ff7733;">export function </span><span style="color:#ffb454;">typeCheck</span><span>(</span><span style="color:#f29718;">val</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">any</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">type</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">stringTypes</span><span>)</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">boolean </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">checkType</span><span>(val) </span><span style="color:#f29668;">=== </span><span>stringTypes[type]</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<p>Usage of the wrapped Ramda value type checking function.</p>
<pre data-lang="ts" style="background-color:#0f1419;color:#bfbab0;" class="language-ts "><code class="language-ts" data-lang="ts"><span style="color:#ff7733;">import </span><span>{ typeCheck</span><span style="color:#bfbab0cc;">, </span><span>stringTypes } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'./type-check'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#ffb454;">typeCheck</span><span>(folderName</span><span style="color:#bfbab0cc;">, </span><span>stringTypes</span><span style="color:#f29668;">.</span><span>Undefined)) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// do something here
</span><span>}
</span></code></pre>
Nodejs - Memory Intensive Promise Operations
2021-11-07T00:00:00+00:00
2021-11-07T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-memory-intensive-promise-operations/
<h3 id="backpressure-for-promises">Backpressure for Promises</h3>
<p>When dealing with promises, the processing of long-running tasks is the commonly encountered scenario. However, some long-running task might also be performing memory intensive operations. To deal with running multiple operations at once, it is important to place a limit on the number of promises allowed to run at the same time as to not exhaust the Nodejs JavaScript heap.</p>
<span id="continue-reading"></span>
<p>Most npm libraries out <a href="https://www.npmjs.com/search?q=promise%20limit">there</a> designed for limiting the promises executions, will offer an option to cap off the amount of running promises.</p>
<p>However, this might not be the most reliable means of making sure that memory intensive tasks do not overtax Node because it is not certain how much memory compounding promise tasks might consume. To overcome this type of limitation, it is helpful to look at what Nodejs streams has to offer in terms of processing larger data sets in memory. Streams possess the ability to limit the amount data consume by implementing <a href="https://nodejs.org/en/docs/guides/backpressuring-in-streams/">backpressure</a>.</p>
<p>Backpressure applies to Nodejs streams, but it would be helpful if this was made available to promises. The answer to this is made possible with the npm module, <a href="https://www.npmjs.com/package/streamie">streamie</a>.</p>
<p>This library provides the ability to iterate over an array of items that gets process in return promises. Streamie is also capable of automatically handling backpressure to alleviate the burden of having to do so manually.</p>
<p>The following example is taken from the streamie source repository showing the simple use case:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">const </span><span>{ source } </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'streamie'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>items </span><span style="color:#f29668;">= </span><span>[
</span><span> {location</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'San Diego'</span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> {location</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Los Angeles'</span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> {location</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Denver'</span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> {location</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'New York'</span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> {location</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'St. Louis'</span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> {location</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Zurich'</span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> {location</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Barcelona'</span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> {location</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Buenos Aires'</span><span>}
</span><span>]
</span><span>
</span><span style="color:#ffb454;">source</span><span>(items</span><span style="color:#bfbab0cc;">, </span><span>(</span><span style="color:#f29718;">item</span><span style="color:#bfbab0cc;">, </span><span>{ </span><span style="color:#f29718;">streamie </span><span>}) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Starting'</span><span style="color:#bfbab0cc;">, </span><span>item)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#f29668;">new </span><span style="color:#59c2ff;">Promise</span><span>((</span><span style="color:#f29718;">resolve</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#f07178;">setTimeout</span><span>(() </span><span style="color:#ff7733;">=> </span><span style="color:#ffb454;">resolve</span><span>()</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#f29668;">Math</span><span style="color:#f29668;">.</span><span style="color:#f07178;">random</span><span>() </span><span style="color:#f29668;">* </span><span style="color:#f29718;">1000</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#f07178;">then</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Done with'</span><span style="color:#bfbab0cc;">, </span><span>item)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">if </span><span>(item</span><span style="color:#f29668;">.</span><span>location </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">'Buenos Aires'</span><span>) streamie</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">complete</span><span>(</span><span style="color:#c2d94c;">'Final Value'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>})
</span><span style="color:#f29668;">.</span><span style="color:#f07178;">then</span><span>((</span><span style="color:#f29718;">value</span><span>) </span><span style="color:#ff7733;">=> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Streamie complete.'</span><span style="color:#bfbab0cc;">, </span><span>value))</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>It is possible to configure the concurrency limit in Streamie by passing in a configuration object as the third argument to the <code>source</code> function:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ffb454;">source</span><span>(items</span><span style="color:#bfbab0cc;">, </span><span>(</span><span style="color:#f29718;">item</span><span style="color:#bfbab0cc;">, </span><span>{ </span><span style="color:#f29718;">streamie </span><span>}) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// ...
</span><span>}</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#5c6773;">/* {concurrency: the_concurrency_limit } */</span><span>)
</span><span style="color:#f29668;">.</span><span style="color:#f07178;">then</span><span>((</span><span style="color:#f29718;">value</span><span>) </span><span style="color:#ff7733;">=> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Streamie complete.'</span><span style="color:#bfbab0cc;">, </span><span>value))</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Nodejs - Quick Picks #2
2021-10-31T00:00:00+00:00
2021-10-31T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-quick-pick-2/
<h3 id="cjstoesm"><a href="https://www.npmjs.com/package/cjstoesm">Cjstoesm</a></h3>
<p>Automate the process of converting over JavaScript files in the cjs format to the newer ESM format with the command line.</p>
<span id="continue-reading"></span><h3 id="pkg"><a href="https://www.npmjs.com/package/pkg">Pkg</a></h3>
<p>Create a self-contained executable bundle for your npm module such that the Nodejs runtime is not required in the environment to run your scripts.</p>
Visual Studio Code Extensions - Quick Picks #4
2021-10-24T00:00:00+00:00
2021-10-24T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/visual-studio-code-extensions-quick-picks-4/
<h3 id="gremlins-tracker-for-visual-studio-code"><a href="https://marketplace.visualstudio.com/items?itemName=nhoizey.gremlins">Gremlins Tracker for Visual Studio Code</a></h3>
<p>Invisible characters that are non-standard in certain file types may cause unexpected problems. This plugin will highlight these whitespace characters in your files.</p>
<span id="continue-reading"></span><img src="https://raw.githubusercontent.com/nhoizey/vscode-gremlins/master/images/screenshot.png" alt="gremlins">
<h3 id="hungry-delete"><a href="https://marketplace.visualstudio.com/items?itemName=jasonlhy.hungry-delete">Hungry Delete</a></h3>
<p>Blank lines can be composed of multiple spaces or tabs and on occasions where you might wish to delete these lines, it will result in a lot of backspacing. "Hungry Delete" provides a "ctrl + backspace" key combination to remove those blanks lines above the cursor with greater ease.</p>
<img src="https://raw.githubusercontent.com/Jasonlhy/VSCode-Hungry-Delete/master/images/before.gif" alt="hungry-delete">
Snowpack - Font URLs in CSS
2021-10-17T00:00:00+00:00
2021-10-17T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/snowpack-font-url-in-css/
<h3 id="problem-with-url-resolution">Problem with URL Resolution</h3>
<p>Up to Snowpack version 3.8.8, there is an issue with how Snowpack resolves path references inside CSS files. This often creates a problem when importing font files as mentioned on this <a href="https://github.com/snowpackjs/snowpack/discussions/1573">page</a>.</p>
<span id="continue-reading"></span>
<p>If you have installed a CSS bundle as a Npm module, you can work around this issue by defining a path which references the original location of the asset in the "node_modules" folder.</p>
<p>Using the installation of <a href="https://www.npmjs.com/package/latex.css">latex.css</a> as an example, the configuration for "snowpack.config.js" will be:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// snowpack.config.js
</span><span>
</span><span style="font-style:italic;color:#39bae6;">module</span><span style="color:#f29668;">.</span><span style="font-style:italic;color:#39bae6;">exports </span><span style="color:#f29668;">= </span><span>{
</span><span> mount</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">'node_modules/latex.css/fonts'</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'/fonts'
</span><span> }
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The font location is explicitly noted for Snowpack to resolve the font URL references in "latex.css".</p>
Nodejs - Executing Pandoc Command for LaTeX
2021-10-10T00:00:00+00:00
2021-10-10T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-executing-pandoc-command-for-latex/
<h3 id="ensuring-consistent-execution-path">Ensuring Consistent Execution Path</h3>
<p>In this example, a script might refer to a file, index.tex, which is referenced by Pandoc to convert a file located within a folder:</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>/contents
</span><span> index.tex
</span></code></pre>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ffb454;">spawn</span><span>(</span><span style="color:#c2d94c;">'pandoc'</span><span style="color:#bfbab0cc;">, </span><span>[
</span><span> </span><span style="color:#c2d94c;">'/the/full/path/to/contents/index.tex'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'-o'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'/the/full/path/to/output/index.html'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'-s'
</span><span>])</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<span id="continue-reading"></span>
<p>When you wish to have a more maintainable writing experience, one can break up the contents of the 'index.tex' into multiple .tex files and place them into a different folder.</p>
<p>The index.tex file will reference the 'chapter-01.tex' file inside the new 'chapters' folder:</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>/contents
</span><span> /chapters
</span><span> chapter-01.tex
</span><span> index.tex
</span></code></pre>
<pre data-lang="ltx" style="background-color:#0f1419;color:#bfbab0;" class="language-ltx "><code class="language-ltx" data-lang="ltx"><span style="font-style:italic;color:#5c6773;">% chapter-01.tex
</span><span>
</span><span style="color:#f07178;">\chapter</span><span>{</span><span style="color:#59c2ff;">Chapter 1</span><span>}
</span><span>
</span><span style="color:#f07178;">\section</span><span>{</span><span style="color:#59c2ff;">section</span><span>}
</span><span>Some section content.
</span></code></pre>
<pre data-lang="ltx" style="background-color:#0f1419;color:#bfbab0;" class="language-ltx "><code class="language-ltx" data-lang="ltx"><span style="font-style:italic;color:#5c6773;">% index.tex
</span><span>
</span><span style="color:#ff7733;">\documentclass</span><span>{</span><span style="font-style:italic;color:#39bae6;">article</span><span>}
</span><span>
</span><span style="color:#f07178;">\title</span><span>{Tex}
</span><span>
</span><span style="color:#ff7733;">\begin</span><span>{</span><span style="color:#f29718;">document</span><span>}
</span><span>
</span><span style="color:#ff7733;">\input</span><span>{chapters/chapter-01}
</span><span>
</span><span style="color:#ff7733;">\end</span><span>{</span><span style="color:#f29718;">document</span><span>}
</span></code></pre>
<p>However, when you refer to Pandoc inside a script to perform the execution, the reference path might not have been what you have expected. If you refer to the file, index.tex, from a directory outside from where the index.tex is located, Pandoc will not render the <code>\input</code> command (the command to include content from other files) properly.</p>
<p>There will be a need to change to location to where the index.tex file is situated for Pandoc to recognize the proper path for execution.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// Before executing the pandoc command, change into the index.tex directory.
</span><span>
</span><span>process</span><span style="color:#f29668;">.</span><span style="color:#f07178;">chdir</span><span>(</span><span style="color:#c2d94c;">'/the/full/path/to/content'</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Snowpack - Running Tests with @web/test-runner
2021-10-03T00:00:00+00:00
2021-10-03T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/snowpack-testing-web-test-runner/
<h3 id="set-up-web-test-runner">Set up @web/test-runner</h3>
<p>Snowpack recommends that <a href="https://www.snowpack.dev/guides/web-test-runner#nav-primary">@web/test-runner</a> be used as the test runner of choice. Using this setup will allow you to conveniently run tests that would run in the browser after the Snowpack dev server has started.</p>
<p>First, install the dependencies found in the "devDependencies" in package.json with</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> install @esm-bundle/chai @snowpack/web-test-runner-plugin @web/test-runner
</span></code></pre>
<span id="continue-reading"></span>
<p>In the package.json, add in the <code>"web-test-runner \"src/tests/*.test.js\" --node-resolve"</code> for the <code>test</code> key for calling upon the test runner.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"Project"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"version"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"1.0.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"description"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"main"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"index.js"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"author"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"license"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"ISC"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"dependencies"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"snowpack"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^3.8.8"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"scripts"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"start"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"snowpack dev"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"test"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"web-test-runner </span><span style="color:#95e6cb;">\"</span><span style="color:#c2d94c;">src/tests/*.test.js</span><span style="color:#95e6cb;">\"</span><span style="color:#c2d94c;"> --node-resolve"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"devDependencies"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"@esm-bundle/chai"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^4.3.4-fix.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"@snowpack/web-test-runner-plugin"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^0.2.2"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"@web/test-runner"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^0.13.18"
</span><span> }
</span><span>}
</span></code></pre>
<p>Create the 'web-test-runner.config.js' file, and reference the 'web-test-runner-plugin':</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// web-test-runner.config.js
</span><span>
</span><span>process</span><span style="color:#f29668;">.</span><span>env</span><span style="color:#f29668;">.</span><span>NODE_ENV </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'test'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#39bae6;">module</span><span style="color:#f29668;">.</span><span style="font-style:italic;color:#39bae6;">exports </span><span style="color:#f29668;">= </span><span>{
</span><span> plugins</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'@snowpack/web-test-runner-plugin'</span><span>)()]</span><span style="color:#bfbab0cc;">,
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Snowpack also requires a mount source and an output url in the snowpack.config.js for the tests to run properly.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// snowpack.config.js
</span><span>
</span><span style="font-style:italic;color:#39bae6;">module</span><span style="color:#f29668;">.</span><span style="font-style:italic;color:#39bae6;">exports </span><span style="color:#f29668;">= </span><span>{
</span><span> mount</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// 'the-source-folder-name': { url: 'the-serving-path-in-the-browser'}
</span><span> src</span><span style="color:#bfbab0cc;">: </span><span>{ url</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'/dist' </span><span>}
</span><span> }
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Create a simple test case in the "src/test" folder for testing:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// sample.test.js
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ expect } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@esm-bundle/chai'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">it</span><span>(</span><span style="color:#c2d94c;">'sum of 1 plus 1 equals 2'</span><span style="color:#bfbab0cc;">, </span><span>() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ffb454;">expect</span><span>(</span><span style="color:#f29718;">1 </span><span style="color:#f29668;">+ </span><span style="color:#f29718;">1</span><span>)</span><span style="color:#f29668;">.</span><span>to</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">equal</span><span>(</span><span style="color:#f29718;">2</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Finally, run the test command:</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> run test
</span></code></pre>
Rust - Serde - Iterating Over JSON keys
2021-09-26T00:00:00+00:00
2021-09-26T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rust-serde-iterating-over-json-keys/
<h3 id="retrieving-data-from-json">Retrieving data from JSON</h3>
<p>The usefulness of reading a JSON file with Serde is being able to iterate over the data, and as a continuation of the post in <a href="https://williamhuey.github.io/posts/rust-read-json-file/">serde - Read JSON File</a>, this article will focus on looping over data once a JSON file data has been read.</p>
<span id="continue-reading"></span>
<p>Update the JSON file to include a "people" key and each of the person object will be placed inside an array for the "people" key's value.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>[
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"people"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"Bob"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"gender"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"male"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"age"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">34
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"Alice"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"gender"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"female"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"age"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">32
</span><span> }
</span><span> ]
</span><span> }
</span><span>]
</span></code></pre>
<p>The following example assumes that not much is known about the structure of the JSON data, so values will be generic when appropriate.</p>
<p>In <code>main.rs</code>, import the <code>Value</code> from the serde_json package and the HashMap from <code>std::collections</code>. These imports will help define the shape of the JSON data:</p>
<pre data-lang="rust" style="background-color:#0f1419;color:#bfbab0;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#ff7733;">use </span><span>serde_json</span><span style="color:#f29668;">::</span><span>{Value}</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">use </span><span>std</span><span style="color:#f29668;">::</span><span>collections</span><span style="color:#f29668;">::</span><span>HashMap</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">use </span><span>std</span><span style="color:#f29668;">::</span><span>fs</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#f29668;">...
</span></code></pre>
<p>The <code>main</code> function will need to output a type of <code>Result<(), serde_json::Error></code> because the use of <code>serde_json::from_str(&json)?</code> requires that the return value within the function is of type <code>Result</code> or <code>Option</code>.</p>
<pre data-lang="rust" style="background-color:#0f1419;color:#bfbab0;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#ff7733;">use </span><span>serde_json</span><span style="color:#f29668;">::</span><span>Value</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">use </span><span>std</span><span style="color:#f29668;">::</span><span>collections</span><span style="color:#f29668;">::</span><span>HashMap</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">use </span><span>std</span><span style="color:#f29668;">::</span><span>fs</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">fn </span><span style="color:#ffb454;">main</span><span>() </span><span style="color:#bfbab0cc;">-> </span><span style="font-style:italic;color:#39bae6;">Result</span><span><(), serde_json</span><span style="color:#f29668;">::</span><span>Error> {
</span><span> </span><span style="color:#ff7733;">let</span><span> json </span><span style="color:#f29668;">= </span><span>fs</span><span style="color:#f29668;">::</span><span>read_to_string(</span><span style="color:#c2d94c;">"./persons.json"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">expect</span><span>(</span><span style="color:#c2d94c;">"Unable to read file"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">let</span><span> sub_values</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#39bae6;">Vec</span><span><HashMap<</span><span style="font-style:italic;color:#39bae6;">String</span><span>, Value>> </span><span style="color:#f29668;">= </span><span>serde_json</span><span style="color:#f29668;">::</span><span>from_str(</span><span style="color:#f29668;">&</span><span>json)</span><span style="color:#f29668;">?</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">Ok</span><span>(())
</span><span>}
</span></code></pre>
<p>The definition of the serde result JSON data will be a <code>Vec<HashMap<String, Value>></code> since the JSON needs iterating over an array, and this array contains an object with a key of "people".</p>
<pre data-lang="rust" style="background-color:#0f1419;color:#bfbab0;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#ff7733;">use </span><span>serde_json</span><span style="color:#f29668;">::</span><span>Value</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">use </span><span>std</span><span style="color:#f29668;">::</span><span>collections</span><span style="color:#f29668;">::</span><span>HashMap</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">use </span><span>std</span><span style="color:#f29668;">::</span><span>fs</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">fn </span><span style="color:#ffb454;">main</span><span>() </span><span style="color:#bfbab0cc;">-> </span><span style="font-style:italic;color:#39bae6;">Result</span><span><(), serde_json</span><span style="color:#f29668;">::</span><span>Error> {
</span><span> </span><span style="color:#ff7733;">let</span><span> json </span><span style="color:#f29668;">= </span><span>fs</span><span style="color:#f29668;">::</span><span>read_to_string(</span><span style="color:#c2d94c;">"./persons.json"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">expect</span><span>(</span><span style="color:#c2d94c;">"Unable to read file"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">let</span><span> sub_values</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#39bae6;">Vec</span><span><HashMap<</span><span style="font-style:italic;color:#39bae6;">String</span><span>, Value>> </span><span style="color:#f29668;">= </span><span>serde_json</span><span style="color:#f29668;">::</span><span>from_str(</span><span style="color:#f29668;">&</span><span>json)</span><span style="color:#f29668;">?</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Print out the first key value of the object.
</span><span> </span><span style="color:#ff7733;">for</span><span> item </span><span style="color:#f29668;">in</span><span> sub_values</span><span style="color:#f29668;">.</span><span style="color:#f07178;">iter</span><span>() {
</span><span> </span><span style="color:#f07178;">dbg!</span><span>(</span><span style="color:#f29668;">&</span><span>item[</span><span style="color:#c2d94c;">"people"</span><span>])</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Print: Get the keys from the object
</span><span> </span><span style="color:#f07178;">dbg!</span><span>(item</span><span style="color:#f29668;">.</span><span style="color:#f07178;">keys</span><span>())</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">Ok</span><span>(())
</span><span>}
</span></code></pre>
<p>The resultant output after running <code>cargo run</code>:</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">[src/main.rs:12] </span><span style="color:#f29668;">&</span><span style="color:#ffb454;">item[</span><span style="color:#c2d94c;">"people"</span><span style="color:#ffb454;">]</span><span> = Array([
</span><span> </span><span style="color:#ffb454;">Object</span><span>({
</span><span> </span><span style="color:#c2d94c;">"age"</span><span>: Number(
</span><span> 34</span><span style="color:#bfbab0cc;">,
</span><span> )</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"gender"</span><span>: String(
</span><span> </span><span style="color:#c2d94c;">"male"</span><span style="color:#bfbab0cc;">,
</span><span> )</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"name"</span><span>: String(
</span><span> </span><span style="color:#c2d94c;">"Bob"</span><span style="color:#bfbab0cc;">,
</span><span> )</span><span style="color:#bfbab0cc;">,
</span><span> })</span><span style="color:#ffb454;">,
</span><span> </span><span style="color:#ffb454;">Object</span><span>({
</span><span> </span><span style="color:#c2d94c;">"age"</span><span>: Number(
</span><span> 32</span><span style="color:#bfbab0cc;">,
</span><span> )</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"gender"</span><span>: String(
</span><span> </span><span style="color:#c2d94c;">"female"</span><span style="color:#bfbab0cc;">,
</span><span> )</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"name"</span><span>: String(
</span><span> </span><span style="color:#c2d94c;">"Alice"</span><span style="color:#bfbab0cc;">,
</span><span> )</span><span style="color:#bfbab0cc;">,
</span><span> })</span><span style="color:#ffb454;">,
</span><span style="color:#ffb454;">]</span><span>)
</span><span style="color:#ffb454;">[src/main.rs:15]</span><span> item.keys() </span><span style="color:#f29668;">= </span><span style="color:#f07178;">[
</span><span> </span><span style="color:#c2d94c;">"people"</span><span style="color:#ffb454;">,
</span><span style="color:#ffb454;">]
</span></code></pre>
Nodejs - Quick Picks #1
2021-09-19T00:00:00+00:00
2021-09-19T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-quick-picks-1/
<h3 id="sabik"><a href="https://www.npmjs.com/package/sabik">Sabik</a></h3>
<p>Analyze the quality of your codebase by calculating the following metrics:</p>
<ul>
<li>Cognitive Complexity</li>
<li>Halstead complexity measures</li>
<li>Line of Code (Logical, Physical)</li>
<li>Maintainability</li>
</ul>
<span id="continue-reading"></span>
<p>Install as a developer dependency</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> install</span><span style="color:#f29718;"> -D</span><span> sabik
</span></code></pre>
<p>Generate the report</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">sabik</span><span> ./path/to/source
</span></code></pre>
<h3 id="dependency-cruiser"><a href="https://www.npmjs.com/package/dependency-cruiser">Dependency Cruiser</a></h3>
<p>Get a visual sense of how your codebase is connected together by the relationships among files.</p>
<p>Install as a developer dependency</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> install</span><span style="color:#f29718;"> -D</span><span> dependency-cruiser
</span></code></pre>
<p>Generate the SVG diagram</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npx</span><span> depcruise</span><span style="color:#f29718;"> --include-only </span><span style="color:#c2d94c;">"^src"</span><span style="color:#f29718;"> --output-type</span><span> dot src </span><span style="color:#f29668;">| </span><span style="color:#ffb454;">dot</span><span style="color:#f29718;"> -T</span><span> svg </span><span style="color:#f29668;">></span><span> dependencygraph.svg
</span></code></pre>
Nodejs - Download Npm Module for Testing
2021-09-12T00:00:00+00:00
2021-09-12T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/download-npm-module-for-testing/
<h3 id="reliance-on-another-npm-module">Reliance on another NPM module</h3>
<p>A Npm module which is heavily dependent on another Npm module because the module being written wraps another module's methods, and it might entail having to download the other module during testing.</p>
<span id="continue-reading"></span>
<p>Also, you might have to do this when your node module's functionality creates new project instances with the downloaded module which you want to perform checks with test cases. You won't necessarily test the other module's methods directly, but you are testing your own module to see if the indirect calling of methods is wired up properly.</p>
<p>Recommendations when interacting with downloaded Npm modules during testing:</p>
<ol>
<li>
<p>Make it the first step in the testing process. However, any kind of units test which do not rely on the downloaded module should be run in parallel to the download Npm module step for speed. You will need to create a new Npm script command to execute the two operations in parallel.</p>
</li>
<li>
<p>Check for internet connectivity and provide warnings if connection is not found and skip the set of tests which depends on the download of the module.</p>
</li>
<li>
<p>Download the appropriate Npm module before running any tests which depends on that module.</p>
</li>
<li>
<p>Any kind of destructive tests performed on the download Npm module should be performed last.</p>
</li>
<li>
<p>Perform cleanup of folders and files which were generated through the test cases.</p>
</li>
</ol>
Rust - Quick Picks #1
2021-09-05T00:00:00+00:00
2021-09-05T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rust-quick-picks-1/
<h3 id="ripgrep-all"><a href="https://crates.io/crates/ripgrep_all">Ripgrep-all</a></h3>
<p>Using ripgrep-all will enable you to search more than just within source code files, it lets you search inside content such as "PDFs, E-Books, Office documents, zip, tar.gz, etc." due to it leveraging ripgrep. This versatility brings a search tool that is close to what you expect from an operating system index file search, except now you can have a more targeted searching experience.</p>
<span id="continue-reading"></span><h3 id="tectonic"><a href="https://crates.io/crates/tectonic">Tectonic</a></h3>
<p>Tectonic is a self-contained package for working with LaTeX files which manages to download the minimum of external resources to get started. It has a CLI which creates a LaTeX project, and it gives you a "watch" command to easily perform a recompile of LaTeX file upon change.</p>
Rust - fzf Alternative with Skim
2021-08-29T00:00:00+00:00
2021-08-29T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rust-fzf-alternative-skim/
<h3 id="open-file-with-real-time-fuzzy-search">Open File with Real-Time Fuzzy Search</h3>
<p>Using an interactive CLI search tool can be a big productivity booster when you are uncertain of which files contain the term you are trying to seek out. You will end up performing multiple searches at a time and may jump into multiple files in doing so. GUI tools will be able to perform such a task, but using Skim offers you the ability to perform this task much faster since it is a keyboard focus tool with instant feedback in mind.</p>
<span id="continue-reading"></span>
<p><a href="https://github.com/lotabout/skim">Skim</a> by itself is a not an extensive search tool, and you will need a dedicated search CLI tool such as grep or rg to search within files to assist Skim in what you need to find. Skim's API is very similar to <a href="https://github.com/junegunn/fzf">fzf</a> as Skim is heavily inspired by it. You might want to use Skim when you prefer to only use Rust applications, and this library has the added convenience of being able to be used as a library too.</p>
<p>In addition to getting Skim onto your system, you will also need the "preview.sh" from the <a href="https://github.com/junegunn/fzf.vim/blob/master/bin/preview.sh">fzf.vi</a> project because this will provide the functionality to get a glimpse into which line contains your search term on the right side of the terminal window.</p>
<p>This example will use the home directory to store the helper, "preview.sh" file, but you may go into a directory of your choice to store the "preview.sh" file.</p>
<p>Make it script executable</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">chmod</span><span> a+x
</span></code></pre>
<p>The first example shown will use skim as a one-time search event in interactive mode like so</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">sk</span><span style="color:#f29718;"> --ansi -i -c </span><span style="color:#c2d94c;">'rg -l <search-term>'
</span></code></pre>
<p>The previous example shows the use of rg with a fixed search term, but this lacks flexibility in interactive mode as you can not type in a new term to update your search.</p>
<p>Now, to overcome this issue and get a sense of the real-time power of Skim, rg can be adjusted using the example below.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">sk</span><span style="color:#f29718;"> --ansi -i -c </span><span style="color:#c2d94c;">'rg --color=always -l "{}"'
</span></code></pre>
<p>However, there is still something to be desired with using this command because
you do not know exactly what lines contain the term within the file when only the filenames are display. We have downloaded the "preview.sh" file from before, but now is the time to use it to get more information from our searches.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">sk</span><span style="color:#f29718;"> --ansi -i -c </span><span style="color:#c2d94c;">'rg --color=always -l "{}"'</span><span style="color:#f29718;"> --preview </span><span style="color:#c2d94c;">"~/preview.sh {}"
</span></code></pre>
<p>Scroll through the preview window using the shift + Up Arrow or shift + Down Arrow to navigate the preview window.</p>
<p>You also have the option to pass in the filename into another external program using a keybinding. This command will open up VsCode and close Skim when an item is selected.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">sk</span><span style="color:#f29718;"> --bind </span><span style="color:#c2d94c;">'f1:execute(code {}),ctrl-y)+abort'
</span></code></pre>
<p>Now to combine all basic features together for a real-time search and preview with hotkey binding to open a file with an external program</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">sk</span><span style="color:#f29718;"> --ansi -i -c </span><span style="color:#c2d94c;">'rg --color=always -l "{}"'</span><span style="color:#f29718;"> --preview </span><span style="color:#c2d94c;">"~/preview.sh {}"</span><span style="color:#f29718;"> --bind </span><span style="color:#c2d94c;">'f1:execute-silent(code {}),ctrl-y)+abort'
</span></code></pre>
<p>Typing all the above out is tedious, and it will simplify your life when you create a shell function to wrap the above command in your startup shell script.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">skc</span><span>() {
</span><span> </span><span style="color:#ffb454;">sk</span><span style="color:#f29718;"> --ansi -i -c </span><span style="color:#c2d94c;">'rg --color=always -l "{}"'</span><span style="color:#f29718;"> --preview </span><span style="color:#c2d94c;">"~/preview.sh {}"</span><span style="color:#f29718;"> --bind </span><span style="color:#c2d94c;">'f1:execute-silent(code {}),ctrl-y)+abort'
</span><span>}
</span></code></pre>
RxJS - Stop Observable During an Interval
2021-08-22T00:00:00+00:00
2021-08-22T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rxjs-stop-observable-on-interval/
<h3 id="replicate-pause-on-an-observable-trigger">Replicate Pause on an Observable Trigger</h3>
<p>A way to simulate a pause of an observable from triggering is to stop it and to restart it.</p>
<p>One might wish to pause an observable because the observable might have activated the run of an expensive or long-running operation such a mathematical computation or a network request and there is a need to have a temporary block on the triggering observable.</p>
<span id="continue-reading"></span>
<p>Breaking down the running of a desired observable into two parts for activation when dealing with a blocking observable event, replicates the pausing of the initial observable event. The triggering observable will have a "before" and "after" phase regarding the pausing event.</p>
<p>To illustrate this behavior, the example below will emulate a pause with the use of a timer. When the timer is active, the desired behavior of being able to press the letter 'a' key will not work.</p>
<p>To replicate a timer observable, a RxJs <code>timer</code> should be coupled with a RxJs <code>interval</code>. For the ease of demonstration, the timer will actually serve as a delay, so one can test out the press of the letter 'a' key before the pause kicks in. The <code>interval</code> will play the role of stepping through the seconds in the time period and after this interval count ends, the press of the letter 'a' is restored.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">const </span><span>{ fromEvent</span><span style="color:#bfbab0cc;">, </span><span>timer</span><span style="color:#bfbab0cc;">, </span><span>interval } </span><span style="color:#f29668;">= </span><span>rxjs</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">const </span><span>{ take</span><span style="color:#bfbab0cc;">, </span><span>filter</span><span style="color:#bfbab0cc;">, </span><span>concatMapTo</span><span style="color:#bfbab0cc;">, </span><span>takeLast</span><span style="color:#bfbab0cc;">, </span><span>takeUntil</span><span style="color:#bfbab0cc;">, </span><span>mergeMap } </span><span style="color:#f29668;">= </span><span>rxjs</span><span style="color:#f29668;">.</span><span>operators</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>keyboardDown$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">fromEvent</span><span>(document</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"keydown"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span style="color:#f29668;">!</span><span>event</span><span style="color:#f29668;">.</span><span>repeat)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>aDown$ </span><span style="color:#f29668;">= </span><span>keyboardDown$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"KeyA"</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>timer$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">timer</span><span>(</span><span style="color:#f29718;">3000</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>interval$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">interval</span><span>(</span><span style="color:#f29718;">1000</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">take</span><span>(</span><span style="color:#f29718;">3</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>timing$ </span><span style="color:#f29668;">= </span><span>timer$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">concatMapTo</span><span>(interval$))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>timerEnd$ </span><span style="color:#f29668;">= </span><span>timing$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">takeLast</span><span>(</span><span style="color:#f29718;">1</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Treat the timer's interval counting as an expensive operation.
</span><span style="font-style:italic;color:#5c6773;">// Pressing the 'a' key might trigger an heavy computation somewhere,
</span><span style="font-style:italic;color:#5c6773;">// and you would like to stop further presses of the 'a' key while
</span><span style="font-style:italic;color:#5c6773;">// the processing is still taking place.
</span><span>timing$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'A second has passed after the initial delay of 3 seconds.'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>timerEnd$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Timer ends.'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Allow only the letter 'a' to be press when the timer has not
</span><span style="font-style:italic;color:#5c6773;">// started counting and after the timer has completed.
</span><span style="color:#ff7733;">const </span><span>aDownAfterTimerEnds$ </span><span style="color:#f29668;">= </span><span>timerEnd$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">mergeMap</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>aDown$</span><span style="color:#bfbab0cc;">;
</span><span> }))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>aDownBeforeTimerStarts$ </span><span style="color:#f29668;">= </span><span>aDown$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">takeUntil</span><span>(timing$)
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>aDownBeforeTimerStarts$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"'A' key pressed before timer starts."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>aDownAfterTimerEnds$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Restored the letter 'A' key press"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Visual Studio Code Extensions - Quick Picks #3
2021-08-15T00:00:00+00:00
2021-08-15T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/visual-studio-code-extensions-quick-picks-3/
<h3 id="auto-close-tag"><a href="https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-close-tag">Auto Close Tag</a></h3>
<p>This plugin will automatically create an HTML closing tag when you start off a new tag. This will halve the typing work that you have to do when you are manually creating HTML tags by hand.</p>
<span id="continue-reading"></span><img src="https://raw.githubusercontent.com/formulahendry/vscode-auto-close-tag/0c784ff156da350cce8374a7f04759cab7e2aaff/images/usage.gif" alt="auto-close-tag">
<h3 id="vscode-dimmer-block"><a href="https://marketplace.visualstudio.com/items?itemName=imagio.vscode-dimmer-block">VSCode Dimmer Block</a></h3>
<p>Taking the idea of focus one step further than only highlighting the current active document group, this plugin will allow you to highlight a certain block
of code of text you are working on so other out of focus blocks of text are dimmed out.</p>
<img src="https://raw.githubusercontent.com/AndrewMorsillo/vscode-dimmer/master/images/context.gif" alt="vscode-dimmer-block">
<h3 id="indenticator"><a href="https://marketplace.visualstudio.com/items?itemName=SirTori.indenticator">Indenticator</a></h3>
<p>Displays a vertical line marker for the level of indent nesting active block of code for better visual focus.</p>
<p><img src="https://raw.githubusercontent.com/SirTori/indenticator/master/img/demo.gif
" alt="indenticator"></p>
RxJS - Buffer with a Pipe Chain
2021-08-08T00:00:00+00:00
2021-08-08T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rxjs-buffer-take/
<h3 id="get-one-event-from-the-group">Get One Event from the Group</h3>
<p>A buffer serves to aggregate multiples of the same observable event type.
However, the example shown for buffer in the official RxJS docs assumes that you have an originating source in the start of the chain which serves as the group of events for buffering as shown in <a href="https://rxjs.dev/api/operators/buffer">here</a>.</p>
<span id="continue-reading"></span>
<p>In the event where an observable event is happening multiple times later in the pipe chain and does not serve as the originating source, where you only want to get the first event, a need arises to selectively pick one out from the group of similar events.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">//...
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">mergeMap</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">getFolderCount</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Assume that tap chain runs more than once even
</span><span> </span><span style="font-style:italic;color:#5c6773;">// though the mergeMap operator function only runs once
</span><span> </span><span style="color:#ffb454;">tap</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>logCreationBegin)</span><span style="color:#bfbab0cc;">,
</span><span style="font-style:italic;color:#5c6773;">// ...
</span></code></pre>
<p>For your buffering situation, when you wish to get one of the events or the last event of the group, you will want to use either <a href="https://rxjs.dev/api/operators/take">take(1)</a> or <a href="https://rxjs.dev/api/operators/takeLast">takeLast(1)</a> respectively. Using <code>take(1)</code> simulates taking only the first of the group while <code>takeLast(1)</code> will get the last within the group of events.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">//...
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">mergeMap</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">getFolderCount</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">// With the introduction of take(1), the tap operator will only run once
</span><span> </span><span style="color:#ffb454;">take</span><span>(</span><span style="color:#f29718;">1</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">tap</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>logCreationBegin)</span><span style="color:#bfbab0cc;">,
</span><span style="font-style:italic;color:#5c6773;">// ...
</span></code></pre>
<p>Another option available will be to use <code>first</code>, but using <code>first</code> entails that the source before the first operator must emit an event, or there will be an error.</p>
<p>Note that, <code>take</code> does not have a <a href="https://github.com/ReactiveX/rxjs/search?q=takefirst&type=code">takeFirst</a> analogue operator.</p>
<p>The last option is to use <a href="https://rxjs.dev/api/operators/single"><code>single</code></a>. You use <code>single</code> to be more strict in the amount of events that are fired. The use of <code>single</code> only anticipates one event that fires and will error out when there are zero or more than one event that occur. So <code>single</code> behaves like a stringent first.</p>
<p>The difference between take, <code>first</code> and <code>single</code> is explained graphically by this <a href="https://thinkrx.io/rxjs/first-vs-take-vs-single/">example</a>.</p>
Rustup - Serde - Read JSON File
2021-08-01T00:00:00+00:00
2021-08-01T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rust-read-json-file/
<p>This is an example on using the <code>serde_json</code> <a href="https://docs.serde.rs/serde_json/">library</a> to read JSON data stored in a file. Serde doesn't have a method to directly read from your file directory and get the data from the JSON file, so it will be a two-step process.</p>
<span id="continue-reading"></span>
<p>Create a new Rust project with</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">cargo</span><span> new json-read
</span></code></pre>
<p>Add in the <code>serde_json</code> crate in Cargo.toml:</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span># ...
</span><span>
</span><span>[dependencies]
</span><span>serde_json = "1.0.66"
</span></code></pre>
<p>Then install the dependencies:</p>
<pre data-lang="rust" style="background-color:#0f1419;color:#bfbab0;" class="language-rust "><code class="language-rust" data-lang="rust"><span>cargo build
</span></code></pre>
<p>Create a JSON file that in the root of the project.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>[
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"Bob"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"gender"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"male"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"age"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">34
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"Alice"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"gender"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"female"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"age"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">32
</span><span> }
</span><span>]
</span></code></pre>
<p>Read the file with Rust's fs module and then pass in the information
to serde to read the JSON.</p>
<pre data-lang="rust" style="background-color:#0f1419;color:#bfbab0;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#ff7733;">use </span><span>std</span><span style="color:#f29668;">::</span><span>fs</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">fn </span><span style="color:#ffb454;">main</span><span>() {
</span><span> </span><span style="color:#ff7733;">let</span><span> data </span><span style="color:#f29668;">= </span><span>fs</span><span style="color:#f29668;">::</span><span>read_to_string(</span><span style="color:#c2d94c;">"./persons.json"</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#f07178;">expect</span><span>(</span><span style="color:#c2d94c;">"Unable to read file"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">let</span><span> json</span><span style="color:#bfbab0cc;">: </span><span>serde_json</span><span style="color:#f29668;">::</span><span>Value </span><span style="color:#f29668;">= </span><span>serde_json</span><span style="color:#f29668;">::</span><span>from_str(</span><span style="color:#f29668;">&</span><span>data)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#f07178;">expect</span><span>(</span><span style="color:#c2d94c;">"JSON does not have correct format."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#f07178;">dbg!</span><span>(json)</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<p>Execute the program:</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">cargo</span><span> r
</span></code></pre>
Rustup Toolchain
2021-07-25T00:00:00+00:00
2021-07-25T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rustup-toolchain/
<h3 id="configure-rust-environments">Configure Rust Environments</h3>
<p>The official rustup toolchain allows you to manage different versions of Rust along with their configurations. Different Rust applications or projects might force you to use a specific version of Rust.</p>
<span id="continue-reading"></span>
<p>Install the Rust toolchain/version manager rustup through your system's application install software or follow these <a href="https://rust-lang.github.io/rustup/installation/other.html">alternative means</a> of installing rustup.</p>
<p>Get a specific version of rust</p>
<pre data-lang="rust" style="background-color:#0f1419;color:#bfbab0;" class="language-rust "><code class="language-rust" data-lang="rust"><span>rustup toolchain install </span><span style="color:#f29718;">1.53</span><span style="color:#f29668;">.</span><span style="color:#f29718;">0
</span></code></pre>
<p>Get the current rust toolchain</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>rustup show
</span></code></pre>
<p>If the version does not show the latest version, switch to the toolchain version.</p>
<p>Switch to a toolchain</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>rustup default 1.53.0-x86_64-unknown-linux-gnu
</span></code></pre>
<p>To make the current toolchain as the stable</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>rustup override set stable
</span></code></pre>
<p>A toml configuration will be used to lock to a <a href="https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file">specific version</a> install of tools</p>
<p>Further information for rustup can be found here:
<a href="https://rust-lang.github.io/rustup/index.html">https://rust-lang.github.io/rustup/index.html</a></p>
Visual Studio Code Extensions - Quick Picks #2
2021-07-18T00:00:00+00:00
2021-07-18T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/visual-studio-code-extensions-quick-picks-2/
<h3 id="activitus-bar"><a href="https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.activitusbar">Activitus Bar</a></h3>
<p>Reduce the amount of screen real estate space that that default toolbar icons take up on the left side of the window. With this plugin, the icons are shrunken and placed in the lower left corner of the window to get out of your way.</p>
<span id="continue-reading"></span><img src="https://gruntfuggly.gallerycdn.vsassets.io/extensions/gruntfuggly/activitusbar/0.0.46/1622195974710/Microsoft.VisualStudio.Services.Icons.Default" alt="activitus-bar">
<h3 id="live-server"><a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer">Live Server</a></h3>
<p>Click a button on the bottom toolbar to quickly spin up a localhost server for hosting your local web assets which avoid the need to go into the terminal to run any commands for viewing your website content.</p>
<img src="https://raw.githubusercontent.com/ritwickdey/vscode-live-server/master/images/Screenshot/vscode-live-server-statusbar-3.jpg" alt="live-server-start">
<h3 id="numbered-bookmarks"><a href="https://marketplace.visualstudio.com/items?itemName=alefragnani.numbered-bookmarks">Numbered Bookmarks</a></h3>
<p>Bookmarks allow you to quickly jump to certain lines within the file you are editing. It is useful if making changes in multiple areas of your file where comparison might be needed. This plugin is a step up from <a href="https://marketplace.visualstudio.com/items?itemName=alefragnani.Bookmarks">Bookmarks</a> because you can use Numbered Bookmarks to assign numbers to bookmarks for jumping to with sensible shortcut command while also providing more cues on location when jumping among bookmarks.</p>
<img src="https://raw.githubusercontent.com/alefragnani/vscode-numbered-bookmarks/master/images/numbered-bookmarks-toggle.png" alt="numbered-bookmarks">
D3FC - X-Axis Adjustments
2021-07-11T00:00:00+00:00
2021-07-11T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/d3fc-axis-adjustments/
<h3 id="label-modifications">Label Modifications</h3>
<p>D3FC provides a nice layer of convenient customization over D3 when working with basic construction of graphs such as when tweaking axis labels. The following examples will be a modification of the <a href="https://github.com/d3fc/d3fc/blob/master/docs/building-a-chart.md">base example</a>.</p>
<span id="continue-reading"></span><h4 id="offset-x-axis-label-text">Offset X-axis Label Text</h4>
<p>By default, text lies directly underneath a tick mark, but there is an option
in D3FC to allow you to move the text slightly over to the right.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span>
</span><span style="font-style:italic;color:#5c6773;">// ...
</span><span>
</span><span style="color:#ff7733;">const </span><span>scaleLinear </span><span style="color:#f29668;">= </span><span>d3</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">scaleLinear</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">const </span><span>scaleBand </span><span style="color:#f29668;">= </span><span>d3</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">scaleBand</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>fc</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">chartCartesian</span><span>(
</span><span> {
</span><span> xScale</span><span style="color:#bfbab0cc;">: </span><span>scaleBand</span><span style="color:#bfbab0cc;">,
</span><span> yScale</span><span style="color:#bfbab0cc;">: </span><span>scaleLinear</span><span style="color:#bfbab0cc;">,
</span><span> xAxis</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#ffb454;">bottom</span><span style="color:#bfbab0cc;">: </span><span>(</span><span style="color:#f29718;">scale</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>fc</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">axisBottom</span><span>(scale)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">tickCenterLabel</span><span>(</span><span style="color:#f29718;">false</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }
</span><span> }
</span><span>)
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// ...
</span></code></pre>
<p><a href="https://jsfiddle.net/b7wkpf98/">Offset X-axis Label Text Example</a></p>
<p>The following shows a customization of tilting the label to 45 degrees using the <code>xDecorate</code> function:</p>
<h4 id="angle-label-text">Angle Label Text</h4>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span>
</span><span style="font-style:italic;color:#5c6773;">//...
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Chart primary options configuration
</span><span style="color:#ff7733;">const </span><span>chart </span><span style="color:#f29668;">= </span><span>fc</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">chartCartesian</span><span>(
</span><span> {
</span><span> xScale</span><span style="color:#bfbab0cc;">: </span><span>scaleBand</span><span style="color:#bfbab0cc;">,
</span><span> yScale</span><span style="color:#bfbab0cc;">: </span><span>scaleLinear</span><span style="color:#bfbab0cc;">,
</span><span> }
</span><span>)
</span><span>
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">chartLabel</span><span>(</span><span style="color:#c2d94c;">'2015 Cumulative Sales'</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// x extent is categorical data so no extent required
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">xDomain</span><span>(data</span><span style="color:#f29668;">.</span><span>sales</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">map</span><span>(</span><span style="color:#f29718;">d </span><span style="color:#ff7733;">=> </span><span>d</span><span style="color:#f29668;">.</span><span>month))
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// y extent used for number ranges
</span><span> </span><span style="font-style:italic;color:#5c6773;">// used to return the minimum and maximum value in an array from the given array using natural order.
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">yDomain</span><span>(</span><span style="color:#ffb454;">yExtent</span><span>(data</span><span style="color:#f29668;">.</span><span>sales))
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// padding is the white space between the bars
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">xPadding</span><span>(</span><span style="color:#f29718;">0.1</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">xDecorate</span><span>(</span><span style="color:#f29718;">selection </span><span style="color:#ff7733;">=> </span><span>{
</span><span> selection
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#f07178;">select</span><span>(</span><span style="color:#c2d94c;">'text'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">attr</span><span>(</span><span style="color:#c2d94c;">'transform'</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'rotate(-45 25 15)'</span><span>)
</span><span> })
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// ...
</span></code></pre>
<p><a href="https://jsfiddle.net/yd50afvj/">Angle Label Text Example</a></p>
<p>If there is a one-off change of tilting the x-axis labels without the need to
perform further customization, there is a built-in faculty in D3FC for
achieving this behavior:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="color:#ff7733;">const </span><span>axis </span><span style="color:#f29668;">= </span><span>fc</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">axisLabelRotate</span><span>(fc</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">axisOrdinalBottom</span><span>(scale))</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>However, if multiple types of transformation are required on the x-axis, one will need
to use the <code>xDecorate</code> function to perform more manual tuning of axis and label options, but you will lose out on the ability to using the convenience "axis" methods.</p>
<p>Below is an example of using multiple x-axis transformation:</p>
<h4 id="change-x-axis-text-color-based-on-corresponding-bar-value">Change X-axis Text Color Based on Corresponding Bar Value</h4>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// ...
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Track the labels which are to have its color changed
</span><span style="font-style:italic;color:#5c6773;">// when the bar chart colors are also changed
</span><span style="color:#ff7733;">const </span><span>monthsSalesStatus </span><span style="color:#f29668;">= </span><span>{}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>bar</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">decorate</span><span>(</span><span style="color:#f29718;">selection </span><span style="color:#ff7733;">=> </span><span>{
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// The selection passed to decorate is the one which the component creates
</span><span> </span><span style="font-style:italic;color:#5c6773;">// within its internal data join, here we use the update selection to
</span><span> </span><span style="font-style:italic;color:#5c6773;">// apply a style to 'path' elements created by the bar series
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Change to green
</span><span> selection</span><span style="color:#f29668;">.</span><span style="color:#f07178;">select</span><span>(</span><span style="color:#c2d94c;">'.bar > path'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">style</span><span>(</span><span style="color:#c2d94c;">'fill'</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">d </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">if </span><span>(d</span><span style="color:#f29668;">.</span><span>sales </span><span style="color:#f29668;">< </span><span>data</span><span style="color:#f29668;">.</span><span>targets[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#f29668;">.</span><span>value) {
</span><span> monthsSalesStatus[d</span><span style="color:#f29668;">.</span><span>month] </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"low"
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#c2d94c;">'inherit'</span><span style="color:#bfbab0cc;">;
</span><span> } </span><span style="color:#ff7733;">else </span><span>{
</span><span> monthsSalesStatus[d</span><span style="color:#f29668;">.</span><span>month] </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"high"
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#c2d94c;">'#0c0'</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// ...
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Chart primary options configuration
</span><span style="color:#ff7733;">const </span><span>chart </span><span style="color:#f29668;">= </span><span>fc</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">chartCartesian</span><span>(
</span><span> {
</span><span> xScale</span><span style="color:#bfbab0cc;">: </span><span>scaleBand</span><span style="color:#bfbab0cc;">,
</span><span> yScale</span><span style="color:#bfbab0cc;">: </span><span>scaleLinear</span><span style="color:#bfbab0cc;">,
</span><span> }
</span><span>)
</span><span>
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">chartLabel</span><span>(</span><span style="color:#c2d94c;">'2015 Cumulative Sales'</span><span>)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// x extent is categorical data so no extent required
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">xDomain</span><span>(data</span><span style="color:#f29668;">.</span><span>sales</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">map</span><span>(</span><span style="color:#f29718;">d </span><span style="color:#ff7733;">=> </span><span>d</span><span style="color:#f29668;">.</span><span>month))
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// y extent used for number ranges
</span><span> </span><span style="font-style:italic;color:#5c6773;">// used to returns the minimum and maximum value in an array from the given array using natural order.
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">yDomain</span><span>(</span><span style="color:#ffb454;">yExtent</span><span>(data</span><span style="color:#f29668;">.</span><span>sales))
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// padding is the white space between the bars
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">xPadding</span><span>(</span><span style="color:#f29718;">0.1</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">xDecorate</span><span>((</span><span style="color:#f29718;">selection</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> selection
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#f07178;">select</span><span>(</span><span style="color:#c2d94c;">'text'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">attr</span><span>(</span><span style="color:#c2d94c;">'transform'</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'rotate(-45 25 15)'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">style</span><span>(</span><span style="color:#c2d94c;">'fill'</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">d </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">if </span><span>(monthsSalesStatus[d] </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">"low"</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#c2d94c;">'#000'
</span><span> } </span><span style="color:#ff7733;">else </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#c2d94c;">'#0c0'
</span><span> }
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// ...
</span></code></pre>
<p>Within the <code>bar.decorate</code> method, tracking of the months with higher is done to allow the <code>xDecorate</code> method below to read the values from <code>monthsSalesStatus</code> to make the appropriate color changes to the x-axis labels.</p>
<p><a href="https://jsfiddle.net/hwy5dtmv/1/">Change X-axis Text Color Based on Corresponding Bar Value Example</a></p>
Python - Quick Picks #1
2021-07-04T00:00:00+00:00
2021-07-04T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/python-quick-picks-1/
<h3 id="seleniumbase"><a href="https://github.com/seleniumbase/SeleniumBase/">SeleniumBase</a></h3>
<p>To avoid the verbosity of Selenium while still being able to leverage Selenium,
one can use SeleniumBase. SeleniumBase provides sensible defaults for testing
when you wish to use Selenium. The common testing setup recommended by Selenium called the <a href="https://www.selenium.dev/documentation/en/guidelines_and_recommendations/page_object_models/">POM</a> is supported.
This is shown by the example: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/boilerplates/base_test_case.py">https://github.com/seleniumbase/SeleniumBase/blob/master/examples/boilerplates/base_test_case.py</a>.</p>
<span id="continue-reading"></span>
<p>It also has extras functionalities that is conducive to supporting web applications:</p>
<ul>
<li>Presenter</li>
<li>Website Tour Builder</li>
<li>Console Scripts</li>
</ul>
<p>and <a href="https://seleniumbase.io/help_docs/features_list/">more</a>.</p>
<h3 id="rxpy"><a href="https://github.com/ReactiveX/RxPY">RxPY</a></h3>
<p>If you are familiar with reactive programming and enjoy the use of observables through <a href="https://github.com/ReactiveX/RxJS">RxJs</a>, one can take comfort in knowing
that there is also an equivalent in the Python community called <a href="https://github.com/ReactiveX/RxPY">RxPY</a>.</p>
Vite - Local Plugin
2021-06-27T00:00:00+00:00
2021-06-27T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/vite-local-plugin-file-type-change/
<h3 id="custom-file-type-change-detection">Custom File Type Change Detection</h3>
<p>Vite has a plugin system where a transform may be performed on file type changes in the following:</p>
<p><a href="https://vitejs.dev/guide/api-plugin.html#transforming-custom-file-types">https://vitejs.dev/guide/api-plugin.html#transforming-custom-file-types</a></p>
<p>Even though the documentation states that transforms might be performed on "custom file types", attempts to listen to changes for file types other than the common web assets type (.js, .ts, .html, .css) will not work.</p>
<span id="continue-reading"></span>
<p>One must use the <a href="https://vitejs.dev/guide/api-plugin.html#handlehotupdate">handleHotUpdate</a> method to listen to "custom file types".
There will be two files which configuration will need to be applied:
<code>vite.config.js</code> and a new plugin definition file for detecting changes.</p>
<p>For this example, in <code>vite.config.js</code>, a local plugin, 'custom-file-type.js, will be imported and inserted into an array and then called.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// vite.config.js
</span><span style="color:#ff7733;">import </span><span>{ defineConfig } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"vite"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">import </span><span>myPlugin </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"./custom-file-type"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">export default </span><span style="color:#ffb454;">defineConfig</span><span>({
</span><span> plugins</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#ffb454;">myPlugin</span><span>()]
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Now the plugin 'custom-file-type.js' has a key of
'handleHotUpdate' method defined to listen to custom file types.
The 'File' is destructured in the method's argument, and this value yields the filename with extension which can be read to discern which file type changed.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Plugin - custom-file-type.js - Listen to external file types
</span><span style="color:#ff7733;">export default function </span><span style="color:#ffb454;">myPlugin</span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>{
</span><span> name</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'custom-file-type'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">handleHotUpdate</span><span>({ </span><span style="color:#f29718;">file </span><span>}) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(file</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">endsWith</span><span>(</span><span style="color:#c2d94c;">".someextension"</span><span>)) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Custom extension type change."</span><span>)
</span><span> }
</span><span> }
</span><span> }
</span><span>}
</span></code></pre>
Image Panning
2021-06-20T00:00:00+00:00
2021-06-20T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/image-panning/
<h3 id="scrollbar-considerations">Scrollbar Considerations</h3>
<p>Many zooming libraries on npm offers the ability to pan images (translate images), after a large image has been zoomed in, however the majority of them do not take consideration of how the movement of the image affects the visibility of scrollbars.</p>
<span id="continue-reading"></span>
<p>Many of the panning libraries are expecting usage where the sole concentration is on the elements being panned without regards to its parent container scrollbars.</p>
<p>It is sometimes desirable to show scrollbars while panning comes up in image viewer or PDF viewer. The content in a "pannable" area permits movement of the image or page while preserving the scroll bars such as a pdf viewer. Viewers may also limit the range of panning movement.</p>
<p>One noteworthy library that addresses the scrollbar problem is <a href="https://github.com/d3/d3">D3</a>. Chart interactivity usually implies zooming and panning and D3 does provide this functionality without the need to use extra packages.</p>
<p>Here is an example of this in play</p>
<p><a href="https://jsfiddle.net/4rhvkc28/">https://jsfiddle.net/4rhvkc28/</a></p>
<p>adapted from this example</p>
<p><a href="https://stackblitz.com/edit/d3-pan-and-zoom?file=index.js">https://stackblitz.com/edit/d3-pan-and-zoom?file=index.js</a></p>
<p>to be usable in D3 v7.</p>
<p>While using a graphing library to implement panning behavior can be excessive, it is useful to know that this can be done if you have the ability to use D3 and that
interactive user event customizations are made available and updated with
D3 library updates.</p>
Give Screenshots More Space
2021-06-13T00:00:00+00:00
2021-06-13T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/css-give-screenshots-more-space/
<h3 id="screenshot-to-gutters">Screenshot To Gutters</h3>
<p>While taking an image screenshot of an entire software application such as the browser or terminal intact yields the most information when attempting to describe the behavior. It can be a bit difficult to discern what is actually happening in the application due to the "zoomed out" nature of the taken image.
It is rare that a user will need to focus on the entirety of the image when a
screenshot is shown, because only a certain portion of image is reference at
one time.</p>
<span id="continue-reading"></span>
<p>This is especially true and more pronounced problem for images taken of the terminal where the font size
is not that large to begin with, and the problem is due in part to people having
larger monitors with high resolutions.</p>
<p>The example show here occurs with the Postman Api tool shows what could happen when you are viewing their documentation site when you are on a midsize screen of 1575px:</p>
<img src="/images/posts/documenting-your-api-postman-learning-center-midsize.png" alt="documenting api postman learning center midsize">
<p>Here the above site shown on with a screen of 800px in width:</p>
<img src="/images/posts/documenting-your-api-postman-learning-center.png" alt="documenting api postman learning center">
<p>Even on the moderately size screen, the image is not ideal as text in the image is not legible. Also, on the second example, while most people aren't using their mobile phones to view the documentation while developing Apis, they might still do in a pinch to reference something useful.</p>
<p>A quick fix for this problem is to use the right gutter as excess space for the display of the screenshot. I found an example of this
using <a href="https://codepen.io/tylersticka/pen/PmRRqb">CSS grid</a> from this <a href="https://cloudfour.com/thinks/breaking-out-with-css-grid-layout/">article</a>.</p>
<p>Borrowing ideas from the article link above, here is a pare-down example of how an image can take up more space on the right when the screen size allows for it:</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span style="color:#f29718;">html</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">html </span><span style="color:#ffb454;">lang</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"en" </span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">meta </span><span style="color:#ffb454;">charset</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> Image spans outside central column. Image flows to the right gutter.
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"./style.css"</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">class</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"content"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">></span><span>Just some words.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">figure</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">img </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"./even-more-amazing.svg" </span><span style="color:#ffb454;">alt</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"smiley"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">figure</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">></span><span>Some more words.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span></code></pre>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="color:#59c2ff;">* </span><span>{
</span><span> </span><span style="color:#39bae6;">margin</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#59c2ff;">body </span><span>{
</span><span> </span><span style="color:#39bae6;">background</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">yellowgreen</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">color</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">#000</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">margin</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#ff7733;">rem </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#59c2ff;">p </span><span>{
</span><span> </span><span style="color:#39bae6;">font-size</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">4</span><span style="color:#ff7733;">rem</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">padding</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#ff7733;">rem</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#59c2ff;">figure </span><span>{
</span><span> </span><span style="color:#39bae6;">background</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">orangered</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#59c2ff;">img </span><span>{
</span><span> </span><span style="color:#39bae6;">max-width</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">100</span><span style="color:#ff7733;">%</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#ffb454;">.content </span><span>{
</span><span> </span><span style="color:#39bae6;">display</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">grid</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">grid-template-columns</span><span style="color:#bfbab0cc;">:
</span><span> [</span><span style="color:#c2d94c;">full-start</span><span>] </span><span style="color:#f07178;">minmax</span><span>(</span><span style="color:#f29718;">1</span><span style="color:#ff7733;">em</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">1</span><span style="color:#ff7733;">fr</span><span>)
</span><span> [</span><span style="color:#c2d94c;">main-start</span><span>] </span><span style="color:#f07178;">minmax</span><span>(</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">40</span><span style="color:#ff7733;">em</span><span>)
</span><span> [</span><span style="color:#c2d94c;">main-end</span><span>] </span><span style="color:#f07178;">minmax</span><span>(</span><span style="color:#f29718;">1</span><span style="color:#ff7733;">em</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">1</span><span style="color:#ff7733;">fr</span><span>)
</span><span> [</span><span style="color:#c2d94c;">full-end</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#ffb454;">.content </span><span style="color:#bfbab0cc;">> </span><span style="color:#59c2ff;">* </span><span>{
</span><span> </span><span style="color:#39bae6;">grid-column</span><span style="color:#bfbab0cc;">: </span><span>main</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#ffb454;">.content </span><span style="color:#bfbab0cc;">> </span><span style="color:#59c2ff;">figure </span><span>{
</span><span> </span><span style="color:#39bae6;">grid-column</span><span style="color:#bfbab0cc;">: </span><span>full</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">padding</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#ff7733;">rem
</span><span>}
</span><span>
</span><span style="color:#ffb454;">.content </span><span style="color:#bfbab0cc;">> </span><span style="color:#59c2ff;">figure img </span><span>{
</span><span> </span><span style="color:#39bae6;">display</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">block</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">width</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">100</span><span style="color:#ff7733;">%</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#ff7733;">@media </span><span>(</span><span style="color:#39bae6;">min-width</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">60</span><span style="color:#ff7733;">em</span><span>) {
</span><span> </span><span style="color:#ffb454;">.content </span><span style="color:#bfbab0cc;">> </span><span style="color:#59c2ff;">figure </span><span>{
</span><span> </span><span style="color:#39bae6;">align-items</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">end</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">display</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">inherit</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">grid-template-columns</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">inherit</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="color:#ffb454;">.content </span><span style="color:#bfbab0cc;">> </span><span style="color:#59c2ff;">figure </span><span style="color:#bfbab0cc;">> </span><span style="color:#59c2ff;">img </span><span>{
</span><span> </span><span style="color:#39bae6;">grid-column</span><span style="color:#bfbab0cc;">: </span><span>main / full</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}
</span></code></pre>
<p>The general idea of the CSS is to divide the page to three vertical columns area
and the image spans the middle (main) and the right of main when the screen size is mid to large (60em or greater) and then the image
takes the whole width of the screen on sizes less than 60em:</p>
<img src="/images/posts/image-spans-to-the-right.png" alt="image spans to the right">
<p>While the CSS grid solution helps with viewing the screenshot on mid to large size screens, it only buys time until the small screen sizes are encountered.</p>
<img src="/images/posts/image-spans-full-width.png" alt="image spans full width">
<p>One solution to solving this problem is to increase the text size when taking a screenshot of the whole application or to crop the important part of the
screenshot out and explain what the image is about. Another idea is to use a <a href="https://nishanths.github.io/loupe-js/?shape=rectangle">loupe</a> to have a "call-out" kind of view of the important parts of the screenshot. This is commonly seen in e-commerce sites where you need to look at the details of an item on the product page.</p>
<img src="/images/posts/loupe.jpg" alt="loupe, zoom in on image section">
<p>Having responsive text is certainly not an issue with the modern web, but having responsive screenshots are also warranted because it serves to better the user experience when viewed when you are on a smaller device. This entails
more careful consideration of how screenshots should be taken.</p>
Visual Studio Code Extensions - Quick Picks #1
2021-06-10T00:00:00+00:00
2021-06-10T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/visual-studio-code-extensions-quick-picks-1/
<h3 id="active-document-indicator"><a href="https://marketplace.visualstudio.com/items?itemName=ojkwon.vscode-activedocumentindicator&ssr=false">Active Document Indicator</a></h3>
<p>Better discern the active editor group by using highlight emphasis on the current editor group while dimming inactive editor groups. This helps with accessibility even though it might only be a small visual change, it is effective in providing more focused editing.</p>
<span id="continue-reading"></span><img src="https://user-images.githubusercontent.com/1210596/55941490-2c4ffc80-5bf7-11e9-8ed9-72ca72255c0a.gif" alt="active-document-screenshot">
<h3 id="ltex"><a href="https://marketplace.visualstudio.com/items?itemName=valentjn.vscode-ltex">lTeX</a></h3>
<p>lTeX is a spelling and grammar checker for LaTeX and other markup language such as BibTEX, markdown, Org, resStructuredText and R Sweave using <a href="https://github.com/languagetool-org/languagetool">LanguageTool</a>. Help with improving sentences readability.</p>
<p><img src="https://raw.githubusercontent.com/valentjn/vscode-ltex/release/img/banner-ltex.png" alt="ltex-screenshot" title="ltex-screenshot" /></p>
<h3 id="restructuredtext"><a href="https://marketplace.visualstudio.com/items?itemName=lextudio.restructuredtext">reStructuredText</a></h3>
<p>Live preview for reStructuredText document edits enables quick feedback when interacting with rst files.</p>
<img src="https://raw.githubusercontent.com/vscode-restructuredtext/vscode-restructuredtext/a7190336d888bee3eeae03b5b9c9289cc796c4a7/images/main.gif" alt="reStructuredText-screenshot">
Snowpack - JavaScript Api
2021-06-03T00:00:00+00:00
2021-06-03T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/snowpack-javascript-api/
<h3 id="control-over-start">Control Over Start</h3>
<p>When the Snowpack CLI is not able to provide fine-tune control over start operations, the Snowpack JavaScript Api should be used. Being able to programmatically control Snowpack is made possible when invoked inside other JavaScript files for enabling more configuration options.</p>
<span id="continue-reading"></span>
<p>One example of using Snowpack programmatically arises when one calls upon the execution of JavaScript file directly with node to start a Snowpack dev server. The "run-server.js" will display console output from the server information logs.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// run-server.js
</span><span>
</span><span style="color:#ff7733;">const </span><span>childProcess </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'child_process'</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> { spawn } </span><span style="color:#f29668;">= </span><span>childProcess</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>server </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">spawn</span><span>(</span><span style="color:#c2d94c;">'node'</span><span style="color:#bfbab0cc;">, </span><span>[</span><span style="color:#c2d94c;">'./server.js'</span><span>])</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>server</span><span style="color:#f29668;">.</span><span>stdout</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">'data'</span><span style="color:#bfbab0cc;">, </span><span>(</span><span style="color:#f29718;">data</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">any</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">error</span><span>(</span><span style="color:#c2d94c;">`Info: ${</span><span>data</span><span style="color:#c2d94c;">}`</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>server</span><span style="color:#f29668;">.</span><span>stdout</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">'error'</span><span style="color:#bfbab0cc;">, </span><span>(</span><span style="color:#f29718;">data</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">any</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">error</span><span>(</span><span style="color:#c2d94c;">`Error: ${</span><span>data</span><span style="color:#c2d94c;">}`</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The following shows a minimal setup for Snowpack configuration that takes a plugin with hot module reloading enabled. This should allow for running a basic Snowpack live dev server when making changes to web assets.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// server.js
</span><span>
</span><span style="color:#ff7733;">const </span><span>snowpack </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'snowpack'</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> path </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'path'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>{ loadConfiguration</span><span style="color:#bfbab0cc;">, </span><span>startServer } </span><span style="color:#f29668;">= </span><span>snowpack</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>(</span><span style="color:#ff7733;">async </span><span>() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">const </span><span>configPath </span><span style="color:#f29668;">= </span><span>path</span><span style="color:#f29668;">.</span><span style="color:#f07178;">resolve</span><span>(process</span><span style="color:#f29668;">.</span><span style="color:#f07178;">cwd</span><span>()</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'snowpack.config.js'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">const </span><span>config </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">await </span><span style="color:#ffb454;">loadConfiguration</span><span>({
</span><span> plugins</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> [</span><span style="color:#c2d94c;">'./plugins/my-plugin.js'</span><span style="color:#bfbab0cc;">, </span><span>{}]
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> devOptions</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> hmr</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true
</span><span> }
</span><span> }</span><span style="color:#bfbab0cc;">, </span><span>configPath)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ffb454;">startServer</span><span>({ config })</span><span style="color:#bfbab0cc;">;
</span><span>})()</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Snowpack's full configuration options can be found in the "types.ts". Look at the SnowpackConfig interface: <a href="https://github.com/snowpackjs/snowpack/blob/main/snowpack/src/types.ts">https://github.com/snowpackjs/snowpack/blob/main/snowpack/src/types.ts</a>.</p>
Testing OpenApi Spec File against Api Server URLs
2021-05-26T00:00:00+00:00
2021-05-26T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/testing-openapi-spec-file-against-api-server-urls/
<h3 id="verifying-apis">Verifying Apis</h3>
<p>Upon creating a REST API and then documenting with OpenApi, the entire set of routes are defined and described properly when the proper care is taken. To ensure that the server provides an Api that matches up to the OpenApi specification JSON or YAML, testing will be required.</p>
<span id="continue-reading"></span>
<p>Although it can be done by writing out each of the test case by hand for each route, it can be cumbersome when there might be a large set of routes to go through, such that it would be more advantageous to automate the testing process.</p>
<p>Since the shape of the routes exhibit a well-defined pattern, Api testing can be automated. One way of doing this is to use property-based testing through the <a href="https://github.com/schemathesis/schemathesis">schemathesis</a> library to automatically generate and run the test cases for you. By using schemathesis, one can gain the convenience of using a single CLI command to run the test suite for all routes.</p>
<p>For example, using schemathesis against the server Api from <a href="https://williamhuey.github.io/posts/nestjs-openapi-example/">my previous post</a> with the following</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">schemathesis</span><span> run http://localhost:3000/api-json
</span></code></pre>
<p>yields the CLI output below</p>
<p><img src="/images/posts/schemathesis-run.svg" alt="schemathesis" title="schemathesis" /></p>
Nestjs - OpenApi Example
2021-05-19T00:00:00+00:00
2021-05-19T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nestjs-openapi-example/
<h3 id="documenting-apis">Documenting Apis</h3>
<p><a href="https://nestjs.com/">Nestjs</a> provides a more opinionated way in expressing structure when developing a backend for your Node.js application, and this prescribed way of doing things coupled with the usage of TypeScript allows for better maintainable code.</p>
<p>As stated in their project <a href="https://github.com/nestjs/nest#philosophy">README.md</a>:</p>
<blockquote>
<p>Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications. The architecture is heavily inspired by Angular.</p>
</blockquote>
<span id="continue-reading"></span>
<p>It is a bit ironic that the front end framework, Angular, was not well-received due to its break of compatibility with Angularjs and also being hampered by competition from other simpler front end frameworks. Yet, Nestjs's core ideals of structuring code into modules and using dependency injection has been successfully implemented, garnering wide adoption.</p>
<p><a href="https://en.wikipedia.org/wiki/OpenAPI_Specification">OpenApi</a>, which was formerly known as Swagger, is a specification standard for describing JSON REST Apis. OpenApi uses a single YAML or JSON file to describe the entirety of an API, so all route resources are detailed in the file. This OpenApi file is usually parsed and a documentation site is generated from it.</p>
<p>Generally, the server code is annotated with structured comments which then a CLI tool is run to process the code to generate the OpenApi file.</p>
<p>With some background information on Nestjs and OpenApi, we can move onto the example of using OpenApi with Nestjs.</p>
<p>Create a folder for the Nestjs project</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">mkdir</span><span> nestjs-open-api
</span></code></pre>
<p>Navigate into the directory</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#f07178;">cd</span><span> nestjs-open-api
</span></code></pre>
<p>Install the Nestjs CLI locally so the <code>npx</code> can be used later on as to avoid
a global Nestjs install.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> i @nestjs/cli
</span></code></pre>
<p>Generate a new project folder inside our 'nestjs-open-api' folder, as this folder
will be the one where the OpenApi example will reside in.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npx</span><span> nest new my-nest-project
</span><span style="color:#f07178;">cd</span><span> my-nest-project
</span></code></pre>
<p>Install additional dependencies because the default Nestjs install does not include the OpenApi modules</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Other required dependencies since the default Nestjs
</span><span style="font-style:italic;color:#5c6773;"># install does not include them
</span><span style="color:#ffb454;">npm</span><span> i</span><span style="color:#f29718;"> --save</span><span> @nestjs/core @nestjs/common rxjs reflect-metadata
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># OpenApi modules
</span><span style="color:#ffb454;">npm</span><span> i</span><span style="color:#f29718;"> --save</span><span> @nestjs/swagger swagger-ui-express class-validator
</span></code></pre>
<p>With the project files in place, it is time to generate a resource for the OpenApi example, since a URL route corresponds to a resource. Nestjs comes with a useful scaffolding tool which we can use:</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">nest</span><span> g resource users
</span></code></pre>
<p>In the above, we have generated a couple of <code>Users</code> URL routes, which will allow for
creating, reading, updating and deleting users.</p>
<p>Now the bootstrap configuration of the Nestjs application will need to register
the OpenApi modules to properly render the documentation page.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ NestFactory } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@nestjs/core'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ SwaggerModule</span><span style="color:#bfbab0cc;">, </span><span>DocumentBuilder } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@nestjs/swagger'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ AppModule } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'./app.module'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">async function </span><span style="color:#ffb454;">bootstrap</span><span>() {
</span><span> </span><span style="color:#ff7733;">const </span><span>app </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">await </span><span>NestFactory</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">create</span><span>(AppModule)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">const </span><span>config </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">DocumentBuilder</span><span>()
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setTitle</span><span>(</span><span style="color:#c2d94c;">'Users example'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setDescription</span><span>(</span><span style="color:#c2d94c;">'The users API description'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setVersion</span><span>(</span><span style="color:#c2d94c;">'1.0'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">addTag</span><span>(</span><span style="color:#c2d94c;">'users'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">build</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">const </span><span>document </span><span style="color:#f29668;">= </span><span>SwaggerModule</span><span style="color:#f29668;">.</span><span style="color:#f07178;">createDocument</span><span>(app</span><span style="color:#bfbab0cc;">, </span><span>config)</span><span style="color:#bfbab0cc;">;
</span><span> SwaggerModule</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setup</span><span>(</span><span style="color:#c2d94c;">'api'</span><span style="color:#bfbab0cc;">, </span><span>app</span><span style="color:#bfbab0cc;">, </span><span>document)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">await </span><span>app</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">listen</span><span>(</span><span style="color:#f29718;">3000</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span style="color:#ffb454;">bootstrap</span><span>()</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Run the development server by</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> start
</span></code></pre>
<p>You will be able to navigate to the following URL to preview the documentation in the browser</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>// Swagger documentation url
</span><span>http://localhost:3000/api/
</span></code></pre>
<p>If you were to interact with the API on the OpenApi page, the response for the API requests will return hard coded strings. These are placeholder routes which need to be updated with Users information.</p>
<p>Stop the server and proceed to update the generated files.</p>
<p>The "user.entity.ts" file will be the location of interest because the code annotation must be placed here for the page to generate the OpenApi documentation.
For our user resource object, we are going to have a "name", "age", and "gender" for this example's sake.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// src/users/entities/user.entity.ts
</span><span style="color:#ff7733;">import </span><span>{ ApiProperty } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@nestjs/swagger'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">export class </span><span style="color:#59c2ff;">User </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">/**
</span><span style="font-style:italic;color:#5c6773;"> * The name of the User
</span><span style="font-style:italic;color:#5c6773;"> * </span><span style="font-style:italic;color:#ff7733;">@example </span><span style="font-style:italic;color:#5c6773;">Bob
</span><span style="font-style:italic;color:#5c6773;"> */
</span><span> name</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">string</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> @</span><span style="color:#ffb454;">ApiProperty</span><span>({ example</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span>description</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'The age of the person' </span><span>})
</span><span> age</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">number</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> @</span><span style="color:#ffb454;">ApiProperty</span><span>({
</span><span> example</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Male'</span><span style="color:#bfbab0cc;">,
</span><span> description</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'The gender of the person'</span><span style="color:#bfbab0cc;">,
</span><span> })
</span><span> gender</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">string</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span></code></pre>
<p>The <a href="https://en.wikipedia.org/wiki/Data_transfer_object">DTO</a>, which will be the shape for the data during transport, will need annotations to be defined for matching up to what is described in the "user.entity.ts".</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">//src/users/dto/create-user.dto.ts
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ IsInt</span><span style="color:#bfbab0cc;">, </span><span>IsString } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'class-validator'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">export class </span><span style="color:#59c2ff;">CreateUserDto </span><span>{
</span><span> @</span><span style="color:#ffb454;">IsString</span><span>()
</span><span> </span><span style="color:#ff7733;">readonly </span><span>name</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">string</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> @</span><span style="color:#ffb454;">IsInt</span><span>()
</span><span> </span><span style="color:#ff7733;">readonly </span><span>age</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">number</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> @</span><span style="color:#ffb454;">IsString</span><span>()
</span><span> </span><span style="color:#ff7733;">readonly </span><span>gender</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">string</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<p>The Users service will provide the methods for processing the user data.
Normally, a proper database will be configured to store and retrieve data in a production
application, but for our example, striving for simplicity, will lead us to use
in-memory JavaScript objects for persistence. The data will only last for as long as the development server is kept running.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">//src/users/users.service.ts
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ Injectable } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@nestjs/common'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ CreateUserDto } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'./dto/create-user.dto'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ UpdateUserDto } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'./dto/update-user.dto'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ User } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'./entities/user.entity'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>@</span><span style="color:#ffb454;">Injectable</span><span>()
</span><span style="color:#ff7733;">export class </span><span style="color:#59c2ff;">UsersService </span><span>{
</span><span>
</span><span> </span><span style="color:#ff7733;">private </span><span>users</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">User</span><span>[] </span><span style="color:#f29668;">= </span><span>[]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Add the user
</span><span> </span><span style="color:#ffb454;">create</span><span>(</span><span style="color:#f29718;">user</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">CreateUserDto</span><span>) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>users</span><span style="color:#f29668;">.</span><span style="color:#f07178;">push</span><span>(user)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span>user</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Find all users
</span><span> </span><span style="color:#ffb454;">findAll</span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>users</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Find a specific user
</span><span> </span><span style="color:#ffb454;">findOne</span><span>(</span><span style="color:#f29718;">id</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">number</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>users[id]</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Update an user
</span><span> </span><span style="color:#ffb454;">update</span><span>(</span><span style="color:#f29718;">id</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">number</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">updateUser</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">UpdateUserDto</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span style="font-style:italic;color:#39bae6;">Object</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">assign</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>users[id]</span><span style="color:#bfbab0cc;">, </span><span>updateUser)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Remove the user
</span><span> </span><span style="color:#ffb454;">remove</span><span>(</span><span style="color:#f29718;">id</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">number</span><span>) {
</span><span> </span><span style="color:#ff7733;">const </span><span>newRemovedUserSet </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>users
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">v</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">i</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">if </span><span>(i </span><span style="color:#f29668;">!== </span><span>id) </span><span style="color:#ff7733;">return </span><span>v</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>users </span><span style="color:#f29668;">= </span><span>newRemovedUserSet</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>users</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}
</span></code></pre>
<p>Restart the development server and go to the OpenApi documentation page and try adding a new user using the <code>POST</code> method with the following data in the Request Body to store a single user for interaction:</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>{
</span><span> "name": "Bob",
</span><span> "age": 30,
</span><span> "gender": "male"
</span><span>}
</span></code></pre>
<p>Then you will be able to read the data with the <code>GET</code> method along with updating (<code>PUT</code>) and deleting (<code>DELETE</code>) of the user resource.</p>
reStructuredText - Include External Documents
2021-05-13T00:00:00+00:00
2021-05-13T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/restructuredtext-include-external-files/
<h3 id="inline-variables-within-a-paragraph">Inline Variables Within a Paragraph</h3>
<p>For general reuse, one can reference another file in reStructuredText using the <code>include</code> directive.</p>
<pre data-lang="rst" style="background-color:#0f1419;color:#bfbab0;" class="language-rst "><code class="language-rst" data-lang="rst"><span style="font-style:italic;color:#5c6773;">.. main.rst - this document will the insert the external content from the path below
</span><span style="font-style:italic;color:#5c6773;">
</span><span>.. include</span><span style="color:#bfbab0cc;">::</span><span> the/path/to/my-included-file.rst
</span></code></pre>
<p>This is good when the content which you want to embed directly into your document can stand by itself as a separate paragraph, however, if you wish to embed content inline within an existing paragraph, it would be necessary to place the included content as variables in another document with the following example.</p>
<span id="continue-reading"></span><pre data-lang="rst" style="background-color:#0f1419;color:#bfbab0;" class="language-rst "><code class="language-rst" data-lang="rst"><span style="font-style:italic;color:#5c6773;">.. main.rst
</span><span style="font-style:italic;color:#5c6773;">
</span><span style="font-style:italic;color:#5c6773;">.. Reference the external file to load the variables
</span><span style="font-style:italic;color:#5c6773;">
</span><span>.. include</span><span style="color:#bfbab0cc;">::</span><span> my-included-file.rst
</span><span>
</span><span style="font-style:italic;color:#5c6773;">.. Using the variables
</span><span style="font-style:italic;color:#5c6773;">
</span><span>My |custom-content|.
</span></code></pre>
<pre data-lang="rst" style="background-color:#0f1419;color:#bfbab0;" class="language-rst "><code class="language-rst" data-lang="rst"><span style="font-style:italic;color:#5c6773;">.. my-included-file.rst
</span><span style="font-style:italic;color:#5c6773;">
</span><span style="font-style:italic;color:#5c6773;">.. The external file with the variables
</span><span style="font-style:italic;color:#5c6773;">
</span><span>.. |custom-content| replace</span><span style="background-color:#bfbab007;color:#bfbab0;">:: words beyond description.</span><span>
</span></code></pre>
Oclif - Delegate / Wrap Existing CLI Commands
2021-05-07T00:00:00+00:00
2021-05-07T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/oclif-delegate-wrap-cli-commands/
<h3 id="cli-wrap-with-spawn-and-programmatic-access">CLI Wrap with Spawn and Programmatic Access</h3>
<p><a href="https://www.npmjs.com/package/oclif">Oclif</a> is a Nodejs command line generator tool that grants you the ability to conveniently create a CLI with the following</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npx</span><span> oclif single mycoollistofthings
</span></code></pre>
<p>Supposedly you have your own custom CLI, but you wish to delegate some of these commands to an existing CLI tool. You are then wrapping another CLI command for the intent of adding additional functionality with <code>mycoollistofthings</code>. Here is the new command's mapping behavior of the <code>ls -r</code> command.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npx</span><span> mycoollistofthings</span><span style="color:#f29718;"> -r
</span></code></pre>
<span id="continue-reading"></span>
<p>Every command created by oclif will take its command line name as its corresponding file name inside the <code>src/commands/</code> folder of the oclif project. This file will be responsible for running the <code>ls</code> command underneath it.</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>src/
</span><span>├── commands
</span><span>│ └── mycoollistofthings.ts
</span><span>...
</span></code></pre>
<p>One way to delegate the command for <code>ls</code> to <code>mycoollistofthings</code> is to spawn the process underneath it when the command is running</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="font-style:italic;color:#5c6773;">// Choosen to create the CLI with the TypeScript option
</span><span style="color:#ff7733;">const </span><span>{ spawn } </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'child_process'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ Command</span><span style="color:#bfbab0cc;">, </span><span>flags } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@oclif/command'
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">MyCoolListOfThings </span><span style="color:#ff7733;">extends </span><span style="text-decoration:underline;color:#59c2ff;">Command </span><span>{
</span><span> </span><span style="color:#ff7733;">static </span><span>description </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'describe the command here'
</span><span>
</span><span> </span><span style="color:#ff7733;">static </span><span>flags </span><span style="color:#f29668;">= </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// add --version flag to show CLI version
</span><span> version</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">version</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'v' </span><span>})</span><span style="color:#bfbab0cc;">,
</span><span> help</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">help</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'h' </span><span>})</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">// flag with a value (-n, --name=VALUE)
</span><span> name</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">string</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'n'</span><span style="color:#bfbab0cc;">, </span><span>description</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'name to print' </span><span>})</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">// flag with no value (-f, --force)
</span><span> force</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">boolean</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'f' </span><span>})
</span><span> }
</span><span>
</span><span> </span><span style="color:#ff7733;">static </span><span>args </span><span style="color:#f29668;">= </span><span>[{ name</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'file' </span><span>}]
</span><span>
</span><span> </span><span style="color:#ff7733;">async </span><span style="color:#ffb454;">run</span><span>() {
</span><span> </span><span style="color:#ff7733;">const </span><span>{ args</span><span style="color:#bfbab0cc;">, </span><span>flags } </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#f07178;">parse</span><span>(MyCoolListOfThings)
</span><span>
</span><span> </span><span style="color:#ff7733;">let </span><span>ls </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">spawn</span><span>(</span><span style="color:#c2d94c;">'ls'</span><span style="color:#bfbab0cc;">, </span><span>[</span><span style="color:#c2d94c;">'-r'</span><span>])</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> ls</span><span style="color:#f29668;">.</span><span>stdout
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">'data'</span><span style="color:#bfbab0cc;">, </span><span>(</span><span style="color:#f29718;">data</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">any</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">`${</span><span>data</span><span style="color:#c2d94c;">}`</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}
</span><span>
</span><span style="color:#ff7733;">export </span><span style="color:#f29668;">= </span><span>MyCoolListOfThings
</span><span>
</span></code></pre>
<p>This is not only good if you wish to have sensible defaults, but spawning the command gives you dynamic access for adding extra flag arguments when needed.</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="color:#ff7733;">const </span><span>{ spawn } </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'child_process'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ Command</span><span style="color:#bfbab0cc;">, </span><span>flags } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@oclif/command'
</span><span>
</span><span style="color:#ff7733;">class </span><span style="color:#59c2ff;">MyCoolListOfThings </span><span style="color:#ff7733;">extends </span><span style="text-decoration:underline;color:#59c2ff;">Command </span><span>{
</span><span> </span><span style="color:#ff7733;">static </span><span>description </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'describe the command here'
</span><span>
</span><span> </span><span style="color:#ff7733;">static </span><span>flags </span><span style="color:#f29668;">= </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// add --version flag to show CLI version
</span><span> version</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">version</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'v' </span><span>})</span><span style="color:#bfbab0cc;">,
</span><span> help</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">help</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'h' </span><span>})</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">// flag with a value (-n, --name=VALUE)
</span><span> name</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">string</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'n'</span><span style="color:#bfbab0cc;">, </span><span>description</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'name to print' </span><span>})</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">// flag with no value (-f, --force)
</span><span> force</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">boolean</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'f' </span><span>})</span><span style="color:#bfbab0cc;">,
</span><span> all</span><span style="color:#bfbab0cc;">: </span><span>flags</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">boolean</span><span>({ char</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'a' </span><span>})</span><span style="color:#bfbab0cc;">,
</span><span> }
</span><span>
</span><span> </span><span style="color:#ff7733;">static </span><span>args </span><span style="color:#f29668;">= </span><span>[{ name</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'file' </span><span>}]
</span><span>
</span><span> </span><span style="color:#ff7733;">async </span><span style="color:#ffb454;">run</span><span>() {
</span><span> </span><span style="color:#ff7733;">const </span><span>{ args</span><span style="color:#bfbab0cc;">, </span><span>flags } </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#f07178;">parse</span><span>(MyCoolListOfThings)
</span><span> </span><span style="color:#ff7733;">const </span><span>spawnArgs </span><span style="color:#f29668;">= </span><span>flags</span><span style="color:#f29668;">.</span><span>all </span><span style="color:#f29668;">? </span><span>[</span><span style="color:#c2d94c;">'--r'</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'--a'</span><span>] </span><span style="color:#f29668;">: </span><span>[</span><span style="color:#c2d94c;">'--r'</span><span>]
</span><span>
</span><span> </span><span style="color:#ff7733;">let </span><span>ls </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">spawn</span><span>(</span><span style="color:#c2d94c;">'ls'</span><span style="color:#bfbab0cc;">, </span><span>spawnArgs)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> ls</span><span style="color:#f29668;">.</span><span>stdout
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">'data'</span><span style="color:#bfbab0cc;">, </span><span>(</span><span style="color:#f29718;">data</span><span style="color:#f29668;">: </span><span style="font-style:italic;color:#39bae6;">any</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">`${</span><span>data</span><span style="color:#c2d94c;">}`</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}
</span><span>
</span><span style="color:#ff7733;">export </span><span style="color:#f29668;">= </span><span>MyCoolListOfThings
</span><span>
</span></code></pre>
<p>However, there will be times when attempting to "wrap" another CLI will not work as expected. Such as the case when attempting to wrap the <a href="https://github.com/snowpackjs/snowpack">snowpack</a> CLI because the <a href="https://www.snowpack.dev/concepts/hot-module-replacement">HMR</a> will not work. The saving grace of using snowpack is that it has <a href="https://www.snowpack.dev/reference/javascript-interface">programmatic access</a>.</p>
<p>So when "spawn wrapping" a CLI does not work, see if the programmatic access is
available for the CLI execution.</p>
Playwright - Cleaner Promise Chains
2021-05-01T00:00:00+00:00
2021-05-01T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/playwright-fluent-api/
<h3 id="fluent-api">Fluent API</h3>
<p>As with many JavaScript libraries, asynchronous operations are dealt with using promises, and the commonly preferred way of structuring promises flows entails the use of async / await.</p>
<p>From the Playwright documentation</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="color:#ff7733;">const </span><span>{ webkit } </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">'playwright'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>(</span><span style="color:#ff7733;">async </span><span>() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">const </span><span>browser </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">await </span><span>webkit</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">launch</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">const </span><span>page </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">await </span><span>browser</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">newPage</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">await </span><span>page</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">goto</span><span>(</span><span style="color:#c2d94c;">'http://whatsmyuseragent.org/'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">await </span><span>page</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">screenshot</span><span>({ path</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">`example.png` </span><span>})</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">await </span><span>browser</span><span style="color:#f29668;">.</span><span style="color:#f07178;">close</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>})()</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Every page operation will require the use of an await since each yields a promise. However, this simple example shows the extra effort needed to tame async control flow by having to prepend each operation with an await. This is a bit noisy and detracts from the true intent of the tests steps.</p>
<span id="continue-reading"></span>
<p>With the help of this library, <a href="https://github.com/hdorgeval/playwright-fluent">playwright-jest</a>, it is possible to clean up an async await block in playwright to use only one await per block.</p>
<p>Modified example from the "playwright-fluent" documentation</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="color:#ff7733;">import </span><span>{ PlaywrightFluent</span><span style="color:#bfbab0cc;">, </span><span>userDownloadsDirectory } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'playwright-fluent'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">const </span><span>p </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">PlaywrightFluent</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">await </span><span>p
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">withBrowser</span><span>(</span><span style="color:#c2d94c;">'firefox'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">withOptions</span><span>({ headless</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">false </span><span>})
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">withCursor</span><span>()
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">recordPageErrors</span><span>()
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">recordFailedRequests</span><span>()
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">recordDownloadsTo</span><span>(userDownloadsDirectory)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">emulateDevice</span><span>(</span><span style="color:#c2d94c;">'iPhone 6 landscape'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">navigateTo</span><span>(</span><span style="color:#c2d94c;">'https://reactstrap.github.io/components/form/'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#f07178;">click</span><span>(</span><span style="color:#c2d94c;">'#exampleEmail'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">typeText</span><span>(</span><span style="color:#c2d94c;">'foo.bar@baz.com'</span><span>)
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Use the playwright api for taking a screenshot
</span><span style="color:#ff7733;">const </span><span>page </span><span style="color:#f29668;">= </span><span>p</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">currentPage</span><span>()
</span><span>
</span><span style="color:#ff7733;">await </span><span>page
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">screenshot</span><span>({ path</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">`example.png` </span><span>})
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Peform more browser actions
</span><span style="color:#ff7733;">await </span><span>p
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pressKey</span><span>(</span><span style="color:#c2d94c;">'Tab'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">expectThatSelector</span><span>(</span><span style="color:#c2d94c;">'#examplePassword'</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#f07178;">hasFocus</span><span>()
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">typeText</span><span>(</span><span style="color:#c2d94c;">"don't tell!"</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pressKey</span><span>(</span><span style="color:#c2d94c;">'Tab'</span><span>)
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Take another screenshot
</span><span style="color:#ff7733;">await </span><span>page
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">screenshot</span><span>({ path</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">`another-example.png` </span><span>})
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Close the browser window
</span><span>p</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">currentBrowser</span><span>()</span><span style="color:#f29668;">.</span><span style="color:#f07178;">close</span><span>()</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The original "playwright" object is needed for certain methods calls that are not implemented in "playwright-fluent" such as the screenshotting to file functionality, but the consecutive promise chains grouped together with "playwright-fluent" still provide greater clarity.</p>
Pandoc - LaTeX - Table of Contents
2021-04-24T00:00:00+00:00
2021-04-24T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/pandoc-latex-table-of-contents/
<h3 id="chapter-links">Chapter Links</h3>
<p>As a LateX document accumulates more content, navigating to a specific piece of information would be cumbersome if there was not an easy way to quickly jump to the area of interest. Providing a table of contents in the beginning of the document will greatly enhance the ability to find relevant data.</p>
<span id="continue-reading"></span>
<p>Supposedly, you have a main LaTeX file, "index.tex", which includes other LaTeX files because you wish to separate content into different chapters.</p>
<pre data-lang="latex" style="background-color:#0f1419;color:#bfbab0;" class="language-latex "><code class="language-latex" data-lang="latex"><span style="font-style:italic;color:#5c6773;">% index.tex
</span><span>
</span><span style="color:#ff7733;">\documentclass</span><span>{</span><span style="font-style:italic;color:#39bae6;">book</span><span>}
</span><span>
</span><span style="color:#ff7733;">\usepackage</span><span>[</span><span style="color:#f29718;">margin</span><span>=0.5in]{</span><span style="font-style:italic;color:#39bae6;">geometry</span><span>}
</span><span>
</span><span style="color:#f07178;">\title</span><span>{Title}
</span><span style="color:#f07178;">\date</span><span>{}
</span><span>
</span><span style="color:#ff7733;">\begin</span><span>{</span><span style="color:#f29718;">document</span><span>}
</span><span>
</span><span style="color:#f07178;">\maketitle
</span><span style="color:#f07178;">\tableofcontents
</span><span>
</span><span style="color:#ff7733;">\include</span><span>{content/chapter1.tex}
</span><span>
</span><span style="color:#ff7733;">\end</span><span>{</span><span style="color:#f29718;">document</span><span>}
</span></code></pre>
<p>The chapter heading and sections of Chapter 1 will be shown in the final table of content links.</p>
<pre data-lang="latex" style="background-color:#0f1419;color:#bfbab0;" class="language-latex "><code class="language-latex" data-lang="latex"><span style="font-style:italic;color:#5c6773;">% chapter1.tex
</span><span>
</span><span style="color:#f07178;">\chapter</span><span>{</span><span style="color:#59c2ff;">First Chapter</span><span>}
</span><span>
</span><span style="color:#f07178;">\section</span><span>{</span><span style="color:#59c2ff;">Chapter 1 - Section</span><span>}
</span><span>
</span><span>The content of Chapter 1.
</span></code></pre>
<p>Generate the html file from the LaTeX inputs.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">pandoc</span><span style="color:#f29718;"> --toc -o </span><span style="color:#c2d94c;">'index.html' '/the/path/to/index.tex'</span><span style="color:#f29718;"> -s
</span></code></pre>
<p>When generating LaTeX files with 'include' using Pandoc, ensure the appropriate folder prefix is given to the LaTeX file relative to where Pandoc command is being run. In the example above, the 'index.tex' file is one folder level above the 'chapter1.tex' and the Pandoc command is executed on the same folder level where the 'index.tex' file is present.</p>
<p>The sample output of the generated html is shown below</p>
<img src="/images/posts/pandoc-latex-table-of-contents.svg" alt="pandoc latex table of contents">
RxJS - Library Picks #1
2021-04-14T00:00:00+00:00
2021-04-14T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rxjs-library-picks-1/
<h3 id="rxdeep"><a href="https://www.npmjs.com/package/rxdeep">Rxdeep</a></h3>
<p>For the easier determination of a value change inside a deeply nested object, use Rxdeep's state's output observable for wrapping an object to subscribe to the change events.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="color:#ff7733;">import </span><span>{ state } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxdeep'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>s </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">state</span><span>([ { name</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'John' </span><span>}</span><span style="color:#bfbab0cc;">, </span><span>{ name</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Jack' </span><span>}</span><span style="color:#bfbab0cc;">, </span><span>{ name</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Jill' </span><span>} ])</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Listen to changes on 'name' property of index 1 on the list:
</span><span>s</span><span style="color:#f29668;">.</span><span style="color:#f07178;">sub</span><span>(</span><span style="color:#f29718;">1</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">sub</span><span>(</span><span style="color:#c2d94c;">'name'</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(</span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">// --> logs `Jack`
</span></code></pre>
<span id="continue-reading"></span><h3 id="rxjs-debug"><a href="https://www.npmjs.com/package/rxjs-debug">RxJs Debug</a></h3>
<p>Wrap a RxJS observable to log out the pipe operator's actions along with phase changes of the observable in a consolidated manner.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// a simple observable
</span><span style="color:#ff7733;">const </span><span>source </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">of</span><span>(</span><span style="color:#f29718;">1</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// wrap it with rxjs-debug
</span><span style="font-style:italic;color:#5c6773;">// you can also provide an optional id to identify the Observable
</span><span style="color:#ffb454;">$D</span><span>(source</span><span style="color:#bfbab0cc;">, </span><span>{id</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'Special'</span><span>}) </span><span style="font-style:italic;color:#5c6773;">// returns a copy of the original Observable with logging enabled
</span><span> </span><span style="font-style:italic;color:#5c6773;">// apply operators on it (optional)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">map</span><span>(</span><span style="color:#f29718;">x </span><span style="color:#ff7733;">=> </span><span>x </span><span style="color:#f29668;">+ </span><span style="color:#f29718;">5</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">switchMap</span><span>(</span><span style="color:#f29718;">x </span><span style="color:#ff7733;">=> </span><span style="color:#ffb454;">of</span><span>(x </span><span style="color:#f29668;">* </span><span style="color:#f29718;">2</span><span>))</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">delay</span><span>(</span><span style="color:#f29718;">200</span><span>)
</span><span> )
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>()</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">// activate the stream
</span><span>
</span><span style="font-style:italic;color:#5c6773;">/*
</span><span style="font-style:italic;color:#5c6773;">// Output
</span><span style="font-style:italic;color:#5c6773;">Special >> SUBSCRIBED--------------------▼
</span><span style="font-style:italic;color:#5c6773;">Special >> START
</span><span style="font-style:italic;color:#5c6773;">0 source 1
</span><span style="font-style:italic;color:#5c6773;">1 map 6
</span><span style="font-style:italic;color:#5c6773;">2 switchMap 12
</span><span style="font-style:italic;color:#5c6773;">3 delay 12
</span><span style="font-style:italic;color:#5c6773;">Special >> END‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾△
</span><span style="font-style:italic;color:#5c6773;">Special >> COMPLETED---------------------▲
</span><span style="font-style:italic;color:#5c6773;">*/
</span></code></pre>
Pandoc - Quick Tips #1
2021-04-07T00:00:00+00:00
2021-04-07T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/pandoc-quick-tips-1/
<h3 id="render-full-html-site">Render Full Html Site</h3>
<p>By default, converting a LaTeX file into an HTML file only produces a partial HTML page. Pandoc conversion strictly contains the content wrapped in the basic HTML equivalent tags, which is spartan as the following example would only output a paragraph tag without a html, head, nor body tag available.</p>
<pre data-lang="latex" style="background-color:#0f1419;color:#bfbab0;" class="language-latex "><code class="language-latex" data-lang="latex"><span style="color:#ff7733;">\documentclass</span><span>{</span><span style="font-style:italic;color:#39bae6;">article</span><span>}
</span><span>
</span><span style="color:#ff7733;">\usepackage</span><span>[</span><span style="color:#f29718;">margin</span><span>=0.5in]{</span><span style="font-style:italic;color:#39bae6;">geometry</span><span>}
</span><span style="color:#f07178;">\title</span><span>{Tex}
</span><span style="color:#f07178;">\date</span><span>{}
</span><span>
</span><span style="color:#ff7733;">\begin</span><span>{</span><span style="color:#f29718;">document</span><span>}
</span><span style="color:#f07178;">\maketitle
</span><span>
</span><span>some content
</span><span>
</span><span style="color:#ff7733;">\end</span><span>{</span><span style="color:#f29718;">document</span><span>}
</span></code></pre>
<p>To fix this problem, the "full html" page requires the "-s" flag (standalone mode) to achieve the proper conversion.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">pandoc</span><span style="color:#f29718;"> -o </span><span style="color:#c2d94c;">'my-output-file.html' 'my-input-file.tex'</span><span style="color:#f29718;"> -s
</span></code></pre>
<span id="continue-reading"></span><h3 id="change-the-default-template-for-html-display">Change the Default Template for HTML Display</h3>
<p>For customization of the default html template which Pandocs uses to produces the HTML output, use the flag 'data-dir' to specify the directory for where the custom html template is located and the 'template' flag for pointing to the actual HTML template.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">pandoc</span><span style="color:#f29718;"> --data-dir</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">'my-custom-directory/for/config/'</span><span style="color:#f29718;"> --template</span><span style="color:#f29668;">=</span><span style="color:#c2d94c;">'default.html5'</span><span style="color:#f29718;"> -o </span><span style="color:#c2d94c;">'my-output-file.html' 'my-input-file.tex'</span><span style="color:#f29718;"> -s
</span></code></pre>
<p>The default sample 'default.html5' file can be found <a href="https://github.com/jgm/pandoc-templates/blob/master/default.html5">here</a>.</p>
Webpage Svg Screenshots
2021-04-03T00:00:00+00:00
2021-04-03T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/svg-screenshots/
<h3 id="accessible-screenshots-of-web-pages">Accessible screenshots of web pages</h3>
<p>Taking a screenshot on a webpage illustrates and preserves the layout information with accompanying text, however, taking a screenshot where the content is primarily text implies a lost of useful information because you can no longer select the text nor zoom into the image without significant quality lost as is the case with most commonly used image formats such as png and jpeg.</p>
<span id="continue-reading"></span>
<p>One way to overcome this problem is to create a svg image out of the website screenshot, and such a tool to do this is available from this NPM module, <a href="https://www.npmjs.com/package/dom-to-svg">dom-to-svg</a>. There is a browser plugin which simplifies the use of this NPM module for <a href="https://addons.mozilla.org/en-US/firefox/addon/svg-screenshots/">Firefox</a> or
<a href="https://chrome.google.com/webstore/detail/svg-screenshot/nfakpcpmhhilkdpphcjgnokknpbpdllg">Chrome</a>.</p>
<h3 id="use-cases">Use Cases</h3>
<h4 id="searching-for-information">Searching for Information</h4>
<p>A positive aspect of creating a screenshot of a website comes from the text search capabilities provided by the svg file format. Since svg is a non-binary file format, you can open up the svg in a text editor and find certain strings of text in the image relatively easy.</p>
<h4 id="readme-md-inline-svg">README.md Inline Svg</h4>
<p>Consider a README.md file in a project folder which you want to include a visual, but you might not want to add in a separate image file in the repository to promote the cleanliness of the folder contents. Directly copying the contents of the svg image inside the README.md would be a viable option using a svg image.</p>
<h4 id="tutorial-walk-thru">Tutorial Walk Thru</h4>
<p>Taking screenshots of web applications is a well suited use case for svg images as most interfaces feature only a few colors with simple geometries.</p>
<img src="/images/posts/walkable.svg" alt="walkable application">
<h3 id="notes">Notes</h3>
<p>Not only are the text preserve in the screenshots, but urls too.</p>
<p>Be wary of taking a svg screenshot where the content contains a photographic/scenery image, because there will be too many details for the browser extension to handle which will result in a locked up browser.</p>
RxJS - Key Combination Detection
2021-03-27T00:00:00+00:00
2021-03-27T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rxjs-key-combination-detection/
<h3 id="hot-keys">Hot Keys</h3>
<p>A hot key combination such as "ctrl + shift + alt + a" could be used to trigger a behavior in a web application such as the opening of a dialog or panel. It also provides a convenient shortcut when an action is often repeated in a workflow. There are certainly many libraries out there designated for such a <a href="https://www.npmjs.com/search?q=hotkey">task</a>, but if you are already using RxJS, it is flexible enough that this functionality can be replicated without using an additional library.</p>
<span id="continue-reading"></span>
<p>Starting from general key press detection</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// Undesirable key repeat events from non-modifier keys
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ fromEvent } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"rxjs"</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ filter } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"rxjs/operators"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>keyboardDown$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">fromEvent</span><span>(document</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"keydown"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>keyboardDown$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(event</span><span style="color:#f29668;">.</span><span>code)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The code above is able to detect held down keys such as the "ctrl", "shift", "alt", "capslock", "os" without repeats, but all the other keys on the keyboard will trigger multiple times when held down.</p>
<p>We wish to know the key that is held down, but only care that it was done before and is still being held, as the repeat events will not be of something of interest because it is considered noise in the case of a key holding combination.</p>
<p>There is a property in the key event which informs us of whether that the key was held down after the first keydown event for a key. We will choose to only concern ourselves with the initial key press of the held down key.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ fromEvent } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ filter } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs/operators'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>keyboardDown$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">fromEvent</span><span>(document</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'keydown'</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> .pipe(filter(event </span><span style="color:#f29668;">=> !</span><span>event</span><span style="color:#f29668;">.</span><span>repeat))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>keyboardDown$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(</span><span style="color:#f29718;">event </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(event</span><span style="color:#f29668;">.</span><span>code)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Now to discern the modifier keys of our choosing, a long-lived history of the keys pressed is required, and the use of Subjects will be suited for this task.</p>
<p>For simplicity's sake, only the left side of the keyboard's modifier keys will be used to demonstrate the key combination.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ fromEvent</span><span style="color:#bfbab0cc;">, </span><span>merge</span><span style="color:#bfbab0cc;">, </span><span>Subject } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"rxjs"</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ filter</span><span style="color:#bfbab0cc;">, </span><span>scan</span><span style="color:#bfbab0cc;">, </span><span>map } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"rxjs/operators"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>keyboardDown$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">fromEvent</span><span>(document</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"keydown"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span style="color:#f29668;">!</span><span>event</span><span style="color:#f29668;">.</span><span>repeat)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>keyboardUp$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">fromEvent</span><span>(document</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"keyup"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span style="color:#f29668;">!</span><span>event</span><span style="color:#f29668;">.</span><span>repeat)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Track the keys for holding
</span><span style="color:#ff7733;">const </span><span>ctlLeftDown$ </span><span style="color:#f29668;">= </span><span>keyboardDown$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"ControlLeft"</span><span>)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>shiftLeftDown$ </span><span style="color:#f29668;">= </span><span>keyboardDown$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"ShiftLeft"</span><span>)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>altLeftDown$ </span><span style="color:#f29668;">= </span><span>keyboardDown$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"AltLeft"</span><span>)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>aDown$ </span><span style="color:#f29668;">= </span><span>keyboardDown$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"KeyA"</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Track the keys for releasing
</span><span style="color:#ff7733;">const </span><span>ctlLeftUp$ </span><span style="color:#f29668;">= </span><span>keyboardUp$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"ControlLeft"</span><span>)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>shiftLeftUp$ </span><span style="color:#f29668;">= </span><span>keyboardUp$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"ShiftLeft"</span><span>)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>altLeftUp$ </span><span style="color:#f29668;">= </span><span>keyboardUp$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"AltLeft"</span><span>)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>aUp$ </span><span style="color:#f29668;">= </span><span>keyboardUp$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">event</span><span>) </span><span style="color:#ff7733;">=> </span><span>event</span><span style="color:#f29668;">.</span><span>code </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">"KeyA"</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>keyGroupDown </span><span style="color:#f29668;">= </span><span>[shiftLeftDown$</span><span style="color:#bfbab0cc;">, </span><span>ctlLeftDown$</span><span style="color:#bfbab0cc;">, </span><span>altLeftDown$</span><span style="color:#bfbab0cc;">, </span><span>aDown$]</span><span style="color:#bfbab0cc;">,
</span><span> keyGroupDownLen </span><span style="color:#f29668;">= </span><span>keyGroupDown</span><span style="color:#f29668;">.</span><span>length</span><span style="color:#bfbab0cc;">,
</span><span> keyGroupUp </span><span style="color:#f29668;">= </span><span>[shiftLeftUp$</span><span style="color:#bfbab0cc;">, </span><span>ctlLeftUp$</span><span style="color:#bfbab0cc;">, </span><span>altLeftUp$</span><span style="color:#bfbab0cc;">, </span><span>aUp$]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Subjects will be the record keepers of the held down key combination group
</span><span style="color:#ff7733;">const </span><span>add$ </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">Subject</span><span>()</span><span style="color:#bfbab0cc;">,
</span><span> clear$ </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">Subject</span><span>()</span><span style="color:#bfbab0cc;">,
</span><span> remove$ </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">Subject</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span style="color:#ffb454;">add </span><span style="color:#f29668;">= </span><span>(</span><span style="color:#f29718;">value</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>(</span><span style="color:#f29718;">state</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>state</span><span style="color:#f29668;">.</span><span style="color:#f07178;">add</span><span>(value)</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span style="color:#ffb454;">remove </span><span style="color:#f29668;">= </span><span>(</span><span style="color:#f29718;">value</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>(</span><span style="color:#f29718;">state</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> state</span><span style="color:#f29668;">.</span><span style="color:#f07178;">delete</span><span>(value)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span>state</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span style="color:#ffb454;">clear </span><span style="color:#f29668;">= </span><span>() </span><span style="color:#ff7733;">=> </span><span>() </span><span style="color:#ff7733;">=> </span><span style="color:#f29668;">new </span><span style="color:#59c2ff;">Set</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>keyUpAndDowns$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">merge</span><span>(
</span><span> add$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">map</span><span>(add))</span><span style="color:#bfbab0cc;">,
</span><span> clear$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">map</span><span>(clear))</span><span style="color:#bfbab0cc;">,
</span><span> remove$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">map</span><span>(remove))
</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">scan</span><span>((</span><span style="color:#f29718;">state</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">innerFn</span><span>) </span><span style="color:#ff7733;">=> </span><span style="color:#ffb454;">innerFn</span><span>(state)</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29668;">new </span><span style="color:#59c2ff;">Set</span><span>()))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>keyUpAndDowns$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">keyCombo</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>keyCombo</span><span style="color:#f29668;">.</span><span>size </span><span style="color:#f29668;">=== </span><span>keyGroupDownLen</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span> )
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">keyCombo</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Key combination detected, keyCombo)</span><span style="color:#ff3333;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">merge</span><span>(</span><span style="color:#f29668;">...</span><span>keyGroupDown)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">res</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> add$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">next</span><span>(res</span><span style="color:#f29668;">.</span><span>code)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">merge</span><span>(</span><span style="color:#f29668;">...</span><span>keyGroupUp)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">res</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> remove$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">next</span><span>(res</span><span style="color:#f29668;">.</span><span>code)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>A Set is used to track the unique keydown interactions because a subset of the key combination can be held and pressed multiple times before the full key combination can be logged in its entirety. Take for example, pressing "ctrl + shift + alt", "ctrl + shift + alt" before finally pressing "ctrl + shift + alt + a", but we only care about the last set of keys.</p>
Selenium - Python - Quick Tips #1
2021-03-17T00:00:00+00:00
2021-03-17T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/selenium-python-quick-tips-1/
<h3 id="webdriver-manager">Webdriver Manager</h3>
<p>Use the latest version of the web driver for your browser of choice when testing by installing the <a href="https://pypi.org/project/webdriver-manager/">webdriver_manager</a> package.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">pip</span><span> install webdriver-manager
</span></code></pre>
<p>The package will automatically download the newest version when tests are run with Selenium. This will relieve you of having to manually download the driver for inclusion in a folder while testing.</p>
<span id="continue-reading"></span>
<p>Use it as follows</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#ff7733;">from </span><span>webdriver_manager</span><span style="color:#f29668;">.</span><span>firefox </span><span style="color:#ff7733;">import </span><span>GeckoDriverManager
</span><span>
</span><span>driver </span><span style="color:#f29668;">= </span><span>webdriver</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">Firefox</span><span>(</span><span style="color:#f29718;">executable_path</span><span style="color:#f29668;">=</span><span style="color:#ffb454;">GeckoDriverManager</span><span>()</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">install</span><span>())
</span></code></pre>
<h3 id="explicit-wait-with-lambda">Explicit Wait with Lambda</h3>
<p>When implicit waits are not enough to detect when an element is present on the screen, the use of the explicit wait with Python's lambda function will provide a better approach to discerning whether an element is present on the page.</p>
<pre data-lang="python" style="background-color:#0f1419;color:#bfbab0;" class="language-python "><code class="language-python" data-lang="python"><span>element </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">WebDriverWait</span><span>(driver</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">20</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">until</span><span>(
</span><span> </span><span style="color:#ff7733;">lambda </span><span style="color:#f29718;">d</span><span>: d</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">execute_script</span><span>(</span><span style="color:#c2d94c;">"return document.querySelector('#my_id');"</span><span>))
</span></code></pre>
Angular - Module for Routes
2021-03-10T00:00:00+00:00
2021-03-10T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/angular-module-route/
<h3 id="organize-routes-into-modules">Organize Routes into Modules</h3>
<p>In Angular, to make routing cleaner, routes may be defined inside modules to localize the path definition to where a specific component is associated.</p>
<p>Here, we have the "/useful/" route and nested child route of "/useful/stuff" defined for our "useful component".</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">//useful.module.ts
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ UsefulComponent } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"./useful.component"</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ NgModule } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"@angular/core"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ RouterModule } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"@angular/router"</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">const </span><span>routes </span><span style="color:#f29668;">= </span><span>[
</span><span> {
</span><span> path</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">,
</span><span> component</span><span style="color:#bfbab0cc;">: </span><span>UsefulComponent</span><span style="color:#bfbab0cc;">,
</span><span> children</span><span style="color:#bfbab0cc;">: </span><span>[{ path</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"stuff"</span><span style="color:#bfbab0cc;">, </span><span>component</span><span style="color:#bfbab0cc;">: </span><span>UsefulComponent }]</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>@</span><span style="color:#ffb454;">NgModule</span><span>({
</span><span> imports</span><span style="color:#bfbab0cc;">: </span><span>[RouterModule</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">forChild</span><span>(routes)]</span><span style="color:#bfbab0cc;">,
</span><span>})
</span><span style="color:#ff7733;">export class </span><span style="color:#59c2ff;">UsefulModule </span><span>{}
</span></code></pre>
<span id="continue-reading"></span>
<p>By convention, there is a dedicated "app-routing.module" defined for aggregating all the routes for the application.
The "useful" path is defined in this module and is lazily loaded with the "loadChildren" key definition.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">//app-routing.module.ts
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ NgModule } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"@angular/core"</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ RouterModule</span><span style="color:#bfbab0cc;">, </span><span>Routes } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"@angular/router"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ HomeComponent } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"./home/home.component"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>routes</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">Routes </span><span style="color:#f29668;">= </span><span>[
</span><span> { path</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">, </span><span>component</span><span style="color:#bfbab0cc;">: </span><span>HomeComponent }</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> path</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"useful"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">loadChildren</span><span style="color:#bfbab0cc;">: </span><span>() </span><span style="color:#ff7733;">=>
</span><span> </span><span style="color:#f29668;">import</span><span>(</span><span style="color:#c2d94c;">"./useful/useful.module"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">then</span><span>((</span><span style="color:#f29718;">m</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>m</span><span style="color:#f29668;">.</span><span>UsefulModule</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>@</span><span style="color:#ffb454;">NgModule</span><span>({
</span><span> imports</span><span style="color:#bfbab0cc;">: </span><span>[RouterModule</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">forRoot</span><span>(routes)]</span><span style="color:#bfbab0cc;">,
</span><span> exports</span><span style="color:#bfbab0cc;">: </span><span>[RouterModule]</span><span style="color:#bfbab0cc;">,
</span><span>})
</span><span style="color:#ff7733;">export class </span><span style="color:#59c2ff;">AppRoutingModule </span><span>{}
</span></code></pre>
<p>The "app-routing.module" is loaded into the main "imports" key of the "app.module" file.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">//app.module.ts
</span><span>
</span><span>@</span><span style="color:#ffb454;">NgModule</span><span>({
</span><span> declarations</span><span style="color:#bfbab0cc;">: </span><span>[AppComponent</span><span style="color:#bfbab0cc;">, </span><span>HomeComponent]</span><span style="color:#bfbab0cc;">,
</span><span> imports</span><span style="color:#bfbab0cc;">: </span><span>[BrowserModule</span><span style="color:#bfbab0cc;">, </span><span>HttpClientModule</span><span style="color:#bfbab0cc;">, </span><span>AppRoutingModule]</span><span style="color:#bfbab0cc;">,
</span><span> bootstrap</span><span style="color:#bfbab0cc;">: </span><span>[AppComponent]</span><span style="color:#bfbab0cc;">,
</span><span>})
</span><span style="color:#ff7733;">export class </span><span style="color:#59c2ff;">AppModule </span><span>{}
</span></code></pre>
<p>Although, lazily loaded modules require more effort to set up as to plain defining the module directly into the "imports" key of the "app.module", there is the added benefit of excluding data loading for other paths since you only need the data for the current path that you are on. It becomes more useful when your application grows over time.</p>
TypeScript - Descriptive String Arrays
2021-03-01T00:00:00+00:00
2021-03-01T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/typescript-descriptive-string-arrays/
<h3 id="strings-from-a-union-type">Strings from a Union Type</h3>
<p>Often times, an array would contain one of many possible string values, and it would be expressed as such</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="color:#ff7733;">interface </span><span style="color:#59c2ff;">BuildFlagsStatus </span><span>{
</span><span> optionalArgsFlagKeys</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">Array</span><span><</span><span style="font-style:italic;color:#39bae6;">string</span><span>>
</span><span>}
</span></code></pre>
<p>However, this is a not very helpful approach because usually the string values allowed placement inside the array comes from a select group of strings.</p>
<p>To be more descriptive, create a string union type and use that for typing an array.</p>
<span id="continue-reading"></span><pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="color:#ff7733;">type </span><span style="color:#59c2ff;">optionalArgsFlagKeys </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'input' </span><span style="color:#f29668;">| </span><span style="color:#c2d94c;">'output'
</span><span style="color:#ff7733;">export type </span><span style="color:#59c2ff;">optionalArgsFlagKeysArray </span><span style="color:#f29668;">= </span><span style="color:#59c2ff;">optionalArgsFlagKeys</span><span>[]
</span><span>
</span><span style="color:#ff7733;">interface </span><span style="color:#59c2ff;">BuildFlagsStatus </span><span>{
</span><span> optionalArgsFlagKeys</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">optionalArgsFlagKeysArray</span><span style="color:#bfbab0cc;">,
</span><span>}
</span></code></pre>
<p>By importing the typed array, and using it directly on the array where the strings of the specified string values are defined, you will provide the TypeScript compiler enough clues to infer the proper value of the array.</p>
<pre data-lang="typescript" style="background-color:#0f1419;color:#bfbab0;" class="language-typescript "><code class="language-typescript" data-lang="typescript"><span style="color:#ff7733;">import </span><span>{ optionalArgsFlagKeysArray } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'./build-report'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">export function </span><span style="color:#ffb454;">buildFlags</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">Build</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">flags</span><span style="color:#f29668;">: </span><span style="color:#59c2ff;">Record</span><span><</span><span style="font-style:italic;color:#39bae6;">string</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">any</span><span>>) {
</span><span> </span><span style="color:#ff7733;">const </span><span>acceptedRequiredFlagKeys </span><span style="color:#f29668;">= </span><span>Build</span><span style="color:#f29668;">.</span><span>requiredFlags</span><span style="color:#bfbab0cc;">,
</span><span> argsFlagKeys </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">Object</span><span style="color:#f29668;">.</span><span style="color:#f07178;">keys</span><span>(flags)</span><span style="color:#bfbab0cc;">,
</span><span> optionalArgsFlagKeys </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">intersection</span><span>(Build</span><span style="color:#f29668;">.</span><span>optionalFlags</span><span style="color:#bfbab0cc;">, </span><span>argsFlagKeys) </span><span style="color:#ff7733;">as </span><span style="color:#59c2ff;">optionalArgsFlagKeysArray</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">return </span><span>{
</span><span> optionalArgsFlagKeys</span><span style="color:#bfbab0cc;">,
</span><span> argsFlagKeys
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
Recording CLI Output
2021-02-24T00:00:00+00:00
2021-02-24T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/record-cli-output/
<h3 id="take-a-frame-from-an-asciicast-recording">Take a Frame from an Asciicast Recording</h3>
<p>Using <a href="https://asciinema.org/">asciinema</a> is a convenient way to create an accessible recording of your terminal if you want to demo features of a CLI app because the output media permits you to select the text that actually runs in the asciinema player.</p>
<p>On occasions, you might be only interested in taking a screenshot of the recording when focusing one command. With the help of <a href="https://github.com/marionebl/svg-term-cli/">"svg-term-cli"</a>, a select frame from asciicast recordings can be exported to a svg file.</p>
<p>It is also helpful to record a series of steps on the CLI at a time as to not disrupt your train of thought when you are going through each CLI command intended for something like an instructional tutorial.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Record your cast
</span><span style="color:#ffb454;">asciinema</span><span> rec my-super-amazing.cast
</span></code></pre>
<span id="continue-reading"></span>
<p>Press the key combo ctrl + d when done.</p>
<p>Install the tool to take a frame of the asciicast to svg</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> install</span><span style="color:#f29718;"> -g</span><span> svg-term-cli
</span></code></pre>
<p>Now to take a frame of the asciicast</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Specify a short millisecond time value to snapshot a single frame
</span><span style="font-style:italic;color:#5c6773;"># and to also avoid seeing the 'exit' command when stopping the asciicast recording
</span><span style="color:#ffb454;">svg-term</span><span style="color:#f29718;"> --in</span><span> my-super-amazing.cast</span><span style="color:#f29718;"> --out</span><span> even-more-amazing.svg</span><span style="color:#f29718;"> --at</span><span> 300
</span></code></pre>
<p>Here is an example output</p>
<img src="/images/posts/even-more-amazing.svg" alt="asciicast frame capture to svg">
RxJS - Dependent Observable for Multiple Matches
2021-02-16T00:00:00+00:00
2021-02-16T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rxjs-dependent-observables-multiple-matches/
<h3 id="give-precedence-to-greater-satisfied-criteria">Give Precedence to Greater Satisfied Criteria</h3>
<p>Observables tend to be created from other observables through transformations by operators in a pipe. On some occasions, one observable is created from another, it creates a chain where you have the latter observable and initial observable both triggering when the initial base condition is met. However, there might be cases, where you would only want the latter observable to trigger because you want to find the observable which matches the most conditions.</p>
<span id="continue-reading"></span>
<p>Take for example of the number 24. This number's factors are to be determined, and multiple factors are known to work from a list that are divisible, but we are only interested in the largest factor from a list of numbers (2, 4, 6). 24 is first divisible by 2, then by 4 and then by 6. </p>
<p>Example below:</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ of</span><span style="color:#bfbab0cc;">, </span><span>operators</span><span style="color:#bfbab0cc;">, </span><span>merge } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ map</span><span style="color:#bfbab0cc;">, </span><span>filter</span><span style="color:#bfbab0cc;">, </span><span>takeLast } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs/operators'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>divisibleNum </span><span style="color:#f29668;">= </span><span>{ num</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">24 </span><span>}</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">const </span><span>divisible$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">of</span><span>(divisibleNum)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>divisibleBy2$ </span><span style="color:#f29668;">= </span><span>divisible$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">data</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>data</span><span style="color:#f29668;">.</span><span>num </span><span style="color:#f29668;">% </span><span style="color:#f29718;">2 </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">map</span><span>((</span><span style="color:#f29718;">data</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>{
</span><span> </span><span style="color:#f29668;">...</span><span>data</span><span style="color:#bfbab0cc;">,
</span><span> from</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2
</span><span> }
</span><span> })
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>divisibleBy2$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Divisible by 2"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>divisibleBy4and2$ </span><span style="color:#f29668;">= </span><span>divisibleBy2$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">data</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>data</span><span style="color:#f29668;">.</span><span>num </span><span style="color:#f29668;">% </span><span style="color:#f29718;">4 </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">map</span><span>((</span><span style="color:#f29718;">data</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>{
</span><span> </span><span style="color:#f29668;">...</span><span>data</span><span style="color:#bfbab0cc;">,
</span><span> from</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">4
</span><span> }
</span><span> })
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>divisibleBy4and2$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Divisible by 4 and 2"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>divisibleBy6And4And2$ </span><span style="color:#f29668;">= </span><span>divisibleBy4and2$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">filter</span><span>((</span><span style="color:#f29718;">data</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>data</span><span style="color:#f29668;">.</span><span>num </span><span style="color:#f29668;">% </span><span style="color:#f29718;">6 </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">map</span><span>((</span><span style="color:#f29718;">data</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span>{
</span><span> </span><span style="color:#f29668;">...</span><span>data</span><span style="color:#bfbab0cc;">,
</span><span> from</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">6
</span><span> }
</span><span> })
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>divisibleBy6And4And2$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Divisible by 6, 4, and 2"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Since multiple divisible observables will trigger, and the
</span><span style="font-style:italic;color:#5c6773;">// last observable in the merge array is what gets triggered
</span><span style="font-style:italic;color:#5c6773;">// after all the prior observable in the list have triggered,
</span><span style="font-style:italic;color:#5c6773;">// get the last return.
</span><span style="color:#ffb454;">merge</span><span>(divisibleBy2$</span><span style="color:#bfbab0cc;">, </span><span>divisibleBy4and2$</span><span style="color:#bfbab0cc;">, </span><span>divisibleBy6And4And2$)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">takeLast</span><span>(</span><span style="color:#f29718;">1</span><span>)
</span><span> )
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">data</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Divisible from divisible factor"</span><span style="color:#bfbab0cc;">, </span><span>data</span><span style="color:#f29668;">.</span><span>from</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"and below"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">/* LOGS
</span><span style="font-style:italic;color:#5c6773;">
</span><span style="font-style:italic;color:#5c6773;">"Divisible by 2"
</span><span style="font-style:italic;color:#5c6773;">"Divisible by 4 and 2"
</span><span style="font-style:italic;color:#5c6773;">"Divisible by 6, 4, and 2"
</span><span style="font-style:italic;color:#5c6773;">"Divisible from divisible factor", 6, "and below"
</span><span style="font-style:italic;color:#5c6773;">
</span><span style="font-style:italic;color:#5c6773;">*/
</span></code></pre>
<p>In the example above, each new observable is created from the one before it, so each divisibility condition is stricter than the one before. The checks above does not provide a general divisibility of a factor but suggests a cumulative one.</p>
<p>The behavior above resembles what you would see if you use a switch statement in JavaScript with the more stringent case declarations placed closer to the beginning of the switch block.</p>
<p><a href="https://jsfiddle.net/f7rdyqs9/">Online Demo</a></p>
Snowpack - "Unbundler"
2021-02-07T00:00:00+00:00
2021-02-07T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/snowpack-unbundler/
<h3 id="configure-a-snowpack-plugin">Configure a Snowpack Plugin</h3>
<p>Snowpack is a frontend build tool that promotes itself as an alternative to Webpack because it uses new JS modules features, and the workflow is "unbundled" which skips the build steps during development to make for a faster workflow.</p>
<p>Snowpack has some <a href="https://www.snowpack.dev/reference/supported-files">sensible defaults</a> which permits the import of commonly used asset files such as scss, .css, .svg in your JavaScript files.</p>
<span id="continue-reading"></span>
<p>Start a Snowpack project by initializing a npm project</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">mkdir</span><span> snowpack-test
</span><span style="color:#f07178;">cd</span><span> snowpack-test
</span><span style="color:#ffb454;">touch</span><span> package.json
</span><span style="color:#ffb454;">touch</span><span> index.html
</span></code></pre>
<p>Update the "package.json" to install Snowpack</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"project"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"version"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"1.0.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"description"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"main"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"index.js"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"author"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"license"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"ISC"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"dependencies"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"snowpack"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^3.0.11"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"scripts"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"start"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"snowpack dev"
</span><span> }
</span><span>}
</span></code></pre>
<h3 id="entry-point-html">Entry Point HTML</h3>
<p>The entry point html file that Snowpack looks at will need to be named "index.html".</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#f07178;">.
</span><span style="color:#ffb454;">├──</span><span> index.html
</span><span style="color:#ffb454;">├──</span><span> my-cool-file.myfileextensiontowatch
</span><span style="color:#ffb454;">├──</span><span> node_modules
</span><span style="color:#ffb454;">├──</span><span> package.json
</span><span style="color:#ffb454;">├──</span><span> package-lock.json
</span><span style="color:#ffb454;">└──</span><span> snowpack.config.js
</span></code></pre>
<p>To customize the directory for where the index.html is served, update "snowpack.config.js" with the following.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>...
</span><span>mount: {
</span><span> </span><span style="color:#c2d94c;">"site"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"/"
</span><span>}
</span><span>...
</span></code></pre>
<p>This will permit you to move the "index.html" file to the "site" folder.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#f07178;">.
</span><span style="color:#ffb454;">├──</span><span> node_modules
</span><span style="color:#ffb454;">├──</span><span> package.json
</span><span style="color:#ffb454;">├──</span><span> package-lock.json
</span><span style="color:#ffb454;">├──</span><span> site
</span><span style="color:#ffb454;">│</span><span> └── index.html
</span><span style="color:#ffb454;">└──</span><span> snowpack.config.js
</span></code></pre>
<p>In the case where you would like to detect a file type change which is not supported by Snowpack natively, you can create a plugin. </p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// new-plugin-for-detecting-file-type-change.js
</span><span>
</span><span style="font-style:italic;color:#39bae6;">module</span><span style="color:#f29668;">.</span><span style="font-style:italic;color:#39bae6;">exports </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">snowpackConfig</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">pluginOptions</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span>{
</span><span> name</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'my-first-snowpack-plugin'</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">load</span><span>() { }</span><span style="color:#bfbab0cc;">,
</span><span> resolve</span><span style="color:#bfbab0cc;">: </span><span>{ input</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#c2d94c;">".myfileextensiontowatch"</span><span>]</span><span style="color:#bfbab0cc;">, </span><span>output</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#c2d94c;">".html"</span><span>] }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">onChange</span><span>(</span><span style="color:#f29718;">change</span><span>) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'changed'</span><span style="color:#bfbab0cc;">, </span><span>change)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The files being watched will be monitor based on where your "index.html" file is located. Watching will be done on the same folder level placement of "index.html" and any folder that is nested under the parent folder of "index.html".</p>
<p>If we were to use a custom folder for "index.html", the file extension to watch will be moved to the same folder as "index.html".</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#f07178;">.
</span><span style="color:#ffb454;">├──</span><span> node_modules
</span><span style="color:#ffb454;">├──</span><span> package.json
</span><span style="color:#ffb454;">├──</span><span> package-lock.json
</span><span style="color:#ffb454;">├──</span><span> site
</span><span style="color:#ffb454;">│</span><span> │── index.html
</span><span style="color:#ffb454;">│</span><span> └── my-cool-file.myfileextensiontowatch
</span><span style="color:#ffb454;">└──</span><span> snowpack.config.js
</span></code></pre>
<p>The Snowpack plugin can be placed in any location as long as the path to it can be referenced.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// snowpack.config.js
</span><span>
</span><span style="color:#c2d94c;">"plugins"</span><span>: [
</span><span> [</span><span style="color:#c2d94c;">"./new-plugin-for-detecting-file-type-change.js"</span><span style="color:#bfbab0cc;">, </span><span>{</span><span style="font-style:italic;color:#5c6773;">/* pluginOptions */ </span><span>}]
</span><span>]
</span></code></pre>
<p>Along with the Snowpack's Plugin Api, there are Apis for use with the CLI and HMR.</p>
<p>Although Snowpack's is on v3, its Api is not as extensive as Webpack, but it is simple enough for smaller projects where you might not be interested in downloading more for what might be used.</p>
RxJS - Logical Operators
2021-01-30T00:00:00+00:00
2021-01-30T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rxjs-logical-operators/
<h3 id="logical-evaluation">Logical Evaluation</h3>
<p>In traditional JavaScript, one would use the logical operators "&&", "||", "!" when evaluating variables for the "and", "or", and "not" conditions respectively.
Similarly, there are RxJS operators which looks like the ones found in JavaScript when you wish to treat observable like values that needs to be compared against one another.</p>
<p>For the examples below, "true" in this sense refers to the observable have "truly" emitted a value and not have it base upon the actual underlying value within the observable.</p>
<h4 id="and">AND</h4>
<p>Use the "forkJoin" operator when every single observable must be activated for the subscription to run.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// When the observables will emit at least once in any order
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ forkJoin</span><span style="color:#bfbab0cc;">, </span><span>of</span><span style="color:#bfbab0cc;">, </span><span>interval } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ take } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs/operators'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>timer$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">interval</span><span>(</span><span style="color:#f29718;">1000</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">take</span><span>(</span><span style="color:#f29718;">1</span><span>))</span><span style="color:#bfbab0cc;">,
</span><span> truthfulness$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">of</span><span>(</span><span style="color:#f29718;">true</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">forkJoin</span><span>([
</span><span> timer$</span><span style="color:#bfbab0cc;">,
</span><span> truthfulness$
</span><span>])
</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'All completed once'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span></code></pre>
<p>Alternatively, you might be able to use "combineLatest" when you
have long-lived observables. Tangentially, "concat" or "zip" will work if a strict order needs to be imposed for activation of observables in a series.</p>
<span id="continue-reading"></span><h4 id="or">OR</h4>
<p>The "race" operator emits when any observable within a group gets trigger.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// When the obervables will emit at least once in any order
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ of</span><span style="color:#bfbab0cc;">, </span><span>interval</span><span style="color:#bfbab0cc;">, </span><span>race } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ take } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs/operators'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>timer$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">interval</span><span>(</span><span style="color:#f29718;">1000</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">take</span><span>(</span><span style="color:#f29718;">1</span><span>))</span><span style="color:#bfbab0cc;">,
</span><span> truthfulness$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">of</span><span>(</span><span style="color:#f29718;">true</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">race</span><span>(
</span><span> timer$</span><span style="color:#bfbab0cc;">,
</span><span> truthfulness$
</span><span>)
</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">first</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Truthiness first'</span><span style="color:#bfbab0cc;">, </span><span>first)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>In addition to "forkJoin", "merge" can be used when order does not matter.</p>
<h4 id="not">NOT</h4>
<p>There is no negation operator you can directly use on an observable, but one can use the "map" operator and check against the negated value inside the observable.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="color:#ff7733;">import </span><span>{ of } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ map } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs/operators'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>truthfulness$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">of</span><span>(</span><span style="color:#f29718;">true</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>truthfulness$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(
</span><span> </span><span style="color:#ffb454;">map</span><span>((</span><span style="color:#f29718;">theValue</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#f29668;">!</span><span>theValue</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span> )
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">negatedValue</span><span>) </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Negated value:"</span><span style="color:#bfbab0cc;">, </span><span>negatedValue)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span></code></pre>
RxJS - Quick Tips #1
2021-01-24T00:00:00+00:00
2021-01-24T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/rxjs-quick-tips-1/
<h3 id="conditional-activation-of-an-observable">Conditional Activation of an Observable</h3>
<p>Only make an observable run based on a ternary matching criteria.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// Third party modules
</span><span style="color:#ff7733;">import </span><span>{ NEVER</span><span style="color:#bfbab0cc;">, </span><span>of } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>evaluateToTrueCriteria </span><span style="color:#f29668;">= </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// 'conditional$' will not run 'subscribe' when the ternary
</span><span style="font-style:italic;color:#5c6773;">// evaluates to the false branch
</span><span style="color:#ff7733;">const </span><span>conditional$ </span><span style="color:#f29668;">= </span><span>evaluateToTrueCriteria </span><span style="color:#f29668;">? </span><span style="color:#ffb454;">of</span><span>(</span><span style="color:#f29718;">true</span><span>) </span><span style="color:#f29668;">: </span><span>NEVER</span><span style="color:#bfbab0cc;">;
</span><span>conditional$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">res</span><span>) </span><span style="color:#ff7733;">=> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(res))</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<span id="continue-reading"></span><h3 id="file-system-wrapper">File System Wrapper</h3>
<p>Use the "@rxnode/fs" module as a convenience wrapper around the default fs modules functions. The functions provided by "@rxnode/fs" will return an observable when called upon. Impose creation order with the help of RxJS's "concat".</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// Third party modules
</span><span style="color:#ff7733;">import </span><span>{ writeFile</span><span style="color:#bfbab0cc;">, </span><span>mkdir } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'@rxnode/fs'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ concat } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>{ share</span><span style="color:#bfbab0cc;">, </span><span>takeLast } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs/operators'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Paths for the folder and file
</span><span style="color:#ff7733;">const </span><span>newFolderPath </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'some/new/folder/path'</span><span style="color:#bfbab0cc;">,
</span><span> newFileName </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">'some/new/folder/path/withFile'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// The folder and file are turned into hot observables
</span><span style="font-style:italic;color:#5c6773;">// because the generation process should only be active once
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Folder creation
</span><span style="color:#ff7733;">const </span><span>createFolder$</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">mkdir</span><span>(newFolderPath)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">share</span><span>())</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// File creation
</span><span style="color:#ff7733;">const </span><span>createFile$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">writeFile</span><span>(newFileName</span><span style="color:#bfbab0cc;">, </span><span>fileContent)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">share</span><span>())</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Wait for the folder to be generate before generating
</span><span style="font-style:italic;color:#5c6773;">// the file within it (when order matters)
</span><span style="color:#ffb454;">concat</span><span>(createFolder$</span><span style="color:#bfbab0cc;">, </span><span>createFile$)
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Prevent multiple triggers with only taking the
</span><span> </span><span style="font-style:italic;color:#5c6773;">// the last activation
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">pipe</span><span>(</span><span style="color:#ffb454;">takeLast</span><span>(</span><span style="color:#f29718;">1</span><span>))
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Folder and file created'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="wrap-command-line-execution">Wrap command line execution</h3>
<p>Hook into a command line's execution to std out and completion with RxJs.</p>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// Run the 'npm install' command using observables
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Native modules
</span><span style="color:#ff7733;">import </span><span>{ spawn } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'child_process'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Third party modules
</span><span style="color:#ff7733;">import </span><span>{ bindCallback } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'rxjs'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>npmService </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">spawn</span><span>(</span><span style="color:#c2d94c;">'npm'</span><span style="color:#bfbab0cc;">, </span><span>[</span><span style="color:#c2d94c;">'install'</span><span>]</span><span style="color:#bfbab0cc;">, </span><span>{
</span><span> cwd</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"path/for/executing/npm/command"
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>npmOnComplete$ </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">bindCallback</span><span>(npmService</span><span style="color:#f29668;">.</span><span>stdout</span><span style="color:#f29668;">.</span><span>on)</span><span style="color:#bfbab0cc;">,
</span><span> npmClose$ </span><span style="color:#f29668;">= </span><span>npmOnComplete$</span><span style="color:#f29668;">.</span><span style="color:#f07178;">call</span><span>(npmService</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">'close'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Listen to the completion event for the npm command
</span><span>npmClose$
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">'Finish npm install command'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Pandoc Filter
2021-01-17T00:00:00+00:00
2021-01-17T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/pandoc-filter/
<h3 id="output-file-manipulation">Output file Manipulation</h3>
<p>When working with a document format conversion, such as converting over a Markdown file to LaTeX,
there will be occasions where you might want to manipulate the output when Pandoc is not able to completely infer the output that is desired.</p>
<span id="continue-reading"></span>
<p>Fortunately, Pandoc does offer a means of performing such a task through something called a
<a href="https://pandoc.org/filters.html">Pandoc filter</a>.</p>
<p>This feature provides the capability to manipulate the line-by-line structure that Pandoc sees when it goes through your document with the filter language of your choice.</p>
<p>To use the JavaScript version of the Pandoc filter, create a new Node package project by creating a new folder and filtering file.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">mkdir</span><span> pandoc-filter
</span><span style="color:#f07178;">cd</span><span> pandoc-filter
</span><span style="color:#ffb454;">touch </span><span style="color:#c2d94c;">"filter.js"
</span></code></pre>
<p>Install the npm module for Pandoc manipulation, "pandoc-filter"</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">npm</span><span> install pandoc-filter
</span></code></pre>
<p>Place the following into a "filter.js" file</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// "filter.js"
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// File operation
</span><span style="color:#ff7733;">const </span><span>fs </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"fs"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Pandoc CLI filter
</span><span style="color:#ff7733;">const </span><span>pandoc </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"pandoc-filter"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Define a logger which outputs to a file for easier debugging
</span><span style="color:#ff7733;">const </span><span>outputLogger </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">console</span><span style="color:#f29668;">.</span><span style="color:#59c2ff;">Console</span><span>(fs</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">createWriteStream</span><span>(</span><span style="color:#c2d94c;">"./output.log"</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// This function will evaluate each of the lines which gets read
</span><span style="font-style:italic;color:#5c6773;">// from the supplied input file
</span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">action</span><span>(</span><span style="color:#f29718;">key</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Log to "output.log" for debugging
</span><span> </span><span style="font-style:italic;color:#5c6773;">// outputLogger.log(key);
</span><span> </span><span style="color:#ff7733;">switch </span><span>(key</span><span style="color:#f29668;">.</span><span>t) {
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#c2d94c;">"Header"</span><span>:
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">header</span><span>(key)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#c2d94c;">"Str"</span><span>:
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">str</span><span>(key)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#c2d94c;">"Code"</span><span>:
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">code</span><span>(key)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#c2d94c;">"RawBlock"</span><span>:
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">rawBlock</span><span>(</span><span style="color:#f29668;">...</span><span>key</span><span style="color:#f29668;">.</span><span>c)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#c2d94c;">"CodeBlock"</span><span>:
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">codeblock</span><span>(</span><span style="color:#f29668;">...</span><span>key</span><span style="color:#f29668;">.</span><span>c)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#c2d94c;">"Para"</span><span>:
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">para</span><span>(key</span><span style="color:#f29668;">.</span><span>c)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">/* Other action functions go here */
</span><span>
</span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">header</span><span>(</span><span style="color:#f29718;">content</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// < Put your transformation code here >
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Return a RawBlock or RawInline for control over the output
</span><span> </span><span style="font-style:italic;color:#5c6773;">// return pandoc.RawBlock("tex", newContent);
</span><span> </span><span style="font-style:italic;color:#5c6773;">// return pandoc.RawInline("tex", `\\kode{${transformedContent}}`);
</span><span>}
</span><span>
</span><span>pandoc</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">stdio</span><span>(action)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Execute the above with</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">pandoc</span><span> /path/to/my_markdown.md</span><span style="color:#f29718;"> --filter</span><span> /path/to/pandoc-filter/filter.js</span><span style="color:#f29718;"> -o</span><span> my_converted.tex</span><span style="color:#f29718;"> --verbose
</span></code></pre>
<h4 id="explanation">Explanation</h4>
<p>The "pandoc.stdio" function gets executed as Pandoc steps through your input file calling on the "action" function. The "action" function is a switch statement function used to check for the document structure type on a specific line or block of text. The switch statement in the "action" function outlines the more common structure types Pandoc will typically encounter in a markdown file. The complete list of "block" and "inline" structures that can be match is found
<a href="https://hackage.haskell.org/package/pandoc-types-1.20/docs/Text-Pandoc-Definition.html#t:MetaValue">here</a>.</p>
<p>You provide the function to call to modify the final output of the Pandoc document.</p>
<p>The output of manipulation functions should return either a "pandoc.RawInline" or "pandoc.RawBlock" with the new content in it.</p>
<p>If you uncommented out the log output lines, the logged values of the Pandoc AST will go into "output.log" in the same folder as where you executed the Pandoc command and the output log will look like the following</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>{
</span><span> t: 'Para',
</span><span> c: [
</span><span> { t: 'Str', c: 'some' },
</span><span> { t: 'Space' },
</span><span> { t: 'Str', c: 'cool' },
</span><span> { t: 'Space' },
</span><span> { t: 'Str', c: 'text' },
</span><span> { t: 'Space' },
</span><span> { t: 'Str', c: 'for' },
</span><span> { t: 'Space' },
</span><span> { t: 'Str', c: 'you' },
</span><span> { t: 'Space' },
</span><span> { t: 'Str', c: 'reader' }
</span><span> ]
</span><span>}
</span><span>{ t: 'Str', c: 'some' }
</span><span>{ t: 'Space' }
</span><span>{ t: 'Str', c: 'cool' }
</span><span>{ t: 'Space' }
</span><span>{ t: 'Str', c: 'text' }
</span><span>{ t: 'Space' }
</span><span>{ t: 'Str', c: 'for' }
</span><span>{ t: 'Space' }
</span><span>{ t: 'Str', c: 'you' }
</span><span>{ t: 'Space' }
</span><span>{ t: 'Str', c: 'reader' }
</span></code></pre>
NX - Angular Storybook and Cypress Testing
2021-01-11T00:00:00+00:00
2021-01-11T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nx-angular-storybook-and-cypress-testing/
<h3 id="scaffolding-for-angular-and-storybook-with-cypress">Scaffolding for Angular and Storybook with Cypress</h3>
<p>First, use npx to localize the install of NX (v11.0.20) and Angular CLI (v11.0.20).</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Create a nx workspace
</span><span style="color:#ffb454;">npx</span><span> create-nx-workspace@latest
</span></code></pre>
<span id="continue-reading"></span>
<p>Then "Choose the Angular workspace" and "Choose Application name of your choice".</p>
<p>If the Angular module install did not appear in the package.json, install it now by</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Install the Angular module
</span><span style="color:#ffb454;">npm</span><span> install</span><span style="color:#f29718;"> -D</span><span> @nrwl/angular
</span></code></pre>
<p>To see a demo of the Cypress test window in persistent standalone mode</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># The defined projects can be found in the "nx.json" under the "projects" key.
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Click on the spec file you wish to execute upon seeing the window
</span><span style="color:#ffb454;">npx</span><span> nx run project-name-e2e:e2e</span><span style="color:#f29718;"> --watch
</span></code></pre>
<p>You will find related information for the Angular plugin with</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># List associated information of the Angular plugin
</span><span style="color:#ffb454;">npx</span><span> nx list @nrwl/angular
</span></code></pre>
<p>Generate a library under the "lib" folder</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># The generated libraries will count as "projects"
</span><span style="color:#ffb454;">npx</span><span> ng g @nrwl/angular:lib ui
</span></code></pre>
<p>The Storybook integration begins with adding the nrwl plugin.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Adding the plugin
</span><span style="color:#ffb454;">npm</span><span> add</span><span style="color:#f29718;"> --dev</span><span> @nrwl/storybook
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Associate Storybook with a "project"
</span><span style="color:#ffb454;">npx</span><span> nx g @nrwl/angular:storybook-configuration project-name
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Demo run of Storybook (Navigate to http://localhost:4400/)
</span><span style="color:#ffb454;">npx</span><span> nx run project-name:storybook
</span></code></pre>
<p>See additional information for the Storybook generator</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Options for the Storybook generator
</span><span style="color:#ffb454;">Options:
</span><span> </span><span style="color:#ffb454;">--name</span><span> Library or application name
</span><span> </span><span style="color:#ffb454;">--configureCypress</span><span> Run the cypress-configure generator
</span><span> </span><span style="color:#ffb454;">--generateStories</span><span> Automatically generate </span><span style="color:#f29668;">*</span><span>.stories.ts files for components declared in this library
</span><span> </span><span style="color:#ffb454;">--generateCypressSpecs</span><span> Automatically generate </span><span style="color:#f29668;">*</span><span>.spec.ts files in the cypress e2e app generated by the cypress-configure generator
</span><span> </span><span style="color:#ffb454;">--linter</span><span> The tool to use for running lint checks. (default: tslint)
</span><span> </span><span style="color:#ffb454;">--dryRun</span><span> Runs through and reports activity without writing to disk.
</span><span> </span><span style="color:#ffb454;">--skip-nx-cache</span><span> Skip the use of Nx cache.
</span><span> </span><span style="color:#ffb454;">--help</span><span> Show available options for project target.
</span></code></pre>
<p>The initial setup association of Storybook</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Use Storybook on a generated 'ui' folder
</span><span style="color:#ffb454;">npx</span><span> nx g @nrwl/angular:storybook-configuration ui
</span></code></pre>
<p>Set the Storybook Cli Prompt Configuration Options to "Yes"</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">?</span><span> Configure a cypress e2e app to run against the storybook instance</span><span style="color:#f29668;">?</span><span> Yes
</span><span style="color:#ffb454;">?</span><span> Automatically generate </span><span style="color:#f29668;">*</span><span>.stories.ts files for components declared in this library</span><span style="color:#f29668;">?</span><span> Yes
</span><span style="color:#ffb454;">?</span><span> Automatically generate </span><span style="color:#f29668;">*</span><span>.spec.ts files in the cypress e2e app generated by the cypress-configure generator</span><span style="color:#f29668;">?</span><span> Yes
</span></code></pre>
<p>The generated integration test folder lies outside the area of the ui folder, which is grouped along with any of your other e2e tests in the "/apps" folder.</p>
<p>When you generate a component, they will need to reside inside a "library" folder.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Generate a component into lib/ui folder
</span><span style="color:#ffb454;">npx</span><span> ng g component button</span><span style="color:#f29718;"> --project</span><span style="color:#f29668;">=</span><span>ui</span><span style="color:#f29718;"> --export
</span></code></pre>
<p>If the automatic generation of spec files for Storybook and Cypress did not
automatically generate the spec files, generate them manually with the command below.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Generate stories for components after initial Storybook configuration
</span><span style="color:#ffb454;">npx</span><span> nx generate @nrwl/angular:stories</span><span style="color:#f29718;"> --name</span><span style="color:#f29668;">=</span><span>ui
</span></code></pre>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Options for generating stories individually for components in the library
</span><span>
</span><span style="color:#ffb454;">Options:
</span><span> </span><span style="color:#ffb454;">--name</span><span> Library or application name
</span><span> </span><span style="color:#ffb454;">--generateCypressSpecs</span><span> Automatically generate </span><span style="color:#f29668;">*</span><span>.spec.ts files in the cypress e2e app generated by the cypress-configure generator
</span><span> </span><span style="color:#ffb454;">--dryRun</span><span> Runs through and reports activity without writing to disk.
</span><span> </span><span style="color:#ffb454;">--skip-nx-cache</span><span> Skip the use of Nx cache.
</span><span> </span><span style="color:#ffb454;">--help</span><span> Show available options for project target.
</span></code></pre>
<p>View Storybook in either your browser or run the Cypress tests against the Storybook components inside a standalone window.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Run the StoryBook server for viewing in the browser
</span><span style="color:#ffb454;">npx</span><span> nx run ui:storybook
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Run Cypress test for the library
</span><span style="color:#ffb454;">npx</span><span> nx run ui-e2e:e2e</span><span style="color:#f29718;"> --watch
</span></code></pre>
Setting Up Zola
2021-01-07T00:00:00+00:00
2021-01-07T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/zola-config/
<h3 id="static-site-generator-configuration">Static Site Generator Configuration</h3>
<p>Zola is a decent static site generator written in Rust. This post will list some of my impressions and settings I made to get it customized to my liking to emulate the look and feel of my previous <a href="https://web.archive.org/web/20200212105912/https://williamhuey.github.io/">blog</a> design.</p>
<h4 id="generating-a-new-project">Generating a new project</h4>
<p>After using the init command, empty folders are generated, but it isn't quite clear on what needs to be modified. Running the server on the newly generated project yields a welcome page, but the physical page is not to be found in any folder.
To get started quickly, I recommend that you use a <a href="https://www.getzola.org/themes/">theme</a> and then customize it to your needs.</p>
<span id="continue-reading"></span><h4 id="adding-posts-to-the-index-page">Adding posts to the index page</h4>
<p>The way posts are display are dependent on how they are nested within the top level "content" folder. Having the "content/blog" route entails that you have a "blog" folder inside the "content" folder. Each url route's configuration is determined by a "_index.md" that lies within each nested folder. This pattern makes for intuitive discernment of content that is in your site.</p>
<p>When you have the folder structure of "content/blog", the site's paginator needs to know that the posts content is one level below the "content" folder. Add the following to "content/blog/_index.md" allows for paginating the posts on the "index.html":</p>
<pre data-lang="md" style="background-color:#0f1419;color:#bfbab0;" class="language-md "><code class="language-md" data-lang="md"><span>transparent = true
</span></code></pre>
<h4 id="mark-the-post-s-summary-content">Mark the post's summary content</h4>
<p>Generally, the index page where you list all the posts will have a quick blurb of the post's content instead of the entire post's listing. They tend to include only the first paragraph of text of the post for each of the paginated post.</p>
<p>By adding</p>
<pre data-lang="md" style="background-color:#0f1419;color:#bfbab0;" class="language-md "><code class="language-md" data-lang="md"><span style="font-style:italic;color:#5c6773;"><!-- more -->
</span></code></pre>
<p>In your post's markdown file, it specifies the point where you want the summary to end and this will truncate the paginated posts display on your "index.html".</p>
<h4 id="note-on-dates-in-the-url">Note on dates in the URL</h4>
<p>Another issue is that there is a common pattern for blogs to have the date encoded into URL scheme.</p>
<p>Take this pattern for example: /2021/01/08/a-new-post</p>
<p>However, due to the explanation of the author of the Zola project, this doesn't seem to be a problem that will be addressed in the near future.
<a href="https://github.com/getzola/zola/issues/635#issuecomment-524564469">https://github.com/getzola/zola/issues/635#issuecomment-524564469</a>.</p>
<p>By forgoing this URL pattern, I have to use an alias field with a value of the old URL scheme in each of the post's front matter to redirect to the new path. This is done to not break the old URL links.</p>
<pre data-lang="md" style="background-color:#0f1419;color:#bfbab0;" class="language-md "><code class="language-md" data-lang="md"><span>aliases = ["2016/12/06/README-md-Reuse/"]
</span></code></pre>
<h4 id="archives-page">Archives page</h4>
<p>The "get_section" helper method comes in handy for globally retrieving the page of concern</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span>{% set section = get_section(path="posts/_index.md") %}
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">h2 </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"title"</span><span style="color:#39bae690;">></span><span>{{section.title}}</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">h2</span><span style="color:#39bae690;">>
</span><span>{% for year, posts in section.pages | reverse | group_by(attribute="year") %}
</span><span>...
</span></code></pre>
<p>Also in the associated "_index.md" file for that template, use the 'sort_by = "date"' key to perform the proper ordering</p>
<pre data-lang="md" style="background-color:#0f1419;color:#bfbab0;" class="language-md "><code class="language-md" data-lang="md"><span>+++
</span><span>title = "Archives"
</span><span>template = "posts.html"
</span><span>aliases = ['/archives']
</span><span>transparent = true
</span><span>sort_by = "date"
</span><span>+++
</span></code></pre>
<h4 id="front-matter-in-posts">Front matter in posts</h4>
<p>Make sure that "[taxonomies]" and "[extra]" go below the other front matter keys in your post markdown files or else Zola will error out.</p>
<pre data-lang="md" style="background-color:#0f1419;color:#bfbab0;" class="language-md "><code class="language-md" data-lang="md"><span>title = 'README.md Reuse'
</span><span>description = "markdown reuse"
</span><span>[taxonomies]
</span></code></pre>
<h4 id="code-blocks">Code Blocks</h4>
<p>Zola does not provide support for description titles headers. Get around this by adding a comment line on the top of the code blocks to describe what you code is about.</p>
<h4 id="assets">Assets</h4>
<p>The "static" folder on the root level is where you should put all images or supporting site files for the site and posts.</p>
<h4 id="additional-notes">Additional Notes</h4>
<h5 id="link-checker">Link Checker</h5>
<p>There is very convenient command built into Zola that can check whether links are dead within your posts</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">zola</span><span> check
</span></code></pre>
<h5 id="documentation">Documentation</h5>
<p>The documentation on <a href="https://tera.netlify.app/docs/">Tera</a>, the templating engine used by Zola, is a good source to consult when you want to modify your templates.</p>
<h5 id="developing">Developing</h5>
<p>When developing, use "http://127.0.0.1:1111/" instead of "http://localhost:1111/" URL in case you get a CORS asset error when accessing fonts.</p>
<h4 id="conclusion">Conclusion</h4>
<p>Overall, Zola is a fast and compact static site generator that is easy to get started due to the ease of setup and configuration. No longer do you need to install NPM modules to get the right dependencies for your static site generator to get off the ground.</p>
README.md Reuse
2016-12-06T00:00:00+00:00
2016-12-06T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/readme-reuse/
<h3 id="common-help-information">Common Help Information</h3>
<p>All NPM and Github repos have README.md as the primary means of communicating the purpose of a specific module or project. In some situations, such as a CLI module, there is almost always a command to list help for the module’s use.</p>
<span id="continue-reading"></span>
<p>Since there is an overlap of providing information in the module and CLI output, it would be beneficial if one can leverage the README.md to display the help text on the console for CLI modules.</p>
<p>One of the ways that this can be done is to use the <a href="https://www.npmjs.com/package/ansimd">ansimd</a> module. This module takes raw markdown input and converts it into an ansi format that is suitable for displaying on the console.</p>
<p>When used with Webpack, this code example will show how ansimd handles markdown for console output:</p>
<p>One will need to use the <a href="https://www.npmjs.com/package/raw-loader">raw-loader</a> module because ansimd operates on raw markdown text.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// webpack.config.js: Loaders Section
</span><span>
</span><span style="color:#59c2ff;">test</span><span style="color:#bfbab0cc;">: </span><span style="color:#95e6cb;">/\.md/</span><span style="color:#bfbab0cc;">,
</span><span style="color:#59c2ff;">loader</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">'raw-loader'
</span></code></pre>
<p>In your specific JavaScript file to display output:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Console ANSI Output
</span><span>
</span><span style="color:#ff7733;">import </span><span>ansimd </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"ansimd"</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>helpText </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"../README.md"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#ffb454;">ansimd</span><span>(helpText))</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Nodejs - Asynchronous File Operations with Try-Catch
2016-11-27T00:00:00+00:00
2016-11-27T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-asynchronous-file-operations-with-try-catch/
<h3 id="handle-situation-when-file-does-not-exist-in-directory">Handle Situation When File Does Not Exist in Directory</h3>
<p>Performing a file reading operation to check whether a file exists before operating might cause a race condition as stated in the Nodejs section on fs.stat:</p>
<span id="continue-reading"></span>
<blockquote>
<p>“Using fs.stat() to check for the existence of a file before calling fs.open(), fs.readFile() or fs.writeFile() is not recommended. Instead, user code should open/read/write the file directly and handle the error raised if the file is not available.”</p>
</blockquote>
<p>In order to make it safer when using an asynchronous file read operation, a try-catch block should always wrap the async file operation because it will allow one to handle the situation when a file is indeed non-existent.</p>
<p>Here is an example where the library ‘co’ and ‘fs-extra-promises’ are used to show safe operation with the try-catch block on async operations:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Log Action of an Observable
</span><span>
</span><span style="color:#ff7733;">import </span><span>{ statAsync } </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'fs-extra-promise'</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">import </span><span>co </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">'co'</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">co</span><span>(</span><span style="color:#ff7733;">function* </span><span style="color:#ffb454;">fileCheck</span><span>() {
</span><span> </span><span style="color:#ff7733;">yield </span><span>co</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">wrap</span><span>(</span><span style="color:#ff7733;">function* </span><span>() {
</span><span> </span><span style="color:#ff7733;">try </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// statAsync is the promise version of fs.stat
</span><span> </span><span style="color:#ff7733;">const </span><span>fileExists </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">yield </span><span style="color:#ffb454;">statAsync</span><span>(</span><span style="color:#c2d94c;">'a/path/that/does/not/exists'</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Check if is a file type of folder type
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Do stuff when the path does exist
</span><span> </span><span style="font-style:italic;color:#5c6773;">// fileExists.isFile() || fileExists.isDirectory()
</span><span> } </span><span style="color:#ff7733;">catch </span><span>(e) {
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Errors out here because the path stated does not exists
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Do stuff here where there is an error
</span><span> </span><span style="font-style:italic;color:#5c6773;">// ...
</span><span> }
</span><span> };
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Nodejs - Quick Tips #4
2016-10-16T00:00:00+00:00
2016-10-16T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-quick-tips-4/
<h3 id="identify-streams-better-when-logging-two-or-more-streams-at-a-time">Identify Streams Better when Logging Two or More Streams at a Time</h3>
<p>Rxjs provides a means of performing a ‘side effect’ without modifying the observable through the observable chain. The ‘do’ command is good candidate for use when there is a need to log out information when specific operations are performed.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Log Action of an Observable
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Provide an indication of which interval has action performed
</span><span style="color:#ff7733;">const </span><span>interval1 </span><span style="color:#f29668;">= </span><span>Rx</span><span style="color:#f29668;">.</span><span>Observable</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">interval</span><span>(</span><span style="color:#f29718;">1000</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">const </span><span>example1 </span><span style="color:#f29668;">= </span><span>interval1</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">do</span><span>((</span><span style="color:#f29718;">val</span><span>) </span><span style="color:#ff7733;">=>
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">`Early interval, second(s) elapsed! : ${</span><span>val</span><span style="color:#c2d94c;">}`</span><span>)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">const </span><span>interval </span><span style="color:#f29668;">= </span><span>Rx</span><span style="color:#f29668;">.</span><span>Observable</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">interval</span><span>(</span><span style="color:#f29718;">2000</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">const </span><span>example2 </span><span style="color:#f29668;">= </span><span>interval</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">do</span><span>((</span><span style="color:#f29718;">val</span><span>) </span><span style="color:#ff7733;">=>
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">`Later interval, second(s) elapsed! : ${</span><span>val</span><span style="color:#c2d94c;">}</span><span style="color:#95e6cb;">\n</span><span style="color:#c2d94c;">`</span><span>)
</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>Observable</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">merge</span><span>(example1</span><span style="color:#bfbab0cc;">, </span><span>example2)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>((</span><span style="color:#f29718;">x</span><span>) </span><span style="color:#ff7733;">=> </span><span>{})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="no-default-call-needed-when-requiring-transpiled-module-from-babel">No ‘default’ Call Needed when ‘requiring’ transpiled module from Babel</h3>
<p>The require call in a ES5 transpiled module from ES6 requires you to call the ‘default’ key of the return function value before the actual functionality can be accessed:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// More Boilerplate for 'Requiring' a Module
</span><span>
</span><span style="color:#ff7733;">var </span><span>fantasticModule </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"my-fantastic-module-name"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>fantasticModule</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">default</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Have to do the above instead of:
</span><span style="font-style:italic;color:#5c6773;">// var fantasticModule = require('my-fantastic-module-name');
</span><span style="font-style:italic;color:#5c6773;">// fantasticModule();
</span></code></pre>
Nodejs - Quick Tips #3
2016-07-03T00:00:00+00:00
2016-07-03T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-quick-tips-3/
<h3 id="babel-requiring-es2015-file-from-es5">Babel - Requiring ES2015 File from ES5</h3>
<p>In the situation where you desire to use a ES5 file to refer to a ES2015 file, the on-the-fly compilation option of Babel can be one of the ways to do so.</p>
<p>This case might come up when you are intending to run an init file that you do not want to perform any Babel compilation, but you still want the ES5 file to serve as the entry point for your module.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// On the Fly Compilation
</span><span>
</span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"babel-core/register"</span><span>)({
</span><span> presets</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#c2d94c;">"es2015"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>This technique is more suited for activities which do not need quick processing time because this method really slows execution.</p>
<p>It will be more appropriate for operations that are not frequently run, such as some tests, and it would also not be advisable for initializing a cli node module because the slowdown will be quite evident.</p>
<p>As a side note for speeding up node cli execution, it is more beneficial to reduce the number of ‘require’ calls as noted here, which makes for the argument of using webpack to bundle your NPM modules into one file.</p>
<h3 id="testing-command-line-npm-modules">Testing Command Line NPM Modules</h3>
<p>Most NPM modules are used programmatically through importing or requiring them into the file you are working on, but for the other times when your NPM module is used as a CLI module, input will need to be taken from the console.</p>
<p>For the properly testing of these CLI modules, the ‘childProcess.exec’ method can be used. The following example will start the npm at the entry point.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// child_process
</span><span>
</span><span style="color:#ff7733;">import </span><span>childProcess </span><span style="color:#ff7733;">from </span><span style="color:#c2d94c;">"child_process"</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">const </span><span>exec </span><span style="color:#f29668;">= </span><span>childProcess</span><span style="color:#f29668;">.</span><span>exec</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">//Point to the entry point of NPM module
</span><span style="color:#ff7733;">const </span><span>cliEntryFile </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"node " </span><span style="color:#f29668;">+ </span><span>__dirname </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"/../bin/my-cli-init.js"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">//Execute the command line with the supplied argument
</span><span style="color:#ffb454;">exec</span><span>(cliEntryFile </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">" my-cool-command"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">error</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">stdout</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">stderr</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">//Rest of command actions
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Nodejs - Quick Tips #2
2016-04-17T00:00:00+00:00
2016-04-17T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-quick-tips-2/
<h3 id="process-exit-and-time-elapse">Process Exit and Time Elapse</h3>
<p>When performing a long-running operation in the terminal, such as file generation, a user would like to know how long the task has run.</p>
<span id="continue-reading"></span>
<p>A simple way to determine how much time has elapsed in general will be to listen to 'exit' event on the process object. This can be combined with the 'hrtime' method on the process object to provide a detailed time interval.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Using Built-In Nodejs Functions for Timing
</span><span>
</span><span style="color:#ff7733;">let </span><span>time </span><span style="color:#f29668;">= </span><span>process</span><span style="color:#f29668;">.</span><span style="color:#f07178;">hrtime</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>process</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"exit"</span><span style="color:#bfbab0cc;">, </span><span>() </span><span style="color:#ff7733;">=> </span><span>{
</span><span> </span><span style="color:#ff7733;">let </span><span>timeDiff </span><span style="color:#f29668;">= </span><span>process</span><span style="color:#f29668;">.</span><span style="color:#f07178;">hrtime</span><span>(time)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(
</span><span> </span><span style="color:#c2d94c;">"Time elapsed for file(s) and folder(s) generation: %d nanoseconds"</span><span style="color:#bfbab0cc;">,
</span><span> timeDiff[</span><span style="color:#f29718;">0</span><span>] </span><span style="color:#f29668;">* </span><span style="color:#f29718;">1e9 </span><span style="color:#f29668;">+ </span><span>timeDiff[</span><span style="color:#f29718;">1</span><span>]
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="babel-webpack-eslint-boilerplate">Babel Webpack Eslint Boilerplate</h3>
<p>The JavaScript community has embraced ES2015 as the go-to JavaScript version to do modern web development. There are many Gulp and Babel boilerplates out there, but I found out that it is not as reliable as the Webpack and Babel combination because the Gulp watch tasks did not always pick up file changes for me.</p>
<p>Here is a simple config for creating a starter ES2015 JavaScript project.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"my-great-module"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"version"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"1.0.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"description"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"main"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"index.js"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"scripts"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"start"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"node_modules/webpack/bin/webpack.js --watch"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"author"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"license"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"ISC"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"dependencies"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"babel"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^6.5.2"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"babel-core"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^6.7.2"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"babel-eslint"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^6.0.2"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"babel-loader"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^6.2.4"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"babel-plugin-syntax-async-functions"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^6.5.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"babel-plugin-transform-runtime"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^6.6.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"babel-preset-es2015"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^6.6.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"babel-preset-stage-3"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^6.5.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"eslint"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^2.8.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"eslint-config-standard"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^5.1.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"eslint-loader"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^1.3.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"eslint-plugin-babel"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^3.2.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"eslint-plugin-promise"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^1.1.0"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"eslint-plugin-standard"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^1.3.2"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"webpack"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"^1.12.14"
</span><span> }
</span><span>}
</span></code></pre>
<p>Async functions are actually a ES2016 feature, but they are a really useful functionality, so useful that I included it into the boilerplate.</p>
<p>Webpack is a module bundler and loader, but it can also perform file transformations for us. Webpack in our case, will be used to transpile ES2015 and for linting.</p>
<p>Webpack is configured with a webpack.config.js file:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// webpack.config.js
</span><span>
</span><span style="color:#ff7733;">var </span><span>path </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"path"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#39bae6;">module</span><span style="color:#f29668;">.</span><span style="font-style:italic;color:#39bae6;">exports </span><span style="color:#f29668;">= </span><span>{
</span><span> entry</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"./the-main-input-file.js"</span><span style="color:#bfbab0cc;">,
</span><span> output</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> path</span><span style="color:#bfbab0cc;">: </span><span>path</span><span style="color:#f29668;">.</span><span style="color:#f07178;">join</span><span>(__dirname</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"/dist/"</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> filename</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"my-output-file.js"</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> module</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> preLoaders</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> { test</span><span style="color:#bfbab0cc;">: </span><span style="color:#95e6cb;">/\.js</span><span style="color:#ff7733;">$</span><span style="color:#95e6cb;">/</span><span style="color:#bfbab0cc;">, </span><span>loader</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"eslint-loader"</span><span style="color:#bfbab0cc;">, </span><span>exclude</span><span style="color:#bfbab0cc;">: </span><span style="color:#95e6cb;">/node_modules/ </span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> loaders</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> {
</span><span> test</span><span style="color:#bfbab0cc;">: </span><span style="color:#95e6cb;">/\.js</span><span style="color:#ff7733;">$</span><span style="color:#95e6cb;">/</span><span style="color:#bfbab0cc;">,
</span><span> exclude</span><span style="color:#bfbab0cc;">: </span><span style="color:#95e6cb;">/node_modules/</span><span style="color:#bfbab0cc;">,
</span><span> loader</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"babel-loader"</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> resolve</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> extensions</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#c2d94c;">""</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">".config.js"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">".js"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> eslint</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> configFile</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"./.eslintrc.json"</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> babel</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> presets</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#c2d94c;">"es2015"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"stage-3"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>By default, Webpack intends to have an entry point file which serves as a manifest file for all your JavaScript files to be transformed to a single output file.</p>
<p>Now a .babelrc is required to configure how Babel is to transpile ES2015 JavaScript:</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"presets"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#c2d94c;">"stage-3"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"es2015"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"plugins"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#c2d94c;">"transform-runtime"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"syntax-async-functions"</span><span>]
</span><span>}
</span></code></pre>
<p>A stage-3 preset is needed for the async function feature in ES2016.</p>
<p>Lastly, for the eslintrc.json file, this will provide the rules for linting JavaScript:</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"parser"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"babel-eslint"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"parserOptions"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"ecmaVersion"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">7</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"sourceType"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"module"
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"plugins"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#c2d94c;">"babel"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"root"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ecmaFeatures"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"arrowFunctions"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"binaryLiterals"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"blockBindings"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"classes"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"defaultParams"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"destructuring"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"forOf"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"generators"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"modules"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"objectLiteralComputedProperties"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"objectLiteralDuplicateProperties"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"objectLiteralShorthandMethods"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"objectLiteralShorthandProperties"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"octalLiterals"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"regexUFlag"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"regexYFlag"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"spread"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"superInFunctions"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"templateStrings"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"unicodeCodePointEscapes"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"globalReturn"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"rules"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"strict"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-var"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"comma-dangle"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"never"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-cond-assign"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"always"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-console"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-debugger"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-alert"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-constant-condition"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-dupe-keys"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-duplicate-case"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-empty"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-ex-assign"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-extra-boolean-cast"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-extra-semi"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-func-assign"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-inner-declarations"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-invalid-regexp"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-irregular-whitespace"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-obj-calls"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"quote-props"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-sparse-arrays"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-unreachable"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"use-isnan"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"block-scoped-var"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"quotes"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"single"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-shadow"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-shadow-restricted-names"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-unused-vars"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"vars"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"local"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"args"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"after-used"
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-use-before-define"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"consistent-return"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"complexity"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">7</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"curly"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"multi-line"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"default-case"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"dot-notation"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"allowKeywords"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"eqeqeq"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"guard-for-in"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-caller"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-else-return"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-eq-null"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-eval"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-extend-native"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-extra-bind"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-fallthrough"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-floating-decimal"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-implied-eval"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-lone-blocks"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-loop-func"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-multi-str"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-native-reassign"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-new"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-new-func"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-new-wrappers"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-octal"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-octal-escape"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-param-reassign"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-proto"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-redeclare"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-return-assign"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-script-url"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-self-compare"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-sequences"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-throw-literal"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-with"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"radix"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"vars-on-top"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"wrap-iife"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"any"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"yoda"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"indent"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"brace-style"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"1tbs"</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"allowSingleLine"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"quotes"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"single"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"avoid-escape"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"camelcase"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"properties"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"never"
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"comma-spacing"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"before"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"after"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"comma-style"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"last"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"eol-last"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"key-spacing"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"beforeColon"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"afterColon"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"new-cap"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"newIsCap"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-multiple-empty-lines"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"max"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-nested-ternary"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-new-object"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-spaced-func"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-trailing-spaces"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-extra-parens"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"no-underscore-dangle"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"one-var"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"never"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"padded-blocks"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"semi"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"always"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"semi-spacing"</span><span style="color:#bfbab0cc;">: </span><span>[
</span><span> </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> {
</span><span> </span><span style="color:#c2d94c;">"before"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"after"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">true
</span><span> }
</span><span> ]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"keyword-spacing"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"space-before-blocks"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"space-before-function-paren"</span><span style="color:#bfbab0cc;">: </span><span>[</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"never"</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"space-infix-ops"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"keyword-spacing"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"spaced-comment"</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0
</span><span> }
</span><span>}
</span></code></pre>
Velocityjs - Effects
2015-07-20T00:00:00+00:00
2015-07-20T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/velocityjs-effects/
<p>For your heavy-duty JavaScript animations, I recommend <a href="http://julian.com/research/velocity/">Velocityjs</a> since it has many features and great documentation. <br> Here are some simple effects that I find useful if you have chosen to use Velocityjs:</p>
<span id="continue-reading"></span><h3 id="pulsate-throb">Pulsate / Throb</h3>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Grow and Shrink Element for Five Times
</span><span>
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">velocity</span><span>({ scale</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2 </span><span>}</span><span style="color:#bfbab0cc;">, </span><span>{ loop</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">5 </span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p><a href="http://jsbin.com/gocinunome/1/">Pulsate Demo</a></p>
<h3 id="show-and-rotate">Show and Rotate</h3>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Appear, Spins, and Disappear
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Complete animation within half a second
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">velocity</span><span>(
</span><span> { scale</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">3</span><span style="color:#bfbab0cc;">, </span><span>opacity</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span>rotateZ</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"360deg" </span><span>}</span><span style="color:#bfbab0cc;">,
</span><span> { duration</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">500 </span><span>}
</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p><a href="http://jsbin.com/razexohare/2">Spin Demo</a></p>
<h3 id="stagger-elements">Stagger Elements</h3>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Group Zoom-in
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Assumes that the UI Pack (velocity.ui.js) is in place
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">".group-of-elements"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">velocity</span><span>(</span><span style="color:#c2d94c;">"transition.whirlIn"</span><span style="color:#bfbab0cc;">, </span><span>{ stagger</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">500 </span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p><a href="http://jsbin.com/tezofuraqi/2/">Stagger Group Demo</a></p>
Meteor - Quick Tips #4
2015-05-16T00:00:00+00:00
2015-05-16T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/meteor-quick-tips-4/
<h3 id="filtering-differences-between-minimongo-and-mongo">Filtering Differences between Minimongo and Mongo</h3>
<p>Minimongo is Meteor's client-side implementation of Mongodb, while Mongodb is referred to as Mongo.</p>
<span id="continue-reading"></span>
<p>In Mongo, when limiting the fields of the return documents, there are two parameters. Minimongo also takes two parameters, but the second parameter needs a field wrapper to denote the fields to return.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Cut Down Documents Field Return
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Mongodb
</span><span>CollectionName</span><span style="color:#f29668;">.</span><span style="color:#f07178;">find</span><span>({}</span><span style="color:#bfbab0cc;">, </span><span>{ onlyThisField</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1 </span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Minimongo
</span><span>CollectionName</span><span style="color:#f29668;">.</span><span style="color:#f07178;">find</span><span>({}</span><span style="color:#bfbab0cc;">, </span><span>{ fields</span><span style="color:#bfbab0cc;">: </span><span>{ onlyThisField</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1 </span><span>} })</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="return-template-in-template-helper">Return Template in Template Helper</h3>
<p>Template helpers only return a string when outputting to the templates, so an object output is not possible. The closest thing to rendering a template out to another template is to use Blaze.toHTML. The spacebar template needs to have the triple braces for raw output to convert a string to an actual element.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Blaze Returns a Html String
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Rendered
</span><span>Template</span><span style="color:#f29668;">.</span><span>blank</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">onRendered</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>data</span><span style="color:#f29668;">.</span><span>rv </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">ReactiveVar</span><span>(</span><span style="color:#c2d94c;">""</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>data</span><span style="color:#f29668;">.</span><span>rv</span><span style="color:#f29668;">.</span><span style="color:#f07178;">set</span><span>(Blaze</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">toHTML</span><span>(Template</span><span style="color:#f29668;">.</span><span>postInfo))</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Helpers
</span><span>Template</span><span style="color:#f29668;">.</span><span>post</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">helpers</span><span>({
</span><span> </span><span style="color:#ffb454;">info</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>Template</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">instance</span><span>()</span><span style="color:#f29668;">.</span><span>data</span><span style="color:#f29668;">.</span><span>rv</span><span style="color:#f29668;">.</span><span style="color:#f07178;">get</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Output the Html String -->
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">template </span><span style="color:#ffb454;">name</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"post"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">class</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"reading"</span><span style="color:#39bae690;">></span><span>{{{info}}}</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">template</span><span style="color:#39bae690;">>
</span></code></pre>
Meteor - Quick Tips #3
2015-03-25T00:00:00+00:00
2015-03-25T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/meteor-quick-tips-3/
<h3 id="template-helpers-and-subscriptions">Template Helpers and Subscriptions</h3>
<p>Templates helpers format data onto your templates, but one must ensure that subscription data is fully loaded before the template helpers have a chance to render.</p>
<span id="continue-reading"></span>
<p>With the help of <a href="https://github.com/iron-meteor/iron-router">Iron Router</a>, use the 'this.ready()' check inside the data option.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Router.js
</span><span>
</span><span>Router</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">route</span><span>(</span><span style="color:#c2d94c;">'/post/:_id'</span><span style="color:#bfbab0cc;">, </span><span>{
</span><span> </span><span style="color:#ffb454;">waitOn</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function</span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>Meteor</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(</span><span style="color:#c2d94c;">'post'</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>params</span><span style="color:#f29668;">.</span><span>_id)
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">data</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">ready</span><span>()) {
</span><span> </span><span style="color:#ff7733;">return </span><span>{
</span><span> post</span><span style="color:#bfbab0cc;">: </span><span>Posts</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">findOne</span><span>({_id</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>params</span><span style="color:#f29668;">.</span><span>_id});
</span><span> }
</span><span> }
</span><span> }
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Once the above is in place, a template helper can now safely render the subscription data.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Template.js
</span><span>
</span><span>Template</span><span style="color:#f29668;">.</span><span>post</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">helpers</span><span>({
</span><span> </span><span style="color:#ffb454;">post</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>Template</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">currentData</span><span>()</span><span style="color:#f29668;">.</span><span>post</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="remove-event-listeners-from-blaze-templates">Remove Event Listeners From Blaze Templates</h3>
<p>As of Meteor 1.0.4.2, this can not be done. The <a href="http://docs.meteor.com/#/full/blaze_tohtml">Blaze to HTML</a> looked promising, but this only creates static html element from a template, it does not provide the ability to render an active Blaze template inert.</p>
<p>For example, the following template has a click event listener attached, but there is no way to undo or remove the click event listener.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Click Event Listener
</span><span>
</span><span>Template</span><span style="color:#f29668;">.</span><span>my</span><span style="color:#f29668;">.</span><span>template</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">events</span><span>({
</span><span> </span><span style="color:#c2d94c;">"click #container a"</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">evt</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">//do some stuff here
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Meteor - Quick Tips #2
2015-02-14T00:00:00+00:00
2015-02-14T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/meteor-quick-tips-2/
<h3 id="blaze-template-removal">Blaze Template Removal</h3>
<p>Instead of using jQuery to perform DOM removal operations, Meteor's Blaze remove can do the same thing with the following</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Remove Element with Blaze
</span><span>
</span><span>Blaze</span><span style="color:#f29668;">.</span><span style="color:#f07178;">remove</span><span>(Template</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">instance</span><span>()</span><span style="color:#f29668;">.</span><span>view)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The above can be run in the Template's render function or in a Template event handler. Most likely, the removal will take place in an event handler.</p>
<h3 id="attach-template-s-local-variables-to-template-instance">Attach Template's Local Variables to Template Instance</h3>
<p>Since all Templates files variables are encapsulated within a closure, there might be possibilities of memory leaks. To ensure that local variables are properly cleaned up, attached a data store object to the Template instance. When the Template instance is destroy, so will all the references to its variables.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// DataStore Object on Template Instance
</span><span>
</span><span style="color:#ff7733;">var </span><span>ds </span><span style="color:#f29668;">= </span><span>{
</span><span> thing1</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">,
</span><span> thing2</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">,
</span><span>}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>Template</span><span style="color:#f29668;">.</span><span>myTemplate</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">created </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span>ds </span><span style="color:#f29668;">= </span><span>ds</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Meteor - Quick Tips #1
2015-01-19T00:00:00+00:00
2015-01-19T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/meteor-quick-tips-1/
<h3 id="redirecting-for-non-logged-in-users">Redirecting for Non-Logged-In Users</h3>
<p>When an app has more than one URL and any other URL other than the /home URL is restricted for logged-in users, than this requireLogin function will direct users back to the home URL when the user is not logged in. This is assuming that the IronRouter package is used.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Force Login for Privileged Areas
</span><span>
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">requireLogin </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">!</span><span>Meteor</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">user</span><span>()) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">!</span><span>Meteor</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">loggingIn</span><span>()) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">redirect</span><span>(</span><span style="color:#c2d94c;">"home"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> } </span><span style="color:#ff7733;">else </span><span>{
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">next</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>Router</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">onBeforeAction</span><span>(requireLogin</span><span style="color:#bfbab0cc;">, </span><span>{ except</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"home" </span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="json-data-for-fixtures">JSON Data for Fixtures</h3>
<p>Assuming that "exercise.json" is stored in your /private directory in the root of the Meteor project, the fixture.js file in your /server folder makes use of Assets.getText in conjunction with JSON.parse to get the data in a form that can be readily accessed.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Get Private JSON Data
</span><span>
</span><span style="color:#ff7733;">var </span><span>exercises </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#f29668;">JSON</span><span style="color:#f29668;">.</span><span style="color:#f07178;">parse</span><span>(Assets</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">getText</span><span>(</span><span style="color:#c2d94c;">"exercises.json"</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">for </span><span>(</span><span style="color:#ff7733;">var </span><span>i </span><span style="color:#f29668;">= </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span>len </span><span style="color:#f29668;">= </span><span>exercises</span><span style="color:#f29668;">.</span><span>length</span><span style="color:#bfbab0cc;">; </span><span>i </span><span style="color:#f29668;">< </span><span>len</span><span style="color:#bfbab0cc;">; </span><span>i</span><span style="color:#f29668;">++</span><span>) {
</span><span> </span><span style="color:#ff7733;">var </span><span>exercise </span><span style="color:#f29668;">= </span><span>exercises[i]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> Exercises</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">insert</span><span>({
</span><span> name</span><span style="color:#bfbab0cc;">: </span><span>exercise</span><span style="color:#f29668;">.</span><span>name</span><span style="color:#bfbab0cc;">,
</span><span> type</span><span style="color:#bfbab0cc;">: </span><span>exercise</span><span style="color:#f29668;">.</span><span>type</span><span style="color:#bfbab0cc;">,
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
Validating Numbers
2014-12-24T00:00:00+00:00
2014-12-24T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/validating-numbers/
<h3 id="is-the-content-intended-to-be-a-number">Is the content intended to be a number?</h3>
<p>When dealing with validations in input forms, one occasionally has to determine if the content entered is actually a number.
However, the input content will always be string when performing a check on an input.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Always a String
</span><span>
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"input"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"change"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Outputs 'string'
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#f29668;">typeof </span><span style="color:#ffb454;">$</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">val</span><span>())</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Although this behavior is convenient for most situations, it could be a hassle for numbers.</p>
<p>To solve this problem, parseInt will be used.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// String to Number
</span><span>
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">'input'</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">'change'</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function</span><span>() {
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Outputs 'string'
</span><span> </span><span style="font-style:italic;color:#5c6773;">// The '10' is for decimal form
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#f29668;">typeof </span><span style="color:#f07178;">parseInt</span><span>(</span><span style="color:#ffb454;">$</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">val</span><span>()</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">10</span><span>);
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Want to point out that my <a href="https://williamhuey.github.io/posts/validating-numbers/2014/08/26/Simple-Validator/">validator</a> function could be used in place of typeof.</p>
<h3 id="mathematically-inclined-cases">Mathematically Inclined Cases</h3>
<p>Besides representing numbers as integers or decimal, there are also situations where numbers could be <a href="//http://speakingjs.com/es5/ch11.html#two_zeros">negative or positive zero</a> or represented in <a href="http://speakingjs.com/es5/ch11.html#_exponent">exponential</a> form. There are even more extreme cases such as <a href="http://speakingjs.com/es5/ch11.html#infinity">infinity</a>.</p>
<p>For these cases, the numbers representations are valid, but may be unusual for some individuals. It could be worthwhile to also validate against these cases and to prevent a jarring user experience when inputting in forms.</p>
WordPress - Mixed Content Warning
2014-11-26T00:00:00+00:00
2014-11-26T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/wordpress-mixed-content-warning/
<h3 id="insecured-content">Insecured Content</h3>
<p>Recently, when working with WordPress, I noticed that when using the <a href="https://wordpress.org/plugins/master-slider/">Master Slider</a> plugin, a content slider/carousel plugin, Firefox was complaining about mixed content from the images. I was using SSL on the site.</p>
<span id="continue-reading"></span>
<p>Initially I thought this was the wrongdoing of the plugin, but looking through the support pages for the plugin did not yield any immediate answers. The source did not yield any obvious error.</p>
<p>While trying to figure out the problem with the slider, I also notice the warning of the mixed content from the media library of WordPress.</p>
<p>This lead me to think that it may not be the plugin's fault, and there might be something wrong with WordPress or with the configuration at least.</p>
<p>Looking further into the situation lead me to figure out that I have forgotten to change the URL settings in WordPress.</p>
<p>To solve my problem I navigated to</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>Settings > General
</span></code></pre>
<p>Then changing</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>WordPress URL
</span><span>Site Address URL
</span></code></pre>
<p>values to use https for the domain to solve the problem.</p>
Bash - Clear History Upon Exiting Terminal
2014-10-28T00:00:00+00:00
2014-10-28T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/bash-clear-history-upon-exiting-terminal/
<h3 id="cleaning-terminal-history">Cleaning terminal history</h3>
<p>Whether you want to have some sense of privacy or a sense of cleanliness, working with the terminal leaves a history that you might want to remove.</p>
<span id="continue-reading"></span>
<p>Removing the .bash_history upon exiting the terminal is the goal for this post.</p>
<p>Create a .rm_terminal_history.sh file in the directory that .bashrc file is in.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># .rm_terminal_history.sh
</span><span>
</span><span style="color:#ffb454;">rm_hist</span><span>(){
</span><span> </span><span style="color:#ff7733;">if </span><span style="color:#f07178;">[ </span><span style="color:#f29718;">-f </span><span style="font-style:italic;color:#39bae6;">~</span><span>/.bash_history </span><span style="color:#f07178;">]
</span><span> </span><span style="color:#ff7733;">then
</span><span> </span><span style="color:#ffb454;">rm </span><span style="font-style:italic;color:#39bae6;">~</span><span>/.bash_history
</span><span> </span><span style="color:#ffb454;">history</span><span style="color:#f29718;"> -c
</span><span> </span><span style="color:#f07178;">echo </span><span style="color:#c2d94c;">".bash_history removed."
</span><span> </span><span style="color:#f07178;">exit</span><span> 0
</span><span> </span><span style="color:#ff7733;">else
</span><span> </span><span style="color:#f07178;">echo </span><span style="color:#c2d94c;">".bash_history can not be found."
</span><span> </span><span style="color:#f07178;">exit</span><span> 1
</span><span> </span><span style="color:#ff7733;">fi
</span><span>}
</span><span>
</span><span style="color:#f07178;">trap</span><span> rm_hist EXIT
</span></code></pre>
<p>After the script is created, give it executable privileges.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Make Script Executable
</span><span>
</span><span style="color:#ffb454;">chmod</span><span> +x .rm_terminal_history.sh
</span></code></pre>
<p>Now add a reference to your .bashrc file for the script to run</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Add Entry to .bashrc
</span><span>
</span><span style="font-style:italic;color:#5c6773;">#Add following line to .bashrc
</span><span style="color:#f07178;">source </span><span style="font-style:italic;color:#39bae6;">~</span><span>/.rm_terminal_history.sh
</span></code></pre>
<p>The .bash_history file will be removed when exiting the terminal at any time.</p>
WordPress Quick Tips #1
2014-09-25T00:00:00+00:00
2014-09-25T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/wordpress-quick-tips-1/
<h3 id="enqueue-multiple-google-fonts-into-one-stylesheet">Enqueue Multiple Google Fonts into One Stylesheet</h3>
<p>Taking the twenty-fourteen theme for example, modify the 'functions.php' by separate the different fonts that is to be used with a pipe character in the twentyfourteen_font_url function.</p>
<span id="continue-reading"></span><pre data-lang="php" style="background-color:#0f1419;color:#bfbab0;" class="language-php "><code class="language-php" data-lang="php"><span># Single Stylesheet for a Group of Fonts
</span><span>
</span><span>function twentyfourteen_font_url() {
</span><span> $font_url = '';
</span><span>
</span><span> if ( 'off' !== _x( 'on', 'Oswald font: on or off', 'twentyfourteen' ) ) {
</span><span> $font_url = add_query_arg( 'family', urlencode( 'Oswald:400|Droid Sans:400'), "//fonts.googleapis.com/css" );
</span><span> }
</span><span>
</span><span> return $font_url;
</span><span>}
</span><span>
</span><span>function twentyfourteen_scripts() {
</span><span> wp_enqueue_style( 'googlefont-oswald-and-opensans', twentyfourteen_font_url(), array(), null );
</span><span>
</span><span> //...
</span><span>}
</span><span>
</span><span>add_action( 'wp_enqueue_scripts', 'twentyfourteen_scripts' );
</span></code></pre>
<h3 id="bouncing-contact-form-7-emails">Bouncing Contact Form 7 Emails</h3>
<p>If you wish to receive messages from the Contact Form 7 form to your personal email, but the behavior is spotty (emails not being sent to you), then it would help to install the <a href="https://wordpress.org/plugins/flamingo/">Flamingo plugin</a>. This plugin will save messages to WordPress, such that messages will be accessible from the WordPress dashboard.</p>
Simple Validator
2014-08-26T00:00:00+00:00
2014-08-26T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/simple-validator/
<h3 id="simply-validating">Simply Validating</h3>
<p>Validation conjures up thoughts of input form validation, but validation could also pop up elsewhere when there is user input such as the case for parameters in jQuery plugins.</p>
<span id="continue-reading"></span>
<p>The following article will describe a build-up of a modular validate function.</p>
<p>The validation will perform as follows</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Format and Example
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// validate(inputData, attr, attrRule, againstValue);
</span><span style="color:#59c2ff;">ex</span><span style="color:#bfbab0cc;">: </span><span style="color:#ffb454;">validate</span><span>(</span><span style="color:#f29718;">10</span><span style="color:#bfbab0cc;">, </span><span>number</span><span style="color:#bfbab0cc;">, </span><span>greaterThan</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">11</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The example function will determine whether 10 as a number is greater than 11, which turns out to be false. The output of validate will be a string that states the error.</p>
<p>We start off with the validate variable as an immediately-invoking function with the variables that are to be accepted in the validate function</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Variables Accepted
</span><span>
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">validate </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span>inputData</span><span style="color:#bfbab0cc;">, </span><span>againstValue</span><span style="color:#bfbab0cc;">, </span><span>attr</span><span style="color:#bfbab0cc;">, </span><span>attrRule</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The validate function will have the blocks within</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// General Function Layout
</span><span>
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">validate </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span>inputData</span><span style="color:#bfbab0cc;">, </span><span>againstValue</span><span style="color:#bfbab0cc;">, </span><span>attr</span><span style="color:#bfbab0cc;">, </span><span>attrRule</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Validation Messages
</span><span> </span><span style="color:#ff7733;">var </span><span>validationMessage </span><span style="color:#f29668;">= </span><span>{}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Validation Definitions
</span><span> </span><span style="color:#ff7733;">var </span><span>validationDefinitions </span><span style="color:#f29668;">= </span><span>{}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Run Check
</span><span> </span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">validationCheck </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Input Gather
</span><span> </span><span style="color:#ff7733;">return function </span><span>() {}</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="accept-variables-input">Accept Variables Input</h3>
<p>The 'Input Gather' function will expose the arguments to the variables that are open within the validate function. The main comparison is done with the validationDefinition function, before its boolean outcome is handed off and checked by validationCheck.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Input Gather
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Start off the validation
</span><span style="color:#ff7733;">return function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span>args </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">arguments</span><span style="color:#bfbab0cc;">;
</span><span> attr </span><span style="color:#f29668;">= </span><span>args[</span><span style="color:#f29718;">1</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span> attrRule </span><span style="color:#f29668;">= </span><span>args[</span><span style="color:#f29718;">2</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span> inputData </span><span style="color:#f29668;">= </span><span>args[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span> againstValue </span><span style="color:#f29668;">= </span><span>args[</span><span style="color:#f29718;">3</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Kicks off the validation check with supplied data
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">validationCheck</span><span>(validationDefinitions[attr][attrRule]())</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="validation-rules">Validation Rules</h3>
<p>The validationDefinitions variable is an object that has a mapping of attr: {attrRule: function(){}}. The actual validation process is done by calling upon the attrRule definition function.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Validation Definitions
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Validation patterns
</span><span style="font-style:italic;color:#5c6773;">// Passed-in data are compared against the desired value (againstValue)
</span><span style="color:#ff7733;">var </span><span>validationDefinitions </span><span style="color:#f29668;">= </span><span>{
</span><span> number</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#ffb454;">greaterThan</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>inputData </span><span style="color:#f29668;">> </span><span>againstValue</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="determining-validness">Determining Validness</h3>
<p>The result of the validation helps determine if a validation message needs to be sent</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Validation Check
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Run the checks against the validation patterns
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">validationCheck </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">passedCheck</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Only generate a message value was not validated
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">!</span><span>passedCheck) {
</span><span> </span><span style="color:#ff7733;">return </span><span>validationMessage[attr][attrRule]()</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="noting-the-validation-error">Noting the Validation Error</h3>
<p>The output of an invalid data input will result in a message being return.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Validation Messages
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Determine which message type should be used
</span><span style="color:#ff7733;">var </span><span>validationMessage </span><span style="color:#f29668;">= </span><span>{
</span><span> number</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Generate the message for a specific attrRule
</span><span> </span><span style="color:#ffb454;">greaterThan</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>inputData </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">" is not greater than " </span><span style="color:#f29668;">+ </span><span>againstValue</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="all-together">All Together</h3>
<p>The validate function is complete on the bottom. More validation definitions and messages be added in the proper blocks.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Complete Validation Function
</span><span>
</span><span style="color:#ff7733;">var </span><span>validate </span><span style="color:#f29668;">= </span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Make these variables accessible to all functions inside validator
</span><span> </span><span style="color:#ff7733;">var </span><span>inputData</span><span style="color:#bfbab0cc;">, </span><span>againstValue</span><span style="color:#bfbab0cc;">, </span><span>attr</span><span style="color:#bfbab0cc;">, </span><span>attrRule</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Determine which message type should be used
</span><span> </span><span style="color:#ff7733;">var </span><span>validationMessage </span><span style="color:#f29668;">= </span><span>{
</span><span> number</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Generate the message for a specific attrRule
</span><span> </span><span style="color:#ffb454;">greaterThan</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>inputData </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">" is not greater than " </span><span style="color:#f29668;">+ </span><span>againstValue</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">/*
</span><span style="font-style:italic;color:#5c6773;"> lessThan: function() {
</span><span style="font-style:italic;color:#5c6773;"> return inputData + ' is not less than ' + againstValue;
</span><span style="font-style:italic;color:#5c6773;"> }
</span><span style="font-style:italic;color:#5c6773;">
</span><span style="font-style:italic;color:#5c6773;"> // More messages here
</span><span style="font-style:italic;color:#5c6773;"> */
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Validation patterns
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Passed-in data are compared against the desired value (againstValue)
</span><span> </span><span style="color:#ff7733;">var </span><span>validationDefinitions </span><span style="color:#f29668;">= </span><span>{
</span><span> number</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#ffb454;">greaterThan</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>inputData </span><span style="color:#f29668;">> </span><span>againstValue</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">/*
</span><span style="font-style:italic;color:#5c6773;"> ,lessThan: function() {
</span><span style="font-style:italic;color:#5c6773;"> return inputData < againstValue;
</span><span style="font-style:italic;color:#5c6773;"> }
</span><span style="font-style:italic;color:#5c6773;"> // More rules here
</span><span style="font-style:italic;color:#5c6773;"> */
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Run the checks against the validation patterns
</span><span> </span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">validationCheck </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">passedCheck</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Only generate a message value when not validated
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">!</span><span>passedCheck) {
</span><span> </span><span style="color:#ff7733;">return </span><span>validationMessage[attr][attrRule]()</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Start off the validation
</span><span> </span><span style="color:#ff7733;">return function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span>args </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">arguments</span><span style="color:#bfbab0cc;">;
</span><span> attr </span><span style="color:#f29668;">= </span><span>args[</span><span style="color:#f29718;">1</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span> attrRule </span><span style="color:#f29668;">= </span><span>args[</span><span style="color:#f29718;">2</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span> inputData </span><span style="color:#f29668;">= </span><span>args[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span> againstValue </span><span style="color:#f29668;">= </span><span>args[</span><span style="color:#f29718;">3</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Kicks off the validation check with supplied data
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#ffb454;">validationCheck</span><span>(validationDefinitions[attr][attrRule]())</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>})()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Usage: validate(inputData, 'number', 'greaterThan', 5);
</span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#ffb454;">validate</span><span>(</span><span style="color:#f29718;">4</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"number"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"greaterThan"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">5</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span style="font-style:italic;color:#5c6773;">// Output: '4 is not greater than 5'
</span></code></pre>
<p><a href="http://jsbin.com/hojovuhemimo/1">Online Demo</a></p>
Namecheap SSL and Nginx
2014-07-29T00:00:00+00:00
2014-07-29T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/namecheap-ssl-and-nginx/
<h3 id="namecheap-positivessl">Namecheap PositiveSSL</h3>
<p>This post will explain the process of setting up your nginx-powered site to used Namecheap's Comodo Positivessl certificate.</p>
<span id="continue-reading"></span>
<p>Navigate to a safe location where your nginx.conf file is able to reference the to-be-generated SSL key.</p>
<p>Generate your site's key in the safe location</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># SSL Certificates
</span><span>
</span><span style="color:#ffb454;">openssl</span><span> req</span><span style="color:#f29718;"> -nodes -newkey</span><span> rsa:2048</span><span style="color:#f29718;"> -keyout</span><span> mydomain_com.key</span><span style="color:#f29718;"> -out</span><span> mydomain_com.csr
</span></code></pre>
<p>You will be prompted to enter some information. Do make sure to fill out this important information.</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>Country: mycountry
</span><span>State: mystate
</span><span>Email: myemail@myemailprovider.com
</span><span>Common Name: mydomain_com
</span><span>Organisation: mycompanyname
</span></code></pre>
<p>Skip entering a 'challenge password', as it does not add to security.</p>
<h3 id="login-to-your-namecheap-account">Login to your Namecheap Account</h3>
<p>Navigate to 'Manage Domains' and select your domain that will require the SSL certificate.</p>
<p>Ensure that the Namecheap DNS servers are used or else your choice of forwarding email address can not be used to verify the confirmation email.
You can tell if you are using another DNS if you can see 'Transfer DNS back' on the left sidebar (do select that option if you see it).</p>
<p>Now for the SSL configuration</p>
<p>For the server, choose 'apache2' and then enter the contents of your 'mydomain_com.csr' into the textarea.</p>
<p>On the second page, the confirmation email is required to confirm a SSL issuance.</p>
<p>Do this by setting up the forwarding email that you can access</p>
<p>Navigate to 'Email Forwarding Setup' and change 'USER NAME' to 'admin'</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>UserName: admin
</span><span>ForwardedTo: myemail@myemailprovider.com
</span></code></pre>
<p>As for the forward email, try to not use a gmail account as I found out that there were some problems receiving emails.</p>
<p>Fill in the 'administrator' account information if not complete.</p>
<h3 id="receiving-confirmation-email">Receiving Confirmation Email</h3>
<p>A Comodo security services email will be delivered shortly to your 'ForwardedTo' email account. Once you receive that, confirm with the link by the validation code that was sent in that email.</p>
<p>The zip file containing your certificates will go to your 'administrator' account, the account that you sign up with namecheap.
Note that the 'ForwardedTo' may not be the same as your 'administrator' account email, if you configured it that way.</p>
<h3 id="unzip-certificates">Unzip Certificates</h3>
<p>Unzip the file to a temp directory and combine the three files into one. The order is important.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Combine Certificates
</span><span>
</span><span style="color:#ffb454;">cat</span><span> MyDomain_com.crt COMODORSADomainValidationSecureServerCA.crt </span><span style="color:#bfbab0cc;">\
</span><span> COMODORSAAddTrustCA.crt </span><span style="color:#f29668;">></span><span> comdo-certs.combined
</span></code></pre>
<h3 id="setup-nginx">Setup Nginx</h3>
<p>Copy or move the 'comodo-certs.combined' file to the same folder as your 'mydomain_com.key' file.</p>
<p>Add or modify the following in your nginx.conf file</p>
<pre data-lang="txt" style="background-color:#0f1419;color:#bfbab0;" class="language-txt "><code class="language-txt" data-lang="txt"><span>server {
</span><span> listen 80;
</span><span> server_name .my_domain.com;
</span><span> rewrite ^ https://$host$request_uri permanent;
</span><span>}
</span><span>
</span><span>server {
</span><span> listen 443;
</span><span>
</span><span> ssl on;
</span><span>
</span><span> ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
</span><span> ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK';
</span><span>
</span><span> ssl_prefer_server_ciphers on;
</span><span>
</span><span> ssl_certificate /path/where/nginx/references/comodo-certs.combined;
</span><span> ssl_certificate_key /path/where/nginx/references/mydomain_com.key;
</span><span>}
</span></code></pre>
<p>The first server block will redirect all variants of non-secured versions of your site to the secured version.</p>
<p>All the following</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>www.my_domain.com
</span><span>my_domain.com
</span><span>http://my_domain.com
</span><span>http://www.my_domain.com
</span></code></pre>
<p>will be redirected to</p>
<pre style="background-color:#0f1419;color:#bfbab0;"><code><span>https://www.my_domain.com
</span></code></pre>
<p>Now to test the changes made to nginx by</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Test First
</span><span>
</span><span style="color:#ffb454;">sudo</span><span> service nginx configtest
</span></code></pre>
<p>Finally, start or restart your nginx server to apply the changes.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">Now</span><span> for Liftoff
</span><span style="color:#ffb454;">sudo</span><span> service nginx reload
</span></code></pre>
File Stream's Nth Line
2014-07-10T00:00:00+00:00
2014-07-10T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/file-streams-nth-line/
<h3 id="nth-line">Nth Line</h3>
<p>In Nodejs, when reading a stream from a file, the process of getting the nth line requires reading (nth - 1) lines. A filestream's data comes as it is ready and in order, but there is <a href="http://stackoverflow.com/questions/6394951/read-nth-line-of-file-in-nodejs">no means of jumping</a> to a specific nth line of the stream.</p>
<span id="continue-reading"></span>
<p>This is an inconvenience, but this required behavior of 'iterating through the lines until the desired line is found' is also present in <a href="http://rosettacode.org/wiki/Read_a_specific_line_from_a_file">many other programming languages</a>.</p>
Typeof Wrapper
2014-06-20T00:00:00+00:00
2014-06-20T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/typeof-wrapper/
<h3 id="robust-typeof">Robust Typeof</h3>
<p>Using typeof in JavaScript does not produce the results that one would expect as explain by many articles found on the <a href="http://tobyho.com/2011/01/28/checking-types-in-javascript/">internet</a>.</p>
<span id="continue-reading"></span>
<p>This snippet adapts <a href="http://jashkenas.github.io/underscore/">underscore's</a> checking of types in a condense function to provide a more compact and predictable means of checking types in JavaScript.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Robust Typeof Wrapper Function
</span><span>
</span><span style="color:#ff7733;">var </span><span>type </span><span style="color:#f29668;">= </span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Alias the object's prototype
</span><span> </span><span style="color:#ff7733;">var </span><span>objProto </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">Object</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#f29668;">.</span><span>toString</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Mapping object for type checking
</span><span> </span><span style="color:#ff7733;">var </span><span>typeObj </span><span style="color:#f29668;">= </span><span>{
</span><span> </span><span style="color:#ffb454;">array</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">obj</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span style="font-style:italic;color:#39bae6;">Array</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">isArray</span><span>(obj) </span><span style="color:#f29668;">|| </span><span>objProto</span><span style="color:#f29668;">.</span><span style="color:#f07178;">call</span><span>(obj) </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">"[object Array]"</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">object</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">obj</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span>obj </span><span style="color:#f29668;">=== </span><span style="font-style:italic;color:#39bae6;">Object</span><span>(obj)</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">boolean</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">obj</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span>(
</span><span> obj </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">true </span><span style="color:#f29668;">||
</span><span> obj </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">false </span><span style="color:#f29668;">||
</span><span> objProto</span><span style="color:#f29668;">.</span><span style="color:#f07178;">call</span><span>(obj) </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">"[object Boolean]"
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">null</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">obj</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span>obj </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">null</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">undefined</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">obj</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span>obj </span><span style="color:#f29668;">=== void </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">nan</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">obj</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">number</span><span>(obj) </span><span style="color:#f29668;">&& </span><span>obj </span><span style="color:#f29668;">!= +</span><span>obj</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">var </span><span>commonCompareTypes </span><span style="color:#f29668;">= </span><span>[</span><span style="color:#c2d94c;">"function"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"string"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"number"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"date"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"regexp"</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">for </span><span>(</span><span style="color:#ff7733;">var </span><span>i </span><span style="color:#f29668;">= </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">; </span><span>i </span><span style="color:#f29668;">< </span><span>commonCompareTypes</span><span style="color:#f29668;">.</span><span>length</span><span style="color:#bfbab0cc;">; </span><span>i</span><span style="color:#f29668;">++</span><span>) {
</span><span> (</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span>currentType </span><span style="color:#f29668;">= </span><span>commonCompareTypes[i]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">fn </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">obj</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span>objProto</span><span style="color:#f29668;">.</span><span style="color:#f07178;">call</span><span>(obj)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">slice</span><span>(</span><span style="color:#f29718;">8</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29668;">-</span><span style="color:#f29718;">1</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">toLowerCase</span><span>() </span><span style="color:#f29668;">=== </span><span>fn</span><span style="color:#f29668;">.</span><span>type</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span> fn</span><span style="color:#f29668;">.</span><span>type </span><span style="color:#f29668;">= </span><span>currentType</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> typeObj[currentType] </span><span style="color:#f29668;">= </span><span>fn</span><span style="color:#bfbab0cc;">;
</span><span> })()</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="color:#ff7733;">return function </span><span>(</span><span style="color:#f29718;">value</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">type</span><span>) {
</span><span> </span><span style="color:#ff7733;">return </span><span>typeObj[type](value)</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>})()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Examples
</span><span style="font-style:italic;color:#5c6773;">// Second parameter needs to be in lowercase for function to work
</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#c2d94c;">"stuff"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"date"</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//false
</span><span style="color:#ffb454;">type</span><span>({}</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"array"</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//false
</span><span style="color:#ffb454;">type</span><span>({}</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"object"</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//true
</span><span style="color:#ffb454;">type</span><span>([]</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"object"</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//true
</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#f29718;">null</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"null"</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//true
</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#f29718;">NaN</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"nan"</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//true
</span><span style="color:#ffb454;">type</span><span>(</span><span style="color:#f29718;">123</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"nan"</span><span>)</span><span style="color:#bfbab0cc;">; </span><span style="font-style:italic;color:#5c6773;">//false
</span></code></pre>
<p>Do note the behaviors of the 'object' and 'nan' check, as this follows underscore's checking implementation. Objects and arrays are considered objects.
The 'nan' check is looking for the 'NaN' value, and when this condition is not satisfied, false will be returned.</p>
jQuery Plugins - Prevent Multiple Instantiations
2014-06-03T00:00:00+00:00
2014-06-03T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/jquery-plugins-prevent-multiple-instantiations/
<h2 id="script-loading-safety">Script Loading Safety</h2>
<p>The <a href="https://github.com/jquery-boilerplate/jquery-boilerplate">jQuery Boilerplate</a> is a popular boilerplate and provides a safety
net for double instantiation of a jQuery object with this code</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Prevent Double Instantation on jQuery Object
</span><span>
</span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">!</span><span>$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">data</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"plugin_" </span><span style="color:#f29668;">+ </span><span>pluginName)) {
</span><span> $</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">data</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"plugin_" </span><span style="color:#f29668;">+ </span><span>pluginName</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29668;">new </span><span style="color:#59c2ff;">Plugin</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">, </span><span>options))</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<p>This is good safeguard for your jQuery objects, but what happens if
your plugin script gets load twice?</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Accidental Reloading of Plugin Script-->
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">></span><span>TakeOut</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">meta </span><span style="color:#ffb454;">charset</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8" </span><span style="color:#39bae690;">/>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script
</span><span> </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"assets/vendor/js/jquery-1.11.1.min.js"
</span><span> </span><span style="color:#ffb454;">type</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"text/javascript"
</span><span> </span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"src/TakeOut.js" </span><span style="color:#ffb454;">type</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"text/javascript"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"src/TakeOut.js" </span><span style="color:#ffb454;">type</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"text/javascript"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span></code></pre>
<p>This is unlikely to happen, but this problem could manifest in more devious or and less apparent ways, such as when project files are minify and concatenated.</p>
<p>It might cause some unexpected behaviors if the plugin attaches event
listeners by default. In order to protect your page, do the following:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Attachment Check
</span><span>
</span><span>(</span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">$</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">window</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">document</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">undefined</span><span>) {
</span><span> </span><span style="color:#ff7733;">var </span><span>pluginName </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"MyMagnificentJQueryPlugin"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Only allow for one instantiation of this script
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">typeof </span><span>$</span><span style="color:#f29668;">.</span><span>fn[pluginName] </span><span style="color:#f29668;">!== </span><span style="color:#c2d94c;">"undefined"</span><span>) {
</span><span> </span><span style="color:#ff7733;">return</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Rest of your jQuery plugin logic here
</span><span>})(jQuery</span><span style="color:#bfbab0cc;">, </span><span>window</span><span style="color:#bfbab0cc;">, </span><span>document)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>There is a check in the beginning of the script to see if the plugin
has already attached itself to the jQuery object.</p>
Nodejs Quick Tips #1
2014-05-22T00:00:00+00:00
2014-05-22T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nodejs-quick-tips-1/
<h3 id="creating-multiple-files">Creating Multiple Files</h3>
<p>Unfortunately, the fs.writeFile does not accept an array for creating a bunch of files at once.
To solve this problem, put all files in an array and loop through
them to create the files.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// More than One File at Once
</span><span>
</span><span style="color:#ff7733;">var </span><span>fs </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"fs"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Use an array to house all files to be created
</span><span>[
</span><span> </span><span style="color:#c2d94c;">"thing.txt"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"thing2.txt"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"otherFile.txt"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"abc.txt"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"def.txt"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"ghi.txt"</span><span style="color:#bfbab0cc;">,
</span><span>]</span><span style="color:#f29668;">.</span><span style="color:#f07178;">forEach</span><span>(</span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">value</span><span>) {
</span><span> fs</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">writeFile</span><span>(value</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">err</span><span>) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(err) </span><span style="color:#ff7733;">throw </span><span>err</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="get-path-of-directory-one-up-from-current">Get Path of Directory One Up from Current</h3>
<p>Using the 'path' variable along with some array operations, the folder one level above the current directory could be found. The value of '1' goes up one level, but this value could be changed to go up many levels as desired.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// One Directory Up
</span><span>
</span><span style="color:#ff7733;">var </span><span>path </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"path"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Using this path for example
</span><span style="font-style:italic;color:#5c6773;">// /home/williamhuey/Desktop/CodeStuff/
</span><span style="color:#ff7733;">var </span><span>cwd </span><span style="color:#f29668;">= </span><span>process</span><span style="color:#f29668;">.</span><span style="color:#f07178;">cwd</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// [ '', 'home', 'williamhuey', 'Desktop', 'CodeStuff']
</span><span style="color:#ff7733;">var </span><span>pathSep </span><span style="color:#f29668;">= </span><span>cwd</span><span style="color:#f29668;">.</span><span style="color:#f07178;">split</span><span>(path</span><span style="color:#f29668;">.</span><span>sep)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// [ '', 'home', 'williamhuey', 'Desktop']
</span><span style="color:#ff7733;">var </span><span>slicedPath </span><span style="color:#f29668;">= </span><span>pathSep</span><span style="color:#f29668;">.</span><span style="color:#f07178;">slice</span><span>(</span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">, </span><span>pathSep</span><span style="color:#f29668;">.</span><span>length </span><span style="color:#f29668;">- </span><span style="color:#f29718;">1</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// /home/williamhuey/Desktop/
</span><span style="color:#ff7733;">var </span><span>oneUpDirectory </span><span style="color:#f29668;">= </span><span>slicedPath</span><span style="color:#f29668;">.</span><span style="color:#f07178;">join</span><span>(path</span><span style="color:#f29668;">.</span><span>sep)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Private Instance Method Variables
2014-05-06T00:00:00+00:00
2014-05-06T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/private-instance-method-variables/
<h3 id="instances-methods-and-their-personal-state">Instances Methods and Their Personal State</h3>
<p>This post is for intended for JavaScript (not Java).</p>
<p>One may put instance method variables within an instance method to provide encapsulation, but what do you do when you want to maintain a private state for each instance method on each instance method execution?</p>
<span id="continue-reading"></span>
<p>The technique in achieving such a task involves wrapping an instance method and its variable within a function as shown below. The result will produce instance method variables that are truly private to the instance method.</p>
<p>The instance method gets attached to the constructor by using the 'this' reference to the constructor.</p>
<p>Each instance function is then placed into an internal array and the array is looped over to execute and initialize each wrapper function and its corresponding static methods and variables.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Instance Variables
</span><span>
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">Time </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Reference the context
</span><span> </span><span style="color:#ff7733;">var </span><span>_this </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Internal array which houses all instance methods
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Wrapping all instance methods in a function to
</span><span> </span><span style="font-style:italic;color:#5c6773;">// contain its private variables for instance methods
</span><span> </span><span style="color:#ff7733;">var </span><span>_time </span><span style="color:#f29668;">= </span><span>[
</span><span> </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Private variables for instance
</span><span> </span><span style="color:#ff7733;">var </span><span>privateStaticVar </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"Time in milliseconds is "</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// A instance method of the Time constructor
</span><span> _this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">getTimeInMilliseconds </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">return </span><span>privateStaticVar </span><span style="color:#f29668;">+ </span><span style="font-style:italic;color:#39bae6;">Date</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">now</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Add more functions within this array
</span><span> </span><span style="font-style:italic;color:#5c6773;">// for other instance methods
</span><span> ]</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Initialize all instance methods
</span><span> </span><span style="color:#ff7733;">for </span><span>(</span><span style="color:#ff7733;">var </span><span>i </span><span style="color:#f29668;">= </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">; </span><span>i </span><span style="color:#f29668;">< </span><span>_time</span><span style="color:#f29668;">.</span><span>length</span><span style="color:#bfbab0cc;">; </span><span>i</span><span style="color:#f29668;">++</span><span>) {
</span><span> _time[i]()</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">var </span><span>time </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">Time</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(time</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">getTimeInMilliseconds</span><span>())</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Pubsub Lists
2014-05-01T00:00:00+00:00
2014-05-01T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/pubsub-lists/
<h3 id="publish-and-subscribe">Publish and Subscribe</h3>
<p>One way of emitting events is by using trigger on a jQuery element.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Event Emitting from Element
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-element-id"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">trigger</span><span>(</span><span style="color:#c2d94c;">"my-beautiful-event"</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>This is okay if we only wanted to trigger an event from a specific element, but what happens if we want a generic way of doing things, such as without referring to an element when triggering?</p>
<p>The way to do this is to use <a href="https://api.jquery.com/jQuery.Callbacks/">jQuery.Callbacks()</a> to create a pubsub system.</p>
<p>An instance of jQuery.Callbacks accumulates functions, and runs one functions after another when the "fire" method is call upon. The property of jQuery.Callbacks that is of interest in the pubsub system, is the ability to fire(call) the functions when needed, whereas the ability to accumulate multiple functions is not as critical to the pubsub system.</p>
<p>To demonstrate pubsub, our example will have three select lists where each subscribes and publishes to one another.</p>
<p>The code from the jQuery Api page will be used</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Pubsub
</span><span style="font-style:italic;color:#5c6773;">// Adapted from jQuery api page (only variable renames)
</span><span style="font-style:italic;color:#5c6773;">// https://api.jquery.com/jQuery.Callbacks/
</span><span style="color:#ff7733;">var </span><span>classGroups </span><span style="color:#f29668;">= </span><span>{}</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">pubsubNameSpace </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">id</span><span>) {
</span><span> </span><span style="color:#ff7733;">var </span><span>callbacks</span><span style="color:#bfbab0cc;">,
</span><span> classGroup </span><span style="color:#f29668;">= </span><span>id </span><span style="color:#f29668;">&& </span><span>classGroups[id]</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">!</span><span>classGroup) {
</span><span> callbacks </span><span style="color:#f29668;">= </span><span>$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">Callbacks</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> classGroup </span><span style="color:#f29668;">= </span><span>{
</span><span> publish</span><span style="color:#bfbab0cc;">: </span><span>callbacks</span><span style="color:#f29668;">.</span><span>fire</span><span style="color:#bfbab0cc;">,
</span><span> subscribe</span><span style="color:#bfbab0cc;">: </span><span>callbacks</span><span style="color:#f29668;">.</span><span>add</span><span style="color:#bfbab0cc;">,
</span><span> unsubscribe</span><span style="color:#bfbab0cc;">: </span><span>callbacks</span><span style="color:#f29668;">.</span><span>remove</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">if </span><span>(id) {
</span><span> classGroups[id] </span><span style="color:#f29668;">= </span><span>classGroup</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }
</span><span> </span><span style="color:#ff7733;">return </span><span>classGroup</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The main point of this code is that 'pubsubNameSpace' will create a namespace for a string that is passed in as 'id'. The 'id' is a key in the 'classGroups' object. The 'classGroup' is an object that is the return value of 'pubsubNameSpace' which has a 'publish', 'subscribe', and 'unsubscribe' key that refer to the jQuery Callbacks methods.</p>
<p>Once we have this code, the following can be called like so</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Pubsub Usage
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Create a namespace
</span><span style="color:#ff7733;">var </span><span>ns </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">pubsubNameSpace</span><span>(</span><span style="color:#c2d94c;">"my-creative-namespace-name"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Subscribe to the Namespace
</span><span>ns</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>(myFunction)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Publish within the Namespace
</span><span>ns</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">publish</span><span>({
</span><span> data</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"just-a-string"</span><span style="color:#bfbab0cc;">,
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Subscribe's function
</span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">myFunction</span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="font-style:italic;color:#39bae6;">arguments</span><span>[</span><span style="color:#f29718;">0</span><span>])</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<p>When publishing, one can pass in any data, but with the subscribe call, a function must be use as a funnel for the data that has been published.</p>
<p>To start the example, the initial variable declarations:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Select List New Namespace
</span><span>
</span><span style="color:#ff7733;">var </span><span>$select </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select.classy"</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> className </span><span style="color:#f29668;">= </span><span>$select</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">prop</span><span>(</span><span style="color:#c2d94c;">"class"</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> ns </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">pubsubNameSpace</span><span>(className)</span><span style="color:#bfbab0cc;">,
</span><span> $info </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#info"</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The class name of the select lists is used as the name space for the pubsub. The '$info' is the div for displaying messages.</p>
<p>The main logic for publishing and subscribing for the select lists.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Select Lists Pubsub
</span><span>
</span><span style="color:#ff7733;">var </span><span>id </span><span style="color:#f29668;">= -</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">;
</span><span>$select</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">each</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// To id each select list
</span><span> id</span><span style="color:#f29668;">++</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">var </span><span>$this </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">$</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> $this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">data</span><span>(</span><span style="color:#c2d94c;">"id"</span><span style="color:#bfbab0cc;">, </span><span>id)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Reset each list
</span><span> $this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">prop</span><span>(</span><span style="color:#c2d94c;">"selectedIndex"</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">0</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Listen to the selection changes for each list
</span><span> $this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"change"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span>$selected </span><span style="color:#f29668;">= </span><span>$this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">children</span><span>(</span><span style="color:#c2d94c;">"option:selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Tell all members of the same class of change
</span><span> ns</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">publish</span><span>({
</span><span> selected</span><span style="color:#bfbab0cc;">: </span><span>$selected</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">text</span><span>()</span><span style="color:#bfbab0cc;">,
</span><span> id</span><span style="color:#bfbab0cc;">: </span><span>$this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">data</span><span>(</span><span style="color:#c2d94c;">"id"</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Listen for changes within the same class
</span><span> ns</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">subscribe</span><span>($</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">proxy</span><span>(explain</span><span style="color:#bfbab0cc;">, </span><span>$this))</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Iterate through each select list and associate them with an id. Attach a 'change' event handler to each list and within it, publish the selected value with the select list id. Also subscribe to messages from the same class.</p>
<p>Now finally for the subscribe function</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Logging Function
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Log info for subscribe function
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">explain </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">data</span><span>(</span><span style="color:#c2d94c;">"id"</span><span>) </span><span style="color:#f29668;">!== </span><span style="font-style:italic;color:#39bae6;">arguments</span><span>[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#f29668;">.</span><span>id) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Display the info in div
</span><span> </span><span style="color:#ff7733;">var </span><span>msg </span><span style="color:#f29668;">=
</span><span> </span><span style="color:#c2d94c;">"List " </span><span style="color:#f29668;">+
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">data</span><span>(</span><span style="color:#c2d94c;">"id"</span><span>) </span><span style="color:#f29668;">+
</span><span> </span><span style="color:#c2d94c;">" heard from List " </span><span style="color:#f29668;">+
</span><span> </span><span style="font-style:italic;color:#39bae6;">arguments</span><span>[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#f29668;">.</span><span>id </span><span style="color:#f29668;">+
</span><span> </span><span style="color:#c2d94c;">". The value selected was " </span><span style="color:#f29668;">+
</span><span> </span><span style="color:#c2d94c;">'"' </span><span style="color:#f29668;">+
</span><span> </span><span style="font-style:italic;color:#39bae6;">arguments</span><span>[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#f29668;">.</span><span>selected </span><span style="color:#f29668;">+
</span><span> </span><span style="color:#c2d94c;">'"'</span><span style="color:#bfbab0cc;">;
</span><span> $info</span><span style="color:#f29668;">.</span><span style="color:#f07178;">prepend</span><span>(</span><span style="color:#c2d94c;">"<p>" </span><span style="color:#f29668;">+ </span><span>msg </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"</p>"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Note that there needs to be a check for whether the published data id is the same as the current list element's id to ensure that our list does not listen to its own published message. This is because all select lists listens subscribe to the same class namespace.</p>
<p><a href="http://jsbin.com/yexiseke/1">Online Demo</a> | <a href="/archives/2014-05-01-pubsub-lists.zip">Offline Demo</a></p>
Readable-stream
2014-04-22T00:00:00+00:00
2014-04-22T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/readable-stream/
<h3 id="streaming-consistency">Streaming Consistency</h3>
<p>Since Node's streaming Api is still changing and is in 'unstable' category, writing a npm module using streams may cause some unexpected behaviors on older versions of Node. To ensure that streams are compatible with older versions of Node, a drop-in replacement for stream is available called 'readable-stream'.</p>
<span id="continue-reading"></span>
<p>The following example uses the 'readable' event, which is not present on Node versions < 0.10, but the readable-stream module is handling this inconsistency which means that this example will work with Node versions < 0.10.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Wrapping fs.createReadStream
</span><span>
</span><span style="color:#ff7733;">var </span><span>fs </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"fs"</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> Readable </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"readable-stream"</span><span>)</span><span style="color:#f29668;">.</span><span>Readable</span><span style="color:#bfbab0cc;">,
</span><span> reader </span><span style="color:#f29668;">= new </span><span style="color:#59c2ff;">Readable</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>reader
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">wrap</span><span>(fs</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">createReadStream</span><span>(</span><span style="color:#c2d94c;">"./test.txt"</span><span>))
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"readable"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">read</span><span>()</span><span style="color:#f29668;">.</span><span style="color:#f07178;">toString</span><span>())</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"end"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Finished reading stream"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Streaming Lines
2014-04-15T00:00:00+00:00
2014-04-15T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/streaming-lines/
<h3 id="line-by-line">Line by Line</h3>
<p>There are many streaming modules on npm to read lines from text files,
but many are inaccurate and slow. Inaccurate means that there is a failure to read many lines and
slow means that files with a lot of text per line will cause the modules to crawl.</p>
<span id="continue-reading"></span>
<p>Below are the lines counts and timings for reading a large json file, 'bird.json' with 909 lines.
The json is densely packed, meaning there are a few lines that are very long.</p>
<img src="/images/posts/2014-04-15-birdJson-T.png" alt="bird json time">
<img src="/images/posts/2014-04-15-birdJson-LC.png" alt="bird json line count time">
<p>Line-reader (excluded from graph) nearly slows to a standstill when reading a json file with dense lines, taking
over 76 seconds to complete the read. This is an exception for line-reader
because line-reader is usually comparable in speed to other streaming modules on
less dense files as shown below.</p>
<p>Now testing line reading on 'War and Peace' founded on <a href="http://www.gutenberg.org/cache/epub/2600/pg2600.txt">Gutenberg</a>.
This text file has 65008 lines.</p>
<img src="/images/posts/2014-04-15-war-and-peace-time.png" alt="war and peace time">
<img src="/images/posts/2014-04-15-war-and-peace-lc.png" alt="war and peace time line count">
<p>Linebyline errored out with 'RangeError: Maximum call stack size exceeded', while most of the stream readers are in the neighborhood of 300ms.</p>
<p>The files for the above benchmark is <a href="/archives/2014-04-15-Streaming-Lines.7z">here</a>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>It was surprising to see that some modules misread lines by a significant amount for 'bird.json' while
almost all modules misreport the line count. The last line on both the json and text file is a blank line and often this is not read.</p>
<p>Most stream readers were not adept at reading the 'bird.json' file.</p>
<p>The more reliable streaming line reader module that I recommend would be 'split2' or 'split',
since both are accurate on the line count and can handle densely packed files.</p>
Simple Server
2014-03-12T00:00:00+00:00
2014-03-12T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/simple-server/
<h3 id="no-nodejs-required">No nodejs required</h3>
<p>Many times there are code samples on Github that have simple static files that you would want to run on a server, such as the case if there are ajax calls in javascript files.</p>
<span id="continue-reading"></span>
<p>Nodejs could have been an alternative, but python provides a simple and fast method to run a server on your machine with a single command line.</p>
<p>Using python3, run this command in the directory of the static files</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">python</span><span style="color:#f29718;"> -m</span><span> http.server
</span></code></pre>
<p>If using python2, use</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#ffb454;">python</span><span style="color:#f29718;"> -m</span><span> SimpleHTTPServer </span><span style="color:#ff7733;">[</span><span>port</span><span style="color:#ff7733;">]
</span></code></pre>
Sprites and Link Padding
2014-02-13T00:00:00+00:00
2014-02-13T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/sprites-and-link-padding/
<p>Sprites are often used to stylize 'a' tags. When a sprite sheet is used, a fixed width and height is used to specific the image on the sprite.</p>
<span id="continue-reading"></span>
<p>Here is a common example of how a sprite is commonly used</p>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* Simple Sprite Css */
</span><span>
</span><span style="color:#ffb454;">#Square </span><span>{
</span><span> </span><span style="color:#39bae6;">background</span><span style="color:#bfbab0cc;">: </span><span style="color:#f07178;">url</span><span>(</span><span style="color:#c2d94c;">sprite-test.png</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#ffb454;">#Square </span><span>{
</span><span> </span><span style="color:#39bae6;">background-position</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">-19</span><span style="color:#ff7733;">px </span><span style="color:#f29718;">-21</span><span style="color:#ff7733;">px</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">width</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">78</span><span style="color:#ff7733;">px</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">height</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">78</span><span style="color:#ff7733;">px</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#59c2ff;">a </span><span>{
</span><span> </span><span style="color:#39bae6;">text-indent</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">-99999</span><span style="color:#ff7733;">px</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">overflow</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">hidden</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">background-repeat</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">no-repeat</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">display</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">block</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- A link for the Sprite -->
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">a </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"#" </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"Square"</span><span style="color:#39bae690;">></span><span>A link</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">a</span><span style="color:#39bae690;">>
</span></code></pre>
<p>In this example, the referenced image on the sprite is sufficiently large to allow for easy clicking. There are however times this is not the case.</p>
<p>In other cases, padding is needed for the sprite image link to promote a greater clicking region for accessibility. To achieve this, the markup must be changed such that the 'a' tag will have a 'span' and the id from the 'a' tag is placed on the 'span tag'.</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Span in Link -->
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">a </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"#"</span><span style="color:#39bae690;">><</span><span style="color:#59c2ff;">span </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"Square"</span><span style="color:#39bae690;">></span><span>A link</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">span</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">a</span><span style="color:#39bae690;">>
</span></code></pre>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* More Padding for Links */
</span><span>
</span><span style="color:#59c2ff;">span </span><span>{
</span><span> </span><span style="color:#39bae6;">display</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">block</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#59c2ff;">a </span><span>{
</span><span> </span><span style="color:#39bae6;">padding</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">2</span><span style="color:#ff7733;">em</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<p>The span carries the image and the 'a' tag is now an expandable wrapper of 'clickability'.</p>
<p><a href="/archives/2014-02-14-sprite-padding.zip">Offline Demo</a></p>
Removing Stylesheet Rules
2014-01-13T00:00:00+00:00
2014-01-13T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/removing-stylesheet-rules/
<h3 id="off-with-the-rule">Off with the Rule</h3>
<p>Most of the time, css rules are overridden to get a different style, but some rules need to be outright removed. For example, if a hover effect is in place when javascript is disabled, but the rule might interfere with the javascript code when javascript is enabled. This might happen when using a jQuery plugin for menu creation or text effect.</p>
<span id="continue-reading"></span>
<p>The following code will demonstrate the removal of a :hover selector from a 'p' tag.</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Example Layout -->
</span><span>
</span><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span style="color:#f29718;">html</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">meta </span><span style="color:#ffb454;">charset</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"utf-8" </span><span style="color:#39bae690;">/>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">></span><span>Removing Stylesheet Rules</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"mainStyles" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"mainStyles.css" </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet" </span><span style="color:#39bae690;">/>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"RemovingStyleSheetRules.js"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">p </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"paragraph-is-orange-when-hover"</span><span style="color:#39bae690;">>
</span><span> This paragraph should be still be black when hover over.
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">p</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span></code></pre>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* mainStyles */
</span><span>
</span><span style="color:#ffb454;">#paragraph-is-orange-when-hover</span><span>:hover {
</span><span> </span><span style="color:#39bae6;">color</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">orange</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<pre data-lang="javascript" style="background-color:#0f1419;color:#bfbab0;" class="language-javascript "><code class="language-javascript" data-lang="javascript"><span style="font-style:italic;color:#5c6773;">// RemovingStyleSheetRules.js
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Retrieve sheet from css dom element
</span><span style="color:#ff7733;">var </span><span>mainStylesHtml </span><span style="color:#f29668;">= </span><span>document</span><span style="color:#f29668;">.</span><span style="color:#f07178;">getElementById</span><span>(</span><span style="color:#c2d94c;">"mainStyles"</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> mainStyles</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">if </span><span>(mainStylesHtml</span><span style="color:#f29668;">.</span><span>sheet) {
</span><span> mainStyles </span><span style="color:#f29668;">= </span><span>mainStylesHtml</span><span style="color:#f29668;">.</span><span>sheet</span><span style="color:#bfbab0cc;">;
</span><span>} </span><span style="color:#ff7733;">else if </span><span>(mainStylesHtml</span><span style="color:#f29668;">.</span><span>styleSheet) {
</span><span> mainStyles </span><span style="color:#f29668;">= </span><span>mainStylesHtml</span><span style="color:#f29668;">.</span><span>styleSheet</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Get rules off the sheet object
</span><span style="color:#ff7733;">var </span><span>mainRules</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">if </span><span>(mainStyles</span><span style="color:#f29668;">.</span><span>cssRules) {
</span><span> mainRules </span><span style="color:#f29668;">= </span><span>mainStyles</span><span style="color:#f29668;">.</span><span>cssRules</span><span style="color:#bfbab0cc;">;
</span><span>} </span><span style="color:#ff7733;">else if </span><span>(mainStyles</span><span style="color:#f29668;">.</span><span>rules) {
</span><span> mainRules </span><span style="color:#f29668;">= </span><span>mainStyles</span><span style="color:#f29668;">.</span><span>rules</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Notes for Rules
</span><span style="font-style:italic;color:#5c6773;">// http://help.dottoro.com/ljnefpqb.php
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Iterate through the stylesheet rules
</span><span style="color:#ff7733;">var </span><span>theKey</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ff7733;">for </span><span>(key </span><span style="color:#f29668;">in </span><span>mainRules) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Make sure key is valid
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">typeof </span><span>mainRules[key]</span><span style="color:#f29668;">.</span><span>selectorText </span><span style="color:#f29668;">!= </span><span style="color:#c2d94c;">"undefined"</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// The string will be the name of the selector that is to be removed
</span><span> </span><span style="color:#ff7733;">if </span><span>(
</span><span> </span><span style="color:#c2d94c;">"#paragraph-is-orange-when-hover:hover" </span><span style="color:#f29668;">== </span><span>mainRules[key]</span><span style="color:#f29668;">.</span><span>selectorText
</span><span> ) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Coercing the string key to a number key
</span><span> theKey </span><span style="color:#f29668;">= </span><span>key </span><span style="color:#f29668;">* </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Remove the rule
</span><span style="color:#ff7733;">if </span><span>(mainStyles</span><span style="color:#f29668;">.</span><span>deleteRule) {
</span><span> mainStyles</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">deleteRule</span><span>(theKey)</span><span style="color:#bfbab0cc;">;
</span><span>} </span><span style="color:#ff7733;">else </span><span>{
</span><span> mainStyles</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">removeRule</span><span>(theKey)</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Notes for Deleting Rules
</span><span style="font-style:italic;color:#5c6773;">// deleteRule: http://help.dottoro.com/ljcihbgl.php
</span><span style="font-style:italic;color:#5c6773;">// removeRule: http://help.dottoro.com/ljdupbal.php
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// Note: Chrome-based browser only allow stylesheet manipulation
</span><span style="font-style:italic;color:#5c6773;">// if the parameter "--allow-file-access-from-files" is set for local file access
</span><span style="font-style:italic;color:#5c6773;">// http://www.chrome-allow-file-access-from-file.com/
</span></code></pre>
<p><a href="/archives/2014-01-13-removing-stylesheet-rules.zip">Offline Demo</a></p>
jQuery Performance Tips #1
2013-12-24T00:00:00+00:00
2013-12-24T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/jquery-performance-tips-number-1/
<h3 id="checking-visibility">Checking Visibility</h3>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Visibility Test Cases
</span><span>
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#word"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">is</span><span>(</span><span style="color:#c2d94c;">":visible"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#word:visible"</span><span>)</span><span style="color:#f29668;">.</span><span>length </span><span style="color:#f29668;">== </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#word:visible"</span><span>)</span><span style="color:#f29668;">.</span><span>length </span><span style="color:#f29668;">> </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#word"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">css</span><span>(</span><span style="color:#c2d94c;">"display"</span><span>) </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">"block"</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#word"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">is</span><span>(</span><span style="color:#c2d94c;">":not(:hidden)"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#f29668;">!</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#word"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">is</span><span>(</span><span style="color:#c2d94c;">":hidden"</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<span id="continue-reading"></span><h3 id="results">Results</h3>
<p>All major browsers perform really well using 4) the css display block, except for Chrome based browsers.
The chrome based browsers, Chrome and new Opera, perform the best with 6) ! is :hidden. The comparison, 6) ! is :hidden, looks like the one to use over the 1) .is(':visible').</p>
<h3 id="finding-option-selected-in-select-list">Finding Option Selected in Select List</h3>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Find Selected Cases
</span><span>
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">find</span><span>(</span><span style="color:#c2d94c;">":selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select option:selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select > option"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">filter</span><span>(</span><span style="color:#c2d94c;">":selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select > option:selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">children</span><span>(</span><span style="color:#c2d94c;">"option:selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select > option"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">find</span><span>(</span><span style="color:#c2d94c;">":selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">children</span><span>(</span><span style="color:#c2d94c;">"option"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">filter</span><span>(</span><span style="color:#c2d94c;">":selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"select"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">children</span><span>()</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">filter</span><span>(</span><span style="color:#c2d94c;">":selected"</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="summary">Summary</h3>
<p>All major browsers perform well using the children selectors (5, 7, 8). The best of children filters tend to be 5) .children('option:selected').</p>
jQuery Event Handler Adapter
2013-11-19T00:00:00+00:00
2013-11-19T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/jquery-event-handler-adapter/
<h3 id="bridging-the-gap">Bridging the Gap</h3>
<p>Older versions of jQuery are still being used (<= 1.6), and those versions do not support the new "on" method of attaching event handlers to elements. If you were authoring jQuery plugins and want to ensure compatibility when working with events, then you would want to write an adapter inside your plugin.</p>
<span id="continue-reading"></span>
<p>The adapter works by performing a check to see if the "on" method is supported. If it is supported, then it is used, otherwise the older "bind" method is used instead. However, regardless of which method is supported both "on" and "bind" will be alias. The alias acts as a wrapper and delegates to which method is supported.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Alias After Checking
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// The alias adapter checks for what event handler methods
</span><span style="font-style:italic;color:#5c6773;">// are supported by the loaded jQuery
</span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#c2d94c;">"on" </span><span style="color:#f29668;">in </span><span>$) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Newer jQuery functions supports the "on" event attachment
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Use the newer event attachment over "bind"
</span><span> $</span><span style="color:#f29668;">.</span><span>fn[</span><span style="color:#c2d94c;">"evtOn"</span><span>] </span><span style="color:#f29668;">= </span><span>$</span><span style="color:#f29668;">.</span><span>fn[</span><span style="color:#c2d94c;">"on"</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span> $</span><span style="color:#f29668;">.</span><span>fn[</span><span style="color:#c2d94c;">"evtOff"</span><span>] </span><span style="color:#f29668;">= </span><span>$</span><span style="color:#f29668;">.</span><span>fn[</span><span style="color:#c2d94c;">"off"</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>} </span><span style="color:#ff7733;">else </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Older jQuery version with no "on" function
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Alias bind functions
</span><span> $</span><span style="color:#f29668;">.</span><span>fn[</span><span style="color:#c2d94c;">"evtOn"</span><span>] </span><span style="color:#f29668;">= </span><span>$</span><span style="color:#f29668;">.</span><span>fn[</span><span style="color:#c2d94c;">"bind"</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span> $</span><span style="color:#f29668;">.</span><span>fn[</span><span style="color:#c2d94c;">"evtOff"</span><span>] </span><span style="color:#f29668;">= </span><span>$</span><span style="color:#f29668;">.</span><span>fn[</span><span style="color:#c2d94c;">"unbind"</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
<p>The alias "evtOn" and "evtOff" will be used for attaching and detaching event handlers.</p>
<p>Now the alias can be used like so</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Example Adapter Usage
</span><span>
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-paragraph"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">evtOn</span><span>(</span><span style="color:#c2d94c;">"click"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">alert</span><span>(</span><span style="color:#c2d94c;">"Clickity clackity!"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-disabling-button"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">evtOn</span><span>(</span><span style="color:#c2d94c;">"click"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-paragraph"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">evtOff</span><span>(</span><span style="color:#c2d94c;">"click"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The online demo below uses an older version of jQuery (1.6.4) and the adapter alias the "bind" method.</p>
<p><a href="http://jsbin.com/IXuyEriB/2/">Online Demo</a></p>
Disable Stylesheets with JavaScript
2013-11-04T00:00:00+00:00
2013-11-04T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/disable-stylesheets-with-javascript/
<h3 id="revile-those-styles">Revile those Styles</h3>
<p>If the styles of stylesheets are atrocious, and you have no control over its loading, you may want to disable specific stylesheets with javascript.</p>
<span id="continue-reading"></span>
<p>However, this may not be good idea because javascript may not be enabled in the browser such that the following will not work, but this post will show that it could be done for learning purposes.</p>
<p>Suppose there are three stylesheets that modify the body of the page that are located in the header. Let's say the goal is to disable the first and third stylesheet in the header.</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Three Stylesheets -->
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="font-style:italic;color:#5c6773;"><!-- First stylesheet turns the body red -->
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"just-a-stylesheet" </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"someStyle.css" </span><span style="color:#39bae690;">/>
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"><!-- Second stylesheet turns the body green -->
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"second.css" </span><span style="color:#39bae690;">/>
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;"><!-- Third stylesheet turns the body yellow -->
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"third.css" </span><span style="color:#39bae690;">/>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span></code></pre>
<p>Since the first stylesheet has an id, this will be used. The following selects the first stylesheet and turns the JQuery object to a DOM element and disables the stylesheet.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Disable the First Stylesheet
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#just-a-stylesheet"</span><span>)[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#f29668;">.</span><span>disabled </span><span style="color:#f29668;">= </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The third stylesheet does not have an id for referencing, so the href will be used to identify the third.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Then Disable the Third Stylesheet
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"head"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">children</span><span>(</span><span style="color:#c2d94c;">'link[href="third.css"]'</span><span>)[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#f29668;">.</span><span>disabled </span><span style="color:#f29668;">= </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The final result of this will make the body green because only the second stylesheet will remain active.
<a href="/archives/2013-11-04-disable-stylesheets-with-javascript.zip">Offline Demo</a></p>
Namespacing Event Handlers
2013-10-19T00:00:00+00:00
2013-10-19T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/namespacing-event-handlers/
<h3 id="conflicting-events-handlers">Conflicting Events Handlers</h3>
<p>Use event namespacing when attaching or detaching event listeners. This reduces the possibility of you accidentally removing event listeners that was not intended to be removed. This is especially important if you plan to use someone else's JQuery plugin that interacts with an element which you are also manipulating through your own event handler attachment or detachment. There could also be the opposite problem where someone else's JQuery plugin removes your attached listeners. This is why namespacing events is a good practice.</p>
<span id="continue-reading"></span>
<p>Not only can namespacing reduce conflicts of interest with other plugins, namespacing also allows for selective removal of your own event listeners.</p>
<p>Supposedly two click handlers are attached to a textarea element</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Two Click Handlers With No Namespacing
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"textarea"</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"click"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">alert</span><span>(</span><span style="color:#c2d94c;">"Making a racket here."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"click"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">alert</span><span>(</span><span style="color:#c2d94c;">"Just to annoy you."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Then you manipulate the element by removing the click handlers</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// No Control Event Handler Removal
</span><span style="font-style:italic;color:#5c6773;">// This could be a very dangerous thing to do
</span><span style="font-style:italic;color:#5c6773;">// because all click handlers are indiscriminately taken out
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"textarea"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">off</span><span>(</span><span style="color:#c2d94c;">"click"</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>However, sometimes you do not wish to remove all click listeners for a certain element. Let say that you would only like to remove the last one. You can accomplish this when a namespace is provided:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Gave each Click Handler a Namespace
</span><span style="font-style:italic;color:#5c6773;">// Each of the click handler has now suffix
</span><span style="font-style:italic;color:#5c6773;">// serving as a namespace
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"textarea"</span><span>)
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"click.first"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">alert</span><span>(</span><span style="color:#c2d94c;">"Making a racket here."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })
</span><span> </span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"click.second"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">alert</span><span>(</span><span style="color:#c2d94c;">"Just to annoy you."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Remove only the second click handler as to preserve the first</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Remove Event Handler Selectively
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"textarea"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">off</span><span>(</span><span style="color:#c2d94c;">"click.second"</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Your first click handler should still be attached.</p>
<p><a href="http://jsbin.com/ICEjoYo/1">Demo</a></p>
Optional Options
2013-09-12T00:00:00+00:00
2013-09-12T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/optional-options/
<h3 id="common-object-format">Common Object Format</h3>
<p>Most JQuery plugins will use the common format of customizing by providing a plain object to the plugin handler. This is well suited for plugins that provide a widget to your page where a callback might not be needed.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Options Object for Plugin
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">widgetLike</span><span>({
</span><span> firstOption</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"setHigh"</span><span style="color:#bfbab0cc;">,
</span><span> secondOption</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">,
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="callback-format">Callback Format</h3>
<p>However, there might be times when the plugin does not need options, or a callback is desired when a certain event happens. This format of plugin is very similar to the native JQuery event handlers.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Callback for the Plugin
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">alertWhenClickedTwice</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">alert</span><span>(</span><span style="color:#c2d94c;">"Be like the native Jquery event handler"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="hybrid-format">Hybrid Format</h3>
<p>There are even occasions where a combination of the above two formats might be needed for some degree of customizing over a plain callback.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Callback with Options
</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">optionsWithCallback</span><span>(
</span><span> {
</span><span> firstOption</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"setHigh"</span><span style="color:#bfbab0cc;">,
</span><span> secondOption</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">alert</span><span>(</span><span style="color:#c2d94c;">"Be like the native Jquery event handler"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Below is a modified version of the <a href="http://jqueryboilerplate.com/">JQuery Boilerplate</a>.</p>
<p>In order for the callback function to work, the event must be triggered within the plugin itself. Look inside Plugin.prototype.init() for details.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Boilerplate - Optional Option
</span><span>(</span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">$</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">window</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">document</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">undefined</span><span>) {
</span><span> </span><span style="color:#ff7733;">var </span><span>pluginName </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"optionsAreOptional"</span><span style="color:#bfbab0cc;">,
</span><span> defaults</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">PluginWrapper </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">element</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">pluginInfo</span><span>) {
</span><span> </span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">Plugin </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">checkArgs</span><span>(</span><span style="color:#f29718;">index</span><span>) {
</span><span> </span><span style="color:#ff7733;">switch </span><span>(pluginInfo[index]) {
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#c2d94c;">"object"</span><span>:
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Overwrite defaults if the args item is an object
</span><span> </span><span style="font-style:italic;color:#39bae6;">Plugin</span><span style="color:#f29668;">.</span><span>options </span><span style="color:#f29668;">= </span><span>$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">extend</span><span>({}</span><span style="color:#bfbab0cc;">, </span><span>defaults</span><span style="color:#bfbab0cc;">, </span><span>pluginInfo</span><span style="color:#f29668;">.</span><span>args[index])</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#c2d94c;">"function"</span><span>:
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Store the index of where the function location in args
</span><span> pluginInfo</span><span style="color:#f29668;">.</span><span>functionIndex </span><span style="color:#f29668;">= </span><span>index</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Check what type of arguments are supplied to
</span><span> </span><span style="font-style:italic;color:#5c6773;">// the first and second parameters
</span><span> </span><span style="color:#ff7733;">switch </span><span>(pluginInfo</span><span style="color:#f29668;">.</span><span>argsLen) {
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#f29718;">1</span><span>:
</span><span> </span><span style="color:#ffb454;">checkArgs</span><span>(</span><span style="color:#f29718;">0</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">case </span><span style="color:#f29718;">2</span><span>:
</span><span> </span><span style="color:#ffb454;">checkArgs</span><span>(</span><span style="color:#f29718;">0</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ffb454;">checkArgs</span><span>(</span><span style="color:#f29718;">1</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Should not have the same parameter types
</span><span> </span><span style="color:#ff7733;">if </span><span>(pluginInfo[</span><span style="color:#f29718;">0</span><span>] </span><span style="color:#f29668;">=== </span><span>pluginInfo[</span><span style="color:#f29718;">1</span><span>]) {
</span><span> </span><span style="color:#ff7733;">throw </span><span>[
</span><span> </span><span style="color:#c2d94c;">"Can not have the first two parameters of the same type of "</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'"'</span><span style="color:#bfbab0cc;">,
</span><span> pluginInfo[</span><span style="color:#f29718;">0</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">'"'</span><span style="color:#bfbab0cc;">,
</span><span> ]</span><span style="color:#f29668;">.</span><span style="color:#f07178;">join</span><span>(</span><span style="color:#c2d94c;">""</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> </span><span style="color:#ff7733;">break</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">Plugin</span><span style="color:#f29668;">.</span><span>prototype </span><span style="color:#f29668;">= </span><span>{
</span><span> </span><span style="color:#ffb454;">init</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">pluginInfo</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Do Stuff
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">stuff</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">var </span><span>$el </span><span style="color:#f29668;">= </span><span style="color:#ffb454;">$</span><span>(element)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Attaching event listener
</span><span> $el</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">on</span><span>(</span><span style="color:#c2d94c;">"optionsAreOptional"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>(</span><span style="color:#f29718;">evt</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Make sure a function exists before executing one
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">typeof </span><span>pluginInfo</span><span style="color:#f29668;">.</span><span>functionIndex </span><span style="color:#f29668;">!== </span><span style="color:#c2d94c;">"undefined"</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Preserve the event and context
</span><span> pluginInfo</span><span style="color:#f29668;">.</span><span>args[pluginInfo</span><span style="color:#f29668;">.</span><span>functionIndex]</span><span style="color:#f29668;">.</span><span style="color:#f07178;">call</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">, </span><span>evt)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Testing out the event listener
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Use this upon a certain condition being met
</span><span> $el</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">trigger</span><span>(</span><span style="color:#c2d94c;">"optionsAreOptional"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Do more stuff here
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">doMoreStuff</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">stuff</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Stuff to be done
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">doMoreStuff</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Even more stuff to be done
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Add more functions here
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Initialize plugin
</span><span> </span><span style="font-style:italic;color:#39bae6;">Plugin</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">Plugin</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">init</span><span>(pluginInfo)</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span> $</span><span style="color:#f29668;">.</span><span>fn[pluginName] </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span>args </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">Array</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#f29668;">.</span><span>slice</span><span style="color:#f29668;">.</span><span style="color:#f07178;">call</span><span>(</span><span style="font-style:italic;color:#39bae6;">arguments</span><span>)</span><span style="color:#bfbab0cc;">,
</span><span> argsLen </span><span style="color:#f29668;">= </span><span>args</span><span style="color:#f29668;">.</span><span>length</span><span style="color:#bfbab0cc;">,
</span><span> pluginInfo </span><span style="color:#f29668;">= </span><span>{}</span><span style="color:#bfbab0cc;">;
</span><span> pluginInfo</span><span style="color:#f29668;">.</span><span>argsLen </span><span style="color:#f29668;">= </span><span>argsLen</span><span style="color:#bfbab0cc;">;
</span><span> pluginInfo</span><span style="color:#f29668;">.</span><span>args </span><span style="color:#f29668;">= </span><span>args</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">checkArgs</span><span>(</span><span style="color:#f29718;">theItem</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">index</span><span>) {
</span><span> </span><span style="color:#ff7733;">try </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Determine if item is a plain object
</span><span> </span><span style="color:#ff7733;">if </span><span>($</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">isPlainObject</span><span>(theItem)) {
</span><span> pluginInfo[index] </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"object"</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> } </span><span style="color:#ff7733;">catch </span><span>(error) {
</span><span> </span><span style="color:#ff7733;">throw </span><span style="color:#c2d94c;">"Not a proper object"</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> </span><span style="color:#ff7733;">try </span><span>{
</span><span> </span><span style="color:#ff7733;">if </span><span>($</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">isFunction</span><span>(theItem)) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Determine if item is a function
</span><span> pluginInfo[index] </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"function"</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> } </span><span style="color:#ff7733;">catch </span><span>(error) {
</span><span> </span><span style="color:#ff7733;">throw </span><span style="color:#c2d94c;">"Not a proper function."</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }
</span><span> </span><span style="color:#ff7733;">return </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">each</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">!</span><span>$</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">data</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"plugin_" </span><span style="color:#f29668;">+ </span><span>pluginName)) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Check for the number of arguments for plugin
</span><span> </span><span style="color:#ff7733;">for </span><span>(</span><span style="color:#ff7733;">var </span><span>i </span><span style="color:#f29668;">= </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">; </span><span>i </span><span style="color:#f29668;">< </span><span>pluginInfo</span><span style="color:#f29668;">.</span><span>argsLen</span><span style="color:#bfbab0cc;">; </span><span>i</span><span style="color:#f29668;">++</span><span>) {
</span><span> </span><span style="color:#ffb454;">checkArgs</span><span>(pluginInfo</span><span style="color:#f29668;">.</span><span>args[i]</span><span style="color:#bfbab0cc;">, </span><span>i)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> $</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">data</span><span>(
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"plugin_" </span><span style="color:#f29668;">+ </span><span>pluginName</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29668;">new </span><span style="color:#59c2ff;">PluginWrapper</span><span>(</span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#bfbab0cc;">, </span><span>pluginInfo)
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>})(jQuery</span><span style="color:#bfbab0cc;">, </span><span>window</span><span style="color:#bfbab0cc;">, </span><span>document)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Accompanying Html -->
</span><span>
</span><span style="color:#39bae690;"><!</span><span style="color:#ff7733;">DOCTYPE </span><span style="color:#f29718;">html</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">></span><span>Optional Options</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">title</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">meta </span><span style="color:#ffb454;">charset</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"UTF-8" </span><span style="color:#39bae690;">/>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"jquery-1.10.2.min.js"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"JqueryBoilerPlateOptionalOptions.js"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#e6b673;">$</span><span>(</span><span style="font-style:italic;color:#39bae6;">document</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">ready</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// 1) Options Only
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Only options provided to the plugin
</span><span> </span><span style="font-style:italic;color:#5c6773;">// This is what most JQuery plugin out there uses
</span><span> </span><span style="color:#e6b673;">$</span><span>(</span><span style="color:#c2d94c;">"#only-options"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">optionsAreOptional</span><span>({
</span><span> stuff</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"myThings"</span><span style="color:#bfbab0cc;">,
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// 2) Function Only
</span><span> </span><span style="font-style:italic;color:#5c6773;">// This format is similar to the native JQuery event handler
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Use this if your plugin needs not to have any configuration options
</span><span> </span><span style="font-style:italic;color:#5c6773;">// In order for this to work, trigger the name of the plugin
</span><span> </span><span style="font-style:italic;color:#5c6773;">// ex. $('#only-function').trigger("optionsAreOptional")
</span><span> </span><span style="font-style:italic;color:#5c6773;">// inside your plugin to activate the event handler
</span><span> </span><span style="color:#e6b673;">$</span><span>(</span><span style="color:#c2d94c;">"#only-function"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">optionsAreOptional</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Only a function"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// 3) Options and Function
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Both option and function are provided for this one
</span><span> </span><span style="font-style:italic;color:#5c6773;">// Use this if a little configuration is needed over the
</span><span> </span><span style="font-style:italic;color:#5c6773;">// second option
</span><span> </span><span style="color:#e6b673;">$</span><span>(</span><span style="color:#c2d94c;">"#options-function"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">optionsAreOptional</span><span>(
</span><span> {
</span><span> moreStuff</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"moreOfMyThings"</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"My callback."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">h1</span><span style="color:#39bae690;">></span><span>The following headers have attached event listeners:</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">h1</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">h2 </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"only-options"</span><span style="color:#39bae690;">></span><span>Only options provided for this header.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">h2</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">h2 </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"only-function"</span><span style="color:#39bae690;">></span><span>A function attached to this header.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">h2</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">h2 </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"options-function"</span><span style="color:#39bae690;">></span><span>This header has options and a function.</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">h2</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span></code></pre>
<p><a href="http://jsbin.com/otIsuta/3/">Online Demo</a> | <a href="/archives/2013-09-12-optional-options.zip">Offline Demo</a></p>
JavaScript Quick Tips #4
2013-08-16T00:00:00+00:00
2013-08-16T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/javascript-quick-tips-number-4/
<h3 id="prototype-and-this">Prototype and This</h3>
<p>When attaching a method onto a prototype, the methods can be called from another prototype method using "this".</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Use this for Prototype functions
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">myObject </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#39bae6;">myObject</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">myMethod </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"executed myMethod"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#39bae6;">myObject</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">anotherMethod </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// no need to run myObject.prototype.myMethod()
</span><span> </span><span style="font-style:italic;color:#5c6773;">// to execute myMethod, but use "this" instead
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">myMethod</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// same concept applies here
</span><span>myObject</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">anotherMethod</span><span>()</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="function-arguments">Function Arguments</h3>
<p>If your function takes in many arguments, it might be more easy to follow when the parameters are broken up to multiple lines.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Breaking up Function Parameters
</span><span>
</span><span style="color:#ff7733;">var </span><span>here </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"here"</span><span style="color:#bfbab0cc;">,
</span><span> is </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"is"</span><span style="color:#bfbab0cc;">,
</span><span> an </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"an"</span><span style="color:#bfbab0cc;">,
</span><span> example </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"example"</span><span style="color:#bfbab0cc;">,
</span><span> that </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"that"</span><span style="color:#bfbab0cc;">,
</span><span> shows </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"shows"</span><span style="color:#bfbab0cc;">,
</span><span> lines </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"lines"</span><span style="color:#bfbab0cc;">,
</span><span> broken </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"broken"</span><span style="color:#bfbab0cc;">,
</span><span> up </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"up"</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">coolFunction</span><span>(</span><span style="color:#f29718;">here</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">is</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">an</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">example</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">that</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">shows</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">lines</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">broken</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">up</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// also works for logging
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(
</span><span> [here</span><span style="color:#bfbab0cc;">, </span><span>is</span><span style="color:#bfbab0cc;">, </span><span>an</span><span style="color:#bfbab0cc;">, </span><span>example</span><span style="color:#bfbab0cc;">, </span><span>that</span><span style="color:#bfbab0cc;">, </span><span>shows</span><span style="color:#bfbab0cc;">, </span><span>lines</span><span style="color:#bfbab0cc;">, </span><span>broken</span><span style="color:#bfbab0cc;">, </span><span>up]</span><span style="color:#f29668;">.</span><span style="color:#f07178;">join</span><span>(</span><span style="color:#c2d94c;">" "</span><span>)
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#ffb454;">coolFunction</span><span>(here</span><span style="color:#bfbab0cc;">, </span><span>is</span><span style="color:#bfbab0cc;">, </span><span>an</span><span style="color:#bfbab0cc;">, </span><span>example</span><span style="color:#bfbab0cc;">, </span><span>that</span><span style="color:#bfbab0cc;">, </span><span>shows</span><span style="color:#bfbab0cc;">, </span><span>lines</span><span style="color:#bfbab0cc;">, </span><span>broken</span><span style="color:#bfbab0cc;">, </span><span>up)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
JavaScript Quick Tips #3
2013-06-19T00:00:00+00:00
2013-06-19T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/javascript-quick-tips-number-3/
<h3 id="function-parameters-from-array-values">Function Parameters from Array Values</h3>
<p>Suppose we have a function with parameters and an array:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// A Function and an Array
</span><span>
</span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">doSomething</span><span>(</span><span style="color:#f29718;">stuff</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">thing1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">thing2</span><span>) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"params were concatenated:" </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">" " </span><span style="color:#f29668;">+ </span><span>stuff </span><span style="color:#f29668;">+ </span><span>thing1 </span><span style="color:#f29668;">+ </span><span>thing2)</span><span style="color:#bfbab0cc;">;
</span><span>}
</span><span>
</span><span style="color:#ff7733;">var </span><span>justAnArray </span><span style="color:#f29668;">= </span><span>[</span><span style="color:#c2d94c;">"a"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"b"</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"c"</span><span>]</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<span id="continue-reading"></span>
<p>We want to pass the function parameters the values from the array. So 'a', 'b', 'c' will correspond to stuff, thing1, and thing2.</p>
<p>Instead of iterating through the array to get the items into the function or doing manual array index reference, you can use JavaScript's apply function.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Example of Using Apply
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// the pattern for using apply
</span><span style="font-style:italic;color:#5c6773;">// theFunction belongs to theContext
</span><span style="font-style:italic;color:#5c6773;">// theFunction.apply(theContext, theArray);
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// in our example, theContext is undefined
</span><span style="font-style:italic;color:#5c6773;">// because theContext refers to an object
</span><span style="font-style:italic;color:#5c6773;">// but we do not have one
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// logs out 'params were concatenated: abc'
</span><span>doSomething</span><span style="color:#f29668;">.</span><span style="color:#f07178;">apply</span><span>(</span><span style="color:#f29718;">undefined</span><span style="color:#bfbab0cc;">, </span><span>justAnArray)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="alternative-to-using-push-for-arrays">Alternative to Using Push for Arrays</h3>
<p>The usual way of adding an item to an array is to use push something into an array:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Common Push Operation for Arrays
</span><span>
</span><span style="color:#ff7733;">var </span><span>friendlyNeighborhoodArray </span><span style="color:#f29668;">= </span><span>[]</span><span style="color:#bfbab0cc;">;
</span><span>friendlyNeighborhoodArray</span><span style="color:#f29668;">.</span><span style="color:#f07178;">push</span><span>(</span><span style="color:#c2d94c;">"Mr. Rogers"</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Another way to perform a push is to get the length of array and use that value as the index to set a value:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Use Array Length to Add Items to Array
</span><span>
</span><span style="color:#ff7733;">var </span><span>friendlyNeighborhoodArray </span><span style="color:#f29668;">= </span><span>[]</span><span style="color:#bfbab0cc;">,
</span><span> arrayLength </span><span style="color:#f29668;">= </span><span>friendlyNeighborhoodArray</span><span style="color:#f29668;">.</span><span>length</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>friendlyNeighborhoodArray[arrayLength] </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"Mr. Rogers"</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>This way is a not as clean as using push, but it looks to perform better than the native push.</p>
$.proxy
2013-06-06T00:00:00+00:00
2013-06-06T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/dollars-dot-proxy/
<h3 id="getting-the-right-this">Getting the Right 'this'</h3>
<p>With jQuery, you often find yourself using an event listener with a callback function like so:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Common Event Handler
</span><span>
</span><span style="color:#ffb454;">$</span><span>(document)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">ready</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">".my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">click</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"this is "</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">this</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<span id="continue-reading"></span>
<p>The 'this' is the console.log() refers to javascript element, '.my-element'. There are however times when you wish to refer to another 'this', such as when you want the parent object:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Wrong Context 'this'
</span><span>
</span><span style="color:#ffb454;">$</span><span>(document)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">ready</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">MyConstructor </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">MyConstructor</span><span style="color:#f29668;">.</span><span>prototype </span><span style="color:#f29668;">= </span><span>{
</span><span> </span><span style="color:#ffb454;">init</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// logs 'doing stuff'
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">doStuff</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// when element is clicked, there will be an error
</span><span> </span><span style="font-style:italic;color:#5c6773;">// because of the wrong 'this' reference
</span><span> </span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">".my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">click</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">doStuff</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">doStuff</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"doing stuff"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">MyConstructor</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">init</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>An error will log in the console when clicking on the words.</p>
<p><a href="http://jsbin.com/umepuf/1/edit">Demo</a></p>
<p>The context must change in order for 'this' inside the event handler to reference the constructor's 'this'.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Using $.proxy to Correct Context
</span><span style="color:#ffb454;">$</span><span>(document)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">ready</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">MyConstructor </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">MyConstructor</span><span style="color:#f29668;">.</span><span>prototype </span><span style="color:#f29668;">= </span><span>{
</span><span> </span><span style="color:#ffb454;">init</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// logs 'doing stuff'
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">doStuff</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// the 'this' now refers to the constructor's 'this'
</span><span> </span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">".my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">click</span><span>(
</span><span> $</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">proxy</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// 'this' should work
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">doStuff</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// to reference back the dom object
</span><span> </span><span style="color:#ff7733;">var </span><span>_this </span><span style="color:#f29668;">= </span><span>event</span><span style="color:#f29668;">.</span><span>target</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">, </span><span style="font-style:italic;color:#39bae6;">this</span><span>)
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">doStuff</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"doing stuff"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">MyConstructor</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">init</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>Now when the words are clicked, the console should log out 'doing stuff'.</p>
<p><a href="http://jsbin.com/umepuf/4/edit">Demo</a></p>
<p>If you wish to refer back to the original 'this' for the event handler you would need to get it from the event.</p>
<p>As a side note, $.proxy could have also been use another way, but the result isn't as clean:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Another $.proxy Alternative
</span><span>
</span><span style="color:#ffb454;">$</span><span>(document)</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">ready</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">MyConstructor </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {}</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">MyConstructor</span><span style="color:#f29668;">.</span><span>prototype </span><span style="color:#f29668;">= </span><span>{
</span><span> </span><span style="color:#ffb454;">init</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// logs 'doing stuff'
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">doStuff</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// alias the prototype
</span><span> </span><span style="color:#ff7733;">var </span><span>mcp </span><span style="color:#f29668;">= </span><span style="font-style:italic;color:#39bae6;">MyConstructor</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#5c6773;">// another way of using proxy
</span><span> </span><span style="font-style:italic;color:#5c6773;">// more in line with the jQuery docs
</span><span> </span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">".my-element"</span><span>)</span><span style="color:#f29668;">.</span><span style="color:#f07178;">click</span><span>(</span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// actually a trivial example
</span><span> </span><span style="font-style:italic;color:#5c6773;">// could have done mcp.doStuff()
</span><span> </span><span style="font-style:italic;color:#5c6773;">// use to demonstrate proxy
</span><span> $</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">proxy</span><span>(mcp</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">doStuff</span><span>()</span><span style="color:#bfbab0cc;">, </span><span>mcp)</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#ffb454;">doStuff</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"doing stuff"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span> }</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="font-style:italic;color:#39bae6;">MyConstructor</span><span style="color:#f29668;">.</span><span>prototype</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">init</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p><a href="http://jsbin.com/umepuf/3/edit">Demo</a></p>
Get Device Width
2013-05-09T00:00:00+00:00
2013-05-09T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/get-device-width/
<h3 id="detect-max-screen-width">Detect Max Screen Width</h3>
<p>When a browser is zoomed in or resized, the reported maximum device screen width may not be what you expect. For example, you have a 1280px by 800px screen and fully maximized browser screen at 100% zoom level, but when you zoom into the page and use window.innerWidth to determine the max width, the value may not be 1280px.</p>
<span id="continue-reading"></span>
<p>To get around this limitation, <a href="https://developer.mozilla.org/en-US/docs/DOM/window.matchMedia">matchMedia</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries">media queries</a> can be used to detect the max device width. Here is a something that allows you to do so:</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Get Max-Device-Width
</span><span>
</span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">getDeviceWidth</span><span>() {
</span><span> </span><span style="color:#ff7733;">var </span><span>isFound </span><span style="color:#f29668;">= </span><span style="color:#f29718;">false</span><span style="color:#bfbab0cc;">,
</span><span> commonResolutions </span><span style="color:#f29668;">= </span><span>[
</span><span> </span><span style="color:#f29718;">360</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">480</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">640</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">800</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">960</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">1024</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">1280</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">1360</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">1366</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">1440</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">1600</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">1680</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">1920</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#f29718;">2560</span><span style="color:#bfbab0cc;">,
</span><span> ]</span><span style="color:#bfbab0cc;">;
</span><span> crLen </span><span style="color:#f29668;">= </span><span>commonResolutions</span><span style="color:#f29668;">.</span><span>length</span><span style="color:#bfbab0cc;">;
</span><span> i </span><span style="color:#f29668;">= </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#5c6773;">// for browsers that support matchMedia
</span><span> </span><span style="color:#ff7733;">if </span><span>(</span><span style="color:#f29668;">typeof </span><span>window</span><span style="color:#f29668;">.</span><span>matchMedia </span><span style="color:#f29668;">!= </span><span style="color:#c2d94c;">"undefined"</span><span>) {
</span><span> i </span><span style="color:#f29668;">= </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">while </span><span>(isFound </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">false</span><span>) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(window</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">matchMedia</span><span>(</span><span style="color:#c2d94c;">"(max-device-width: " </span><span style="color:#f29668;">+ </span><span>i </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"px)"</span><span>)</span><span style="color:#f29668;">.</span><span>matches) {
</span><span> isFound </span><span style="color:#f29668;">= </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"MatchMedia detects max device width as " </span><span style="color:#f29668;">+ </span><span>i </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"px."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> document</span><span style="color:#f29668;">.</span><span style="color:#f07178;">write</span><span>(</span><span style="color:#c2d94c;">"MatchMedia detects max device width as " </span><span style="color:#f29668;">+ </span><span>i </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"px."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> i</span><span style="color:#f29668;">++</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> } </span><span style="color:#ff7733;">else </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// check screen size against common resolutions
</span><span> </span><span style="color:#ff7733;">for </span><span>(</span><span style="color:#ff7733;">var </span><span>j </span><span style="color:#f29668;">= </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">; </span><span>j </span><span style="color:#f29668;">< </span><span>crLen</span><span style="color:#bfbab0cc;">; </span><span>j</span><span style="color:#f29668;">++</span><span>) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(
</span><span> Modernizr</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">mq</span><span>(
</span><span> </span><span style="color:#c2d94c;">"screen and (max-device-width: " </span><span style="color:#f29668;">+ </span><span>commonResolutions[j] </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"px)"
</span><span> )
</span><span> ) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(
</span><span> </span><span style="color:#c2d94c;">"Modernizr detects max device width at " </span><span style="color:#f29668;">+
</span><span> commonResolutions[j] </span><span style="color:#f29668;">+
</span><span> </span><span style="color:#c2d94c;">"px."
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span> document</span><span style="color:#f29668;">.</span><span style="color:#f07178;">write</span><span>(
</span><span> </span><span style="color:#c2d94c;">"Modernizr detects max device width at " </span><span style="color:#f29668;">+
</span><span> commonResolutions[j] </span><span style="color:#f29668;">+
</span><span> </span><span style="color:#c2d94c;">"px."
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span> j </span><span style="color:#f29668;">= </span><span>crLen</span><span style="color:#bfbab0cc;">;
</span><span> isFound </span><span style="color:#f29668;">= </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }
</span><span> </span><span style="font-style:italic;color:#5c6773;">// use more exhaustive approach if width is not found in common resolutions
</span><span> </span><span style="color:#ff7733;">while </span><span>(isFound </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">false</span><span>) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(Modernizr</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">mq</span><span>(</span><span style="color:#c2d94c;">"screen and (max-device-width: " </span><span style="color:#f29668;">+ </span><span>i </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"px)"</span><span>)) {
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"Modernizr detects max device width at " </span><span style="color:#f29668;">+ </span><span>i </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"px."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> document</span><span style="color:#f29668;">.</span><span style="color:#f07178;">write</span><span>(
</span><span> </span><span style="color:#c2d94c;">"Modernizr detects max device width at " </span><span style="color:#f29668;">+
</span><span> commonResolutions[j] </span><span style="color:#f29668;">+
</span><span> </span><span style="color:#c2d94c;">"px."
</span><span> )</span><span style="color:#bfbab0cc;">;
</span><span> isFound </span><span style="color:#f29668;">= </span><span style="color:#f29718;">true</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> i</span><span style="color:#f29668;">++</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span> }
</span><span>}
</span></code></pre>
<p>The media queries portion of the function relies on <a href="http://modernizr.com/download/">modernizr</a>, a feature detection library, to work. You can get a custom build of modernizr to include only the media queries detection.</p>
<p>This function will work when the browser supports matchMedia and will fall back to using media queries if it does not. If your browser does not support either matchMedia and media queries then the function will not work. This function is tested with Opera 12.15, Chrome 26.0.1410.64, and IE 10. Firefox 20.0, however does not report the proper max-device-width when the browser window is zoomed or resized.</p>
<p><a href="http://jsbin.com/iwumid/1">Demo</a></p>
Standalone Mocha with Component
2013-05-02T00:00:00+00:00
2013-05-02T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/standalone-mocha-with-component/
<h3 id="run-mocha-on-the-client-side">Run Mocha on the Client Side</h3>
<p>Install Nvm to install Node by following instructions <a href="https://github.com/creationix/nvm">here</a>. Nvm allows you to switch to different versions of Node to manage dependencies.
Install Component after Node is properly setup from <a href="https://github.com/component/component">here</a>. Component is an asset management tool for the client side.
After Nvm, Node and Component are working properly, make a directory on the desktop and change to it.</p>
<span id="continue-reading"></span><pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Make and Change to Directory
</span><span>
</span><span style="color:#f07178;">cd</span><span> Desktop
</span><span style="color:#ffb454;">mkdir</span><span> standalone-mocha
</span><span style="color:#f07178;">cd</span><span> standalone-mocha
</span></code></pre>
<p>Make an index.html and component.json file in the root of the folder.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Create a HTML and JSON File
</span><span>
</span><span style="color:#ffb454;">touch</span><span> index.html
</span><span style="color:#ffb454;">touch</span><span> component.json
</span></code></pre>
<p>Input the following to component.json. The name can be whatever you want it to be, but the important dependencies are in the development key. Component/assert is needed because Mocha does not have an assertion library by default.</p>
<pre data-lang="json" style="background-color:#0f1419;color:#bfbab0;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#c2d94c;">"name"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"a-standalone-mocha"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"development"</span><span style="color:#bfbab0cc;">: </span><span>{
</span><span> </span><span style="color:#c2d94c;">"component/assert"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"*"</span><span style="color:#bfbab0cc;">,
</span><span> </span><span style="color:#c2d94c;">"visionmedia/mocha"</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"*"
</span><span> }
</span><span>}
</span></code></pre>
<p>Input the following to index.html:</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Html for Browser -->
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"stylesheet" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"build/build.css" </span><span style="color:#39bae690;">/>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">head</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"mocha"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"parent"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"child"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"build/build.js"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> assert </span><span style="color:#f29668;">= </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"assert"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#f07178;">require</span><span>(</span><span style="color:#c2d94c;">"visionmedia-mocha"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> mocha</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">setup</span><span>(</span><span style="color:#c2d94c;">"bdd"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span> </span><span style="color:#ffb454;">describe</span><span>(</span><span style="color:#c2d94c;">"Array"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">describe</span><span>(</span><span style="color:#c2d94c;">"#indexOf()"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">it</span><span>(</span><span style="color:#c2d94c;">"should return -1 when the value is not present"</span><span style="color:#bfbab0cc;">, </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="color:#ffb454;">assert</span><span>(</span><span style="color:#f29668;">-</span><span style="color:#f29718;">1 </span><span style="color:#f29668;">=== </span><span>[</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span>]</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">indexOf</span><span>(</span><span style="color:#f29718;">5</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ffb454;">assert</span><span>(</span><span style="color:#f29668;">-</span><span style="color:#f29718;">1 </span><span style="color:#f29668;">=== </span><span>[</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span>]</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">indexOf</span><span>(</span><span style="color:#f29718;">0</span><span>))</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> })</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> mocha</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">run</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">script</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">body</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">html</span><span style="color:#39bae690;">>
</span></code></pre>
<p>Install and build with component. The -d flag is used because mocha is intended for use in development mode.</p>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Tell Component to Generated Files
</span><span>
</span><span style="color:#ffb454;">component</span><span> install</span><span style="color:#f29718;"> -d
</span><span style="color:#ffb454;">component</span><span> build</span><span style="color:#f29718;"> -d
</span></code></pre>
<p>Open the index.html file, and you will be greeted with the following:</p>
<img src="/images/posts/2013-05-02-standalone-mocha-with-component.png" alt="Standalone Mocha with Component">
<p><a href="/archives/2013-05-02-standalone-mocha-with-component.zip">Offline Demo</a></p>
JavaScript Quick Tips #2
2013-04-28T00:00:00+00:00
2013-04-28T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/javascript-quick-tips-number-2/
<h3 id="concatenating-when-logging-without-the-plus-sign">Concatenating when Logging without the Plus Sign</h3>
<p>You can use the comma in place of the plus sign when concatenation is needed.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Give the Comma a Try When Logging
</span><span>
</span><span style="color:#ff7733;">var </span><span>stuff </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"my stuff"</span><span style="color:#bfbab0cc;">;
</span><span style="font-style:italic;color:#5c6773;">// the comma acts like the plus to concatenate your strings
</span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(</span><span style="color:#c2d94c;">"some text:"</span><span style="color:#bfbab0cc;">, </span><span>stuff)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<span id="continue-reading"></span><h3 id="attaching-properties-to-non-object-objects">Attaching Properties to Non-Object Objects</h3>
<p>Usually when you deal with an array you normally do not attach properties to it, but you are allowed to do such a thing.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Attaching Property to an Array
</span><span>
</span><span style="color:#ff7733;">var </span><span>myArray </span><span style="color:#f29668;">= </span><span>[</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span>]</span><span style="color:#bfbab0cc;">;
</span><span>myArray</span><span style="color:#f29668;">.</span><span>aKey </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"myValue"</span><span style="color:#bfbab0cc;">;
</span><span style="font-style:italic;color:#5c6773;">// outputs "myValue"
</span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(myArray</span><span style="color:#f29668;">.</span><span>akey)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>You can also do the same thing for a function and other non-object objects.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Now Attaching Property to a Function
</span><span>
</span><span style="color:#ff7733;">var </span><span style="color:#ffb454;">myFunction </span><span style="color:#f29668;">= </span><span style="color:#ff7733;">function </span><span>() {}</span><span style="color:#bfbab0cc;">;
</span><span style="font-style:italic;color:#5c6773;">// outputs "myValue"
</span><span>myFunction</span><span style="color:#f29668;">.</span><span>aKey </span><span style="color:#f29668;">= </span><span style="color:#c2d94c;">"myValue"</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p>The reason you can do this is that everything in JavaScript is treated like an object. You may want to do this to include metadata on your arrays, functions or other variable types that are not object objects, but do use your discretion when an object is more fitting for the task.</p>
Checking Attribute Status with JQuery
2013-04-24T00:00:00+00:00
2013-04-24T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/checking-attribute-status-with-jquery/
<h3 id="get-element-s-attribute-value-or-status">Get Element's Attribute Value or Status</h3>
<p>With JQuery, you can do this $('#your-element').hasClass('a-class') to check if the element has a certain class. The problem is that you have to know the class name ahead of time when you use .hasClass. I wanted a general way to know if the class attribute actually exists on the element, so I created the getAttrStat function for JQuery to see if the attribute in question on the element is undefined, empty, or has a value without knowing the attribute value ahead of time.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Function to Get Attribute Status
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// the return codes are arbitrary
</span><span style="color:#ff7733;">function </span><span style="color:#ffb454;">getAttrStat</span><span>(</span><span style="color:#f29718;">elem</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">attr</span><span>) {
</span><span> </span><span style="color:#ff7733;">var </span><span>attrValue </span><span style="color:#f29668;">= </span><span style="color:#f29718;">null</span><span style="color:#bfbab0cc;">,
</span><span> attrStatus </span><span style="color:#f29668;">= </span><span>(attrValue </span><span style="color:#f29668;">= </span><span>elem</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">attr</span><span>(attr)) </span><span style="color:#f29668;">|| </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">if </span><span>(attrStatus </span><span style="color:#f29668;">=== </span><span style="color:#f29718;">0</span><span>) {
</span><span> </span><span style="color:#ff7733;">if </span><span>(attrValue </span><span style="color:#f29668;">=== </span><span style="color:#c2d94c;">""</span><span>) {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// attr is empty
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(elem</span><span style="color:#f29668;">.</span><span>selector </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">" '" </span><span style="color:#f29668;">+ </span><span>attr </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"' is empty."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">;
</span><span> } </span><span style="color:#ff7733;">else if </span><span>(</span><span style="color:#f29668;">typeof </span><span>attrValue </span><span style="color:#f29668;">== </span><span style="color:#c2d94c;">"undefined"</span><span>)
</span><span> </span><span style="font-style:italic;color:#5c6773;">// attr is undefined
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(elem</span><span style="color:#f29668;">.</span><span>selector </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">" '" </span><span style="color:#f29668;">+ </span><span>attr </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"' is undefined."</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span> } </span><span style="color:#ff7733;">else </span><span>{
</span><span> </span><span style="font-style:italic;color:#5c6773;">// attr has a value
</span><span> </span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(elem</span><span style="color:#f29668;">.</span><span>selector </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">" '" </span><span style="color:#f29668;">+ </span><span>attr </span><span style="color:#f29668;">+ </span><span style="color:#c2d94c;">"' has a value: " </span><span style="color:#f29668;">+ </span><span>attrValue)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#ff7733;">return </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">;
</span><span> }
</span><span>}
</span></code></pre>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Usage of Function
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// returns 0 and logs #a-id 'class' is undefined.
</span><span style="color:#ffb454;">getAttrStat</span><span>(</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#a-id"</span><span>)</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"class"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// returns 1 and logs #b-id 'class' is undefined.
</span><span style="color:#ffb454;">getAttrStat</span><span>(</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#b-id"</span><span>)</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"class"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// returns 2 and logs #c-id 'class' is undefined.
</span><span style="color:#ffb454;">getAttrStat</span><span>(</span><span style="color:#ffb454;">$</span><span>(</span><span style="color:#c2d94c;">"#c-id"</span><span>)</span><span style="color:#bfbab0cc;">, </span><span style="color:#c2d94c;">"class"</span><span>)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Divs with Attributes -->
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"a-id"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">class</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"" </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"b-id"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">class</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"c-class" </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"c-id"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span></code></pre>
<p><a href="http://jsbin.com/apodom/1/edit">Demo</a></p>
Nested Divs Spaced Evenly
2013-04-18T00:00:00+00:00
2013-04-18T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/nested-divs-spaced-evenly/
<h3 id="get-child-divs-to-align-vertically-with-spacing">Get Child Divs to Align Vertically with Spacing</h3>
<p>You may find yourself having to align fixed-height divs that are nested within a parent div. For example, you might have images that need equal spacing at the top and the bottom. In order to do this, set a margin-bottom on all the child divs (B, C, D) within the parent div (A).</p>
<span id="continue-reading"></span><img src="/images/posts/2013-04-18-nested-divs-spaced-evenly-Margin-Bottom.png" alt="nested div spaced bottom">
<p>Then set a margin-top for the first child (B). The first nested div is given an id and the css pseudo class of :first-child is applied. The reason I did it this way, instead of using margin-top on all the child divs with :last-child psuedo class on the last child div, is because the :first-child is supported in older browsers.</p>
<img src="/images/posts/2013-04-18-nested-divs-spaced-evenly-Last-Child-Margin-Bottom.png" alt="nested div spaced bottom last child">
<p><a href="http://jsbin.com/uqileq/1/edit">Demo</a></p>
JavaScript Quick Tips #1
2013-04-14T00:00:00+00:00
2013-04-14T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/javascript-quick-tips-number-1/
<h3 id="solutions-to-common-javascript-problems">Solutions to Common JavaScript Problems</h3>
<h3 id="problem">Problem</h3>
<p>Alerting an object returns [object Object].</p>
<span id="continue-reading"></span><h3 id="solution">Solution</h3>
<p>Use JSON.stringify on the object before alerting.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Convert Object to JSON for Alert
</span><span>
</span><span style="color:#ff7733;">var </span><span>myVar </span><span style="color:#f29668;">= </span><span>{ myKey</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"myValue" </span><span>}</span><span style="color:#bfbab0cc;">;
</span><span style="color:#ffb454;">alert</span><span>(</span><span style="font-style:italic;color:#f29668;">JSON</span><span style="color:#f29668;">.</span><span style="color:#f07178;">stringify</span><span>(myVar))</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<h3 id="problem-1">Problem</h3>
<p>You want to use splice, but it is destructive.</p>
<h3 id="solution-1">Solution</h3>
<p>Use slice on the original array to make a copy. The spliced array will not affect the array created by slice.</p>
<pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Slice Before You Splice
</span><span>
</span><span style="color:#ff7733;">var </span><span>myArray </span><span style="color:#f29668;">= </span><span>[</span><span style="color:#f29718;">1</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">3</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">4</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">5</span><span>]</span><span style="color:#bfbab0cc;">,
</span><span> copyArray </span><span style="color:#f29668;">= </span><span>myArray</span><span style="color:#f29668;">.</span><span style="color:#f07178;">slice</span><span>()</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span>myArray</span><span style="color:#f29668;">.</span><span style="color:#f07178;">splice</span><span>(</span><span style="color:#f29718;">2</span><span style="color:#bfbab0cc;">, </span><span style="color:#f29718;">1</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// copyArray is your original
</span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(copyArray)</span><span style="color:#bfbab0cc;">;
</span><span>
</span><span style="font-style:italic;color:#5c6773;">// myArray will be spliced
</span><span style="font-style:italic;color:#39bae6;">console</span><span style="color:#f29668;">.</span><span style="color:#f07178;">log</span><span>(myArray)</span><span style="color:#bfbab0cc;">;
</span></code></pre>
Ember Routes Redirect
2013-04-13T00:00:00+00:00
2013-04-13T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/ember-routes-redirect/
<h3 id="from-index-to-another-route">From Index to Another Route</h3>
<p>You want your root index route to redirect to another route such as when you are on the index URL (root_url) and you need to get to root_url/#/another_route. This may be useful because you wish to use the model information from another_route on initial page load. A downloadable demo is located below.</p>
<span id="continue-reading"></span><pre data-lang="js" style="background-color:#0f1419;color:#bfbab0;" class="language-js "><code class="language-js" data-lang="js"><span style="font-style:italic;color:#5c6773;">// Index Route to Another Route
</span><span>
</span><span>App</span><span style="color:#f29668;">.</span><span>IndexRoute </span><span style="color:#f29668;">= </span><span>Ember</span><span style="color:#f29668;">.</span><span>Route</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">extend</span><span>({
</span><span> </span><span style="color:#ffb454;">redirect</span><span style="color:#bfbab0cc;">: </span><span style="color:#ff7733;">function </span><span>() {
</span><span> </span><span style="font-style:italic;color:#5c6773;">// replace 'guitars' with your specific route name
</span><span> </span><span style="font-style:italic;color:#39bae6;">this</span><span style="color:#f29668;">.</span><span style="color:#ffb454;">transitionTo</span><span>(</span><span style="color:#c2d94c;">"guitars"</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> }</span><span style="color:#bfbab0cc;">,
</span><span>})</span><span style="color:#bfbab0cc;">;
</span></code></pre>
<p><a href="/archives/2013-04-13-ember-routes-redirect.zip">Download Demo</a></p>
Basic Gemset Management
2013-04-11T00:00:00+00:00
2013-04-11T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/basic-gemset-management/
<h3 id="crud-for-your-rvm-gemset">CRUD for your rvm gemset</h3>
<p>Rvm stands for ruby version manager. It is used to manage ruby environments with something called gemsets. More info can be found <a href="https://rvm.io/">here</a>. Rvm comes in handy when you're working with <a href="http://www.rubyonrails.org/">Rails</a> because you can isolate ruby environments. Here are some snippets for common tasks when dealing with gemsets.</p>
<span id="continue-reading"></span><pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Creating a Gemset
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Format:
</span><span style="color:#ffb454;">rvm</span><span> gemset create </span><span style="color:#f29668;"><</span><span>gemset_name</span><span style="color:#f29668;">>
</span><span style="font-style:italic;color:#5c6773;"># fill in gemset name
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Example:
</span><span style="color:#ffb454;">rvm</span><span> gemset create rails3.2.13
</span><span style="font-style:italic;color:#5c6773;"># gemset name is "rails3.2.13"
</span></code></pre>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># List Current Gemset Being Used
</span><span>
</span><span style="color:#ffb454;">rvm</span><span> gemset list
</span></code></pre>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Using a Gemset
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Format:
</span><span style="color:#ffb454;">rvm</span><span> use </span><span style="color:#f29668;"><</span><span>ruby_version_number</span><span style="color:#f29668;">></span><span>@</span><span style="color:#f29668;"><</span><span>gemset_name</span><span style="color:#f29668;">>
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># fill in ruby version number and gemset name of your choosing
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Example:
</span><span style="font-style:italic;color:#5c6773;"># uses ruby 1.9.3 with gemset name of "rails version 3.2.13"
</span><span style="color:#ffb454;">rvm</span><span> use 1.9.3@rails3.2.13</span><span style="color:#f29718;"> --default
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># also using a default flag to set the gemset as the default
</span></code></pre>
<pre data-lang="bash" style="background-color:#0f1419;color:#bfbab0;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#5c6773;"># Deleting a Gemset
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Format:
</span><span style="color:#ffb454;">rvm</span><span> gemset delete </span><span style="color:#f29668;"><</span><span>gemset_name</span><span style="color:#f29668;">>
</span><span style="font-style:italic;color:#5c6773;"># fill in gemset name
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># Example:
</span><span style="color:#ffb454;">rvm</span><span> gemset delete gemset_to_delete
</span><span style="font-style:italic;color:#5c6773;">#"gemset_to_delete" is the gemset that you want to delete
</span></code></pre>
Whole Header Region Clickable
2013-04-03T00:00:00+00:00
2013-04-03T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/whole-header-region-clickable/
<h3 id="header-text-and-image-are-clickable">Header Text and Image are Clickable</h3>
<p>On the majority the sites out there, the click of the upper-left hand side where logo and text is situated, will take you to the home page. Take for example <a href="https://trello.com/">Trello</a> or <a href="http://www.pcworld.com/">PcWorld</a>. However, I do not have a small logo on the upper-left of the site because I want my whole header region to lead to the home page.</p>
<span id="continue-reading"></span>
<p>The general idea on how to do this is to make a header tag that will contain all header text and logo along with a link. To illustrate this, I will use my site as an example. If you want to make changes in your Octopress blog, I am modifying my source/_includes/custom/header.html file.</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span style="font-style:italic;color:#5c6773;"><!-- Header Region -->
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">title</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"Home is where the heart is." </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"main-header-container"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"top-header-area"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">div </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"main-header"</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">img
</span><span> </span><span style="color:#ffb454;">alt</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"my-main-logo"
</span><span> </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"my-main-logo"
</span><span> </span><span style="color:#ffb454;">src</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"{{ root_url }}/images/logoSmall.png"
</span><span> </span><span style="color:#39bae690;">/>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">h1 </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"site-title-header"</span><span style="color:#39bae690;">></span><span>{{ site.title }}</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">h1</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span><span> </span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">a </span><span style="color:#ffb454;">id</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"home-link" </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"/"</span><span style="color:#39bae690;">></</span><span style="color:#59c2ff;">a</span><span style="color:#39bae690;">>
</span><span style="color:#39bae690;"></</span><span style="color:#59c2ff;">div</span><span style="color:#39bae690;">>
</span></code></pre>
<p>To make the link work for all browsers, which includes IE, there is an additional css trick. The A tag needs to have a background color (it does not matter which color) and set the opacity of the A tag to zero.</p>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* Absolute Position the A Tag */
</span><span>
</span><span style="color:#ffb454;">#home-link </span><span>{
</span><span> </span><span style="color:#39bae6;">position</span><span style="color:#bfbab0cc;">: </span><span style="font-style:italic;color:#f29668;">absolute</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">top</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">height</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">100</span><span style="color:#ff7733;">%</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">width</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">100</span><span style="color:#ff7733;">%</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">background-color</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">#fff</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="font-style:italic;color:#5c6773;">-ms-</span><span style="color:#39bae6;">filter</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">filter</span><span style="color:#bfbab0cc;">: </span><span style="color:#f07178;">alpha</span><span>(opacity=</span><span style="color:#f29718;">0</span><span>)</span><span style="color:#bfbab0cc;">;
</span><span> </span><span style="color:#39bae6;">opacity</span><span style="color:#bfbab0cc;">: </span><span style="color:#f29718;">0</span><span style="color:#bfbab0cc;">;
</span><span>}
</span></code></pre>
First Official Post
2013-03-24T00:00:00+00:00
2013-03-24T00:00:00+00:00
Unknown
https://williamhuey.github.io/posts/first-official-post/
<h2 id="customizing-octopress-default-theme">Customizing Octopress Default Theme</h2>
<h3 id="change-default-theme-css">Change Default Theme CSS</h3>
<p>In your sass/custom/_colors.scss file, define the values for the items below. I'm using the following colors for my theme, but feel free to change them to whatever you want them to be.</p>
<span id="continue-reading"></span><h3 id="header-colors">Header Colors</h3>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* Header Background and Subtitle Color */
</span><span>
</span><span>$</span><span style="color:#59c2ff;">header-bg</span><span>: #1a1a1a;
</span><span>$</span><span style="color:#59c2ff;">subtitle-color</span><span>: </span><span style="color:#ffb454;">#c4c4c4</span><span> !default;
</span></code></pre>
<h3 id="text-colors">Text Colors</h3>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* Text Regular and Text Light Colors */
</span><span>
</span><span>$</span><span style="color:#59c2ff;">text-color</span><span>: </span><span style="color:#ffb454;">#fafafa</span><span> !default;
</span><span>$</span><span style="color:#59c2ff;">text-color-light</span><span>: #919191 !default;
</span></code></pre>
<h3 id="link-colors">Link Colors</h3>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* Link State Colors */
</span><span>
</span><span>$</span><span style="color:#59c2ff;">link-color</span><span>: </span><span style="color:#ffb454;">#fffffa</span><span> !default;
</span><span>$</span><span style="color:#59c2ff;">link-color-hover</span><span>: </span><span style="color:#ffb454;">#c4c4c4</span><span> !default;
</span><span>$</span><span style="color:#59c2ff;">link-color-visited</span><span>: </span><span style="color:#ffb454;">#a8a8a8</span><span> !default;
</span></code></pre>
<h3 id="nav-background-colors">Nav Background Colors</h3>
<pre data-lang="css" style="background-color:#0f1419;color:#bfbab0;" class="language-css "><code class="language-css" data-lang="css"><span style="font-style:italic;color:#5c6773;">/* Nav Foreground and Background Color */
</span><span>
</span><span>$</span><span style="color:#59c2ff;">nav-bg-front</span><span>: </span><span style="color:#59c2ff;">background-color</span><span>(none) !default;
</span><span>$</span><span style="color:#59c2ff;">nav-bg-back</span><span>: </span><span style="color:#59c2ff;">background-color</span><span>(none) !default;
</span></code></pre>
<h3 id="cut-out-google-fonts">Cut Out Google Fonts</h3>
<p>Reduce the number of requests that you make to get your site to load faster. Follow the directions on the <a href="https://web.archive.org/web/20150419021552/http://blog.bigdinosaur.org/using-at-font-face-with-octopress/">big dinosaur blog.</a></p>
<h3 id="removing-default-javascript">Removing Default Javascript</h3>
<p>In the /source/_include/head.html file, remove any unwanted javascript. I decided to do this because having dom manipulation or feature detection javascript libraries were not critical to consuming the information on my blog.</p>
<h3 id="adding-a-custom-favicon">Adding a Custom Favicon</h3>
<p>Navigate to source/_include/custom/head.html and insert these lines:</p>
<pre data-lang="html" style="background-color:#0f1419;color:#bfbab0;" class="language-html "><code class="language-html" data-lang="html"><span>/* Adding Favicon in Ico and Png Format */
</span><span>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link
</span><span> </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"{{ root_url }}/favicon.ico"
</span><span> </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"shortcut icon"
</span><span> </span><span style="color:#ffb454;">type</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"image/x-icon"
</span><span style="color:#39bae690;">/>
</span><span style="color:#39bae690;"><</span><span style="color:#59c2ff;">link
</span><span> </span><span style="color:#ffb454;">href</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"{{ root_url }}/favicon.png"
</span><span> </span><span style="color:#ffb454;">rel</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"shortcut icon"
</span><span> </span><span style="color:#ffb454;">type</span><span style="color:#bfbab0cc;">=</span><span style="color:#c2d94c;">"image/x-icon"
</span><span style="color:#39bae690;">/>
</span></code></pre>
<p>Make sure to include the favicon.ico and favicon.png to source/_includes directory for this to work. Before including the lines below, be sure to open the ico file in a couple of different browsers to check if the ico is loaded properly and there are no visual defects on your ico file.</p>
<p>I used an online tool to convert my png file to an ico over at <a href="http://www.rw-designer.com/image-to-icon">rw-designer.com</a>. The default settings should work ok.</p>
<p>On another note you may also want to include additional icons for <a href="http://hiltmon.com/blog/2013/02/10/add-web-clip-icons-to-octopress/">Apple devices</a>.</p>
<h3 id="settings-in-config-yml">Settings in _config.yml</h3>
<pre data-lang="yml" style="background-color:#0f1419;color:#bfbab0;" class="language-yml "><code class="language-yml" data-lang="yml"><span style="font-style:italic;color:#5c6773;"># Some Changes to _config.yml
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># change the date format for posts to mm/dd/yyyy
</span><span style="color:#59c2ff;">date</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">"%m/%d/%Y"
</span><span>
</span><span style="font-style:italic;color:#5c6773;"># remove the recent post sidebar on the right
</span><span style="font-style:italic;color:#5c6773;"># recent posts will now appear on the bottom
</span><span style="color:#59c2ff;">sidebar</span><span style="color:#bfbab0cc;">: </span><span style="color:#c2d94c;">collapse
</span></code></pre>
<h3 id="minifying-content">Minifying Content</h3>
<p>Install <a href="https://github.com/stereobooster/jekyll-press">jekyll-press</a> to minify your html, css and javascript. Detailed instructions are on the github page.</p>
<h3 id="use-monokai-syntax-highlighting-scheme">Use Monokai Syntax Highlighting Scheme</h3>
<p>Go to https://github.com/sanukcode/Monokai-Sublime-Text-Octopress and follow the instructions.</p>