A place to cache linked articles (think custom and personal wayback machine)
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

4 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  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,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Whistleblower Says Facebook Ignored Global Political Manipulation (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f0f0ea">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f0f0ea">
  26. <!-- Documented, feel free to shoot an email. -->
  27. <link rel="stylesheet" href="/static/david/css/style_2020-06-19.css">
  28. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  29. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  30. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  31. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <script type="text/javascript">
  36. function toggleTheme(themeName) {
  37. document.documentElement.classList.toggle(
  38. 'forced-dark',
  39. themeName === 'dark'
  40. )
  41. document.documentElement.classList.toggle(
  42. 'forced-light',
  43. themeName === 'light'
  44. )
  45. }
  46. const selectedTheme = localStorage.getItem('theme')
  47. if (selectedTheme !== 'undefined') {
  48. toggleTheme(selectedTheme)
  49. }
  50. </script>
  51. <meta name="robots" content="noindex, nofollow">
  52. <meta content="origin-when-cross-origin" name="referrer">
  53. <!-- Canonical URL for SEO purposes -->
  54. <link rel="canonical" href="https://www.buzzfeednews.com/article/craigsilverman/facebook-ignore-political-manipulation-whistleblower-memo">
  55. <body class="remarkdown h1-underline h2-underline h3-underline hr-center ul-star pre-tick">
  56. <article>
  57. <header>
  58. <h1>Whistleblower Says Facebook Ignored Global Political Manipulation</h1>
  59. </header>
  60. <nav>
  61. <p class="center">
  62. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  63. <a href="https://www.buzzfeednews.com/article/craigsilverman/facebook-ignore-political-manipulation-whistleblower-memo" title="Lien vers le contenu original">Source originale</a>
  64. </p>
  65. </nav>
  66. <hr>
  67. <main>
  68. <p>Facebook ignored or was slow to act on evidence that fake accounts on its platform have been undermining elections and political affairs around the world, according to an explosive memo sent by a recently fired Facebook employee and obtained by BuzzFeed News.</p>
  69. <p>The 6,600-word memo, written by former Facebook data scientist Sophie Zhang, is filled with concrete examples of heads of government and political parties in Azerbaijan and Honduras using fake accounts or misrepresenting themselves to sway public opinion. In countries including India, Ukraine, Spain, Brazil, Bolivia, and Ecuador, she found evidence of coordinated campaigns of varying sizes to boost or hinder political candidates or outcomes, though she did not always conclude who was behind them.</p>
  70. <p>“In the three years I’ve spent at Facebook, I’ve found multiple blatant attempts by foreign national governments to abuse our platform on vast scales to mislead their own citizenry, and caused international news on multiple occasions,” wrote Zhang, who declined to talk to BuzzFeed News. Her LinkedIn profile said she “worked as the data scientist for the Facebook Site Integrity fake engagement team” and dealt with “bots influencing elections and the like.”</p>
  71. <p>“I have personally made decisions that affected national presidents without oversight, and taken action to enforce against so many prominent politicians globally that I’ve lost count,” she wrote.</p>
  72. <p>The memo is a damning account of Facebook’s failures. It’s the story of Facebook abdicating responsibility for malign activities on its platform that could affect the political fate of nations outside the United States or Western Europe. It's also the story of a junior employee wielding extraordinary moderation powers that affected millions of people without any real institutional support, and the personal torment that followed.</p>
  73. <p>“I know that I have blood on my hands by now,” Zhang wrote.</p>
  74. <p><b>These are some of the biggest revelations in Zhang’s memo:</b></p>
  75. <ul><li><i>It took Facebook’s leaders nine months to act on a coordinated campaign “that used thousands of inauthentic assets to boost President Juan Orlando Hernandez of Honduras on a massive scale to mislead the Honduran people.” Two weeks after Facebook took action against the perpetrators in July, they returned, leading to a game of “whack-a-mole” between Zhang and the operatives behind the fake accounts, which are still active.</i></li><li><i>In Azerbaijan, Zhang discovered the ruling political party “utilized thousands of inauthentic assets... to harass the opposition en masse.” Facebook began looking into the issue a year after Zhang reported it. The investigation is ongoing.</i></li><li><i>Zhang and her colleagues removed “10.5 million fake reactions and fans from high-profile politicians in Brazil and the US in the 2018 elections.”</i></li><li><i>In February 2019, a NATO researcher informed Facebook that "he’d obtained Russian inauthentic activity on a high-profile U.S. political figure that we didn’t catch." Zhang removed the activity, “dousing the immediate fire,” she wrote.</i></li><li><i>In Ukraine, Zhang “found inauthentic scripted activity” supporting both former prime minister Yulia Tymoshenko, a pro–European Union politician and former presidential candidate, as well as Volodymyr Groysman, a former prime minister and ally of former president Petro Poroshenko. “Volodymyr Zelensky and his faction was the only major group not affected,” Zhang said of the current Ukrainian president.</i></li><li><i>Zhang discovered inauthentic activity — a Facebook term for engagement from bot accounts and coordinated manual accounts— in Bolivia and Ecuador but chose “not to prioritize it,” due to her workload. The amount of power she had as a mid-level employee to make decisions about a country’s political outcomes took a toll on her health.</i></li><li><i>After becoming aware of coordinated manipulation on the Spanish Health Ministry’s Facebook page during the COVID-19 pandemic, Zhang helped find and remove 672,000 fake accounts “acting on similar targets globally” including in the US.</i></li><li><i>In India, she worked to remove “a politically-sophisticated network of more than a thousand actors working to influence" the local elections taking place in Delhi in February. Facebook never publicly disclosed this network or that it had taken it down.</i></li></ul>
  76. <p>“We’ve built specialized teams, working with leading experts, to stop bad actors from abusing our systems, resulting in the removal of more than 100 networks for coordinated inauthentic behavior," Facebook spokesperson Liz Bourgeois said in a statement. "It’s highly involved work that these teams do as their full-time remit. Working against coordinated inauthentic behavior is our priority, but we’re also addressing the problems of spam and fake engagement. We investigate each issue carefully, including those that Ms. Zhang raises, before we take action or go out and make claims publicly as a company."</p>
  77. <p>BuzzFeed News is not publishing Zhang’s full memo because it contains personal information. This story includes full excerpts when possible to provide appropriate context.</p>
  78. <p>In her post, Zhang said she did not want it to go public for fear of disrupting Facebook’s efforts to prevent problems around the upcoming 2020 US presidential election, and due to concerns about her own safety. BuzzFeed News is publishing parts of her memo that are clearly in the public interest.</p>
  79. <p>“I consider myself to have been put in an impossible spot – caught between my loyalties to the company and my loyalties to the world as a whole,” she said. “The last thing I want to do is distract from our efforts for the upcoming U.S. elections, yet I know this post will likely do so internally.”</p>
  80. <p>Zhang said she turned down a $64,000 severance package from the company to avoid signing a nondisparagement agreement. Doing so allowed her to speak out internally, and she used that freedom to reckon with the power that she had to police political speech.</p>
  81. <p>“There was so much violating behavior worldwide that it was left to my personal assessment of which cases to further investigate, to file tasks, and escalate for prioritization afterwards,” she wrote.</p>
  82. <p>That power contrasted with what she said seemed to be a lack of desire from senior leadership to protect democratic processes in smaller countries. Facebook, Zhang said, prioritized regions including the US and Western Europe, and often only acted when she repeatedly pressed the issue publicly in comments on Workplace, the company’s internal, employee-only message board.</p>
  83. <p>“With no oversight whatsoever, I was left in a situation where I was trusted with immense influence in my spare time,” she wrote. “A manager on Strategic Response mused to myself that most of the world outside the West was effectively the Wild West with myself as the part-time dictator – he meant the statement as a compliment, but it illustrated the immense pressures upon me.”</p>
  84. <p>A former Facebook engineer who knew her told BuzzFeed News that Zhang was skilled at discovering fake account networks on the platform.</p>
  85. <p>“She's the only person in this entire field at Facebook that I ever trusted to be earnest about this work," said the engineer, who had seen a copy of Zhang’s post and asked not to be named because they no longer work at the company.</p>
  86. <p>“A lot of what I learned from that post was shocking even to me as someone who's often been disappointed at how the company treats its best people," they said.</p>
  87. <p>Zhang’s memo said the lack of institutional support and heavy stakes left her unable to sleep. She often felt responsible when civil unrest took hold in places she didn’t prioritize for investigation and action.</p>
  88. <p>“I have made countless decisions in this vein – from Iraq to Indonesia, from Italy to El Salvador,” she wrote. “Individually, the impact was likely small in each case, but the world is a vast place.”</p>
  89. <p>Still, she did not believe that the failures she observed during her two and a half years at the company were the result of bad intent by Facebook’s employees or leadership. It was a lack of resources, Zhang wrote, and the company’s tendency to focus on global activity that posed public relations risks, as opposed to electoral or civic harm.</p>
  90. <p>“Facebook projects an image of strength and competence to the outside world that can lend itself to such theories, but the reality is that many of our actions are slapdash and haphazard accidents,” she wrote.</p>
  91. <h2>“We simply didn’t care enough to stop them”</h2>
  92. <p>Zhang wrote that she was just six months into the job when she found coordinated inauthentic behavior — Facebook’s internal term for the use of multiple fake accounts to boost engagement or spread content — benefiting Honduran President Juan Orlando Hernández.</p>
  93. <p>The connection to the Honduran leader was made, Zhang said, because an administrator for the president’s Facebook page had been “happily running hundreds of these fake assets without any obfuscation whatsoever in a show of extreme chutzpah.” The data scientist said she reported the operation, which involved thousands of fake accounts, to Facebook’s threat intelligence and policy review teams, both of which took months to act.</p>
  94. <p>“Local policy teams confirmed that President JOH’s marketing team had openly admitted to organizing the activity on his behalf,” she wrote. “Yet despite the blatantly violating nature of this activity, it took me almost a year to take down his operation.”</p>
  95. <p>That takedown was <a href="https://about.fb.com/news/2019/07/removing-cib-thailand-russia-ukraine-honduras/" target="_blank">announced by Facebook in July 2019</a>, but proved futile. Soon, the operation was soon back up and running, a fact Facebook has never disclosed.</p>
  96. <p>“They had returned within two weeks of our takedown and were back in a similar volume of users,” Zhang wrote, adding that she did a final sweep for the fake accounts on her last day at Facebook. “A year after our takedown, the activity is still live and well.”</p>
  97. <p>In Azerbaijan, she found a large network of inauthentic accounts used to attack opponents of President Ilham Aliyev of Azerbaijan and his ruling New Azerbaijan Party, which uses the acronym YAP. Facebook still has not disclosed the influence campaign, according to Zhang.</p>
  98. <p>The operation detailed in the memo is reminiscent of those of Russia’s Internet Research Agency, a private troll farm that tried to influence the 2016 US elections, because it involved “dedicated employees who worked 9-6 Monday-Friday work weeks to create millions of comments” targeting members of the opposition and media reports seen as negative to Aliyev.</p>
  99. <p>“Multiple official accounts for district-level divisions of the ruling YAP political party directly controlled numerous of these fake assets without any obfuscation whatsoever in another display of arrogance,” she wrote. “Perhaps they thought they were clever; the truth was, we simply didn’t care enough to stop them.”</p>
  100. <p>Katy Pearce, an associate professor at the University of Washington who studies social media and communication technology in Azerbaijan, told BuzzFeed News that fake Facebook accounts have been used to undermine the opposition and independent media in the country for years.</p>
  101. <p>“One of the big tools of authoritarian regimes is to humiliate the opposition in the mind of the public so that they're not viewed as a credible or legitimate alternative,” she told BuzzFeed News. “There's a chilling effect. Why would I post something if I know that I'm going to deal with thousands or hundreds of these comments, that I'm going to be targeted?”</p>
  102. <p>Pearce said Zhang’s comment in the memo that Facebook “didn’t care enough to stop” the fake accounts and trolling aligns with her experience. “They have bigger fish to fry,” she said.</p>
  103. <p>A person who managed social media accounts for news organizations in Azerbaijan told BuzzFeed News that their pages were inundated with inauthentic Facebook comments.</p>
  104. <p>“We used to delete and ban them because we didn’t want people who came to our page to be discouraged and not react or comment,” said the person, who asked not to be named because they were not authorized to speak for their employer. “But since [the trolls] are employees, it’s easy for them to open new accounts.”</p>
  105. <p>They said Facebook has at times made things worse by removing the accounts or pages of human rights activists and other people after trolls report them. “We tried to tell Facebook that this is a real person who does important work,” but it took weeks for the page to be restored.</p>
  106. <p>Zhang wrote that a Facebook investigation into fake accounts and trolling in Azerbaijan is now underway, more than a year after she first reported the issue. On the day of her departure, she called it her “greatest unfinished business” to stop the fake behavior in the country.</p>
  107. <p>“Many others would think nothing of myself devoting this attention to the United States, but are shocked to see myself fighting for these small countries,” she wrote. “To put it simply, my methodologies were systematic globally, and I fought for Honduras and Azerbaijan because that was where I saw the most ongoing harm.”</p>
  108. <h2>“I have blood on my hands”</h2>
  109. <p>In other examples, Zhang revealed new information about a large-scale fake account network used to amplify and manipulate information about COVID-19, as well as a political influence operation that used fake accounts to influence 2018 elections in the US and Brazil. Some of these details were not previously disclosed by Facebook, suggesting the company’s regular takedown announcements remain selective and incomplete.</p>
  110. <p>Zhang said Facebook removed 672,000 “low-quality fake accounts” after <a href="https://www.euronews.com/2020/04/24/facebook-investigates-fake-accounts-sharing-spanish-government-content-thecube" target="_blank">press reports in April</a> that some of the accounts had been engaging with COVID-19 content on the Spanish Health Ministry’s page. She said accounts in that network also engaged with content on US pages. Facebook did not disclose how many accounts it removed, or that those accounts engaged with content in other countries, including the US.</p>
  111. <p>Zhang also shared new details about the scale of inauthentic activity during the 2018 midterm elections in the US, and from Brazilian politicians that same year. “We ended up removing 10.5 million fake reactions and fans from high-profile politicians in Brazil and the U.S. in the 2018 elections – major politicians of all persuasions in Brazil, and a number of lower-level politicians in the United States,” she wrote.</p>
  112. <p>A <a href="https://about.fb.com/news/2018/09/us-brazil-elections/" target="_blank">September 2018 briefing</a> about Facebook’s election work in the US and Brazil disclosed that it had acted against a network in Brazil that used “fake accounts to sow division and share disinformation,” as well as a set of groups, pages, and accounts that were “falsely amplifying engagement for financial gain.” It did not fully mention Zhang's findings.</p>
  113. <p>The scale of this activity — 672,000 fake accounts in one network, 10.5 million fake engagement and fans in others — indicates <a href="https://www.buzzfeednews.com/article/craigsilverman/facebook-fake-accounts-afd" target="_blank">active fake accounts are a global problem</a>, and are used to manipulate elections and public debate around the world.</p>
  114. <p>As one of the few people looking for and identifying fake accounts impacting civic activity outside of “priority” regions, Zhang struggled with the power she had been handed.</p>
  115. <p>“We focus upon harm and priority regions like the United States and Western Europe,” Zhang wrote, adding that “it became impossible to read the news and monitor world events without feeling the weight of my own responsibility.”</p>
  116. <p>In Bolivia, Zhang said she found “inauthentic activity supporting the opposition presidential candidate in 2019” and chose not to prioritize it. Months later, Bolivian politics fell into turmoil, leading to the resignation of President Evo Morales and “mass protests leading to dozens of deaths.”</p>
  117. <p>The same happened in Ecuador, according to Zhang, who “found inauthentic activity supporting the ruling government… and made the decision not to prioritize it.” The former Facebook employee then wondered how her decision led to downstream effects on how Ecuador’s government handled the COVID-19 pandemic — which has <a href="https://www.buzzfeednews.com/article/karlazabludovsky/guayaquil-ecuador-coronavirus-missing-bodies" target="_blank">devastated the country</a> — and if that would have been different if she'd acted.</p>
  118. <p>“I have made countless decisions in this vein – from Iraq to Indonesia, from Italy to El Salvador. Individually, the impact was likely small in each case, but the world is a vast place. Although I made the best decision I could based on the knowledge available at the time, ultimately I was the one who made the decision not to push more or prioritize further in each case, and I know that I have blood on my hands by now.”</p>
  119. <p>Zhang also uncovered issues in India, Facebook’s largest market, in the lead up to the local Delhi elections in February 2020. “I worked through sickness to take down a politically-sophisticated network of more than a thousand actors working to influence the election,” she wrote.</p>
  120. <p>Last month, Facebook’s Indian operation came under scrutiny after <a href="https://www.wsj.com/articles/facebook-hate-speech-india-politics-muslim-hindu-modi-zuckerberg-11597423346" target="_blank">reports</a> in the Wall Street Journal revealed a top policy executive in the country had stopped local staffers from applying the company’s hate speech policies to ruling party politicians who posted anti-Muslim hate speech.</p>
  121. <h2>“Haphazard Accidents”</h2>
  122. <p>In her “spare time” in 2019, Zhang took on tasks usually reserved for product managers and investigators, searching out countries including Ukraine, Turkey, India, Indonesia, the Philippines, Australia, the United Kingdom, Taiwan, “and many many more.”</p>
  123. <p>Zhang said she found and took down “inauthentic scripted activity” in Ukraine that supported Yulia Tymoshenko, a complicated political figure who has been involved in controversial gas deals with Russia but taken a more pro-Western tack in her later career, as well as for former prime minister Volodymyr Groysman, an ally of former president Petro Poroshenko. “Volodymyr Zelensky and his faction was the only major group not affected,” she wrote.</p>
  124. <p>In another part of her memo, Zhang said she wanted to push back on the idea that Facebook was run by malicious people hoping to achieve a particular outcome. That was not the case, she wrote, attributing actions to “slapdash and haphazard accidents.”</p>
  125. <p>“Last year when we blocked users from naming the Ukraine whistleblower, we forgot to cover hashtags until I stepped in,” she wrote.</p>
  126. <p>But she also remarked on Facebook’s habit of <a href="https://www.buzzfeednews.com/article/ryanmac/facebook-privacy-optics-clear-history-zuckerberg" target="_blank">prioritizing public relations over real-world problems</a>. “It’s an open secret within the civic integrity space that Facebook’s short-term decisions are largely motivated by PR and the potential for negative attention,” she wrote, noting that she was told directly at a 2020 summit that anything published in the New York Times or Washington Post would obtain elevated priority.</p>
  127. <p>“It’s why I’ve seen priorities of escalations shoot up when others start threatening to go to the press, and why I was informed by a leader in my organization that my civic work was not impactful under the rationale that if the problems were meaningful they would have attracted attention, became a press fire, and convinced the company to devote more attention to the space.”</p>
  128. <p>Zhang mentioned one example in February 2019, when a NATO strategic communications researcher reached out to Facebook, alerting the company that <a href="https://www.buzzfeednews.com/article/albertonardelli/facebook-twitter-google-manipulation-nato-stratcom" target="_blank">he'd "obtained" Russian inauthentic activity</a> “on a high-profile U.S. political figure that we didn’t catch.” That researcher said they were planning on briefing Congress the next day.<br/></p>
  129. <p>“I quickly investigated the case, determined what was going on, and removed the activity, dousing the immediate fire,” Zhang wrote. “Perhaps motivated by the experience, the same researcher tried the same experiment within a month or two, waiting half a year afterwards before sending the report to the press and finally causing the PR fire.”</p>
  130. <h2>“Human Resources Are Limited”</h2>
  131. <p>Beyond specific examples from around the world, Zhang provided insight into the inner workings at Facebook. She criticized her team’s focus on issues related to “99% of activity that’s essentially spam.”</p>
  132. <p>“Overall, the focus of my organization – and most of Facebook – was on large-scale problems, an approach which fixated us on spam,” she said. “The civic aspect was discounted because of its small volume, its disproportionate impact ignored.”</p>
  133. <p>Zhang outlined the political processes within Facebook itself. She said the best way for her to gain attention for her work was not to go through the proper reporting channels, but to post about the issues on Facebook’s internal employee message board to build pressure.</p>
  134. <p>“In the office, I realized that my viewpoints weren’t respected unless I acted like an arrogant asshole,” Zhang said.</p>
  135. <p>When she asked the company to do more in terms of finding and stopping malicious activity related to elections and political activity, she said she was told that “human resources are limited.” And when she was ordered to stop focusing on civic work, “I was told that Facebook would no longer have further need for my services if I refused.”</p>
  136. <p>Zhang was fired this month and posted her memo on her last day, even after offering to stay on through the election as an unpaid volunteer. In her goodbye, she encouraged her colleagues to remain at Facebook and to fix the company from within.</p>
  137. <p>“But you don’t – and shouldn’t – need to do it alone,” she wrote. “Find others who share your convictions and values to work on it together. Facebook is too big of a project for any one person to fix.” ●</p>
  138. </main>
  139. </article>
  140. <hr>
  141. <footer>
  142. <p>
  143. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  144. <a href="/david/log/" title="Accès au flux RSS">🤖</a> •
  145. <a href="http://larlet.com" title="Go to my English profile" data-instant>🇨🇦</a> •
  146. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">📮</a> •
  147. <abbr title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340">🧚</abbr>
  148. </p>
  149. <template id="theme-selector">
  150. <form>
  151. <fieldset>
  152. <legend>Thème</legend>
  153. <label>
  154. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  155. </label>
  156. <label>
  157. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  158. </label>
  159. <label>
  160. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  161. </label>
  162. </fieldset>
  163. </form>
  164. </template>
  165. </footer>
  166. <script type="text/javascript">
  167. function loadThemeForm(templateName) {
  168. const themeSelectorTemplate = document.querySelector(templateName)
  169. const form = themeSelectorTemplate.content.firstElementChild
  170. themeSelectorTemplate.replaceWith(form)
  171. form.addEventListener('change', (e) => {
  172. const chosenColorScheme = e.target.value
  173. localStorage.setItem('theme', chosenColorScheme)
  174. toggleTheme(chosenColorScheme)
  175. })
  176. const selectedTheme = localStorage.getItem('theme')
  177. if (selectedTheme && selectedTheme !== 'undefined') {
  178. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  179. }
  180. }
  181. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  182. window.addEventListener('load', () => {
  183. let hasDarkRules = false
  184. for (const styleSheet of Array.from(document.styleSheets)) {
  185. let mediaRules = []
  186. for (const cssRule of styleSheet.cssRules) {
  187. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  188. continue
  189. }
  190. // WARNING: Safari does not have/supports `conditionText`.
  191. if (cssRule.conditionText) {
  192. if (cssRule.conditionText !== prefersColorSchemeDark) {
  193. continue
  194. }
  195. } else {
  196. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  197. continue
  198. }
  199. }
  200. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  201. }
  202. // WARNING: do not try to insert a Rule to a styleSheet you are
  203. // currently iterating on, otherwise the browser will be stuck
  204. // in a infinite loop…
  205. for (const mediaRule of mediaRules) {
  206. styleSheet.insertRule(mediaRule.cssText)
  207. hasDarkRules = true
  208. }
  209. }
  210. if (hasDarkRules) {
  211. loadThemeForm('#theme-selector')
  212. }
  213. })
  214. </script>
  215. </body>
  216. </html>