pressoir 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. pressoir/__init__.py +4 -0
  2. pressoir/__main__.py +3 -0
  3. pressoir/additionals.py +119 -0
  4. pressoir/cli.py +133 -0
  5. pressoir/docs/pressoir/book.toml +17 -0
  6. pressoir/docs/pressoir/static/css/custom.css +294 -0
  7. pressoir/docs/pressoir/static/css/fonts.css +16 -0
  8. pressoir/docs/pressoir/static/css/vars.css +33 -0
  9. pressoir/docs/pressoir/static/fonts/averialibre-bold.woff +0 -0
  10. pressoir/docs/pressoir/static/fonts/averialibre-bold.woff2 +0 -0
  11. pressoir/docs/pressoir/static/fonts/averiaseriflibre-light.woff +0 -0
  12. pressoir/docs/pressoir/static/fonts/averiaseriflibre-light.woff2 +0 -0
  13. pressoir/docs/pressoir/static/img/pressoir-logo.png +0 -0
  14. pressoir/docs/pressoir/static/svg/minus.svg +1 -0
  15. pressoir/docs/pressoir/static/svg/parcours-numeriques.png +0 -0
  16. pressoir/docs/pressoir/static/svg/personnalite.svg +1 -0
  17. pressoir/docs/pressoir/static/svg/plus.svg +1 -0
  18. pressoir/docs/pressoir/static/svg/pum-logo-couleur.svg +101 -0
  19. pressoir/docs/pressoir/static/svg/pum-logo-noir.svg +101 -0
  20. pressoir/docs/pressoir/static/svg/quote.svg +1 -0
  21. pressoir/docs/textes/bibliographie/bibliographie.bib +148 -0
  22. pressoir/docs/textes/bibliographie/bibliographie.md +1 -0
  23. pressoir/docs/textes/bibliographie/bibliographie.yaml +85 -0
  24. pressoir/docs/textes/chapitre1/additionnels.md +51 -0
  25. pressoir/docs/textes/chapitre1/chapitre1.bib +0 -0
  26. pressoir/docs/textes/chapitre1/chapitre1.md +114 -0
  27. pressoir/docs/textes/chapitre1/chapitre1.yaml +84 -0
  28. pressoir/docs/textes/chapitre2/additionnels.md +382 -0
  29. pressoir/docs/textes/chapitre2/chapitre2.bib +0 -0
  30. pressoir/docs/textes/chapitre2/chapitre2.md +163 -0
  31. pressoir/docs/textes/chapitre2/chapitre2.yaml +84 -0
  32. pressoir/docs/textes/chapitre3/additionnels.md +149 -0
  33. pressoir/docs/textes/chapitre3/chapitre3.bib +0 -0
  34. pressoir/docs/textes/chapitre3/chapitre3.md +79 -0
  35. pressoir/docs/textes/chapitre3/chapitre3.yaml +84 -0
  36. pressoir/docs/textes/chapitre4/additionnels.md +287 -0
  37. pressoir/docs/textes/chapitre4/chapitre4.bib +0 -0
  38. pressoir/docs/textes/chapitre4/chapitre4.md +380 -0
  39. pressoir/docs/textes/chapitre4/chapitre4.yaml +84 -0
  40. pressoir/docs/textes/faq/additionnels.md +0 -0
  41. pressoir/docs/textes/faq/faq.bib +32 -0
  42. pressoir/docs/textes/faq/faq.md +273 -0
  43. pressoir/docs/textes/faq/faq.yaml +84 -0
  44. pressoir/docs/textes/garde/homepage.md +11 -0
  45. pressoir/docs/textes/garde/livre.yaml +141 -0
  46. pressoir/docs/textes/index-np/index-np.bib +0 -0
  47. pressoir/docs/textes/index-np/index-np.md +5 -0
  48. pressoir/docs/textes/index-np/index-np.yaml +80 -0
  49. pressoir/docs/textes/introduction/additionnels.md +24 -0
  50. pressoir/docs/textes/introduction/introduction.bib +15 -0
  51. pressoir/docs/textes/introduction/introduction.md +81 -0
  52. pressoir/docs/textes/introduction/introduction.yaml +84 -0
  53. pressoir/docs/textes/media/BlocDeCitationFIA.png +0 -0
  54. pressoir/docs/textes/media/ExemplePictogrammesBalise.png +0 -0
  55. pressoir/docs/textes/media/PictoHypothesis.png +0 -0
  56. pressoir/docs/textes/media/couv.png +0 -0
  57. pressoir/docs/textes/media/imagelivre.jpeg +0 -0
  58. pressoir/docs/textes/media/volet-index.png +0 -0
  59. pressoir/generator.py +159 -0
  60. pressoir/indexes.py +133 -0
  61. pressoir/init/blank/pressoir/book.toml +17 -0
  62. pressoir/init/blank/pressoir/static/css/custom.css +292 -0
  63. pressoir/init/blank/pressoir/static/css/fonts.css +16 -0
  64. pressoir/init/blank/pressoir/static/css/vars.css +33 -0
  65. pressoir/init/blank/pressoir/static/fonts/averialibre-bold.woff +0 -0
  66. pressoir/init/blank/pressoir/static/fonts/averialibre-bold.woff2 +0 -0
  67. pressoir/init/blank/pressoir/static/fonts/averiaseriflibre-light.woff +0 -0
  68. pressoir/init/blank/pressoir/static/fonts/averiaseriflibre-light.woff2 +0 -0
  69. pressoir/init/blank/pressoir/static/img/pressoir-logo.png +0 -0
  70. pressoir/init/blank/pressoir/static/svg/minus.svg +1 -0
  71. pressoir/init/blank/pressoir/static/svg/parcours-numeriques.png +0 -0
  72. pressoir/init/blank/pressoir/static/svg/personnalite.svg +1 -0
  73. pressoir/init/blank/pressoir/static/svg/plus.svg +1 -0
  74. pressoir/init/blank/pressoir/static/svg/pum-logo-couleur.svg +101 -0
  75. pressoir/init/blank/pressoir/static/svg/pum-logo-noir.svg +101 -0
  76. pressoir/init/blank/pressoir/static/svg/quote.svg +1 -0
  77. pressoir/init/blank/textes/bibliographie/bibliographie.bib +125 -0
  78. pressoir/init/blank/textes/bibliographie/bibliographie.md +1 -0
  79. pressoir/init/blank/textes/bibliographie/bibliographie.yaml +19 -0
  80. pressoir/init/blank/textes/chapitre1/additionnels.md +82 -0
  81. pressoir/init/blank/textes/chapitre1/chapitre1.bib +60 -0
  82. pressoir/init/blank/textes/chapitre1/chapitre1.md +48 -0
  83. pressoir/init/blank/textes/chapitre1/chapitre1.yaml +17 -0
  84. pressoir/init/blank/textes/chapitre2/additionnels.md +83 -0
  85. pressoir/init/blank/textes/chapitre2/chapitre2.bib +0 -0
  86. pressoir/init/blank/textes/chapitre2/chapitre2.md +28 -0
  87. pressoir/init/blank/textes/chapitre2/chapitre2.yaml +23 -0
  88. pressoir/init/blank/textes/chapitre3/additionnels.md +83 -0
  89. pressoir/init/blank/textes/chapitre3/chapitre3.bib +0 -0
  90. pressoir/init/blank/textes/chapitre3/chapitre3.md +24 -0
  91. pressoir/init/blank/textes/chapitre3/chapitre3.yaml +23 -0
  92. pressoir/init/blank/textes/chapitre4/additionnels.md +83 -0
  93. pressoir/init/blank/textes/chapitre4/chapitre4.bib +0 -0
  94. pressoir/init/blank/textes/chapitre4/chapitre4.md +24 -0
  95. pressoir/init/blank/textes/chapitre4/chapitre4.yaml +23 -0
  96. pressoir/init/blank/textes/chapitre5/additionnels.md +83 -0
  97. pressoir/init/blank/textes/chapitre5/chapitre5.bib +0 -0
  98. pressoir/init/blank/textes/chapitre5/chapitre5.md +24 -0
  99. pressoir/init/blank/textes/chapitre5/chapitre5.yaml +23 -0
  100. pressoir/init/blank/textes/conclusion/additionnels.md +23 -0
  101. pressoir/init/blank/textes/conclusion/conclusion.bib +30 -0
  102. pressoir/init/blank/textes/conclusion/conclusion.md +31 -0
  103. pressoir/init/blank/textes/conclusion/conclusion.yaml +15 -0
  104. pressoir/init/blank/textes/garde/homepage.md +1 -0
  105. pressoir/init/blank/textes/garde/livre.yaml +92 -0
  106. pressoir/init/blank/textes/index-np/index-np.bib +0 -0
  107. pressoir/init/blank/textes/index-np/index-np.md +5 -0
  108. pressoir/init/blank/textes/index-np/index-np.yaml +18 -0
  109. pressoir/init/blank/textes/introduction/additionnels.md +98 -0
  110. pressoir/init/blank/textes/introduction/introduction.bib +40 -0
  111. pressoir/init/blank/textes/introduction/introduction.md +84 -0
  112. pressoir/init/blank/textes/introduction/introduction.yaml +22 -0
  113. pressoir/init/blank/textes/media/imagelivre.jpeg +0 -0
  114. pressoir/init/pum/doc/documentation.md +5 -0
  115. pressoir/init/pum/doc/journal.md +3 -0
  116. pressoir/init/pum/pressoir/book.toml +20 -0
  117. pressoir/init/pum/pressoir/static/css/custom.css +297 -0
  118. pressoir/init/pum/pressoir/static/css/fonts.css +39 -0
  119. pressoir/init/pum/pressoir/static/css/vars.css +32 -0
  120. pressoir/init/pum/pressoir/static/fonts/Montserrat-Bold.woff +0 -0
  121. pressoir/init/pum/pressoir/static/fonts/Montserrat-Bold.woff2 +0 -0
  122. pressoir/init/pum/pressoir/static/fonts/Montserrat-Italic.woff +0 -0
  123. pressoir/init/pum/pressoir/static/fonts/Montserrat-Italic.woff2 +0 -0
  124. pressoir/init/pum/pressoir/static/fonts/Montserrat-Medium.woff +0 -0
  125. pressoir/init/pum/pressoir/static/fonts/Montserrat-Medium.woff2 +0 -0
  126. pressoir/init/pum/pressoir/static/fonts/Montserrat-Regular.woff +0 -0
  127. pressoir/init/pum/pressoir/static/fonts/Montserrat-Regular.woff2 +0 -0
  128. pressoir/init/pum/pressoir/static/img/adophobie.jpg +0 -0
  129. pressoir/init/pum/pressoir/static/img/adophobie_pattern.jpg +0 -0
  130. pressoir/init/pum/pressoir/static/img/ameetipad.jpg +0 -0
  131. pressoir/init/pum/pressoir/static/img/ameetipad_pattern.jpg +0 -0
  132. pressoir/init/pum/pressoir/static/img/experimenterleshumanitesnumeriques.jpg +0 -0
  133. pressoir/init/pum/pressoir/static/img/experimenterleshumanitesnumeriques_pattern.jpg +0 -0
  134. pressoir/init/pum/pressoir/static/img/lesmoocs.jpg +0 -0
  135. pressoir/init/pum/pressoir/static/img/lesmoocs_pattern.jpg +0 -0
  136. pressoir/init/pum/pressoir/static/img/logo-crihn.png +0 -0
  137. pressoir/init/pum/pressoir/static/img/logo-ecritures-numeriques.png +0 -0
  138. pressoir/init/pum/pressoir/static/img/memoiresaudiovisuelles.jpg +0 -0
  139. pressoir/init/pum/pressoir/static/img/memoiresaudiovisuelles_pattern.jpg +0 -0
  140. pressoir/init/pum/pressoir/static/img/pratiques.jpg +0 -0
  141. pressoir/init/pum/pressoir/static/img/pratiques_pattern.jpg +0 -0
  142. pressoir/init/pum/pressoir/static/img/surveilleretsourire.jpg +0 -0
  143. pressoir/init/pum/pressoir/static/img/surveilleretsourire_pattern.jpg +0 -0
  144. pressoir/init/pum/pressoir/static/img/tousartistes.jpg +0 -0
  145. pressoir/init/pum/pressoir/static/img/tousartistes_pattern.jpg +0 -0
  146. pressoir/init/pum/pressoir/static/img/virusparasitesetordinateurs.jpg +0 -0
  147. pressoir/init/pum/pressoir/static/img/virusparasitesetordinateurs_pattern.jpg +0 -0
  148. pressoir/init/pum/pressoir/static/svg/minus.svg +1 -0
  149. pressoir/init/pum/pressoir/static/svg/parcours-numeriques.png +0 -0
  150. pressoir/init/pum/pressoir/static/svg/plus.svg +1 -0
  151. pressoir/init/pum/pressoir/static/svg/pum-logo-couleur.svg +101 -0
  152. pressoir/init/pum/pressoir/static/svg/pum-logo-noir.svg +101 -0
  153. pressoir/init/pum/pressoir/static/svg/quote.svg +1 -0
  154. pressoir/init/pum/textes/bibliographie/bibliographie.bib +0 -0
  155. pressoir/init/pum/textes/bibliographie/bibliographie.md +1 -0
  156. pressoir/init/pum/textes/bibliographie/bibliographie.yaml +13 -0
  157. pressoir/init/pum/textes/chapitre1/additionnels.md +19 -0
  158. pressoir/init/pum/textes/chapitre1/chapitre1.bib +0 -0
  159. pressoir/init/pum/textes/chapitre1/chapitre1.md +8 -0
  160. pressoir/init/pum/textes/chapitre1/chapitre1.yaml +14 -0
  161. pressoir/init/pum/textes/chapitre2/additionnels.md +19 -0
  162. pressoir/init/pum/textes/chapitre2/chapitre2.bib +0 -0
  163. pressoir/init/pum/textes/chapitre2/chapitre2.md +8 -0
  164. pressoir/init/pum/textes/chapitre2/chapitre2.yaml +14 -0
  165. pressoir/init/pum/textes/chapitre3/additionnels.md +19 -0
  166. pressoir/init/pum/textes/chapitre3/chapitre3.bib +0 -0
  167. pressoir/init/pum/textes/chapitre3/chapitre3.md +7 -0
  168. pressoir/init/pum/textes/chapitre3/chapitre3.yaml +14 -0
  169. pressoir/init/pum/textes/chapitre4/additionnels.md +19 -0
  170. pressoir/init/pum/textes/chapitre4/chapitre4.bib +0 -0
  171. pressoir/init/pum/textes/chapitre4/chapitre4.md +5 -0
  172. pressoir/init/pum/textes/chapitre4/chapitre4.yaml +14 -0
  173. pressoir/init/pum/textes/chapitre5/additionnels.md +19 -0
  174. pressoir/init/pum/textes/chapitre5/chapitre5.bib +0 -0
  175. pressoir/init/pum/textes/chapitre5/chapitre5.md +5 -0
  176. pressoir/init/pum/textes/chapitre5/chapitre5.yaml +14 -0
  177. pressoir/init/pum/textes/chapitreadd/additionnels.md +19 -0
  178. pressoir/init/pum/textes/chapitreadd/chapitreadd.bib +0 -0
  179. pressoir/init/pum/textes/chapitreadd/chapitreadd.md +3 -0
  180. pressoir/init/pum/textes/chapitreadd/chapitreadd.yaml +14 -0
  181. pressoir/init/pum/textes/conclusion/additionnels.md +19 -0
  182. pressoir/init/pum/textes/conclusion/conclusion.bib +1 -0
  183. pressoir/init/pum/textes/conclusion/conclusion.md +7 -0
  184. pressoir/init/pum/textes/conclusion/conclusion.yaml +14 -0
  185. pressoir/init/pum/textes/garde/livre.yaml +74 -0
  186. pressoir/init/pum/textes/index-np/index-np.bib +0 -0
  187. pressoir/init/pum/textes/index-np/index-np.md +3 -0
  188. pressoir/init/pum/textes/index-np/index-np.yaml +17 -0
  189. pressoir/init/pum/textes/introduction/additionnels.md +19 -0
  190. pressoir/init/pum/textes/introduction/introduction.bib +0 -0
  191. pressoir/init/pum/textes/introduction/introduction.md +8 -0
  192. pressoir/init/pum/textes/introduction/introduction.yaml +17 -0
  193. pressoir/init/pum/textes/media/imagelivre.jpeg +0 -0
  194. pressoir/init/sp/doc/documentation.md +5 -0
  195. pressoir/init/sp/doc/journal.md +3 -0
  196. pressoir/init/sp/pressoir/book.toml +29 -0
  197. pressoir/init/sp/pressoir/static/css/custom.css +196 -0
  198. pressoir/init/sp/pressoir/static/css/fonts.css +31 -0
  199. pressoir/init/sp/pressoir/static/css/vars.css +35 -0
  200. pressoir/init/sp/pressoir/static/fonts/jannon10pro-bold.woff +0 -0
  201. pressoir/init/sp/pressoir/static/fonts/jannon10pro-bold.woff2 +0 -0
  202. pressoir/init/sp/pressoir/static/fonts/jannon10pro-italic.woff +0 -0
  203. pressoir/init/sp/pressoir/static/fonts/jannon10pro-italic.woff2 +0 -0
  204. pressoir/init/sp/pressoir/static/fonts/jannon10pro.woff +0 -0
  205. pressoir/init/sp/pressoir/static/fonts/jannon10pro.woff2 +0 -0
  206. pressoir/init/sp/pressoir/static/js/custom.js +45 -0
  207. pressoir/init/sp/pressoir/static/svg/conceptCR.svg +1 -0
  208. pressoir/init/sp/pressoir/static/svg/conceptEX.svg +1 -0
  209. pressoir/init/sp/pressoir/static/svg/dispositif.svg +1 -0
  210. pressoir/init/sp/pressoir/static/svg/logo_ateliersSP-short_chemin.svg +9 -0
  211. pressoir/init/sp/pressoir/static/svg/minus-reversed.svg +1 -0
  212. pressoir/init/sp/pressoir/static/svg/minus.svg +1 -0
  213. pressoir/init/sp/pressoir/static/svg/personnalite.svg +1 -0
  214. pressoir/init/sp/pressoir/static/svg/plus-reversed.svg +1 -0
  215. pressoir/init/sp/pressoir/static/svg/plus.svg +1 -0
  216. pressoir/init/sp/pressoir/static/svg/sp_logo_acronyme.svg +22 -0
  217. pressoir/init/sp/pressoir/static/svg/user-circle.svg +1 -0
  218. pressoir/init/sp/textes/bibliographie/bibliographie.bib +0 -0
  219. pressoir/init/sp/textes/bibliographie/bibliographie.md +1 -0
  220. pressoir/init/sp/textes/bibliographie/bibliographie.yaml +13 -0
  221. pressoir/init/sp/textes/chapitre1/additionnels.md +19 -0
  222. pressoir/init/sp/textes/chapitre1/chapitre1.bib +0 -0
  223. pressoir/init/sp/textes/chapitre1/chapitre1.md +8 -0
  224. pressoir/init/sp/textes/chapitre1/chapitre1.yaml +14 -0
  225. pressoir/init/sp/textes/chapitre2/additionnels.md +19 -0
  226. pressoir/init/sp/textes/chapitre2/chapitre2.bib +0 -0
  227. pressoir/init/sp/textes/chapitre2/chapitre2.md +8 -0
  228. pressoir/init/sp/textes/chapitre2/chapitre2.yaml +14 -0
  229. pressoir/init/sp/textes/chapitre3/additionnels.md +19 -0
  230. pressoir/init/sp/textes/chapitre3/chapitre3.bib +0 -0
  231. pressoir/init/sp/textes/chapitre3/chapitre3.md +7 -0
  232. pressoir/init/sp/textes/chapitre3/chapitre3.yaml +14 -0
  233. pressoir/init/sp/textes/chapitre4/additionnels.md +19 -0
  234. pressoir/init/sp/textes/chapitre4/chapitre4.bib +0 -0
  235. pressoir/init/sp/textes/chapitre4/chapitre4.md +5 -0
  236. pressoir/init/sp/textes/chapitre4/chapitre4.yaml +14 -0
  237. pressoir/init/sp/textes/chapitre5/additionnels.md +19 -0
  238. pressoir/init/sp/textes/chapitre5/chapitre5.bib +0 -0
  239. pressoir/init/sp/textes/chapitre5/chapitre5.md +5 -0
  240. pressoir/init/sp/textes/chapitre5/chapitre5.yaml +14 -0
  241. pressoir/init/sp/textes/colophon/colophon.bib +0 -0
  242. pressoir/init/sp/textes/colophon/colophon.md +29 -0
  243. pressoir/init/sp/textes/colophon/colophon.yaml +14 -0
  244. pressoir/init/sp/textes/conclusion/additionnels.md +19 -0
  245. pressoir/init/sp/textes/conclusion/conclusion.bib +1 -0
  246. pressoir/init/sp/textes/conclusion/conclusion.md +7 -0
  247. pressoir/init/sp/textes/conclusion/conclusion.yaml +14 -0
  248. pressoir/init/sp/textes/garde/livre.yaml +63 -0
  249. pressoir/init/sp/textes/index-np/index-np.bib +0 -0
  250. pressoir/init/sp/textes/index-np/index-np.md +3 -0
  251. pressoir/init/sp/textes/index-np/index-np.yaml +17 -0
  252. pressoir/init/sp/textes/introduction/additionnels.md +19 -0
  253. pressoir/init/sp/textes/introduction/introduction.bib +0 -0
  254. pressoir/init/sp/textes/introduction/introduction.md +8 -0
  255. pressoir/init/sp/textes/introduction/introduction.yaml +17 -0
  256. pressoir/init/sp/textes/media/imagelivre.jpeg +0 -0
  257. pressoir/models.py +151 -0
  258. pressoir/project.toml +24 -0
  259. pressoir/sidenotes.py +64 -0
  260. pressoir/static/balloon.css-1.0.0/balloon.css +216 -0
  261. pressoir/static/css/contenuadd.css +204 -0
  262. pressoir/static/css/default.css +116 -0
  263. pressoir/static/css/footer.css +40 -0
  264. pressoir/static/css/header.css +107 -0
  265. pressoir/static/css/indexnp.css +25 -0
  266. pressoir/static/css/references.css +35 -0
  267. pressoir/static/css/responsive.css +129 -0
  268. pressoir/static/css/termeenrichi.css +50 -0
  269. pressoir/static/css/toc.css +36 -0
  270. pressoir/static/js/contenuadd.js +11 -0
  271. pressoir/static/js/navigation.js +24 -0
  272. pressoir/static/js/references.js +101 -0
  273. pressoir/static/js/termeenrichi.js +102 -0
  274. pressoir/static/js/toc.js +83 -0
  275. pressoir/static/js/utils.js +17 -0
  276. pressoir/static/svg/additional.svg +2 -0
  277. pressoir/static/svg/article.svg +1 -0
  278. pressoir/static/svg/audio.svg +1 -0
  279. pressoir/static/svg/chevron-bottom.svg +1 -0
  280. pressoir/static/svg/chevron-left.svg +1 -0
  281. pressoir/static/svg/chevron-right.svg +1 -0
  282. pressoir/static/svg/close.svg +1 -0
  283. pressoir/static/svg/expand.svg +1 -0
  284. pressoir/static/svg/image.svg +1 -0
  285. pressoir/static/svg/lien.svg +1 -0
  286. pressoir/static/svg/lieu.svg +1 -0
  287. pressoir/static/svg/logo_ateliersSP-short_chemin.svg +9 -0
  288. pressoir/static/svg/logo_orcid.svg +19 -0
  289. pressoir/static/svg/minimize.svg +1 -0
  290. pressoir/static/svg/organisme.svg +1 -0
  291. pressoir/static/svg/pdf.svg +1 -0
  292. pressoir/static/svg/source.svg +1 -0
  293. pressoir/static/svg/sp_logo_acronyme.svg +22 -0
  294. pressoir/static/svg/video.svg +1 -0
  295. pressoir/static/tocbot-4.9.1/tocbot.css +1 -0
  296. pressoir/static/tocbot-4.9.1/tocbot.min.js +1 -0
  297. pressoir/static/tufte-css-1.7.2/tufte.css +469 -0
  298. pressoir/statics.py +99 -0
  299. pressoir/templates/article.html +23 -0
  300. pressoir/templates/chapitre.html +342 -0
  301. pressoir/templates/dossier.html +19 -0
  302. pressoir/templates/homepage.html +266 -0
  303. pressoir/templates/image.html +25 -0
  304. pressoir/templates/index.html +22 -0
  305. pressoir/templates/pageWeb.html +20 -0
  306. pressoir/templates/pdf.html +21 -0
  307. pressoir/templates/texte.html +17 -0
  308. pressoir/templates/video.html +25 -0
  309. pressoir/utils.py +57 -0
  310. pressoir-3.0.0.dist-info/METADATA +206 -0
  311. pressoir-3.0.0.dist-info/RECORD +314 -0
  312. pressoir-3.0.0.dist-info/WHEEL +4 -0
  313. pressoir-3.0.0.dist-info/entry_points.txt +2 -0
  314. pressoir-3.0.0.dist-info/licenses/LICENSE +661 -0
pressoir/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ from pathlib import Path
2
+
3
+ VERSION = "3.0.0"
4
+ ROOT_DIR = Path(__file__).parent
pressoir/__main__.py ADDED
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ main()
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python3
2
+ import html
3
+ import tempfile
4
+ from collections import namedtuple
5
+
6
+ import pypandoc
7
+ import yaml
8
+ from progressist import ProgressBar
9
+
10
+ from .utils import get_template_path, strip_html_comments
11
+
12
+ AdditionalContent = namedtuple("AdditionalContent", "id, title, type, yaml, md, html")
13
+ SEPARATOR = "## "
14
+
15
+
16
+ def extract_additional_data(repository_path, chapter):
17
+ additional_path = repository_path / "textes" / chapter.id / "additionnels.md"
18
+ if not additional_path.exists():
19
+ return False
20
+ additional_data = additional_path.read_text()
21
+ if not additional_data.strip() or SEPARATOR not in additional_data:
22
+ return False
23
+ return additional_data
24
+
25
+
26
+ def extract_additional_content(repository_path, chapter, additional_item):
27
+ try:
28
+ additional_id, yaml_content, md_content = additional_item.split("---", 2)
29
+ except ValueError as error:
30
+ print(f" /!\\ Error in {chapter.id}/additionels.md (malformed file)")
31
+ print(additional_item)
32
+ print(error)
33
+ return False
34
+
35
+ additional_id = additional_id.strip()
36
+ if additional_id.startswith(SEPARATOR):
37
+ additional_id = strip_html_comments(additional_id[len(SEPARATOR) :]).strip()
38
+
39
+ try:
40
+ yaml_content_loaded = yaml.load(yaml_content, Loader=yaml.Loader)
41
+ except yaml.scanner.ScannerError as error:
42
+ print(f" /!\\ Error in {chapter.id}/additionels.md (malformed file)")
43
+ print(error)
44
+ return False
45
+
46
+ additional_title = yaml_content_loaded.get("title")
47
+ additional_type = yaml_content_loaded.get("type")
48
+
49
+ if additional_type is None:
50
+ return False
51
+
52
+ if additional_type.startswith("texte"):
53
+ additional_type = "texte"
54
+ elif additional_type in ["entretien", "situation", "tableau"]:
55
+ additional_type = "article"
56
+ template_path = get_template_path(repository_path, f"{additional_type}.html")
57
+ with tempfile.NamedTemporaryFile() as metadata_file:
58
+ yaml_content += "suppress-bibliography: true\n"
59
+ metadata_file.write(yaml_content.encode("utf-8"))
60
+ metadata_file.read() # Required to be readable by Pandoc.
61
+ bib_file = repository_path / "textes" / chapter.id / f"{chapter.id}.bib"
62
+ html_content = pypandoc.convert_text(
63
+ md_content,
64
+ "html",
65
+ format="md",
66
+ extra_args=[
67
+ "--ascii",
68
+ "--citeproc",
69
+ f"--bibliography={bib_file}",
70
+ f"--template={template_path}",
71
+ f"--metadata-file={metadata_file.name}",
72
+ f"--variable=additional_id:{additional_id}",
73
+ ],
74
+ )
75
+ return AdditionalContent(
76
+ **{
77
+ "id": additional_id,
78
+ "title": additional_title,
79
+ "type": additional_type,
80
+ "yaml": yaml_content,
81
+ "md": md_content,
82
+ "html": html_content,
83
+ }
84
+ )
85
+
86
+
87
+ def extract_additional_contents(repository_path, chapter):
88
+ additional_contents = []
89
+ additional_data = extract_additional_data(repository_path, chapter)
90
+ if not additional_data:
91
+ return []
92
+ additional_parts = additional_data.split(f"\n{SEPARATOR}")
93
+ bar = ProgressBar(
94
+ total=len(additional_parts), prefix=" Loading additional contents:"
95
+ )
96
+ for additional_item in bar.iter(additional_parts):
97
+ if not additional_item:
98
+ continue
99
+ additional_content = extract_additional_content(
100
+ repository_path, chapter, additional_item
101
+ )
102
+ if not additional_content:
103
+ continue
104
+ additional_contents.append(additional_content)
105
+ return additional_contents
106
+
107
+
108
+ def include_additional_contents(repository_path, chapter, html_content):
109
+ # Useful to be able to match the `contenuadd_pattern`, otherwise
110
+ # escaped special chars will not match:
111
+ # "EnvironnementNumérique" vs. "EnvironnementNumérique".
112
+ html_content = html.unescape(html_content)
113
+ for additional_content in extract_additional_contents(repository_path, chapter):
114
+ contenuadd_pattern = f"!contenuadd(./{additional_content.id})"
115
+ html_content = html_content.replace(
116
+ f"<p>{contenuadd_pattern}</p>",
117
+ f"<!-- From: {contenuadd_pattern} -->\n{additional_content.html}",
118
+ )
119
+ return html_content
pressoir/cli.py ADDED
@@ -0,0 +1,133 @@
1
+ import contextlib
2
+ import os
3
+ import shutil
4
+ import socket
5
+ from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer, test
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ from minicli import cli, run
10
+
11
+ from . import ROOT_DIR, VERSION
12
+ from .generator import generate_chapters, generate_homepage
13
+ from .indexes import generate_indexes
14
+ from .models import configure_book
15
+ from .statics import bundle_statics, sync_statics
16
+
17
+
18
+ @cli
19
+ def version():
20
+ """Return the current version of pressoir."""
21
+ print(f"Pressoir version: {VERSION}")
22
+
23
+
24
+ @cli
25
+ @cli("collection", choices=["pum", "sp", "blank"])
26
+ def init(repository_path: Path = Path(), collection: str = "blank"):
27
+ """Initialize a new book to `repository_path` or current directory.
28
+
29
+ :repository_path: Absolute or relative path to book’s sources (default: current).
30
+ :collection: Name of the collection (default: blank).
31
+ """
32
+ print(
33
+ f"Initializing a new book: `{repository_path}` for `{collection}` collection."
34
+ )
35
+
36
+ if not (repository_path / "presssoir").exists():
37
+ shutil.copytree(
38
+ ROOT_DIR / "init" / collection / "pressoir",
39
+ repository_path / "pressoir",
40
+ dirs_exist_ok=True,
41
+ )
42
+
43
+ if "textes" not in os.listdir(repository_path):
44
+ shutil.copytree(
45
+ ROOT_DIR / "init" / collection / "textes",
46
+ repository_path / "textes",
47
+ dirs_exist_ok=True,
48
+ )
49
+
50
+ if "doc" not in os.listdir(repository_path) and "doc" in os.listdir(
51
+ ROOT_DIR / "init" / collection
52
+ ):
53
+ shutil.copytree(
54
+ ROOT_DIR / "init" / collection / "doc",
55
+ repository_path / "doc",
56
+ dirs_exist_ok=True,
57
+ )
58
+
59
+
60
+ @cli
61
+ def docs(target_path: Optional[Path] = None):
62
+ """Generate documentation with pressoir itself. #SoMeta"""
63
+ if target_path is None:
64
+ target_path = Path(os.getenv("PWD")) / "public"
65
+ else:
66
+ target_path = Path(target_path)
67
+ print(f"Generating documentation in `{target_path.resolve()}`.")
68
+ build(ROOT_DIR / "docs", target_path)
69
+
70
+
71
+ @cli
72
+ def build(
73
+ repository_path: Path = Path(),
74
+ target_path: Optional[Path] = None,
75
+ chapter: str = "",
76
+ verbose: bool = False,
77
+ ):
78
+ """Build a book from `repository_path` or current directory.
79
+
80
+ :repository_path: Absolute or relative path to book’s sources (default: current).
81
+ :target_path: Where the book will be built (default: `repository_path`/public).
82
+ :chapter: Specify a given chapter id (e.g. `chapter1`).
83
+ :verbose: Display more informations during the build.
84
+ """
85
+ if target_path is None:
86
+ target_path = repository_path / "public"
87
+ target_path.mkdir(parents=True, exist_ok=True)
88
+ print(
89
+ f"Building a book from {repository_path.resolve()} to {target_path.resolve()}."
90
+ )
91
+ sync_statics(repository_path, target_path)
92
+ css_filename, js_filename = bundle_statics(repository_path, target_path)
93
+ book = configure_book(repository_path / "textes" / "garde" / "livre.yaml")
94
+ if verbose:
95
+ import pprint
96
+
97
+ pprint.pprint(book)
98
+
99
+ meta = {"css_filename": css_filename, "js_filename": js_filename}
100
+ generate_homepage(repository_path, target_path, book, meta)
101
+ generate_chapters(repository_path, target_path, book, meta, chapter)
102
+ generate_indexes(repository_path, target_path, book)
103
+
104
+
105
+ @cli
106
+ def serve(repository_path: Path = Path(), port: int = 8000):
107
+ """Serve an HTML book from `repository_path`/public or current directory/public.
108
+
109
+ :repository_path: Absolute or relative path to book’s sources (default: current).
110
+ :port: Port to serve the book from (default=8000)
111
+ """
112
+ print(
113
+ f"Serving HTML book from `{repository_path}/public` to http://127.0.0.1:{port}"
114
+ )
115
+
116
+ # From https://github.com/python/cpython/blob/main/Lib/http/server.py#L1307-L1326
117
+ class DirectoryServer(ThreadingHTTPServer):
118
+ def server_bind(self):
119
+ # suppress exception when protocol is IPv4
120
+ with contextlib.suppress(Exception):
121
+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
122
+ return super().server_bind()
123
+
124
+ def finish_request(self, request, client_address):
125
+ self.RequestHandlerClass(
126
+ request, client_address, self, directory=str(repository_path / "public")
127
+ )
128
+
129
+ test(HandlerClass=SimpleHTTPRequestHandler, ServerClass=DirectoryServer, port=port)
130
+
131
+
132
+ def main():
133
+ run()
@@ -0,0 +1,17 @@
1
+ [statics]
2
+ css_files = [
3
+ "static/css/fonts.css",
4
+ "static/css/vars.css",
5
+ "static/css/custom.css",
6
+ ]
7
+
8
+ [indexes]
9
+ ids = [
10
+ "personnalite",
11
+ ]
12
+ names = [
13
+ "Personnalités",
14
+ ]
15
+ images = [
16
+ "./svg/personnalite.svg",
17
+ ]
@@ -0,0 +1,294 @@
1
+ /* The place to define a new theme/identity. */
2
+ h1, h2, h3, h4, h5, h6 {
3
+ font-family: var(--font-family-headers);
4
+ }
5
+
6
+ header.main a.logo {
7
+ width: 322px;
8
+ }
9
+
10
+ header.main {
11
+ border-bottom-width: 2px;
12
+ }
13
+
14
+ header.main h1 {
15
+ font-variant: small-caps;
16
+ }
17
+
18
+ header.main h2 a {
19
+ border-color: var(--body-color);
20
+ }
21
+
22
+ h1.title {
23
+ margin-top: 7rem;
24
+ font-size: 4rem;
25
+ max-width: 60rem;
26
+ line-height: 1.15;
27
+ margin-bottom: 3rem;
28
+ color: black;
29
+ font-variant: small-caps;
30
+ }
31
+ h1.title::after {
32
+ display: block;
33
+ content: " ";
34
+ height: 2px;
35
+ width: 50%;
36
+ background: red;
37
+ margin-top: 2rem;
38
+ margin-left: 3rem;
39
+ }
40
+
41
+ blockquote::after,
42
+ .introchapitre::after,
43
+ .sidenote::after,
44
+ .marginnote::after {
45
+ display: block;
46
+ content: " ";
47
+ height: 2px;
48
+ width: 35%;
49
+ background: red;
50
+ margin-top: 1rem;
51
+ margin-bottom: 2rem;
52
+ margin-left: 8rem;
53
+ }
54
+
55
+ blockquote {
56
+ background: no-repeat top left/3rem url("./svg/quote.svg");
57
+ padding-top: 1rem;
58
+ padding-left: 3.5rem;
59
+ margin: 4rem 0 4rem -1.5rem;
60
+ }
61
+ blockquote::after,
62
+ .introchapitre::after {
63
+ width: 13%;
64
+ margin-left: 30rem;
65
+ }
66
+
67
+ blockquote p {
68
+ margin-top: 0;
69
+ width: 54%;
70
+ }
71
+
72
+ @media (max-width: 760px) {
73
+ blockquote::after,
74
+ .introchapitre::after {
75
+ width: 13%;
76
+ margin-left: 10rem;
77
+ }
78
+
79
+ blockquote p,
80
+ blockquote ul,
81
+ blockquote ol {
82
+ width: 80%;
83
+ font-size: medium;
84
+ line-height: 1.5;
85
+ }
86
+ }
87
+
88
+ img {
89
+ border-bottom: 2px solid red;
90
+ }
91
+ blockquote img {
92
+ border-bottom: none;
93
+ margin: 2rem;
94
+ }
95
+
96
+ .introchapitre,
97
+ .concluchapitre {
98
+ font-family: 'Averia Libre';
99
+ width: 55%;
100
+ }
101
+ .introchapitre {
102
+ margin-bottom: 5rem;
103
+ }
104
+
105
+ .introchapitre p::first-letter,
106
+ .concluchapitre p::first-letter {
107
+ font-size: 5rem;
108
+ padding-left: .5rem;
109
+ padding-right: .5rem;
110
+ float: left;
111
+ color: red;
112
+ }
113
+
114
+ .epigraphe {
115
+ width: 50%;
116
+ text-align: right;
117
+ margin: 1rem 0 5rem 7rem;
118
+ }
119
+ .epigraphe p {
120
+ margin-right: 2rem;
121
+ font-size: 1.1rem;
122
+ color: black;
123
+ }
124
+ .epigraphe p .citation {
125
+ display: block;
126
+ }
127
+
128
+ .contenuadd,
129
+ .contenuadd a,
130
+ .contenuadd p.source {
131
+ color: var(--body-color);
132
+ }
133
+ .contenuadd.lowpriority.expanded .source a.button,
134
+ .contenuadd.highpriority .source a.button {
135
+ background-color: var(--body-color);
136
+ }
137
+
138
+ footer {
139
+ border-top: 2px solid #b3b3b3;
140
+ background: white;
141
+ width: 100%;
142
+ }
143
+
144
+ footer nav ul {
145
+ font-variant: small-caps;
146
+ }
147
+
148
+ footer nav ul li:not(:first-child):not(:last-child) {
149
+ border-left: none;
150
+ border-right: none;
151
+ }
152
+ footer nav ul li:not(:first-child):not(:last-child)::before {
153
+ display: inline-block;
154
+ content: " ";
155
+ height: 40%;
156
+ width: 2px;
157
+ background: var(--footer-border-color);
158
+ margin-right: 1rem;
159
+ }
160
+ footer nav ul li:not(:first-child):not(:last-child)::after {
161
+ display: inline-block;
162
+ content: " ";
163
+ height: 40%;
164
+ width: 2px;
165
+ background: var(--footer-border-color);
166
+ margin-left: 1rem;
167
+ }
168
+
169
+ @media (max-width: 1025px) {
170
+ header.main a.logo {
171
+ background-image: url("./svg/pum-logo-couleur.svg");
172
+ }
173
+ }
174
+
175
+ table tbody tr.odd {
176
+ background: var(--contenuadd-background);
177
+ }
178
+ table tbody td {
179
+ padding: 0.2rem;
180
+ min-width: 65px;
181
+ }
182
+
183
+ .grand-tableau table {
184
+ font-size: 0.75em;
185
+ }
186
+
187
+ pre {
188
+ max-width: 55%;
189
+ padding: 1em;
190
+ background-color: lavenderblush;
191
+ }
192
+
193
+ pre > code {
194
+ font-size: 1rem;
195
+ white-space: pre-wrap;
196
+ }
197
+
198
+ article ul {
199
+ max-width: none;
200
+ }
201
+
202
+ code {
203
+ font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
204
+ font-size: 85%;
205
+ margin: 0;
206
+ }
207
+ pre {
208
+ margin: 1em 0;
209
+ overflow: auto;
210
+ }
211
+ pre code {
212
+ padding: 0;
213
+ overflow: visible;
214
+ overflow-wrap: normal;
215
+ }
216
+ .sourceCode {
217
+ width:55%;
218
+ background-color: transparent;
219
+ overflow: visible;
220
+ }
221
+ .sourceCode .sourceCode,
222
+ li .sourceCode {
223
+ width: 98%;
224
+ }
225
+ code{white-space: pre-wrap;}
226
+ span.smallcaps{font-variant: small-caps;}
227
+ span.underline{text-decoration: underline;}
228
+ div.column{display: inline-block; vertical-align: top; width: 50%;}
229
+ div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
230
+ ul.task-list{list-style: none;}
231
+ pre > code.sourceCode { white-space: pre; position: relative; }
232
+ pre > code.sourceCode > span { display: inline-block; line-height: 1.25; width: 98%; }
233
+ pre > code.sourceCode > span.highlight { background: #00ffcf3b; }
234
+ pre > code.sourceCode > span:empty { height: 1.2em; }
235
+ .sourceCode { overflow: visible; }
236
+ code.sourceCode > span { color: inherit; text-decoration: inherit; }
237
+ div.sourceCode { margin: 1em 0; }
238
+ pre.sourceCode { margin: 0; }
239
+ @media screen {
240
+ div.sourceCode { overflow: auto; }
241
+ }
242
+ @media print {
243
+ pre > code.sourceCode { white-space: pre-wrap; }
244
+ pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
245
+ }
246
+ pre.numberSource code
247
+ { counter-reset: source-line 0; }
248
+ pre.numberSource code > span
249
+ { position: relative; left: -4em; counter-increment: source-line; }
250
+ pre.numberSource code > span > a:first-child::before
251
+ { content: counter(source-line);
252
+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
253
+ border: none; display: inline-block;
254
+ -webkit-touch-callout: none; -webkit-user-select: none;
255
+ -khtml-user-select: none; -moz-user-select: none;
256
+ -ms-user-select: none; user-select: none;
257
+ padding: 0 4px; width: 4em;
258
+ color: #aaaaaa;
259
+ }
260
+ pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
261
+ div.sourceCode
262
+ { background-color: #f8f8f8; }
263
+ @media screen {
264
+ pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
265
+ }
266
+ code span.al { color: #ef2929; } /* Alert */
267
+ code span.an { color: #8f5902; font-weight: bold; font-style: italic; } /* Annotation */
268
+ code span.at { color: #c4a000; } /* Attribute */
269
+ code span.bn { color: #0000cf; } /* BaseN */
270
+ code span.cf { color: #204a87; font-weight: bold; } /* ControlFlow */
271
+ code span.ch { color: #4e9a06; } /* Char */
272
+ code span.cn { color: #000000; } /* Constant */
273
+ code span.co { color: #8f5902; font-style: italic; } /* Comment */
274
+ code span.cv { color: #8f5902; font-weight: bold; font-style: italic; } /* CommentVar */
275
+ code span.do { color: #8f5902; font-weight: bold; font-style: italic; } /* Documentation */
276
+ code span.dt { color: #204a87; } /* DataType */
277
+ code span.dv { color: #0000cf; } /* DecVal */
278
+ code span.er { color: #a40000; font-weight: bold; } /* Error */
279
+ code span.ex { } /* Extension */
280
+ code span.fl { color: #0000cf; } /* Float */
281
+ code span.fu { color: #204a87; } /* Function */
282
+ code span.im { } /* Import */
283
+ code span.in { color: #8f5902; font-weight: bold; font-style: italic; } /* Information */
284
+ code span.kw { color: #204a87; font-weight: bold; } /* Keyword */
285
+ code span.op { color: #ce5c00; font-weight: bold; } /* Operator */
286
+ code span.ot { color: #8f5902; } /* Other */
287
+ code span.pp { color: #8f5902; font-style: italic; } /* Preprocessor */
288
+ code span.sc { color: #000000; } /* SpecialChar */
289
+ code span.ss { color: #4e9a06; } /* SpecialString */
290
+ code span.st { color: #4e9a06; } /* String */
291
+ code span.va { color: #000000; } /* Variable */
292
+ code span.vs { color: #4e9a06; } /* VerbatimString */
293
+ code span.wa { color: #8f5902; font-weight: bold; font-style: italic; } /* Warning */
294
+ .display.math{display: block; text-align: center; margin: 0.5rem auto;}
@@ -0,0 +1,16 @@
1
+ @font-face {
2
+ font-family: 'Averia Serif Libre';
3
+ src: url('./fonts/averiaseriflibre-light.woff2') format('woff2'),
4
+ url('./fonts/averiaseriflibre-light.woff') format('woff');
5
+ font-weight: normal;
6
+ font-style: normal;
7
+ font-display: swap;
8
+ }
9
+ @font-face {
10
+ font-family: 'Averia Libre';
11
+ src: url('./fonts/averialibre-bold.woff2') format('woff2'),
12
+ url('./fonts/averialibre-bold.woff') format('woff');
13
+ font-weight: bold;
14
+ font-style: normal;
15
+ font-display: swap;
16
+ }
@@ -0,0 +1,33 @@
1
+ /* Beware: Safari does not handle well relative paths in CSS vars.
2
+ See https://bugs.webkit.org/show_bug.cgi?id=190807 for reference. */
3
+ :root {
4
+ --font-family: 'Averia Serif Libre';
5
+ --font-family-headers: 'Averia Libre';
6
+ --body-background: #fff;
7
+ --body-color: #432c2c;
8
+
9
+ --logo-position: no-repeat left center/100%;
10
+ --logo-url: url("./img/pressoir-logo.png");
11
+ --small-logo-url: url("./svg/pum-logo-couleur.svg");
12
+
13
+ --balloon-color: #686868;
14
+ --balloon-color-font: #e9ecef;
15
+ --balloon-font-size: .9rem;
16
+
17
+ --termeenrichi-background-image: url("./svg/plus.svg");
18
+ --termeenrichi-background-image-expanded: url("./svg/minus.svg");
19
+
20
+ --header-background-color: #eaeaea;
21
+ --header-border-color: #f00;
22
+ --header-color: #000;
23
+ --header-dropdown-background: 99% center no-repeat url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='35' height='35' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
24
+
25
+ --toc-border-color: #b3b3b3;
26
+ --toc-border-active-color: #000;
27
+
28
+ --contenuadd-border-color: #b3b3b3;
29
+ --contenuadd-background: #eaeaea;
30
+
31
+ --footer-background-color: #eaeaea;
32
+ --footer-border-color: #f00;
33
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3h18v18H3zM8 12h8"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="#e9ecef" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3h18v18H3zM12 8v8m-4-4h8"/></svg>