Repository with sources and generator of https://larlet.fr/david/ https://larlet.fr/david/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang=en>
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset=utf-8>
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>DNS and privacy — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <!-- Canonical URL for SEO purposes -->
  28. <link rel="canonical" href="https://larlet.fr/david/stream/2018/04/05/">
  29. <style>
  30. /* http://meyerweb.com/eric/tools/css/reset/ */
  31. html, body, div, span,
  32. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  33. a, abbr, address, big, cite, code,
  34. del, dfn, em, img, ins,
  35. small, strike, strong, tt, var,
  36. dl, dt, dd, ol, ul, li,
  37. fieldset, form, label, legend,
  38. table, caption, tbody, tfoot, thead, tr, th, td,
  39. article, aside, canvas, details, embed,
  40. figure, figcaption, footer, header, hgroup,
  41. menu, nav, output, ruby, section, summary,
  42. time, mark, audio, video {
  43. margin: 0;
  44. padding: 0;
  45. border: 0;
  46. font-size: 100%;
  47. font: inherit;
  48. vertical-align: baseline;
  49. }
  50. /* HTML5 display-role reset for older browsers */
  51. article, aside, details, figcaption, figure,
  52. footer, header, hgroup, menu, nav, section { display: block; }
  53. body { line-height: 1; }
  54. blockquote, q { quotes: none; }
  55. blockquote:before, blockquote:after,
  56. q:before, q:after {
  57. content: '';
  58. content: none;
  59. }
  60. table {
  61. border-collapse: collapse;
  62. border-spacing: 0;
  63. }
  64. /* http://practicaltypography.com/equity.html */
  65. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  66. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  67. @font-face {
  68. font-family: 'EquityTextB';
  69. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  70. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  71. font-weight: 300;
  72. font-style: normal;
  73. font-display: swap;
  74. }
  75. @font-face {
  76. font-family: 'EquityTextB';
  77. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  78. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  79. font-weight: 300;
  80. font-style: italic;
  81. font-display: swap;
  82. }
  83. @font-face {
  84. font-family: 'EquityTextB';
  85. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  86. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  87. font-weight: 700;
  88. font-style: normal;
  89. font-display: swap;
  90. }
  91. @font-face {
  92. font-family: 'TriplicateT4c';
  93. src: url('/static/david/css/fonts/Triplicate-T4-Code-Regular-webfont.woff2') format('woff2'),
  94. url('/static/david/css/fonts/Triplicate-T4-Code-Regular-webfont.woff') format('woff');
  95. font-weight: 300;
  96. font-style: normal;
  97. font-display: swap;
  98. }
  99. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  100. body {
  101. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  102. font-family: "EquityTextB", Palatino, serif;
  103. background-color: #f0f0ea;
  104. color: #07486c;
  105. font-kerning: normal;
  106. -moz-osx-font-smoothing: grayscale;
  107. -webkit-font-smoothing: subpixel-antialiased;
  108. text-rendering: optimizeLegibility;
  109. font-variant-ligatures: common-ligatures contextual;
  110. font-feature-settings: "kern", "liga", "clig", "calt";
  111. }
  112. pre, code, kbd, samp, var, tt {
  113. font-family: 'TriplicateT4c', monospace;
  114. }
  115. em {
  116. font-style: italic;
  117. color: #323a45;
  118. }
  119. strong {
  120. font-weight: bold;
  121. color: black;
  122. }
  123. nav {
  124. background-color: #323a45;
  125. color: #f0f0ea;
  126. display: flex;
  127. justify-content: space-around;
  128. padding: 1rem .5rem;
  129. }
  130. nav:first-child {
  131. border-top: 1vh solid #2d7474;
  132. }
  133. nav:last-child {
  134. border-bottom: 1vh solid #2d7474;
  135. }
  136. nav a {
  137. color: #f0f0ea;
  138. }
  139. nav abbr {
  140. border-bottom: 1px dotted white;
  141. }
  142. h1 {
  143. border-bottom: .2vh solid #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 2rem 0 1rem;
  148. width: 100%;
  149. }
  150. h2 {
  151. margin: 4rem 0 1rem;
  152. border-top: .2vh solid #2d7474;
  153. }
  154. h3 {
  155. text-align: center;
  156. margin: 3rem 0 .75em;
  157. }
  158. hr {
  159. height: .4rem;
  160. width: .4rem;
  161. border-radius: .4rem;
  162. background: #07486c;
  163. margin: 2.5rem auto;
  164. }
  165. time {
  166. display: bloc;
  167. background-color: #2d7474;
  168. color: #e3e1e1;
  169. padding: .29rem 1rem;
  170. float: right;
  171. }
  172. ul, ol {
  173. margin: 2rem;
  174. }
  175. ul {
  176. list-style-type: square;
  177. }
  178. a {
  179. text-decoration-skip-ink: auto;
  180. }
  181. article {
  182. max-width: 50rem;
  183. display: flex;
  184. flex-direction: column;
  185. margin: 3rem auto 1rem auto;
  186. }
  187. article p:last-child {
  188. margin-bottom: 1rem;
  189. }
  190. p {
  191. padding: 0 .5rem;
  192. }
  193. p + p {
  194. margin-top: 2rem;
  195. }
  196. blockquote {
  197. background-color: #e3e1e1;
  198. border-left: .5vw solid #2d7474;
  199. display: flex;
  200. flex-direction: column;
  201. align-items: center;
  202. padding: 1rem;
  203. margin: 1.5rem;
  204. }
  205. blockquote cite {
  206. font-style: italic;
  207. }
  208. figure {
  209. border-top: .2vh solid #2d7474;
  210. background-color: #e3e1e1;
  211. text-align: center;
  212. padding: 1.5rem 0;
  213. margin: 1rem 0 0;
  214. font-size: 1.5rem;
  215. width: 100%;
  216. }
  217. figure img {
  218. width: 250px;
  219. height: 250px;
  220. border: .5vw solid #323a45;
  221. padding: 1px;
  222. }
  223. figcaption {
  224. padding: 1rem;
  225. line-height: 1.4;
  226. }
  227. aside {
  228. display: flex;
  229. flex-direction: column;
  230. background-color: #e3e1e1;
  231. padding: 1rem 0;
  232. border-bottom: .2vh solid #07486c;
  233. }
  234. aside p {
  235. max-width: 50rem;
  236. margin: 0 auto;
  237. }
  238. /* https://fvsch.com/code/css-locks/ */
  239. p, li, pre, code, kbd, samp, var, tt, time {
  240. font-size: .95rem;
  241. line-height: calc( 1.5em + 0.2 * 1rem );
  242. }
  243. h1 {
  244. font-size: 1.7rem;
  245. line-height: calc( 1.2em + 0.2 * 1rem );
  246. }
  247. h2 {
  248. font-size: 1.6rem;
  249. line-height: calc( 1.3em + 0.2 * 1rem );
  250. }
  251. h3 {
  252. font-size: 1.35rem;
  253. line-height: calc( 1.4em + 0.2 * 1rem );
  254. }
  255. @media (min-width: 20em) {
  256. /* The (100vw - 20rem) / (50 - 20) part
  257. resolves to 0-1rem, depending on the
  258. viewport width (between 20em and 50em). */
  259. p, li, pre, code, kbd, samp, var, tt, time {
  260. font-size: calc( .95rem + .6 * (100vw - 20rem) / (50 - 20) );
  261. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  262. }
  263. h1 {
  264. font-size: calc( 1.7rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  265. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  266. }
  267. h2 {
  268. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  269. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  270. }
  271. h3 {
  272. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  273. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  274. }
  275. }
  276. @media (min-width: 50em) {
  277. /* The right part of the addition *must* be a
  278. rem value. In this example we *could* change
  279. the whole declaration to font-size:2.5rem,
  280. but if our baseline value was not expressed
  281. in rem we would have to use calc. */
  282. p, li, pre, code, kbd, samp, var, tt, time {
  283. font-size: calc( .95rem + .6 * 1rem );
  284. line-height: 1.5em;
  285. }
  286. h1 {
  287. font-size: calc( 1.7rem + 1.5 * 1rem );
  288. line-height: 1.2em;
  289. }
  290. h2 {
  291. font-size: calc( 1.5rem + 1.5 * 1rem );
  292. line-height: 1.3em;
  293. }
  294. h3 {
  295. font-size: calc( 1.35rem + 1.5 * 1rem );
  296. line-height: 1.4em;
  297. }
  298. figure img {
  299. width: 500px;
  300. height: 500px;
  301. }
  302. blockquote {
  303. margin-left: -1.5rem;
  304. }
  305. }
  306. figure.unsquared {
  307. margin-bottom: 1.5rem;
  308. }
  309. figure.unsquared img {
  310. height: inherit;
  311. }
  312. /* https://github.com/richleland/pygments-css */
  313. .codehilite{
  314. background-color: #fdf6e3;
  315. margin: 1rem auto;
  316. padding: 1rem;
  317. overflow-x:auto;
  318. box-shadow:inset 0 0 2px rgba(0,0,0,0.2)
  319. }
  320. .codehilite .t{color:#586e75}
  321. .codehilite .w{color:#073642}
  322. .codehilite .err{color:#cb4b16}
  323. .codehilite .k{color:#859900}
  324. .codehilite .kc{color:#2aa198}
  325. .codehilite .kd{color:#268bd2}
  326. .codehilite .kn{color:#b58900}
  327. .codehilite .kp{color:#859900}
  328. .codehilite .kr{color:#073642}
  329. .codehilite .kt{color:#b58900}
  330. .codehilite .n{color:#586e75}
  331. .codehilite .na{color:#2aa198}
  332. .codehilite .nb{color:#268bd2}
  333. .codehilite .nc{color:#268bd2}
  334. .codehilite .ne{color:#cb4b16}
  335. .codehilite .no{color:#2aa198}
  336. .codehilite .nd{color:#2aa198}
  337. .codehilite .ni{color:#2aa198;font-weight:bold}
  338. .codehilite .nf{color:#268bd2}
  339. .codehilite .nn{color:#586e75}
  340. .codehilite .nt{color:#2aa198;font-weight:bold}
  341. .codehilite .nv{color:#cb4b16}
  342. .codehilite .b{color:#859900}
  343. .codehilite .bp{color:#586e75}
  344. .codehilite .v{color:#586e75}
  345. .codehilite .vc{color:#586e75}
  346. .codehilite .vg{color:#268bd2}
  347. .codehilite .vi{color:#268bd2}
  348. .codehilite .m{color:#268bd2}
  349. .codehilite .mf{color:#268bd2}
  350. .codehilite .mh{color:#268bd2}
  351. .codehilite .mi{color:#268bd2}
  352. .codehilite .mo{color:#268bd2}
  353. .codehilite .s{color:#2aa198}
  354. .codehilite .sb{color:#2aa198}
  355. .codehilite .sc{color:#2aa198}
  356. .codehilite .sd{color:#2aa198}
  357. .codehilite .s2{color:#2aa198}
  358. .codehilite .se{color:#cb4b16}
  359. .codehilite .sh{color:#2aa198}
  360. .codehilite .si{color:#cb4b16}
  361. .codehilite .sx{color:#2aa198}
  362. .codehilite .sr{color:#cb4b16}
  363. .codehilite .s1{color:#2aa198}
  364. .codehilite .ss{color:#cb4b16}
  365. .codehilite .il{color:#268bd2}
  366. .codehilite .o{color:#586e75}
  367. .codehilite .ow{color:#859900}
  368. .codehilite .p{color:#586e75}
  369. .codehilite .c{color:#93a1a1;font-style:italic}
  370. .codehilite .cm{color:#93a1a1}
  371. .codehilite .cp{color:#93a1a1}
  372. .codehilite .c1{color:#93a1a1}
  373. .codehilite .cs{color:#93a1a1}
  374. .codehilite .hll{background-color:#dc322f}
  375. .codehilite .g{color:#586e75}
  376. .codehilite .gd{color:#586e75}
  377. .codehilite .ge{font-style:italic}
  378. .codehilite .gr{color:#586e75}
  379. .codehilite .gh{color:#586e75;font-weight:bold}
  380. .codehilite .gi{color:#586e75}
  381. .codehilite .go{color:#586e75}
  382. .codehilite .gp{color:#586e75}
  383. .codehilite .gs{font-weight:bold}
  384. .codehilite .gu{color:#586e75;font-weight:bold}
  385. .codehilite .gt{color:#586e75}
  386. @media print {
  387. body { font-size: 100%; }
  388. a:after { content: " (" attr(href) ")"; }
  389. a, a:link, a:visited, a:after {
  390. text-decoration: underline;
  391. text-shadow: none !important;
  392. background-image: none !important;
  393. background: white;
  394. color: black;
  395. }
  396. abbr[title] { border-bottom: 0; }
  397. abbr[title]:after { content: " (" attr(title) ")"; }
  398. img { page-break-inside: avoid; }
  399. @page { margin: 2cm .5cm; }
  400. h1, h2, h3 { page-break-after: avoid; }
  401. p3 { orphans: 3; widows: 3; }
  402. img {
  403. max-width: 250px !important;
  404. max-height: 250px !important;
  405. }
  406. nav, aside { display: none; }
  407. }
  408. /* Dark theme */
  409. [lang=en] body {
  410. background: #323a45;
  411. }
  412. [lang=en] article,
  413. [lang=en] article em,
  414. [lang=en] article strong {
  415. color: #f0f0ea;
  416. }
  417. [lang=en] article a {
  418. color: #ffbd2b;
  419. }
  420. [lang=en] article a:visited {
  421. color: #ff6b03;
  422. }
  423. [lang=en] blockquote,
  424. [lang=en] figure {
  425. background: #111930;
  426. color: #ccc;
  427. }
  428. </style>
  429. <nav>
  430. <p>
  431. <a href="/david/" title="Profil public">David&nbsp;Larlet</a> partage ses <a href="/david/blog/" title="Expériences bienveillantes">réflexions</a> et sa <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a>.
  432. </p>
  433. </nav>
  434. <h1>DNS and privacy</h1>
  435. <time>2018-04-05</time>
  436. <article>
  437. <blockquote>
  438. <p>The problem is that these DNS services are often slow and not privacy respecting. What many Internet users don’t realize is that even if you’re visiting a website that is encrypted — has the little green lock in your browser — that doesn’t keep your DNS resolver from knowing the identity of all the sites you visit. That means, by default, your ISP, every wifi network you’ve connected to, and your mobile network provider have a list of every site you’ve visited while using them.</p>
  439. <p><cite><em><a href="https://blog.cloudflare.com/announcing-1111/">Announcing 1.1.1.1: the fastest, privacy-first consumer DNS service</a></em> (<a href="/david/cache/558df36be2c166357e092d0a774059eb/">cache</a>)</cite></p>
  440. </blockquote>
  441. <p>That’s not the first time I talked about <a href="/david/stream/2015/10/12/">DNS and trust</a>, last time I encouraged you to switch to FDN ones if you are in France. Is there a better alternative three years later? You might be tempted by <a href="https://www.quad9.net/">Quad9</a> which is a not-for-profit organization with <a href="https://www.dnsperf.com/#!dns-resolvers">decent performances</a> and a better presence around the globe (when you have to cross an ocean that makes a difference!) or use a <a href="https://github.com/jedisct1/dnscrypt-proxy">DNS proxy</a> in order to hit multiple DNS services and cover your tracks (there is a <a href="https://github.com/alterstep/dnscrypt-osxclient">macOS client</a>) or even hosting <a href="https://unbound.net/">your own DNS caching</a> service.</p>
  442. <p>But what if the best DNS for privacy is actually no DNS at all?!</p>
  443. <p>The idea is <a href="https://gnunet.org/taxonomy/term/34">not new</a> and there are more recent <a href="https://docs.meshwith.me/">initiatives</a> to <a href="https://github.com/cjdelisle/cjdns/">ease the setup of a mesh network</a>, definitely something to consider for something local. I look forward for your suggestions/experiences!</p>
  444. </article>
  445. <nav>
  446. <p>
  447. <a rel=prev href="/david/stream/2018/04/04/">← Pourquoi</a> | <a href="/david/stream/2018/" title="Retour à la liste complète">↑</a> | <a rel=next href="/david/stream/2018/04/06/">Mind the gap →</a>
  448. </p>
  449. </nav>
  450. <aside>
  451. <p>
  452. Other articles in English:
  453. <a href="/david/blog/2018/caching-links/">On caching links</a>,
  454. <a href="/david/blog/2018/bushcraft-retrospective/">Bushcraft retrospective</a>,
  455. <a href="/david/blog/2018/into-the-raft/">Into the Raft</a>,
  456. <a href="/david/blog/2018/into-the-bugs/">Into the Bugs</a>,
  457. <a href="/david/blog/2018/meritocracy-crisis/">Meritocracy crisis</a>,
  458. <a href="/david/blog/2018/seller-teacher-wise/">The Seller, the Teacher and the Wise</a>,
  459. <a href="/david/blog/2018/into-the-good/">Into the Good</a>,
  460. <a href="/david/blog/2018/into-the-mice/">Into the Mice</a>,
  461. <a href="/david/blog/2018/into-the-camp/">Into the Camp</a>,
  462. <a href="/david/blog/2018/into-the-wind/">Into the Wind</a>,
  463. <a href="/david/blog/2018/into-the-snow/">Into the Snow</a>,
  464. <a href="/david/blog/2018/into-the-cold/">Into the Cold</a>,
  465. <a href="/david/blog/2017/async-python-frameworks/">Async Python Frameworks</a>,
  466. <a href="/david/blog/2017/distributed-teams/">Distributed teams</a>,
  467. <a href="/david/blog/2017/into-the-wild/">Into the Wild</a>,
  468. <a href="/david/blog/2017/without-javascript/">Without JavaScript</a>,
  469. <a href="/david/blog/2017/inclusive-python/">Inclusive Python</a>,
  470. <a href="/david/blog/2017/micro-cultures-governance/">Micro-cultures and governance</a>,
  471. <a href="/david/blog/2017/resilient-web-tools/">Resilient Web and Tools</a>,
  472. <a href="/david/blog/2017/bitcoin-energy/">Bitcoin and energy</a>,
  473. <a href="/david/blog/2016/team-building/">Team building</a>,
  474. <a href="/david/blog/2016/inclusive-developer/">Inclusive developer</a>,
  475. <a href="/david/blog/2016/cultural-intimacy/">Cultural Intimacy</a>,
  476. <a href="/david/blog/2016/tools-teams/">Tools and teams</a>,
  477. <a href="/david/blog/2016/senior-developer/">Senior developer</a>,
  478. <a href="/david/blog/2016/slow-data/">Slow Data</a>,
  479. <a href="/david/blog/2016/inclusive-communities/">Inclusive communities</a>,
  480. <a href="/david/blog/2016/delivery-values/">Delivery and value(s)</a>,
  481. <a href="/david/blog/2016/collaboration-debt/">Collaboration debt</a>,
  482. <a href="/david/blog/2016/communities-leadership/">Communities and leadership</a>,
  483. <a href="/david/blog/2016/specifications-apis/">Specifications and APIs</a>.
  484. Oh, and most of <a href="/david/stream/2018/">the 2018 thoughts</a>.
  485. </p>
  486. </aside>
  487. <nav>
  488. <p>
  489. <abbr title="Lieu de vie et de potentielles rencontres actuel">Montréal</abbr> ·
  490. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">Contact</a> ·
  491. <a href="http://larlet.com" title="Identité professionnelle">[Travailler ensemble ?]</a> ·
  492. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">Hébergeur</abbr> ·
  493. <a href="/david/log/" title="S’abonner aux publications via RSS">Flux</a>
  494. </p>
  495. </nav>
  496. <script>
  497. /* Service workers */
  498. if (navigator.serviceWorker) {
  499. window.addEventListener('load', function () {
  500. var selector = 'a[href^="/david/cache/"], a[rel=prev], a[rel=next]'
  501. function sendLinks (selector) {
  502. var links = [].slice.call(document.querySelectorAll(selector)).map(function (link) {
  503. return link.getAttribute('href')
  504. })
  505. links.push(location.pathname) // Put the current page in cache too.
  506. navigator.serviceWorker.controller.postMessage({ links: links })
  507. }
  508. navigator.serviceWorker.getRegistration()
  509. .then(function (registration) {
  510. if (!registration || !navigator.serviceWorker.controller) {
  511. return navigator.serviceWorker.register('/serviceworker.js')
  512. .then(navigator.serviceWorker.ready)
  513. .then(function () {
  514. console.log('[ServiceWorker] Ready to go!')
  515. })
  516. .catch(console.error.bind(console))
  517. } else {
  518. console.log('[ServiceWorker] Send links via registration')
  519. sendLinks(selector)
  520. }
  521. })
  522. navigator.serviceWorker.addEventListener('controllerchange', function () {
  523. console.log('[ServiceWorker] Send links via controller change')
  524. sendLinks(selector)
  525. })
  526. navigator.serviceWorker.addEventListener('message', function (event) {
  527. var link = document.querySelector('a[href="' + event.data.link + '"]')
  528. if (event.data.status && link) {
  529. link.style.backgroundColor = '#2d7474'
  530. link.style.color = '#f0f0ea'
  531. link.setAttribute('title', 'Put in cache for offline use')
  532. }
  533. })
  534. })
  535. } else {
  536. console.warn('[ServiceWorker] No cache for old browsers.')
  537. }
  538. </script>