tag:blogger.com,1999:blog-26839904618915134612024-03-05T10:00:37.181+00:00Development notesA piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.Unknownnoreply@blogger.comBlogger748125tag:blogger.com,1999:blog-2683990461891513461.post-48576703698998070252024-01-18T11:33:00.003+00:002024-01-18T11:33:22.144+00:00How to really loop over filenames with spaces in<p> Don't parse the output of "ls".</p><p>Instead:</p><p><span style="font-family: courier;"></span></p><blockquote><p><span style="font-family: courier;">for file in *</span></p><p><span style="font-family: courier;">do</span></p><p><span style="font-family: courier;"> ...</span></p><p><span style="font-family: courier;">done</span></p><div></div></blockquote><div><br /></div><pre style="--theme-background-attachment: auto; --theme-background-color: hsl(0,0%,100%); --theme-background-position: top left; --theme-background-repeat: repeat; --theme-background-size: 21px 21px; --theme-base-primary-color-h: 204.24242424; --theme-base-primary-color-l: 27.64705882%; --theme-base-primary-color-s: 70.21276596%; --theme-body-font-color: var(--black-600); --theme-body-font-family: var(--ff-sans); --theme-button-active-background-color: var(--theme-primary-200); --theme-button-color: var(--theme-primary); --theme-button-hover-background-color: var(--theme-primary-100); --theme-button-hover-color: var(--theme-primary-400); --theme-button-outlined-border-color: var(--theme-primary-400); --theme-button-outlined-selected-border-color: var(--theme-primary-500); --theme-button-primary-active-background-color: var(--theme-primary-600); --theme-button-primary-active-color: var(--white); --theme-button-primary-background-color: var(--theme-primary-400); --theme-button-primary-color: var(--white); --theme-button-primary-hover-background-color: var(--theme-primary-500); --theme-button-primary-hover-color: var(--white); --theme-button-primary-selected-background-color: var(--theme-primary-600); --theme-button-primary-selected-color: var(--white); --theme-button-selected-background-color: var(--theme-primary-300); --theme-button-selected-color: var(--theme-primary-600); --theme-content-background-color: var(--white); --theme-content-border-color: hsl(210,8%,90%); --theme-footer-background-border-top: 0; --theme-footer-background-color: transparent; --theme-footer-background-position: top left; --theme-footer-background-repeat: no-repeat; --theme-footer-background-size: auto; --theme-footer-divider-color: hsl(210,8%,85%); --theme-footer-link-color-hover: hsl(210,8%,25%); --theme-footer-link-color: hsl(210,8%,25%); --theme-footer-padding-bottom: 0; --theme-footer-padding-top: 0; --theme-footer-text-color: hsl(210,8%,68%); --theme-footer-title-color: #155078; --theme-header-background-border-bottom: 0; --theme-header-background-color: transparent; --theme-header-background-position: center left; --theme-header-background-repeat: repeat; --theme-header-background-size: auto; --theme-header-foreground-color: transparent; --theme-header-foreground-position: bottom right; --theme-header-foreground-repeat: no-repeat; --theme-header-foreground-size: auto; --theme-header-link-color: var(--theme-primary); --theme-header-sponsored-color: hsl(210,8%,25%); --theme-link-color-hover: #1d6da3; --theme-link-color-visited: #061621; --theme-link-color: #155078; --theme-post-body-font-family: var(--ff-sans); --theme-post-owner-background-color: var(--theme-primary-100); --theme-post-owner-new-background-color: var(--theme-primary-200); --theme-post-title-color-hover: var(--theme-link-color-hover); --theme-post-title-color-visited: var(--theme-link-color-visited); --theme-post-title-color: #155078; --theme-post-title-font-family: var(--ff-serif); --theme-primary-custom-100: hsl(var(--theme-base-primary-color-h), var(--theme-base-primary-color-s), calc(var(--theme-base-primary-color-l) + ((100% - var(--theme-base-primary-color-l)) * .9))); --theme-primary-custom-200: hsl(var(--theme-base-primary-color-h), var(--theme-base-primary-color-s), calc(var(--theme-base-primary-color-l) + ((100% - var(--theme-base-primary-color-l)) * .75))); --theme-primary-custom-300: hsl(var(--theme-base-primary-color-h), var(--theme-base-primary-color-s), calc(var(--theme-base-primary-color-l) + ((100% - var(--theme-base-primary-color-l)) * .5))); --theme-primary-custom-400: hsl(var(--theme-base-primary-color-h), var(--theme-base-primary-color-s), var(--theme-base-primary-color-l)); --theme-primary-custom-500: hsl(var(--theme-base-primary-color-h), var(--theme-base-primary-color-s), calc(var(--theme-base-primary-color-l) + (var(--theme-base-primary-color-l) * -.3))); --theme-primary-custom-600: hsl(var(--theme-base-primary-color-h), var(--theme-base-primary-color-s), calc(var(--theme-base-primary-color-l) + (var(--theme-base-primary-color-l) * -.6))); --theme-primary-custom: var(--theme-primary-custom-400); --theme-tag-background-color: var(--theme-secondary-100); --theme-tag-border-color: transparent; --theme-tag-color: var(--theme-secondary-500); --theme-tag-hover-background-color: var(--theme-secondary-200); --theme-tag-hover-border-color: transparent; --theme-tag-hover-color: var(--theme-secondary-600); --theme-tag-required-background-color: var(--theme-secondary-500); --theme-tag-required-border-color: transparent; --theme-tag-required-color: var(--white); --theme-tag-required-hover-background-color: var(--theme-secondary-400); --theme-tag-required-hover-border-color: transparent; --theme-tag-required-hover-color: var(--white); --theme-topbar-bottom-border: none; border-radius: var(--br-md); border: 0px; box-sizing: inherit; color: #0c0d0e; font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--fs-body1); font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;">(<a href="https://unix.stackexchange.com/a/195542">source</a>)</pre>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-38652252118151432832024-01-17T22:06:00.002+00:002024-01-17T22:09:51.188+00:00Automating mouse movement and clicks on Linux<p>Windows has <b>AutoHotkey</b> (AHK), and Linux has <a href="https://github.com/jordansissel/xdotool">xdotool</a>.</p><p>But <b>xdotool</b> <span face="-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"" style="background-color: white; color: #1f2328; font-size: 14px;">3.20160805.1 </span>doesn't work on Wayland at all. It silently fails. Turns out xdotool only works on X11, which is no longer the default for Ubuntu.</p><p><span face="-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"" style="background-color: white; color: #1f2328; font-size: 14px;">In 2024, using Ubuntu 22, this version of xdotool is the latest one available by running `apt install xdotool`.</span></p><p>To find out if you're using Wayland:</p><div class="snippet-clipboard-content notranslate position-relative overflow-auto" style="background-color: white; box-sizing: border-box; color: #1f2328; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 14px; overflow: auto; position: relative;"><pre class="notranslate" style="background-color: var(--bgColor-muted, var(--color-canvas-subtle)); border-radius: 6px; box-sizing: border-box; color: var(--fgColor-default, var(--color-fg-default)); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 11.9px; line-height: 1.45; margin-bottom: 16px; margin-top: 0px; overflow-wrap: normal; overflow: auto; padding: 16px;"><code class="notranslate" style="background: transparent; border-radius: 6px; border: 0px; box-sizing: border-box; display: inline; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 11.9px; line-height: inherit; margin: 0px; overflow-wrap: normal; overflow: visible; padding: 0px; word-break: normal;">$ loginctl show-session 2 -p Type
Type=wayland
$ echo $XDG_SESSION_TYPE
wayland
</code></pre><div class="zeroclipboard-container position-absolute right-0 top-0" style="box-sizing: border-box; position: absolute; right: 0px; top: 0px;"></div></div><p dir="auto" style="background-color: white; box-sizing: border-box; color: #1f2328; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 14px; margin-bottom: 16px; margin-top: 0px;">To switch to X11, edit<code class="notranslate" style="background-color: var(--bgColor-neutral-muted, var(--color-neutral-muted)); border-radius: 6px; box-sizing: border-box; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 11.9px; margin: 0px; padding: 0.2em 0.4em; white-space-collapse: break-spaces;">/etc/gdm3/custom.conf</code>, uncomment the line <code class="notranslate" style="background-color: var(--bgColor-neutral-muted, var(--color-neutral-muted)); border-radius: 6px; box-sizing: border-box; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 11.9px; margin: 0px; padding: 0.2em 0.4em; white-space-collapse: break-spaces;">WaylandEnable=false</code>, and reboot.<br /></p><p dir="auto" style="background-color: white; box-sizing: border-box; color: #1f2328; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 14px; margin-bottom: 16px; margin-top: 0px;">Now xdotool will work perfectly.</p><p dir="auto" style="background-color: white; box-sizing: border-box; color: #1f2328; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 14px; margin-bottom: 16px; margin-top: 0px;"><a href="https://github.com/jordansissel/xdotool" style="font-family: "Times New Roman"; font-size: medium;">xdotool README</a> does mention some alternatives:</p><p style="background-color: white; box-sizing: border-box; margin-bottom: 16px; margin-top: 0px; text-align: left;"></p><ul style="text-align: left;"><li><span face="-apple-system, BlinkMacSystemFont, Segoe UI, Noto Sans, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji" style="color: #1f2328;"><span style="font-size: 14px;"><a href="https://github.com/ReimuNotMoe/ydotool">ydotool</a> (available in apt) -- last updated January 2023, also didn't work for me on Wayland or X11</span></span></li><li><span face="-apple-system, BlinkMacSystemFont, Segoe UI, Noto Sans, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji" style="color: #1f2328;"><span style="font-size: 14px;"><a href="https://git.sr.ht/~geb/dotool">dotool</a> -- updated more recently, but not packaged for Ubuntu, and building from source requires Go, which is quite heavy so it's easier to just switch to X11 for xdotool.</span></span></li></ul><div><span face="-apple-system, BlinkMacSystemFont, Segoe UI, Noto Sans, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji" style="color: #1f2328;"><span style="font-size: 14px;"><br /></span></span></div><p></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-42542282922528275792023-10-07T21:12:00.006+01:002023-10-09T09:18:24.942+01:00Ubuntu Linux setup basics<p><span style="font-family: courier; font-size: x-small;">For username "foo":</span></p><p><span style="font-family: courier; font-size: x-small;">$ adduser foo</span></p><p><span style="font-family: courier; font-size: x-small;">$ passwd foo</span></p><p><span style="font-family: courier; font-size: x-small;">$ sudo usermod -aG sudo foo</span></p><p><span style="font-family: courier; font-size: x-small;">$ <span color="var(--black-800)" face="var(--ff-mono)" style="font-size: var(--_pr-code-fs); font-style: inherit; font-variant-caps: inherit; font-variant-ligatures: inherit; font-weight: inherit; white-space: inherit;">mkdir -p /home/foo/.ssh</span></span></p><p><span style="font-family: courier; font-size: x-small;"><span color="var(--black-800)" face="var(--ff-mono)" style="font-size: var(--_pr-code-fs); font-style: inherit; font-variant-caps: inherit; font-variant-ligatures: inherit; font-weight: inherit; white-space: inherit;">$ cat the_public_key.pem >> </span><span color="var(--black-800)" face="var(--ff-mono)" style="font-size: var(--_pr-code-fs); font-style: inherit; font-variant-caps: inherit; font-variant-ligatures: inherit; font-weight: inherit; white-space: inherit;">/home/foo/.ssh/authorized_keys</span></span></p><p><span style="font-family: courier; font-size: x-small;">$ <span color="var(--black-800)" face="var(--ff-mono)" style="font-size: var(--_pr-code-fs); font-style: inherit; font-variant-caps: inherit; font-variant-ligatures: inherit; font-weight: inherit; white-space: inherit;">chown -R foo:foo /home/foo/.ssh</span></span></p><p><span color="var(--black-800)" face="var(--ff-mono)" style="font-family: courier; font-size: x-small; font-style: inherit; font-variant-caps: inherit; font-variant-ligatures: inherit; font-weight: inherit; white-space: inherit;">$ chmod 700 /home/foo/.ssh</span></p><pre style="border-radius: var(--br-md); border: 0px; box-sizing: inherit; color: var(--highlight-color); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--fs-body1); font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;"><code style="border-radius: 0px; border: 0px; box-sizing: inherit; color: var(--black-800); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--_pr-code-fs); font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"><span style="font-family: courier; font-size: x-small;">$ chmod 600 /home/foo/.ssh/authorized_keys</span></code></pre><pre style="border-radius: var(--br-md); border: 0px; box-sizing: inherit; color: var(--highlight-color); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--fs-body1); font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;"><code style="border-radius: 0px; border: 0px; box-sizing: inherit; color: var(--black-800); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--_pr-code-fs); font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"><span style="font-family: inherit;">Disable default account:</span></code></pre><pre style="border-radius: var(--br-md); border: 0px; box-sizing: inherit; color: var(--highlight-color); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--fs-body1); font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;"><code style="border-radius: 0px; border: 0px; box-sizing: inherit; color: var(--black-800); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--_pr-code-fs); font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-family: courier; font-size: x-small;">$ usermod -s /usr/sbin/nologin default_username</span>
</code></pre><pre style="border-radius: var(--br-md); border: 0px; box-sizing: inherit; color: var(--highlight-color); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--fs-body1); font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;"><code style="border-radius: 0px; border: 0px; box-sizing: inherit; color: var(--black-800); font-family: var(--ff-mono); font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: var(--_pr-code-fs); font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-family: courier; font-size: x-small;"><br /></span></code></pre><pre style="border-radius: var(--br-md); border: 0px; box-sizing: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;"><span style="font-family: "Times New Roman";">Notes:</span></pre><pre style="border-radius: var(--br-md); border: 0px; box-sizing: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;"><span style="font-family: Times New Roman;"><ul style="text-align: left;"><li><span style="font-family: Times New Roman;">Not useradd.</span></li><li><span style="font-family: Times New Roman;">Even when logging in with just SSH key, user must have a password. It will only be used for sudo commands.</span></li></ul></span>
</pre><div><pre style="border-radius: var(--br-md); border: 0px; box-sizing: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;"><code style="border-radius: 0px; border: 0px; box-sizing: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-family: Times New Roman;">Sources:</span></code></pre><pre style="border-radius: var(--br-md); border: 0px; box-sizing: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: var(--lh-md); margin-bottom: calc(1.5em); margin-top: 0px; max-height: 600px; overflow-wrap: normal; overflow: auto; padding: var(--su12); vertical-align: baseline; width: auto;"><ul><li><code style="border-radius: 0px; border: 0px; box-sizing: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-variant-alternates: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-variant-position: inherit; font-variation-settings: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-family: Times New Roman;"><a href="https://unix.stackexchange.com/questions/210228/add-a-user-without-password-but-with-ssh-and-public-key">https://unix.stackexchange.com/questions/210228/add-a-user-without-password-but-with-ssh-and-public-key</a></span></code></li></ul></pre></div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-263445337471834792023-10-07T21:03:00.001+01:002023-10-07T21:03:05.546+01:00Sudoers basics<script src="https://gist.github.com/willsheppard/f5ec8609a971e6c76f43c6a575c44d5d.js"></script>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-31470160959298721172023-09-29T11:33:00.009+01:002023-09-29T11:33:51.426+01:00Elasticsearch advanced queriesSee also <a href="https://wills-tech-notes.blogspot.com/2016/11/elasticsearch-basics.html">ElasticSearch basics</a>.<div><br /></div><div>DQL to filter by non-zero length: <span style="font-family: courier;">Advert.location_query:*</span><span style="font-family: inherit;"> (does not work as a filter)</span></div><div>Or in Lucene: <span style="font-family: courier;">Advert.location_query:?*</span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;">Results are <a href="https://opensearch.org/docs/2.4/opensearch/search/paginate/#the-from-and-size-parameters">limited to 10,000 records</a>, unless you use the <a href="https://opensearch.org/docs/2.4/opensearch/search/paginate/#scroll-search">scroll API</a> which can paginate and also make parallel requests.</span></div><div><span style="font-family: courier;"><br /></span></div>
Gist:
<script src="https://gist.github.com/willsheppard/d54d89c87f1ff6cc9d2b8c70b9d71962.js"></script>
Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-55573900064842914792023-09-12T16:55:00.003+01:002023-09-12T16:55:47.854+01:00MySQL date display format conversion<p>MySQL date time conversion functions: </p><p></p><ul style="text-align: left;"><li>UNIX_TIMESTAMP(date) <a href="https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_unix-timestamp" target="_blank">docs</a></li><li>FROM_UNIXTIME(epoch) <a href="https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_from-unixtime" target="_blank">docs</a></li></ul><p></p><p>Examples:</p><p><span style="font-family: courier;">select name, from_unixtime(time_added, '%Y-%m-%d %h:%i')</span></p><p><span style="font-family: courier;">from company</span></p><p><span style="font-family: courier;">order by date_added </span><span style="font-family: courier;">desc</span></p><p><span style="font-family: courier;">limi</span><span style="font-family: courier;">t 10; -- list the most recently added companies</span></p><p><span style="font-family: inherit;">You may also omit the </span><span style="font-family: courier;">'%Y-%m-%d %h:%i'</span><span style="font-family: inherit;"> format string, to get the default format YYYY-MM-DD HH:MM:SS, e.g. `</span>2023-09-07 09:43:51`</p><p><br /></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-44981455230933725062023-06-27T13:32:00.005+01:002023-09-19T12:09:29.438+01:00Test2 cheat sheet for Perl<h4 style="text-align: left;">Cheat sheet</h4>
<script src="https://gist.github.com/willsheppard/e78fad4cb1156b1be45c2ab97d6601e0.js"></script>
<div><br /></div><p></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-68995965979726491902023-06-18T16:37:00.001+01:002023-06-18T16:37:17.012+01:00Chrome extensions: Download manager reviews<p><br></p><ul><li>DownThemAll: Queues, but doesn't intercept</li><li>Thunder Download Manager: Intercepts, but doesn't queue</li><li>Free Download Manager: Just says "Loading..." (on Ubuntu)</li><li>Chrono Download Manager: Intercepts and queues! And resumes. Perfect!</li></ul>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-19697963703493446202023-05-26T10:05:00.003+01:002023-05-26T10:05:39.385+01:00curl -o / wget -O<div><span style="background-color: white; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;"><span style="font-family: courier;">curl --output file</span></span><div><span style="font-family: courier;"><span style="background-color: white; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;">curl -o file</span><br style="background-color: white; box-sizing: inherit; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;" /></span></div></div><div><span style="background-color: white; color: #1d1c1d; font-family: Slack-Lato, Slack-Fractions, appleLogo, sans-serif; font-size: 15px; font-variant-ligatures: common-ligatures;"><br /></span></div><span style="font-family: courier;"><span style="background-color: white; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;">wget --output-document file</span><br style="background-color: white; box-sizing: inherit; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;" /><span style="background-color: white; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;">wget -O file</span><br style="background-color: white; box-sizing: inherit; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;" /></span><div><span style="background-color: white; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;"><span style="font-family: courier;"><br /></span></span></div><div><span style="background-color: white; color: #1d1c1d; font-family: inherit; font-size: 15px; font-variant-ligatures: common-ligatures;">Best to just always use curl, and know it uses lowercase for common arguments like normal.</span></div><div><span style="background-color: white; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;"><span style="font-family: inherit;"><br /></span></span></div><div><span style="background-color: white; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;"><span style="font-family: inherit;">It's usually already installed as well.</span></span></div><div><span style="background-color: white; color: #1d1c1d; font-size: 15px; font-variant-ligatures: common-ligatures;"><span style="font-family: inherit;"><br /></span></span></div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-44013396951891595272023-05-12T14:09:00.005+01:002023-05-12T14:09:55.880+01:00Analyzing HAR files with jqSee gist:
<script src="https://gist.github.com/willsheppard/f0bdc1a2290f3d24d9579856ab5b7b53.js"></script>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-72991133943618342432023-04-07T09:34:00.007+01:002023-04-11T05:13:28.646+01:00Video processing for fun<h2 style="text-align: left;">Mac</h2><div><ul style="text-align: left;"><li>QuickTime Player</li><ul><li>Edit menu | Add clip after...</li><li>40 videos, total 250Mb = (Not Responding) & Pinwheel of doom</li><li>34 videos, total 140Mb = several minutes of editing, then (Not Responding) & Pinwheel of doom</li></ul><li>iMovie</li><ul><li>To download for an older version of MacOS, open App Store | Purchased | Install</li></ul></ul></div><h2 style="text-align: left;">Linux</h2><h2 style="text-align: left;">Windows</h2><h2 style="text-align: left;">Web</h2><div><ul style="text-align: left;"><li><a href="https://wave.video">wave.video</a> - Really good. Limited to 15 mins.</li><li><a href="https://wave.video/blog/11-best-online-video-makers/">More</a></li></ul></div><h2 style="text-align: left;">Android</h2><h2 style="text-align: left;">iPhone</h2><div><br /></div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-4909989050562034812023-02-28T16:35:00.006+00:002023-03-01T09:27:45.886+00:00Command-line data processing 2023<p>Some developer tools with CLI for processing XML, XHTML, HTML, JSON, YAML, etc.</p><h3 style="text-align: left;">XML</h3><p></p><ul style="text-align: left;"><li><a href="https://metacpan.org/pod/XML::XSH2"><span style="font-family: courier;">xsh</span></a> (perl - <a href="https://metacpan.org/author/CHOROBA">Choroba</a>)</li><ul><li><span style="font-family: courier;"><a href="https://wills-tech-notes.blogspot.com/2018/10/use-cpm-to-manage-your-perl-dependencies.html">cpm</a> XML::XSH2</span></li><li><span style="font-family: courier;">xsh -P file.xml</span></li><li><span style="font-family: courier;">ls</span></li><li><span style="font-family: courier;">help ls</span></li><li><span style="font-family: courier;">help | less</span></li><li><span style="font-family: courier;"><TAB> autocompletion</span></li></ul><li><span style="font-family: courier;">xmllint</span></li><ul><li><span style="font-family: courier;">xmllint --xpath "//foo" file.xml</span></li><li><span style="font-family: courier;">xmllint --shell file.xml</span></li></ul><li><span style="font-family: courier;">xmltarlet</span></li><li><span style="font-family: courier;">xq</span><span style="font-family: inherit;"> (golang - </span><a class="url fn" data-hovercard-type="user" data-hovercard-url="/users/sibprogrammer/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/sibprogrammer" rel="author" style="box-sizing: border-box; text-decoration-line: none;">sibprogrammer</a>)</li><ul><li><span style="font-family: courier;">apt-get install xq</span></li></ul><li><span style="font-family: courier;">xq</span> (python - <a href="https://github.com/jeffbr13">jeffbr13</a>)</li><ul><li><span style="font-family: courier;">pip install xq</span></li></ul></ul><h3 style="text-align: left;"><span style="font-family: inherit;">JSON</span></h3><div><ul style="text-align: left;"><li><span style="font-family: courier;">jq</span></li><ul><li><span style="font-family: courier;">cat file.json | jq . # format</span></li><li><span style="font-family: courier;">cat file.json | jq '.[]' # extract array</span></li></ul></ul></div><h3 style="text-align: left;"><span style="font-family: inherit;">Search</span></h3><ul style="text-align: left;"><li><a href="https://github.com/junegunn/fzf"><span style="font-family: courier;">fzf</span></a></li><li><span style="font-family: courier;">ripgrep</span></li><li><span style="font-family: courier;">ag</span></li><li><span style="font-family: courier;">ack</span></li><ul><li>Doesn't search "binary" files by default</li></ul><li><span style="font-family: courier;">vim</span> - for searching files</li></ul><div><br /></div><p></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-44759480185372469842023-02-07T13:07:00.003+00:002023-02-07T13:07:23.895+00:00Windows 10 robocopy basics<span style="font-family: courier; font-size: x-small;">robocopy c:\temp\source c:\temp\destination /E /DCOPY:DAT /R:10 /W:3
</span><div><br /></div><div>(<a href="https://4sysops.com/archives/robocopy-usage-examples/" target="_blank">source</a>)</div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-88724217827271778652023-01-01T16:24:00.007+00:002023-01-01T16:24:51.480+00:00Running Emby on Linux<p>wget https://github.com/MediaBrowser/Emby.Releases/releases/download/4.5.4.0/emby-server-deb_4.5.4.0_amd64.deb</p><p><br /></p><p>sudo dpkg -i emby-server-deb_4.5.4.0_amd64.deb</p><p><br /></p><p>sudo systemctl status emby-server.service</p><p><br /></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-37772478170261681022022-11-18T12:04:00.008+00:002022-11-19T13:40:45.167+00:00How to maintain software<p>You have a massive legacy spaghetti mess of code, and you need to add a new feature.</p><p>Write tests first.</p><p>Put <b>all</b> your new code in a <b>new module</b>, and only insert <b>single lines</b> into the legacy code to call the new code. This allows you to properly encapsulate the new code, wrap it in try/catch blocks, etc. and not break the legacy system.</p><p>Pass <b>whole objects</b> into the new code, this is a necessary consequence of encapsulation.</p><p><br /></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-35746066944865135082022-11-10T13:10:00.008+00:002022-11-18T12:01:42.387+00:00How big is libgen? Answer: 131TiB (= 144Tb)<p><span style="background-color: white; font-family: Menlo; font-size: 11px; font-variant-ligatures: no-common-ligatures;"># First method: 131TiB</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s1" style="font-variant-ligatures: no-common-ligatures;">$ wget https://phillm.net/libgen-stats.php -O </span><span style="font-variant-ligatures: no-common-ligatures;">libgen-stats.json</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s1" style="font-variant-ligatures: no-common-ligatures;"><br /></span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s2" style="font-variant-ligatures: no-common-ligatures;">$ cat libgen-stats.json | jq '.[]|.size_bytes' | perl -lne'$x+=$_;END{print$x}'</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s2" style="font-variant-ligatures: no-common-ligatures;">144116297318150</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s2" style="font-variant-ligatures: no-common-ligatures;"><br /></span></p><p class="p2" style="background-color: white; color: #5230e1; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s4" style="color: black; font-variant-ligatures: no-common-ligatures;">$ bc -l</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span style="font-variant-ligatures: no-common-ligatures;">144116297318150 / 1024 / 1024 / 1024 / 1024</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s2" style="font-variant-ligatures: no-common-ligatures;">131.07300884998949186410 Tebibytes</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><br /></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;">$ bc -l</p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s1" style="font-variant-ligatures: no-common-ligatures;">144116297318150 / 1000 /</span><span style="font-variant-ligatures: no-common-ligatures;"> 1000 / 1000 / 1000</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span class="s1" style="font-variant-ligatures: no-common-ligatures;">144.11629731815000000000 Terabytes</span></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><br /></p><p class="p1" style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;"><span style="font-variant-ligatures: no-common-ligatures;"><br /></span></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-14781010362773039632022-11-08T19:13:00.003+00:002024-02-04T16:37:22.291+00:00New software cheat sheet<p> </p><p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">## Languages</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">- Perl: best for fast prototyping</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- Ruby: best for having fun</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- Node: best for public projects</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- Python: best for experiments</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">## Frameworks</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">### Perl</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">- DBIx::Class 💯</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- Mojolicious 💯</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">### Node</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">- Express (popular)</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- React?</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- Koa?</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- NestJS?</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">-....? for testing: Qunit?</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">-....? for web framework</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">### Python</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">- Django? (this one)</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- Flask?</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">### Ruby</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">- Rails? </span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- Active Record? </span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">## Libraries</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">### Perl</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">- just everything</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">### Node</span></span></p>
<p dir="ltr"><span style="font-size: 14px;"><span style="color: #32373f;">- minimist reads command line arguments</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- cheerio parses HTML</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- daysjs manages dates/times</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;"> - customParseFormat plugin parses dates</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- knex does CRUD on databases</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- fs perfoms operations on the file system</span></span><br />
<span style="font-size: 14px;"><span style="color: #32373f;">- import process from 'node:process'; // process.exit(1);</span></span><br /></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-17376921990939771332022-10-18T13:39:00.000+01:002022-10-18T13:39:05.856+01:00Books about software design theory<p data-pm-slice="0 0 []"><strong>Ludo: </strong><a href="https://perl.plover.com/yak/design/">Here's the online slide deck from</a> Mark Jason Dominus’ 2002 YAPC lightning talk “Design Patterns Aren’t”, on Professor <a href="https://en.wikipedia.org/wiki/Christopher_Alexander">Christoper Alexander</a>, his book <a href="https://en.wikipedia.org/wiki/A_Pattern_Language"><em>A Pattern Language</em></a>, the ‘Gang of Four’ and design patterns.</p><p data-pm-slice="0 0 []"><em>APL</em> was book two of a trilogy also incorporating <a href="https://en.wikipedia.org/wiki/The_Timeless_Way_of_Building"><em>The Timeless Way of Building</em></a> (volume 1) and <a href="https://en.wikipedia.org/wiki/The_Oregon_Experiment"><em>The Oregon Experiment</em></a> (volume 3).</p><p data-pm-slice="0 0 []">Alexander’s earlier work <a href="https://en.wikipedia.org/wiki/Notes_on_the_Synthesis_of_Form"><em>Notes on the Synthesis of Form</em></a> was also a big hit with computer scientists in the 1960s, even though it, too, was primarily aimed at designers and architects. (And if you still have any empty shelves on your bookcase, Alexander’s 2002-2004 four-volume work <a href="https://en.wikipedia.org/wiki/The_Nature_of_Order"><em>The Nature of Order: An Essay on the Art of Building and the Nature of the Universe</em></a><em><strong> </strong></em>is apparently considered his <em>magum opus</em>; and he also published <em>The Battle for the Life and Beauty of the Earth: A Struggle between Two World-Systems</em>, about how his team designed & constructed a Japanese school, in 2012.)</p><p><strong>Will:</strong> There's another book with a possibly contrasting view: <a href="https://www.oreilly.com/library/view/semantic-software-design/9781492045946/"><i>Semantic Software Design</i></a>. It says the main work in software is coming up with the concepts/paradigm/metaphor which explains what the software is doing. And also we shouldn't think of developers as manufacturers, builders or architects. But rather creative artists. Mainly because we never produce the same piece of work twice.</p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-42220661070849842582022-09-28T15:14:00.007+01:002022-09-28T16:03:58.037+01:00Cloud development machines<p> A list of cloud servers for basic hobby-level software development.</p><p>All prices per month:</p><p></p><ul style="text-align: left;"><li><a href="https://www.digitalocean.com/pricing/droplets">DigitalOcean</a>: $4 for 512Mb memory, 10Gb file storage, 500Gb transfer</li><ul><li>$6 for 1Gb memory, 25Gb file storage, 1000Gb transfer</li><li>Block storage:</li><ul><li>$10 for 100Gb</li></ul><li>Object storage:</li><ul><li>$5 for 250Gb, 1Tb outbound transfer</li></ul><li>Images: $0.06/GiB/mo</li><ul><li>= $1.50 for 25Gb</li></ul></ul><li><a href="https://www.vultr.com/pricing/">Vultr</a>: $6 for 1Gb memory, 25Gb file storage, 2Tb transfer</li><ul><li>Block storage: $1 per 10Gb</li><li>Object storage: $5 for 250Gb, 1Tb outbound transfer</li></ul><li><a href="https://www.linode.com/pricing/#compute-shared">Linode</a>: $5 for 1Gb memory, 25Gb file storage, 1Tb transfer</li><ul><li>Block storage: $1 per 10Gb</li><li>Object storage: $5 for 250Gb, 1Tb outbound transfer</li><li>Images:</li><ul><li>$0.10 for 1Gb x 25</li><li>$2.50 for 25Gb x 25</li></ul></ul><li><a href="https://www.kamatera.com/Products/201/Cloud_Servers#page_250">Kamatera</a>: $4 for 1Gb memory, 20Gb file storage, 5000Gb transfer</li><ul><li>File storage:</li><ul><li>$6 for 30Gb</li><li>$7 for 40Gb</li><li>$8 for 50Gb</li><li>$12 for 100Gb</li></ul></ul></ul><div>(<a href="https://www.codeinwp.com/blog/digitalocean-alternatives">source</a>)</div><p></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-37039782053784996282022-08-15T15:03:00.003+01:002022-11-03T10:53:48.426+00:00Database schema diagrams in 2022<p><br /></p><h2 data-renderer-start-pos="301" id="Suggestions" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.43em; font-weight: 500; letter-spacing: -0.008em; line-height: 1.2; margin: 1.8em 0px 0px; padding: 0px; white-space: pre-wrap;">Suggestions<span class="heading-anchor-wrapper" role="presentation" style="height: 1.2em; margin-left: 6px; position: absolute;"><button aria-label="Copy link to heading" class="css-779anb" data-dashlane-label="true" data-dashlane-rid="8b67d5a312388cae" data-form-type="" style="border-color: initial; border-style: none; border-width: initial; cursor: pointer; display: inline; font-family: inherit; opacity: 1; outline: none; padding-left: 0px; padding-right: 0px; right: 0px; transform: none; transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;"><span aria-label="Copy" class="css-1ncnk3i" role="img" style="--icon-primary-color: var(--ds-icon-subtle, #6B778C); --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 24px; line-height: 1; width: 24px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></button></span></h2><ul class="ak-ul" data-indent-level="1" style="background-color: white; box-sizing: border-box; color: #172b4d; display: flow-root; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; margin: 10px 0px 0px; padding: 0px 0px 0px 24px; white-space: pre-wrap;"><li><p data-renderer-start-pos="316" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Whenever you publish a diagram, also include a comment explaining which software/website was used.</p><ul class="ak-ul" data-indent-level="2" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="418" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">If you need to log into a website in order to update the diagram, post the login details… somewhere.</p><ul class="ak-ul" data-indent-level="3" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="541" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Ideally you would first create an account that is intended to be shared within you team.</p></li></ul></li></ul></li><li style="margin-top: 4px;"><p data-renderer-start-pos="637" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">If the diagram was generated from source code, publish the source code (or a link to it) along with the diagram.</p><ul class="ak-ul" data-indent-level="2" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="753" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">For bonus points, include this information in the image itself.</p></li></ul></li><li style="margin-top: 4px;"><p data-renderer-start-pos="822" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">These suggestions apply equally to email, chat, wiki, printouts, etc.</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="896" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Don’t send the source to clients, only to colleagues.</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="963" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Read <span data-card-url="https://c4model.com/" data-inline-card="true"><span class="loader-wrapper"><a class="css-1xdzogm eeajecn0" data-dashlane-label="true" data-dashlane-rid="d99ac4ccb0cb41f5" data-form-type="" data-testid="inline-card-resolved-view" href="https://c4model.com/" role="button" style="-webkit-box-decoration-break: clone; background-color: var(--ds-surface-raised,white); border-radius: 3px; box-shadow: var(--ds-shadow-raised,0 1px 1px rgba(9,30,66,0.25),0 0 1px 1px rgba(9,30,66,0.13)); cursor: pointer; display: inline; line-height: 16px; padding: 1px 0.24em 2px; text-decoration-line: none; transition: all 0.1s ease-in-out 0s; user-select: text;" tabindex="0"><span class="css-1p7ax5 e158gagu2" style="word-break: break-all;"><span class="css-7h21dr e158gagu6" style="display: inline-block; margin-right: 4px; position: relative;"><span class="css-klch0j e158gagu7" style="display: inline-block; height: 0px; opacity: 0; width: 14px;"></span><span class="css-19n4c3d e158gagu0" style="user-select: none;"><span aria-label="link" class="css-hakgx8" data-testid="inline-card-icon-and-title-default" role="img" style="--icon-primary-color: currentColor; --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 16px; left: 0px; line-height: 14px; position: absolute; top: 0px; width: 14px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></span></span><span class="smart-link-title-wrapper css-0 e158gagu8">The C4 model for visualising software architecture</span></span></a></span></span> for a good system and suggestions on diagrams (then look at using plantUML with the C4 extentions).</p><ul class="ak-ul" data-indent-level="2" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="1074" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">This is a good talk on the topic: </p></li></ul></li></ul><div class="ak-renderer-extension" data-layout="default" style="background-color: white; clear: both; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; margin: 0.75rem 0px 0px; padding: 0px; white-space: pre-wrap; width: 1276px;"><div class="ak-renderer-extension-overflow-container" style="margin: 0px; overflow-x: auto; padding: 0px;"><div class="css-r4oreg e1ihjts80" data-fabric-macro="c2057d93-3a52-47a9-9672-6c0af4ef2d8d" data-macro-body="" data-macro-parameters="{"overlay":"youtube","_parentId":"2760179713","_template":"com/atlassian/confluence/extra/widgetconnector/templates/youtube.vm","width":"400px","url":"https://www.youtube.com/watch?v=Za1-v4Zkq5E","height":"300px"}" data-testid="legacy-macro-element" style="clear: both; margin: 0px; padding: 0px; white-space: normal;"><iframe class="youtube-player conf-macro output-block" data-dashlane-frameid="3564" data-dashlane-rid="e3aacfad9ca9323e" data-form-type="" data-hasbody="false" data-local-id="126afd3e-be82-41a3-aaf3-fce76dc55dd3" data-macro-id="c2057d93-3a52-47a9-9672-6c0af4ef2d8d" data-macro-name="widget" frameborder="0" src="https://www.youtube.com/embed/Za1-v4Zkq5E?wmode=opaque" style="height: 300px; width: 400px;" type="text/html"></iframe></div></div></div><hr style="border-radius: 1px; border: none; clear: both; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; height: 2px; margin: 1.714em 0px; white-space: pre-wrap;" /><h2 data-renderer-start-pos="1116" id="Types-of-diagram" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.43em; font-weight: 500; letter-spacing: -0.008em; line-height: 1.2; margin: 1.8em 0px 0px; padding: 0px; white-space: pre-wrap;">Types of diagram<span class="heading-anchor-wrapper" role="presentation" style="height: 1.2em; margin-left: 6px; position: absolute;"><button aria-label="Copy link to heading" class="css-779anb" style="border-color: initial; border-style: none; border-width: initial; cursor: pointer; display: inline; font-family: inherit; opacity: 0; outline: none; padding-left: 0px; padding-right: 0px; right: 0px; transform: translate(-8px, 0px); transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;"><span aria-label="Copy" class="css-1ncnk3i" role="img" style="--icon-primary-color: var(--ds-icon-subtle, #6B778C); --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 24px; line-height: 1; width: 24px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></button></span></h2><ul class="ak-ul" data-indent-level="1" style="background-color: white; box-sizing: border-box; color: #172b4d; display: flow-root; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; margin: 10px 0px 0px; padding: 0px 0px 0px 24px; white-space: pre-wrap;"><li><p data-renderer-start-pos="1136" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Database schema diagram</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1173" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Flowchart</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1196" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Sequence diagram</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1226" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Component/Class diagram</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1263" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Code workflow</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1290" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">…</p></li></ul><hr style="border-radius: 1px; border: none; clear: both; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; height: 2px; margin: 1.714em 0px; white-space: pre-wrap;" /><h2 data-renderer-start-pos="1296" id="Desktop-software" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.43em; font-weight: 500; letter-spacing: -0.008em; line-height: 1.2; margin: 1.8em 0px 0px; padding: 0px; white-space: pre-wrap;">Desktop software<span class="heading-anchor-wrapper" role="presentation" style="height: 1.2em; margin-left: 6px; position: absolute;"><button aria-label="Copy link to heading" class="css-779anb" style="border-color: initial; border-style: none; border-width: initial; cursor: pointer; display: inline; font-family: inherit; opacity: 0; outline: none; padding-left: 0px; padding-right: 0px; right: 0px; transform: translate(-8px, 0px); transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;"><span aria-label="Copy" class="css-1ncnk3i" role="img" style="--icon-primary-color: var(--ds-icon-subtle, #6B778C); --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 24px; line-height: 1; width: 24px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></button></span></h2><h3 data-renderer-start-pos="1314" id="Flowcharts" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.142em; letter-spacing: -0.006em; line-height: 1.5; margin: 10px 0px 0px; padding: 0px; white-space: pre-wrap;">Flowcharts<span class="heading-anchor-wrapper" role="presentation" style="height: 1.25em; margin-left: 6px; position: absolute;"><button aria-label="Copy link to heading" class="css-779anb" style="border-color: initial; border-style: none; border-width: initial; cursor: pointer; display: inline; font-family: inherit; opacity: 0; outline: none; padding-left: 0px; padding-right: 0px; right: 0px; transform: translate(-8px, 0px); transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;"><span aria-label="Copy" class="css-1ncnk3i" role="img" style="--icon-primary-color: var(--ds-icon-subtle, #6B778C); --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 24px; line-height: 1; width: 24px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></button></span></h3><ul class="ak-ul" data-indent-level="1" style="background-color: white; box-sizing: border-box; color: #172b4d; display: flow-root; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; margin: 10px 0px 0px; padding: 0px 0px 0px 24px; white-space: pre-wrap;"><li><p data-renderer-start-pos="1328" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">VIsual-only</p><ul class="ak-ul" data-indent-level="2" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="1343" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="http://dia-installer.de/" style="text-decoration-line: none;" title="http://dia-installer.de/">Dia</a> - beware, it's Dia by name and dire by nature</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1396" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="https://www.omnigroup.com/omnigraffle" style="text-decoration-line: none;" title="https://www.omnigroup.com/omnigraffle">Omnigraffle</a> - Mac only</p></li></ul></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1424" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Source + Visual</p><ul class="ak-ul" data-indent-level="2" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="1443" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">VS Code - has nice plantuml integration - live preview</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1502" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">PlantUML (example)</p><ul class="ak-ul" data-indent-level="3" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="1524" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Summary: Full featured language designed for visualising software architecture, build multiple diagrams from a single model, etc.</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1657" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">See also <span data-card-url="https://structurizr.com/" data-inline-card="true"><span class="loader-wrapper"><a class="css-1xdzogm eeajecn0" data-dashlane-label="true" data-dashlane-rid="8d396fe0e5e58e0c" data-form-type="" data-testid="inline-card-resolved-view" href="https://structurizr.com/" role="button" style="-webkit-box-decoration-break: clone; background-color: var(--ds-surface-raised,white); border-radius: 3px; box-shadow: var(--ds-shadow-raised,0 1px 1px rgba(9,30,66,0.25),0 0 1px 1px rgba(9,30,66,0.13)); cursor: pointer; display: inline; line-height: 16px; padding: 1px 0.24em 2px; text-decoration-line: none; transition: all 0.1s ease-in-out 0s; user-select: text;" tabindex="0"><span class="css-1p7ax5 e158gagu2" style="word-break: break-all;"><span class="css-7h21dr e158gagu6" style="display: inline-block; margin-right: 4px; position: relative;"><span class="css-klch0j e158gagu7" style="display: inline-block; height: 0px; opacity: 0; width: 14px;"></span><img class="smart-link-icon css-168a27h e1bjtjov0" data-testid="inline-card-icon-and-title-image" src="https://static.structurizr.com/img/favicon.png" style="border-radius: 2px; border: 0px; height: 14px; left: 7px; margin: 0px 4px 0px 0px; padding: 0px; position: absolute; top: 8px; transform: translate(-50%, -50%); user-select: none; width: 14px;" /></span><span class="smart-link-title-wrapper css-0 e158gagu8">Structurizr</span></span></a></span></span> </p></li></ul></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1674" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="https://graphviz.org/" style="text-decoration-line: none;" title="https://graphviz.org/">GraphViz</a></p><ul class="ak-ul" data-indent-level="3" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="1686" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Summary: Simpler, general purpose language for diagrams (<a class="css-tgpl01" data-renderer-mark="true" href="https://graphviz.org/doc/info/command.html" style="text-decoration-line: none;" title="https://graphviz.org/doc/info/command.html">dot language</a>)</p></li></ul></li></ul></li></ul><h3 data-renderer-start-pos="1764" id="Database" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.142em; letter-spacing: -0.006em; line-height: 1.5; margin: 2em 0px 0px; padding: 0px; white-space: pre-wrap;">Database<span class="heading-anchor-wrapper" role="presentation" style="height: 1.25em; margin-left: 6px; position: absolute;"><button aria-label="Copy link to heading" class="css-779anb" style="border-color: initial; border-style: none; border-width: initial; cursor: pointer; display: inline; font-family: inherit; opacity: 0; outline: none; padding-left: 0px; padding-right: 0px; right: 0px; transform: translate(-8px, 0px); transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;"><span aria-label="Copy" class="css-1ncnk3i" role="img" style="--icon-primary-color: var(--ds-icon-subtle, #6B778C); --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 24px; line-height: 1; width: 24px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></button></span></h3><ul class="ak-ul" data-indent-level="1" style="background-color: white; box-sizing: border-box; color: #172b4d; display: flow-root; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; margin: 10px 0px 0px; padding: 0px 0px 0px 24px; white-space: pre-wrap;"><li><p data-renderer-start-pos="1776" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">…</p></li></ul><hr style="border-radius: 1px; border: none; clear: both; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; height: 2px; margin: 1.714em 0px; white-space: pre-wrap;" /><h2 data-renderer-start-pos="1782" id="Online-software" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.43em; font-weight: 500; letter-spacing: -0.008em; line-height: 1.2; margin: 1.8em 0px 0px; padding: 0px; white-space: pre-wrap;">Online software<span class="heading-anchor-wrapper" role="presentation" style="height: 1.2em; margin-left: 6px; position: absolute;"><button aria-label="Copy link to heading" class="css-779anb" style="border-color: initial; border-style: none; border-width: initial; cursor: pointer; display: inline; font-family: inherit; opacity: 0; outline: none; padding-left: 0px; padding-right: 0px; right: 0px; transform: translate(-8px, 0px); transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;"><span aria-label="Copy" class="css-1ncnk3i" role="img" style="--icon-primary-color: var(--ds-icon-subtle, #6B778C); --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 24px; line-height: 1; width: 24px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></button></span></h2><h3 data-renderer-start-pos="1799" id="Flowcharts.1" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.142em; letter-spacing: -0.006em; line-height: 1.5; margin: 10px 0px 0px; padding: 0px; white-space: pre-wrap;">Flowcharts<span class="heading-anchor-wrapper" role="presentation" style="height: 1.25em; margin-left: 6px; position: absolute;"><button aria-label="Copy link to heading" class="css-779anb" style="border-color: initial; border-style: none; border-width: initial; cursor: pointer; display: inline; font-family: inherit; opacity: 0; outline: none; padding-left: 0px; padding-right: 0px; right: 0px; transform: translate(-8px, 0px); transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;"><span aria-label="Copy" class="css-1ncnk3i" role="img" style="--icon-primary-color: var(--ds-icon-subtle, #6B778C); --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 24px; line-height: 1; width: 24px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></button></span></h3><ul class="ak-ul" data-indent-level="1" style="background-color: white; box-sizing: border-box; color: #172b4d; display: flow-root; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; margin: 10px 0px 0px; padding: 0px 0px 0px 24px; white-space: pre-wrap;"><li><p data-renderer-start-pos="1813" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="https://asciiflow.com/#/" style="text-decoration-line: none;" title="https://asciiflow.com/#/">ASCIIFlow</a></p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1826" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="http://gliffy.com/" style="text-decoration-line: none;" title="http://Gliffy.com"><span data-renderer-mark="true" style="text-decoration-line: line-through;">Gliffy.com</span></a><span data-renderer-mark="true" style="text-decoration-line: line-through;"> (now paid)</span></p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1851" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="https://moqups.com/" style="text-decoration-line: none;" title="https://moqups.com/">moqups</a> (has a free plan)</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1879" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">PlantUML</p><ul class="ak-ul" data-indent-level="2" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="1891" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="http://www.plantuml.com/" style="text-decoration-line: none;" title="http://www.plantuml.com/">PlantUML Webserver</a> </p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1914" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><span data-card-url="https://sujoyu.github.io/plantuml-previewer/" data-inline-card="true"><span class="loader-wrapper"><a class="css-1xdzogm eeajecn0" data-dashlane-label="true" data-dashlane-rid="e62e307e566d894f" data-form-type="" data-testid="inline-card-resolved-view" href="https://sujoyu.github.io/plantuml-previewer/" role="button" style="-webkit-box-decoration-break: clone; background-color: var(--ds-surface-raised,white); border-radius: 3px; box-shadow: var(--ds-shadow-raised,0 1px 1px rgba(9,30,66,0.25),0 0 1px 1px rgba(9,30,66,0.13)); cursor: pointer; display: inline; line-height: 16px; padding: 1px 0.24em 2px; text-decoration-line: none; transition: all 0.1s ease-in-out 0s; user-select: text;" tabindex="0"><span class="css-1p7ax5 e158gagu2" style="word-break: break-all;"><span class="css-7h21dr e158gagu6" style="display: inline-block; margin-right: 4px; position: relative;"><span class="css-klch0j e158gagu7" style="display: inline-block; height: 0px; opacity: 0; width: 14px;"></span><span class="css-19n4c3d e158gagu0" style="user-select: none;"><span aria-label="link" class="css-hakgx8" data-testid="inline-card-icon-and-title-default" role="img" style="--icon-primary-color: currentColor; --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 16px; left: 0px; line-height: 14px; position: absolute; top: 0px; width: 14px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></span></span><span class="smart-link-title-wrapper css-0 e158gagu8">Online Plant UML Editor</span></span></a></span></span> </p></li></ul></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1922" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Graphviz</p><ul class="ak-ul" data-indent-level="2" style="box-sizing: border-box; display: flow-root; margin: 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="1934" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="https://dreampuf.github.io/GraphvizOnline/" style="text-decoration-line: none;" title="https://dreampuf.github.io/GraphvizOnline/">Graphviz online</a></p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1953" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="https://edotor.net/" style="text-decoration-line: none;" title="https://edotor.net/">Edotor</a></p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="1963" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><span data-card-url="http://magjac.com/graphviz-visual-editor/" data-inline-card="true"><span class="loader-wrapper"><a class="css-1xdzogm eeajecn0" data-dashlane-label="true" data-dashlane-rid="27606e122c254080" data-form-type="" data-testid="inline-card-resolved-view" href="http://magjac.com/graphviz-visual-editor/" role="button" style="-webkit-box-decoration-break: clone; background-color: var(--ds-surface-raised,white); border-radius: 3px; box-shadow: var(--ds-shadow-raised,0 1px 1px rgba(9,30,66,0.25),0 0 1px 1px rgba(9,30,66,0.13)); cursor: pointer; display: inline; line-height: 16px; padding: 1px 0.24em 2px; text-decoration-line: none; transition: all 0.1s ease-in-out 0s; user-select: text;" tabindex="0"><span class="css-1p7ax5 e158gagu2" style="word-break: break-all;"><span class="css-7h21dr e158gagu6" style="display: inline-block; margin-right: 4px; position: relative;"><span class="css-klch0j e158gagu7" style="display: inline-block; height: 0px; opacity: 0; width: 14px;"></span><span class="css-19n4c3d e158gagu0" style="user-select: none;"><span aria-label="link" class="css-hakgx8" data-testid="inline-card-icon-and-title-default" role="img" style="--icon-primary-color: currentColor; --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 16px; left: 0px; line-height: 14px; position: absolute; top: 0px; width: 14px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></span></span><span class="smart-link-title-wrapper css-0 e158gagu8">Graphviz Visual Editor</span></span></a></span></span> </p></li></ul></li></ul><h3 data-renderer-start-pos="1971" id="Database.1" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.142em; letter-spacing: -0.006em; line-height: 1.5; margin: 2em 0px 0px; padding: 0px; white-space: pre-wrap;">Database</h3><ul style="text-align: left;"><li style="margin-top: 4px;"></li><li><a class="css-tgpl01" data-renderer-mark="true" href="https://app.diagrams.net/" style="background-color: white; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1em; letter-spacing: -0.005em; text-decoration-line: none; white-space: pre-wrap;" title="https://app.diagrams.net/">diagrams.net</a><span style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1em; letter-spacing: -0.005em; white-space: pre-wrap;"> (formerly </span><a class="css-tgpl01" data-renderer-mark="true" href="http://draw.io/" style="background-color: white; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1em; letter-spacing: -0.005em; text-decoration-line: none; white-space: pre-wrap;" title="http://draw.io/">draw.io</a><span style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1em; letter-spacing: -0.005em; white-space: pre-wrap;">)</span></li><ul><li><span style="color: #172b4d; font-family: -apple-system, system-ui, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;"><span style="background-color: white; letter-spacing: -0.08px; white-space: pre-wrap;">Quite heavy</span></span></li><li><span style="color: #172b4d; font-family: -apple-system, system-ui, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;"><span style="background-color: white; letter-spacing: -0.08px; white-space: pre-wrap;">Like an online omnigraffle</span></span></li><li><span style="color: #172b4d; font-family: -apple-system, system-ui, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;"><span style="background-color: white; letter-spacing: -0.08px; white-space: pre-wrap;">Doesn't specialise in databases</span></span></li><li><span style="color: #172b4d; font-family: -apple-system, system-ui, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;"><span style="background-color: white; letter-spacing: -0.08px; white-space: pre-wrap;">No import function for SQL</span></span></li></ul><li style="margin-top: 4px;"><p data-renderer-start-pos="2018" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><a class="css-tgpl01" data-renderer-mark="true" href="http://dbdiagram.io/" style="text-decoration-line: none;" title="http://dbdiagram.io">dbdiagram.io</a></p></li><ul><li>Free for up to 10 diagrams :-|</li><li>Fairly good</li><li>Has multiple import/export</li><li>Importing is quite easy (although doesn't support all syntax)</li><li>Diagrams don't look quite as good as dbdesigner.net</li></ul><li><a href="https://app.dbdesigner.net/">dbdesigner.net</a></li><ul><li>Free for 2 diagrams? :-/</li><li>Slightly better looking diagrams</li><li>But more buggy (Login & save before starting!)</li><li>Importing is more painful than dbdiagram.io</li></ul></ul><ul style="text-align: left;"><ul></ul></ul><div></div><h2 data-renderer-start-pos="2045" id="Hardware" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 1.43em; font-weight: 500; letter-spacing: -0.008em; line-height: 1.2; margin: 1.8em 0px 0px; padding: 0px; white-space: pre-wrap;">Hardware<span class="heading-anchor-wrapper" role="presentation" style="height: 1.2em; margin-left: 6px; position: absolute;"><button aria-label="Copy link to heading" class="css-779anb" style="border-color: initial; border-style: none; border-width: initial; cursor: pointer; display: inline; font-family: inherit; opacity: 0; outline: none; padding-left: 0px; padding-right: 0px; right: 0px; transform: translate(-8px, 0px); transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;"><span aria-label="Copy" class="css-1ncnk3i" role="img" style="--icon-primary-color: var(--ds-icon-subtle, #6B778C); --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 24px; line-height: 1; width: 24px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><g fill-rule="evenodd" fill="currentColor"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"></path><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"></path></g></svg></span></button></span></h2><ul class="ak-ul" data-indent-level="1" style="background-color: white; box-sizing: border-box; color: #172b4d; display: flow-root; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; margin: 10px 0px 0px; padding: 0px 0px 0px 24px; white-space: pre-wrap;"><li><p data-renderer-start-pos="2057" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Pencil and paper - consider this for a first draft (scan/photo if necessary)</p></li></ul><h2 style="text-align: left;"><hr style="border-radius: 1px; border: none; clear: both; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; height: 2px; margin: 1.714em 0px; white-space: pre-wrap;" />Comments</h2><div aria-label="Comment by Will Sheppard" class="_e0oi19bv _15cx1ohn _12ji1r31 _1qu2glyw _12y31o36 _11q71kw7 _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyr1tcg _18u0kr80 fabric-comment" data-test-id="comment-2770173953" id="comment-2770173953" level="0" role="comment" style="--_1b0bc4y: 0px; --_1lywnwv: -10px; background-attachment: inherit; background-clip: inherit; background-color: white; background-image: inherit; background-origin: inherit; background-position: inherit; background-repeat: inherit; background-size: inherit; color: #091e42; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 14px; margin-bottom: 24px; margin-left: var(--_1b0bc4y); margin-right: 0px; margin-top: 10px; outline: currentcolor none medium; padding: 0px;" tabindex="-1"><div class="css-svjjbw" style="display: grid; gap: 8px; grid-template: "avatar-area comment-area" auto ". nested-comments-area" auto / auto 1fr; margin: 0px; padding: 0px; position: relative;"><div class="css-arz0qc" style="grid-area: comment-area / comment-area / comment-area / comment-area; margin: 2px 0px 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px;"><div style="margin: 0px; padding: 0px;"><div class="css-6z8gtv" style="color: var(--ds-text,#172B4D); margin: 4px 0px 0px; padding: 0px;"><div class="_19pkmyb0 wiki-content" style="margin: -4px 0px 0px; padding: 0px;"><div class="css-j3idn3 esiuh5h0" style="margin: 0px; overflow: hidden; padding: 10px 0px;"><div class="ak-renderer-wrapper css-2c6ch1" style="margin: 0px; padding: 0px; position: relative; width: 1226px;"><div class="css-1y0slr1" style="color: var(--ds-text, #172B4D); line-height: 1.5rem; margin: 0px; overflow-wrap: break-word; padding: 0px; white-space: pre-wrap;"><div class="ak-renderer-document" style="margin: 0px; padding: 0px;"><p data-renderer-start-pos="1" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">There are a number of ways to evaluate these software packages:</p><ul class="ak-ul" data-indent-level="1" style="box-sizing: border-box; display: flow-root; margin: 10px 0px 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="68" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Flowchart vs Database</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="93" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Online vs Desktop</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="114" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Visual-only vs Generated from source</p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="154" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">Source language: General (e.g. Dot) vs Specific (e.g. PlantUML + C4)</p></li></ul><p data-renderer-start-pos="226" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0.75rem 0px 0px; padding: 0px;"> </p><p data-renderer-start-pos="228" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0.75rem 0px 0px; padding: 0px;">Source-generated diagrams have many benefits:</p><p data-renderer-start-pos="275" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0.75rem 0px 0px; padding: 0px;"><strong data-renderer-mark="true">Dot</strong> is the easiest to learn, and <strong data-renderer-mark="true">PlantUML</strong> has the most features.</p></div></div></div></div></div></div><div class="css-1s4q3yq" style="-webkit-box-align: center; align-items: center; display: flex; flex-wrap: wrap; margin: 6px 0px 0px; padding: 0px;"></div></div></div></div><div class="_18u012am _19pk1vh9" style="margin: -9pt 0px 0px 50px; padding: 0px;"><div class="CommentActions_actions_Hnn" style="color: #707070; font-size: 12px; margin: 4px 0px 0px; padding: 0px;"><ul class="CommentActions_actionsListWithReactions_3mp" style="align-items: center; display: flex; flex-wrap: wrap; margin: 0px; padding: 0px;"><li class="CommentActions_actionItem_1ro action-reply-comment" style="align-items: flex-end; display: inline-flex; flex-flow: row nowrap; margin-bottom: 8px; margin-top: 4px;"><a class="comment-reply-link" href="https://broadbean.atlassian.net/wiki/spaces/ATS/pages/2760179713/Creating+and+updating+diagrams" style="color: #707070; cursor: pointer; text-decoration-line: none;">Reply</a></li><li class="CommentActions_actionItem_1ro comment-action-edit" style="align-items: flex-end; display: inline-flex; flex-flow: row nowrap; margin-bottom: 8px; margin-top: 4px;"><a class="comment-edit-link" href="https://broadbean.atlassian.net/wiki/spaces/ATS/pages/2760179713/Creating+and+updating+diagrams" style="color: #707070; cursor: pointer; text-decoration-line: none;">Edit</a></li><li class="CommentActions_actionItem_1ro" style="align-items: flex-end; display: inline-flex; flex-flow: row nowrap; margin-bottom: 8px; margin-top: 4px;"><a data-test-id="comment-delete-link" href="https://broadbean.atlassian.net/wiki/spaces/ATS/pages/2760179713/Creating+and+updating+diagrams" id="remove-comment-2770173953" style="color: #707070; cursor: pointer; text-decoration-line: none;">Delete</a></li><span class="reactions-spacer CommentActions_reactionsSpacer_3fd" style="padding-left: 5px;"></span><li class="comment-action-reaction CommentActions_actionItem_1ro CommentActions_noDot_1Yj CommentActions_actionItemReactions_2Q5" style="align-items: flex-end; display: inline-flex; flex-flow: row nowrap; margin-bottom: 8px;"><div class="css-1cqbirf e1mxqiaj2" data-testid="reactions-container" id="reactions-container-comment-2770173953" style="clear: both; margin: 4px 0px 0px; overflow: hidden; padding: 0px;"><div class="css-1qf46xg" style="-webkit-box-align: center; align-items: center; border-radius: 15px; display: flex; flex-wrap: wrap; margin: -2px 0px 0px; padding: 0px; position: relative;"><div role="presentation" style="margin: 0px; padding: 0px;"><div class="miniMode css-1x68nms" style="display: inline-block; margin: 2px 4px 0px; padding: 0px; vertical-align: middle;"><button class="miniMode css-1p9i8k6" data-dashlane-rid="63d2a756c4f637e3" data-form-type="" style="-webkit-box-align: center; -webkit-box-pack: center; align-items: center; background-attachment: initial; background-clip: initial; background-image: none; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 3px; border-width: 0px; cursor: pointer; display: flex; font-family: inherit; font-size: inherit; font-style: normal; font-weight: 500; height: 24px; justify-content: center; line-height: 16px; margin: 0px; max-width: 100%; overflow: hidden; padding: 0px; position: relative; transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s; vertical-align: baseline; white-space: nowrap; width: 24px;" tabindex="0" type="button"><span class="css-113mohm" style="-webkit-box-flex: 0; align-self: center; display: flex; flex-grow: 0; flex-shrink: 0; font-size: 0px; line-height: 0; margin: 0px; opacity: 1; transition: opacity 0.3s ease 0s; user-select: none;"><span aria-label="Add reaction" class="css-hakgx8" role="img" style="--icon-primary-color: currentColor; --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 16px; line-height: 1; width: 16px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><path d="M8.049 14.197c-.166-.476.103-.991.602-1.15.5-.159 1.039.098 1.205.575.06.174.225.487.495.796.426.488.955.764 1.649.764.693 0 1.223-.276 1.65-.764.27-.31.433-.622.494-.796.166-.476.706-.734 1.204-.575.5.159.77.673.603 1.15-.13.371-.395.876-.839 1.385C14.348 16.458 13.306 17 12 17s-2.348-.542-3.112-1.418a4.382 4.382 0 01-.839-1.385zM9.5 11a1.5 1.5 0 110-3 1.5 1.5 0 010 3zm5 0a1.5 1.5 0 110-3 1.5 1.5 0 010 3zM19 5h1a1 1 0 010 2h-1v1a1 1 0 01-2 0V7h-1a1 1 0 010-2h1V4a1 1 0 012 0v1zm-5-1.777V5.29A7 7 0 1018.71 10h2.067A9 9 0 1114 3.223z" fill="currentColor"></path></svg></span></span></button></div></div></div></div></li></ul></div></div></div><div aria-label="Comment by Will Sheppard" class="_e0oi19bv _15cx1ohn _12ji1r31 _1qu2glyw _12y31o36 _11q71kw7 _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyr1tcg _18u0kr80 fabric-comment" data-test-id="comment-2769518735" id="comment-2769518735" level="0" role="comment" style="--_1b0bc4y: 0px; --_1lywnwv: -10px; background-attachment: inherit; background-clip: inherit; background-color: white; background-image: inherit; background-origin: inherit; background-position: inherit; background-repeat: inherit; background-size: inherit; color: #091e42; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 14px; margin-bottom: 24px; margin-left: var(--_1b0bc4y); margin-right: 0px; margin-top: 0px; outline: currentcolor none medium; padding: 0px;" tabindex="-1"><div class="css-svjjbw" style="display: grid; gap: 8px; grid-template: "avatar-area comment-area" auto ". nested-comments-area" auto / auto 1fr; margin: 0px; padding: 0px; position: relative;"><div class="css-arz0qc" style="grid-area: comment-area / comment-area / comment-area / comment-area; margin: 2px 0px 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px;"><div style="margin: 0px; padding: 0px;"><div class="css-6z8gtv" style="color: var(--ds-text,#172B4D); margin: 4px 0px 0px; padding: 0px;"><div class="_19pkmyb0 wiki-content" style="margin: -4px 0px 0px; padding: 0px;"><div class="css-j3idn3 esiuh5h0" style="margin: 0px; overflow: hidden; padding: 10px 0px;"><div class="ak-renderer-wrapper css-2c6ch1" style="margin: 0px; padding: 0px; position: relative; width: 1226px;"><div class="css-1y0slr1" style="color: var(--ds-text, #172B4D); line-height: 1.5rem; margin: 0px; overflow-wrap: break-word; padding: 0px; white-space: pre-wrap;"><div class="ak-renderer-document" style="margin: 0px; padding: 0px;"><p data-renderer-start-pos="1" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">There are online visual editors for both PlantUML and Graphviz! Best of both worlds <span data-emoji-id="1f642" data-emoji-short-name=":slight_smile:" data-emoji-text="🙂"><span aria-label=":slight_smile:" class="emoji-common-main-styles emoji-common-node emoji-common-emoji-image css-1wpdzyr" data-emoji-type="image" data-testid="image-emoji-:slight_smile:" style="background-color: transparent; border-radius: 5px; display: inline-block; margin: -1px 0px; vertical-align: middle;" title=":slight_smile:"><img alt=":slight_smile:" class="emoji" data-emoji-id="1f642" data-emoji-short-name=":slight_smile:" data-emoji-text="🙂" height="20" loading="lazy" src="https://pf-emoji-service--cdn.us-east-1.prod.public.atl-paas.net/standard/a51a7674-8d5d-4495-a2d2-a67c090f5c3b/64x64/1f642.png" style="border: 0px; display: block; margin: 0px; padding: 0px; visibility: visible;" width="20" /></span></span></p></div></div></div></div></div></div><div class="css-1s4q3yq" style="-webkit-box-align: center; align-items: center; display: flex; flex-wrap: wrap; margin: 6px 0px 0px; padding: 0px;"></div></div></div></div><div class="_18u012am _19pk1vh9" style="margin: -9pt 0px 0px 50px; padding: 0px;"><div class="CommentActions_actions_Hnn" style="color: #707070; font-size: 12px; margin: 4px 0px 0px; padding: 0px;"><ul class="CommentActions_actionsListWithReactions_3mp" style="align-items: center; display: flex; flex-wrap: wrap; margin: 0px; padding: 0px;"><li class="CommentActions_actionItem_1ro comment-action-edit" style="align-items: flex-end; display: inline-flex; flex-flow: row nowrap; margin-bottom: 8px; margin-top: 4px;"><br /></li><li class="CommentActions_actionItem_1ro" style="align-items: flex-end; display: inline-flex; flex-flow: row nowrap; margin-bottom: 8px; margin-top: 4px;"><br /></li><span class="reactions-spacer CommentActions_reactionsSpacer_3fd" style="padding-left: 5px;"></span><li class="comment-action-reaction CommentActions_actionItem_1ro CommentActions_noDot_1Yj CommentActions_actionItemReactions_2Q5" style="align-items: flex-end; display: inline-flex; flex-flow: row nowrap; margin-bottom: 8px;"><div class="css-1cqbirf e1mxqiaj2" data-testid="reactions-container" id="reactions-container-comment-2769518735" style="clear: both; margin: 4px 0px 0px; overflow: hidden; padding: 0px;"><div class="css-1qf46xg" style="-webkit-box-align: center; align-items: center; border-radius: 15px; display: flex; flex-wrap: wrap; margin: -2px 0px 0px; padding: 0px; position: relative;"><div role="presentation" style="margin: 0px; padding: 0px;"><div class="miniMode css-1x68nms" style="display: inline-block; margin: 2px 4px 0px; padding: 0px; vertical-align: middle;"><button class="miniMode css-1p9i8k6" data-dashlane-rid="f1bffbb8701a89da" data-form-type="" style="-webkit-box-align: center; -webkit-box-pack: center; align-items: center; background-attachment: initial; background-clip: initial; background-image: none; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: 3px; border-width: 0px; cursor: pointer; display: flex; font-family: inherit; font-size: inherit; font-style: normal; font-weight: 500; height: 24px; justify-content: center; line-height: 16px; margin: 0px; max-width: 100%; overflow: hidden; padding: 0px; position: relative; transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s; vertical-align: baseline; white-space: nowrap; width: 24px;" tabindex="0" type="button"><span class="css-113mohm" style="-webkit-box-flex: 0; align-self: center; display: flex; flex-grow: 0; flex-shrink: 0; font-size: 0px; line-height: 0; margin: 0px; opacity: 1; transition: opacity 0.3s ease 0s; user-select: none;"><span aria-label="Add reaction" class="css-hakgx8" role="img" style="--icon-primary-color: currentColor; --icon-secondary-color: var(--ds-surface, #FFFFFF); display: inline-block; flex-shrink: 0; height: 16px; line-height: 1; width: 16px;"><svg height="24" role="presentation" viewbox="0 0 24 24" width="24"><path d="M8.049 14.197c-.166-.476.103-.991.602-1.15.5-.159 1.039.098 1.205.575.06.174.225.487.495.796.426.488.955.764 1.649.764.693 0 1.223-.276 1.65-.764.27-.31.433-.622.494-.796.166-.476.706-.734 1.204-.575.5.159.77.673.603 1.15-.13.371-.395.876-.839 1.385C14.348 16.458 13.306 17 12 17s-2.348-.542-3.112-1.418a4.382 4.382 0 01-.839-1.385zM9.5 11a1.5 1.5 0 110-3 1.5 1.5 0 010 3zm5 0a1.5 1.5 0 110-3 1.5 1.5 0 010 3zM19 5h1a1 1 0 010 2h-1v1a1 1 0 01-2 0V7h-1a1 1 0 010-2h1V4a1 1 0 012 0v1zm-5-1.777V5.29A7 7 0 1018.71 10h2.067A9 9 0 1114 3.223z" fill="currentColor"></path></svg></span></span></button></div></div></div></div></li></ul></div></div></div><div aria-label="Comment by Will Sheppard" class="_e0oi19bv _15cx1ohn _12ji1r31 _1qu2glyw _12y31o36 _11q71kw7 _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyr1tcg _18u0kr80 fabric-comment" data-test-id="comment-2769977352" id="comment-2769977352" level="0" role="comment" style="--_1b0bc4y: 0px; --_1lywnwv: -10px; background-attachment: inherit; background-clip: inherit; background-color: white; background-image: inherit; background-origin: inherit; background-position: inherit; background-repeat: inherit; background-size: inherit; color: #091e42; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 14px; margin-bottom: 24px; margin-left: var(--_1b0bc4y); margin-right: 0px; margin-top: 0px; outline: currentcolor none medium; padding: 0px;" tabindex="-1"><div class="css-svjjbw" style="display: grid; gap: 8px; grid-template: "avatar-area comment-area" auto ". nested-comments-area" auto / auto 1fr; margin: 0px; padding: 0px; position: relative;"><div class="css-arz0qc" style="grid-area: comment-area / comment-area / comment-area / comment-area; margin: 2px 0px 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px;"><div style="margin: 0px; padding: 0px;"><div class="css-6z8gtv" style="color: var(--ds-text,#172B4D); margin: 4px 0px 0px; padding: 0px;"><div class="_19pkmyb0 wiki-content" style="margin: -4px 0px 0px; padding: 0px;"><div class="css-j3idn3 esiuh5h0" style="margin: 0px; overflow: hidden; padding: 10px 0px;"><div class="ak-renderer-wrapper css-2c6ch1" style="margin: 0px; padding: 0px; position: relative; width: 1226px;"><div class="css-1y0slr1" style="color: var(--ds-text, #172B4D); line-height: 1.5rem; margin: 0px; overflow-wrap: break-word; padding: 0px; white-space: pre-wrap;"><div class="ak-renderer-document" style="margin: 0px; padding: 0px;"><p data-renderer-start-pos="1" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;">More PlantUML resources:</p><ul class="ak-ul" data-indent-level="1" style="box-sizing: border-box; display: flow-root; margin: 10px 0px 0px; padding: 0px 0px 0px 24px;"><li><p data-renderer-start-pos="29" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><span data-card-url="https://crashedmind.github.io/PlantUMLHitchhikersGuide/" data-inline-card="true"><span class="loader-wrapper"><a class="css-1xdzogm eeajecn0" data-testid="inline-card-resolved-view" href="https://crashedmind.github.io/PlantUMLHitchhikersGuide/" role="button" style="-webkit-box-decoration-break: clone; background-color: var(--ds-surface-raised,white); border-radius: 3px; box-shadow: var(--ds-shadow-raised,0 1px 1px rgba(9,30,66,0.25),0 0 1px 1px rgba(9,30,66,0.13)); cursor: pointer; display: inline; line-height: 16px; padding: 1px 0.24em 2px; text-decoration-line: none; transition: all 0.1s ease-in-out 0s; user-select: text;" tabindex="0"><span class="css-1p7ax5 e158gagu2" style="word-break: break-all;"><span class="css-7h21dr e158gagu6" style="display: inline-block; margin-right: 4px; position: relative;"><span class="css-klch0j e158gagu7" style="display: inline-block; height: 0px; opacity: 0; width: 14px;"></span><img class="smart-link-icon css-168a27h e1bjtjov0" data-testid="inline-card-icon-and-title-image" src="https://crashedmind.github.io/PlantUMLHitchhikersGuide/_static/plantumllogo.png" style="border-radius: 2px; border: 0px; height: 14px; left: 7px; margin: 0px 4px 0px 0px; padding: 0px; position: absolute; top: 8px; transform: translate(-50%, -50%); user-select: none; width: 14px;" /></span><span class="smart-link-title-wrapper css-0 e158gagu8">Welcome to The Hitchhiker’s Guide to PlantUML! — The Hitchhiker's Guide to PlantUML documentation</span></span></a></span></span> </p></li><li style="margin-top: 4px;"><p data-renderer-start-pos="35" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0px; padding: 0px;"><span data-card-url="https://plantuml.com/guide" data-inline-card="true"><span class="loader-wrapper"><a class="css-1xdzogm eeajecn0" data-testid="inline-card-resolved-view" href="https://plantuml.com/guide" role="button" style="-webkit-box-decoration-break: clone; background-color: var(--ds-surface-raised,white); border-radius: 3px; box-shadow: var(--ds-shadow-raised,0 1px 1px rgba(9,30,66,0.25),0 0 1px 1px rgba(9,30,66,0.13)); cursor: pointer; display: inline; line-height: 16px; padding: 1px 0.24em 2px; text-decoration-line: none; transition: all 0.1s ease-in-out 0s; user-select: text;" tabindex="0"><span class="css-1p7ax5 e158gagu2" style="word-break: break-all;"><span class="css-7h21dr e158gagu6" style="display: inline-block; margin-right: 4px; position: relative;"><span class="css-klch0j e158gagu7" style="display: inline-block; height: 0px; opacity: 0; width: 14px;"></span><img class="smart-link-icon css-168a27h e1bjtjov0" data-testid="inline-card-icon-and-title-image" src="https://plantuml.com/favicon.ico" style="border-radius: 2px; border: 0px; height: 14px; left: 7px; margin: 0px 4px 0px 0px; padding: 0px; position: absolute; top: 8px; transform: translate(-50%, -50%); user-select: none; width: 14px;" /></span><span class="smart-link-title-wrapper css-0 e158gagu8">PlantUML Language Reference Guide</span></span></a></span></span> </p></li></ul><p data-renderer-start-pos="41" style="font-size: 1em; letter-spacing: -0.005em; line-height: 1.714; margin: 0.75rem 0px 0px; padding: 0px;"> </p></div></div></div></div></div></div></div></div></div></div><p data-renderer-start-pos="2138" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin: 0.75rem 0px 0px; padding: 0px; white-space: pre-wrap;"><span color="var(--ds-text, #172B4D)" style="font-size: 1em; letter-spacing: -0.005em;">Note: PlantUML uses Graphviz to draw some diagrams.</span> </p><p data-renderer-start-pos="2138" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin: 0.75rem 0px 0px; padding: 0px; white-space: pre-wrap;"><br /></p><p data-renderer-start-pos="2138" style="background-color: white; color: #172b4d; font-family: -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin: 0.75rem 0px 0px; padding: 0px; white-space: pre-wrap;">(sorry, the formatting of this post is a <i>complete mess</i>)</p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-10348364369411612542022-08-11T22:52:00.003+01:002022-08-11T22:52:39.920+01:00jq cheat sheet<p><a href="https://stedolan.github.io/jq/manual" target="_blank">jq manual</a></p><p><br /></p><p><script src="https://gist.github.com/willsheppard/f0bdc1a2290f3d24d9579856ab5b7b53.js"></script></p>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-42701567685166451562022-08-09T11:16:00.004+01:002022-09-28T16:06:40.171+01:00Javascript web frameworks, 2022<p> A list:</p><ul>
<li>React - library, jsx, facebook</li>
<li>Vue - easier than backbone, good cli</li>
<li>Angular - typescript, heavy, google</li>
<li><b>Ember - opinionated, fast development</b> <-- this one is good</li>
<li>Backbone - stable, reliable, data rendering, easy, lightweight</li>
<li>Aurelia - convention over configuration, standards, very easy</li>
<li>Lit - very fast, lightweight, google</li>
<li>Mithril - lean, fast, simple</li></ul><div><br /></div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-34762539601990948622022-07-20T13:39:00.002+01:002022-07-20T13:39:45.955+01:00Improve website usability, with Javascript<p>// You need a certain control to be clicked when you press a certain button? Such codez!</p><p><span style="font-family: courier;">window.addEventListener('keyup', function(event) {</span></p><p><span style="font-family: courier;"> if (event.keyCode === 27) { // escape</span></p><p><span style="font-family: courier;"> $('.component---BWa8p').focus().click();</span></p><p><span style="font-family: courier;"> }</span></p><p><span style="font-family: courier;">});</span></p><div>(<a href="https://www.codegrepper.com/code-examples/javascript/javascript+bind+key+to+button">source</a>, <a href="https://stackoverflow.com/questions/24278469/click-a-button-programmatically-js">source</a>)</div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-91656417410840832862022-07-13T13:19:00.010+01:002022-07-13T14:50:31.017+01:00Node CRUD basics<p>Javascript philosophy and execution flow is quite different to Perl:</p><p></p><ul style="text-align: left;"><li>With Perl it's strongly discouraged to wrap an operation in a `try { ... }` block without a `catch { ... }` block following it, because any errors would be hidden and the operation might silently fail.</li><li>With Javascript and Promises, many operations are automatically wrapped in a `try { ... }` block, and are not even executed if they don't have a `.then()` or a `.catch()` added, so they silently fail!</li></ul><div>Knex basics</div><div><br /></div>
<script src="https://gist.github.com/willsheppard/372ee75563930e0f8e4487522c357c41.js"></script>
Unknownnoreply@blogger.comtag:blogger.com,1999:blog-2683990461891513461.post-80607707925631687812022-07-12T11:14:00.003+01:002022-11-08T19:58:22.108+00:00Basic Node package recommendations<p>Recommendations for your javascript application:</p><p></p><ul style="text-align: left;"><li>Web framework: express</li><li>DB abstraction: knex, sequelize, db-migrate</li><li>DB Migration: <b>knex</b>, db-migrate</li><li>HTTP client (for external API requests): axios (older apps use superagent, axios has better features)</li><li>Templating: handlebars</li><li>Testing: mocha, sinon (mocking), chai (assertions), karma, jasmine, qunit, jest, cypress, storybook, ava</li><li>Integration testing: puppeteer, playwright, webdriverIO</li><li>Code Coverage: Istanbul</li><li>Process management (in production): pm2</li><li>Linting and code standards: eslint prettier</li><li>Inline documentation: <a href="https://jsdoc.app/about-getting-started.html" target="_blank">JSDoc</a></li><li>Typescript: https://www.typescriptlang.org/docs/handbook/interfaces.html</li></ul><div><br /></div><p></p>Unknownnoreply@blogger.com