<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sean Brunnock</title>
    <description>The latest articles on DEV Community by Sean Brunnock (@brunnock).</description>
    <link>https://dev.to/brunnock</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F883734%2F130ccdf2-9138-4de1-97f5-fb1bd80ed618.jpeg</url>
      <title>DEV Community: Sean Brunnock</title>
      <link>https://dev.to/brunnock</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brunnock"/>
    <language>en</language>
    <item>
      <title>EPubbing</title>
      <dc:creator>Sean Brunnock</dc:creator>
      <pubDate>Mon, 29 Aug 2022 15:24:00 +0000</pubDate>
      <link>https://dev.to/brunnock/epubbing-2d2</link>
      <guid>https://dev.to/brunnock/epubbing-2d2</guid>
      <description>&lt;p&gt;I've been an avid reader for as long as I can remember. When I bought my first house, I made sure there would be a dedicated library with lots of bookshelves.&lt;/p&gt;

&lt;p&gt;Since then, I've become addicted to ebooks and can't abide paper books. &lt;/p&gt;

&lt;p&gt;I feel terrible confessing this. Paper books have been a part of my life for so long and I thought the idea of reading a book on a smartphone was ridiculous. But my eyesight is deteriorating and ebooks make it so easy to set a comfortable font. Another advantage, since my phone only displays a paragraph at a time, it's forced me to slow down and savor the words. I can also look up any words I'm unfamiliar with instantly.&lt;/p&gt;

&lt;p&gt;But, I've got a lot of books in my library that aren't available as ebooks. Time to learn to create them.&lt;/p&gt;

&lt;p&gt;So, the &lt;a href="https://en.wikipedia.org/wiki/EPUB" rel="noopener noreferrer"&gt;EPUB&lt;/a&gt; format is an open format that is supported by almost all ereaders. It was started by the Open eBook Forum, but it's now maintained by the &lt;a href="https://www.w3.org/TR/epub-overview-33/" rel="noopener noreferrer"&gt;W3C&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;EPUB is over 10 years old, and there have been some changes over time, so there's a lot of outdated docs out there. But of course, nobody ever points out that their docs are outdated. It's left as an exercise for the reader.&lt;/p&gt;

&lt;p&gt;Most of the docs that I've read insist that you should use existing software to convert text to EPUB, but I found that Apple's Page app injects useless Javascript. So I decided to use my own technique.&lt;/p&gt;

&lt;p&gt;I created a &lt;a href="https://sean.brunnock.com/HTML/EPUB/" rel="noopener noreferrer"&gt;simple guide to EPUB's structure&lt;/a&gt;. It doesn't go into excessive detail. It just shows how to create a very simple ebook that complies with EPUB v3.2. &lt;/p&gt;

&lt;p&gt;To create an ebook, I use the "Scan Text" feature on my iPhone's Notes app to convert the page to ASCII text. The Notes app syncs with my Apple account, so the text shows up on my desktop as well.&lt;/p&gt;

&lt;p&gt;Next, I use &lt;a href="https://sean.brunnock.com/React/ScannedTextCleaner/" rel="noopener noreferrer"&gt;my own software&lt;/a&gt; to convert the raw text into XHTML. I copy the text to my app and compare it to the original book and insert a mark (three backticks) at the start of each paragraph. My app can delete all of the existing newlines and then replace the backticks with newlines. I can then triple-click entire paragraphs and mark them up.&lt;/p&gt;

&lt;p&gt;Notes is great at scanning words, but not so great with punctuation. All em dashes get turned into hyphens, for example. My app can highlight all of the puncuation so you can hopefully eyeball any mistakes.&lt;/p&gt;

&lt;p&gt;My app removes hyphens from the ends of lines and combines word parts into single words. Sometimes, the hyphen at the end of a line was meant to be part of a hyphenated word. Chrome's textarea has a spellcheck feature that can highlight those mistakes.&lt;/p&gt;

&lt;p&gt;My app doesn't create an entire XHTML file. It just marks up the raw text and I copy that into a template. &lt;/p&gt;

&lt;p&gt;So far, I'e managed to turn &lt;a href="https://www.w3.org/People/Berners-Lee/Weaving/Overview.html" rel="noopener noreferrer"&gt;Weaving the Web&lt;/a&gt; into an ebook which I'm now finally reading comfortably. Very strange that a book by the guy who invented the Web isn't available in electronic format.&lt;/p&gt;

</description>
      <category>epub</category>
    </item>
    <item>
      <title>Cookies, I hardy knew ye.</title>
      <dc:creator>Sean Brunnock</dc:creator>
      <pubDate>Wed, 27 Jul 2022 11:03:00 +0000</pubDate>
      <link>https://dev.to/brunnock/cookies-i-hardy-knew-ye-2pjp</link>
      <guid>https://dev.to/brunnock/cookies-i-hardy-knew-ye-2pjp</guid>
      <description>&lt;p&gt;Even though, I've been a developer for over 25 years, I've never really dealt with cookies. Back in my Perl days, I used hidden fields to manage sessions. Now that I'm using &lt;a href="https://expressjs.com/en/resources/middleware/session.html" rel="noopener noreferrer"&gt;express-session&lt;/a&gt;, I figured it would be a good idea to get more familiar with cookies. That turned out to be tougher than I thought it would be.&lt;/p&gt;

&lt;p&gt;Normally, cookies are created by the server and, if the server enables the &lt;code&gt;HttpOnly&lt;/code&gt; flag, then your browser's JS code won't even be able to see the cookies. But, I like making demos that work in your browser.&lt;/p&gt;

&lt;p&gt;Cookies are represented in JS by the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie" rel="noopener noreferrer"&gt;document.cookie&lt;/a&gt; object. Running &lt;code&gt;console.log(typeof document.cookie)&lt;/code&gt; returns &lt;code&gt;string&lt;/code&gt;, but it's not a string. It's an object with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get" rel="noopener noreferrer"&gt;getters&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set" rel="noopener noreferrer"&gt;setters&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's very easy to add a cookie in your browser- &lt;code&gt;document.cookie = 'cookie1=New Cookie!'&lt;/code&gt;. And it's very easy to change it- &lt;code&gt;document.cookie = 'cookie1=New value.'&lt;/code&gt;. Deleting it is a different matter.&lt;/p&gt;

&lt;p&gt;You don't actually delete cookies, you expire them. Most examples that I've found state that you should use some variation of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let date = new Date(0);
document.cookie = 'cookie1=; expires='+date.toUTCString();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I find that setting &lt;code&gt;max-age&lt;/code&gt; is easier-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.cookie = 'cookie1=; max-age=0';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something fun I learned is that you can have multiple cookies with the same name and different values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.cookie = 'cookie1=root; path=/';
document.cookie = 'cookie1=parent; path=/Parent';
document.cookie = 'cookie1=cwd;';
console.log(document.cookie);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you serve the preceding code to a browser with the pathname &lt;code&gt;/Parent&lt;/code&gt;, then the output  should be &lt;code&gt;cookie1=cwd; cookie1=parent; cookie1=root&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are a few tricky points here. One, you can't use any arbitrary value for &lt;code&gt;path&lt;/code&gt;. It has to be an actual path in &lt;code&gt;document.location.pathname&lt;/code&gt;. Second, while &lt;code&gt;document.cookie&lt;/code&gt; will return all of the cookies, it won't tell you which one is associated with which path. The cookies are in ascending order from the longest to the shortest path.  You can do something like &lt;code&gt;let cookies = document.cookie.split('; ')&lt;/code&gt; and the array will be in ascending order (tested on Chrome, Firefox, and Safari).&lt;/p&gt;

&lt;p&gt;In order to alter or delete a specific cookie, you need to specify its corresponding path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.cookie = `cookie1=NewValue; path=/;`;
document.cookie = `cookie1=; path=/; max-age=0;`;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can't alter a cookie's path.&lt;/p&gt;

&lt;p&gt;I should point out that running &lt;code&gt;document.cookie = 'cookie1=New Cookie!'&lt;/code&gt; is bad form. You should encode the data like so- &lt;code&gt;document.cookie = 'goodCookie=' +encodeURIComponent('data to encode')&lt;/code&gt;. This will allow you to use semicolons in your data.&lt;/p&gt;

&lt;p&gt;Well, that's enough to get started. I've got a bunch more working examples at &lt;a href="https://sean.brunnock.com/Javascript/Cookies/" rel="noopener noreferrer"&gt;https://sean.brunnock.com/Javascript/Cookies/&lt;/a&gt;. I hope you find it helpful.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Express devs and WHATWG editors have very different ideas about accessing headers.</title>
      <dc:creator>Sean Brunnock</dc:creator>
      <pubDate>Sun, 10 Jul 2022 15:34:00 +0000</pubDate>
      <link>https://dev.to/brunnock/express-devs-and-whatwg-editors-have-very-different-ideas-about-accessing-headers-1jai</link>
      <guid>https://dev.to/brunnock/express-devs-and-whatwg-editors-have-very-different-ideas-about-accessing-headers-1jai</guid>
      <description>&lt;p&gt;I did what I thought would be an easy project. Oh, how wrong I was.&lt;/p&gt;

&lt;p&gt;I had an ERN (Express/React/Node) app that simply printed the HTTP headers that your browser sent to my server. I thought it would be a simple matter to also show the HTTP headers that your browser &lt;em&gt;received&lt;/em&gt; from my server. It turns out that this list of headers is a very different data structure.&lt;/p&gt;

&lt;p&gt;To access the headers on an express server, just use &lt;em&gt;req.headers&lt;/em&gt;. It's a simple object with the expected keys and values.&lt;/p&gt;

&lt;p&gt;The Fetch API allows your browser to access HTTP headers via &lt;em&gt;response.headers&lt;/em&gt;. For example, you could run &lt;code&gt;fetch('http://example.com/').then(response=&amp;gt;console.log(response.headers))&lt;/code&gt;. The problem is that the Fetch API returns an &lt;a href="https://javascript.info/iterable" rel="noopener noreferrer"&gt;iterable&lt;/a&gt; which is very different from Express's simple object.&lt;/p&gt;

&lt;p&gt;To render the iterable, I have to use &lt;code&gt;let headersARR=[];&lt;br&gt;
for (let header of [...response.headers.entries()]) {&lt;br&gt;
            headersArr.push(header);&lt;br&gt;
          }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm sure that the Express folks and the WHATWG folks have their reasons for handling HTTP headers differently. It just makes things more difficult for us mere developers.&lt;/p&gt;

&lt;p&gt;Anyways, you can try my demo at &lt;a href="https://sean.brunnock.com/PERN/HTTPheaders/" rel="noopener noreferrer"&gt;sean.brunnock.com&lt;/a&gt; and view the source to see the nuts and bolts and you can visit &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Headers" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Headers&lt;/a&gt; for lots more info about accessing headers with fetch.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>4 examples of fetching with React and useEffect</title>
      <dc:creator>Sean Brunnock</dc:creator>
      <pubDate>Tue, 05 Jul 2022 15:45:00 +0000</pubDate>
      <link>https://dev.to/brunnock/4-examples-of-fetching-with-react-and-useeffect-55b2</link>
      <guid>https://dev.to/brunnock/4-examples-of-fetching-with-react-and-useeffect-55b2</guid>
      <description>&lt;p&gt;Here are 4 simple examples of React using the useEffect hook and the Fetch API- getting plain text; getting JSON; posting JSON; and handling errors. All four examples are running live code, so you can play around with it and hopefully get a feel for it. At least it worked for me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sean.brunnock.com/React/Examples/ReactFetchDemos/" rel="noopener noreferrer"&gt;https://sean.brunnock.com/React/Examples/ReactFetchDemos/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>Baby steps</title>
      <dc:creator>Sean Brunnock</dc:creator>
      <pubDate>Tue, 05 Jul 2022 12:24:00 +0000</pubDate>
      <link>https://dev.to/brunnock/baby-steps-5gbp</link>
      <guid>https://dev.to/brunnock/baby-steps-5gbp</guid>
      <description>&lt;p&gt;So, in my quest to switch from LAMP to PERN, I'm going to update my old MySQL DB manager and turn it into a modern Postgres DB manager. This time, I'm going to use modern authentication techniques rather than my old basic HTTP authentication.&lt;/p&gt;

&lt;p&gt;So, how do we do this? The &lt;a href="https://www.passportjs.org/" rel="noopener noreferrer"&gt;Passport&lt;/a&gt; library seems to be the most popular. Great, let's use that. Passport uses sessions. Which library should I use? The Express team maintains &lt;a href="http://expressjs.com/en/resources/middleware/session.html" rel="noopener noreferrer"&gt;express-session&lt;/a&gt; and &lt;a href="http://expressjs.com/en/resources/middleware/cookie-session.html" rel="noopener noreferrer"&gt;cookie-session&lt;/a&gt;. Cookie-session looks simpler. Let's use that. Nope. &lt;a href="https://github.com/jaredhanson/passport/issues/904" rel="noopener noreferrer"&gt;It's not compatible with Passport currently&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fine, we'll use express-session. express-session creates a session id and stores it in a cookie. How do I manipulate cookies in JS? I have to use something called encodeURIComponent. I've never used it. How does it differ from encodeURI? Time to do some research.&lt;/p&gt;

&lt;p&gt;OK. I've updated my &lt;a href="https://sean.brunnock.com/Javascript/Core/encodeURI.html" rel="noopener noreferrer"&gt;encodeURI demo&lt;/a&gt; so it now includes examples of encodeURIComponent and decodeURIComponent. That'll do for today.&lt;/p&gt;

&lt;p&gt;Baby steps.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
  </channel>
</rss>
