Astuces
Des astuces divers et variées…
- Déverrouiller un document Microsoft Office sans connaître le mot de passe
- Ajouter du texte Lorem ipsum sous Microsoft Office
- Insérer des caractères d'après le code Unicode dans LibreOffice ou Microsoft Office
- Masquer les éléments « Premium » dans Canva.com
- Table de remplacement intégrée à LibreOffice
- Obtenir des infos sur une image docker
- Command Line Interface - Tips en vrac
- Récupérer les réponses de ChatGPT en markdown
- Obtenir les request headers avec curl
- Astuces dans la console de navigateur
- Lister les aliases dans Mailo
- Lister les nouveautés de GitLab-CE
- Lister les mises à jour de WordPress
- Exporter des données du DOM dans un fichier .csv
- Yt-dlp dans France.tv
- Supprimer plusieurs tickets d'un coup sur GitLab
- Obtenir l'URL pour l'abonnement d'agendas et de contacts iCloud
- Claviers US
Déverrouiller un document Microsoft Office sans connaître le mot de passe
Afficher les extentions
Il faut que les extensions soient visibles. Sur Windows 10 :
- Depuis l'Explorateur de fichiers ;
-
Fichier
; -
Modifier les options des dossiers et de recherche
; -
Affichage
; - Décocher
Masquer les extensions des fichiers dont le type est connu
de l'encartParamètres avancés
; - Bouton
OK
.
Changer l'extension
Un document Microsoft Office est une archive compressée de fichier .xml.
Pour accéder aux fichiers internes, il faut changer l'extension du document (.docx
, .xlsx
, etc) par .zip
.
Décompresser le fichier .zip
Clic droit Extraire tout…
.
Bouton Extraire
.
Modifier le fichier .xml
- Entrer dans le dossier créé suite à l'extraction.
- Dans ce même dossier, aller dans le dossier correspondant au programme du fichier (par exemple
word
ouexcel
). - Ouvrir le fichier
settings.xml
avec un éditeur de texte (Bloc-notes par exemple). - Rechercher
Protection
. - Supprimer tout ce qu'il se trouve dans cette balise pour ne garder que le texte suivant (sans les crochets évidemment) :
[…]<w:documentProtection />[…]
Reconstruire le document Microsoft Office
- À l'intérieur du dossier créé suite à l'extraction, sélectionner tout les fichiers et dossiers (
Ctrl
+A
). - Clic droit
Envoyer vers
,Dossier compressé
. - Nommer ce fichier.
- Changer l'extension pour remettre l'extension de départ (
.docx
,.xlsx
, etc). - Voilà…
Ajouter du texte Lorem ipsum sous Microsoft Office
Il suffit de taper :
-
=lorem()
; - Touche
Entrée
.
La syntaxe complète est du type :
=lorem(paragraphes,phrases)
Par exemple, pour avoir 6 paragraphes de 20 phrases :
=lorem(6,20)
Insérer des caractères d'après le code Unicode dans LibreOffice ou Microsoft Office
- Écrire
U+26A0
; - Sélectionner texte ;
- Presser
Alt
+x
.
Et voilà.
Du coup : Symboles et codes clavier.
Masquer les éléments « Premium » dans Canva.com
Pourquoi faire ?
Le but est simplement de masquer les éléments qui demande de payer un abonnement (ceux avec la petite couronne).
Installation de Tapermonkey
Se rendre sur le site officiel du projet www.tampermonkey.net pour télécharger le plugin en fonction de son navigateur :
- Firefox
- Safari
- Chrome
- Opera Next
- etc.
Le script
Un fois l'installation (très rapide) terminée, cliquer sur l'icône de l'extension dans le navigateur et choisir Ajouter un nouveau script…
.
Coller tout le script suivant :
// ==UserScript==
// @name Canva - Hide Premium Content
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Hide premimum content on Canva.com
// @author MickGe
// @match https://www.canva.com/design/*
// @icon https://icons.duckduckgo.com/ip2/canva.com.ico
// @grant none
// ==/UserScript==
(function() {
const clearPremium = () => {
const classesPremium = "MSQthA";
const classesPicPremium = "A0JANA ADVZ4g";
const picPremium = [...document.getElementsByClassName(classesPicPremium)];
picPremium.forEach(el => {
const premimum = [...el.getElementsByClassName(classesPremium)].length;
if (premimum) el.style.display = 'none';
});
}
setInterval(clearPremium, 2000);
})();
Résultat
Pour désactiver le script, il suffit de cliquer sur l'icône de l'extension dans le navigateur puis sur Canva - Hide Premium Content
.
Table de remplacement intégrée à LibreOffice
Divers
©
®
™
•
nº
Nº
№
Lettres grecques
α
Α
β
Β
δ
ε
Ε
φ
Φ
γ
Γ
η
Η
ι
Ι
θ
Θ
κ
Κ
λ
Λ
μ
Μ
ν
Ν
ο
Ο
π
Π
χ
Χ
ρ
Ρ
σ
Σ
τ
Τ
Δ
υ
Υ
ω
Ω
ξ
Ξ
ψ
Ψ
ζ
Ζ
∂
∆
∫
ℓ
Ø
Ω
∏
√
∑
Flèches, ponctuations et arithmétique
↘
–
—
→
—
–
−
∓
…
’
∕
∖
±
≪
≤
≥
≫
≈
←
▼
▲
◄
►
↗
↔
↔
←
⇐
⇒
“
”
÷
‰
±
≤
≠
≡
×
≥
≈
½
⅓
¼
⅛
⅔
¾
⅜
⅝
⅞
Exposants
⁻
⁽
⁾
⁺
⁼
⁰
¹
²
³
⁴
⁵
⁶
⁷
⁸
⁹
ᵃ
ᴬ
ᵅ
ᵇ
ᴮ
ᵝ
ᶜ
ᵈ
ᴰ
ᵟ
ᵉ
ᴱ
ᵋ
ᶠ
ᵍ
ᴳ
ᵞ
ʰ
ᴴ
ⁱ
ᴵ
ᶥ
ʲ
ᴶ
ᵏ
ᴷ
ᵡ
ˡ
ᴸ
ᵐ
ᴹ
ⁿ
ᴺ
ᵒ
ᴼ
ᵖ
ᴾ
ᵠ
ᶲ
ʳ
ᴿ
ˢ
ᵗ
ᵀ
ᶿ
ᵘ
ᵁ
ᵛ
ⱽ
ʷ
ᵂ
ˣ
ʸ
ᶻ
Émojis
❕
‼
⁉
❗
❓
❔
🕐
½
⅓
¼
⅛
🕙
💯
🕚
🕛
🕑
⅔
🕒
¾
⅜
🕓
🕔
⅝
🕕
🕖
⅞
🕗
🕘
🔤
🐝
☬
🧑
🗜
🗖
🦅
⚗
α
Α
🚑
💘
🤟
🏺
💡
🍍
⚓
👼
∠
∡
😧
💍
🎂
🗙
📡
📷
📲
👏
⛐
🕷
🌳
🌈
🏹
💸
💰
🤑
🗄
🚏
🛬
🂡
🍽
⚛
☡
🍆
🛣
⚠
✈
🛩
🛧
🛨
🛦
🛪
🥑
🥓
📛
🏸
🛄
🥢
฿
🛁
🛀
⚖
♎
🐳
🐋
⛹
🏉
🎈
🎍
🍌
🏦
🕃
🕄
🧔
☟
👇
🖟
🖗
🖣
🖡
⚾
🏀
🛥
⚕
⚚
🔋
🤤
👶
🚼
🤱
♮
🐏
♈
♭
🍱
β
Β
🍼
🚲
🥫
🍺
🍻
👙
🎱
☣
💏
😘
😙
😚
😗
₿
𝅗𝅥
🛡
⛨
🗇
🗊
🗒
🐂
🥤
🍹
📪
📫
📬
📭
📥
📤
📮
🗃
🍜
💣
🍬
🙋
☃
⛄
🤞
💥
👢
😮
👄
➰
➿
🙎
🕯
🔮
🍙
🥟
💐
🎕
🛍
🔘
🔳
🔲
🎳
🥊
🥨
🥦
🥉
🌫
🌁
🐃
💬
🗩
💭
🗫
🗯
🗭
🗱
🗬
🗮
🗰
🏤
🏣
🌯
🚌
🚍
👤
👥
💩
🥜
🌵
🎁
🖾
🖽
☤
☕
🦑
🖩
📅
📆
🗓
🎥
📹
🛱
🚒
⛟
🚚
🏕
🛋
🦆
♋
🐩
🛶
♑
🎐
🥕
□
◼
◻
■
♦
♢
🎒
💳
🗺
🎴
🖭
☑
☒
☐
🗷
🗹
🗵
🎧
⛑
🧢
♘
♞
💿
¢
⚪
⚫
●
○
🔾
🔿
⚰
🍒
🧠
⛓
🚣
🐫
🍄
👒
👲
🛒
😽
😾
😹
😼
😿
😸
😺
🙀
🐈
🐱
🌰
🏰
🏯
🧦
👞
👟
👠
🦇
🐛
🐎
🐴
🗗
🏇
👱
🐐
🦌
🐕
🐶
🍫
🤯
🦉
⏱
🎯
🎇
🎦
🎪
✂
✄
✁
✃
🍋
🎬
⌨
🖮
🖦
🔧
🔑
🗝
𝄞
📸
😉
🕭
🖈
🤡
🐞
✓
✔
✅
🗴
🗸
🍸
💖
💓
💔
😻
💗
💟
🖤
🧡
💝
😍
❤
🎔
♡
💞
♥
💈
💢
📿
🕊
📞
🕻
🕽
🕼
☄
🥒
😖
😕
🛅
∋
🎛
🍪
🥠
©
🐓
🐚
📯
🗑
🍦
🤘
🌆
🕴
💇
👫
👬
👭
💑
🏃
👑
🏁
🔪
🗡
🤠
∎
🦀
🍘
😨
💀
👔
✎
✏
✐
🍮
🍤
🏏
🦗
😱
𝅘𝅥𝅮
🐊
🌙
🥐
☥
🕈
☩
☨
✠
☓
✚
✙
✝
🕆
🕇
☦
🥄
🍳
🍗
🥌
🍛
🚴
🌀
🏧
†
‡
♕
🂭
🍡
💃
🕺
🐬
🔰
😥
°
δ
Δ
𝄼
𝄾
🛫
😒
🌘
🌗
🎲
⚀
⚁
⚂
⚃
⚄
⚅
😞
🏜
🕵
💕
🔓
👿
📈
💹
🗠
♯
≠
🦃
🦕
🦖
🖴
🖸
💾
🖬
🖫
🖪
∣
⚮
🗋
🗎
🖹
🖻
🖺
🖕
💲
💵
🁠
🍩
📁
📂
🗀
🗁
🖿
🛃
𝄫
𝅘𝅥𝅯
𝄪
🚿
🐉
🐲
🚩
⚑
🏳
⚐
🎌
🎏
☞
👉
☛
🖛
🖙
🖝
🐪
📀
📧
→
⇒
🚱
🚰
💱
🧕
🗲
🏫
🖵
✍
🖎
⛪
🐘
🧝
⬭
👣
😠
🤰
😴
🧒
⚙
⏺
∅
☀
✉
🖃
🖂
🖄
🖅
📨
📩
↔
⇔
⚔
ε
Ε
😫
🐌
🤺
∈
∧
η
Η
🤧
❇
✨
🏷
☆
✡
☪
⭐
★
🌟
🌠
😲
💫
🤗
€
💶
🖆
🤩
👽
👾
👪
🏲
🏱
👻
☫
😩
☭
♿
📠
🖷
🧚
♀
👩
🚺
🗔
🤐
⛴
🎉
🎊
🥂
🍾
🎆
🔥
🍁
🍂
🍃
😯
🚥
🚦
🚨
ff
ffi
ffl
fi
👧
🛊
🎞
🍥
fl
🗘
💮
⚜
⚘
🌼
🌸
❄
🎡
🎠
⛲
🏈
⚽
🥅
♗
♝
🌩
☇
🧣
🐜
🍓
🍟
🧀
🗻
🚬
🚞
🚀
🥙
γ
Γ
🧤
👦
🛉
💂
🚉
🍰
☜
👈
☚
🖚
🖜
🖘
♊
🧞
🦒
🍧
🍨
🎚
🌍
🌎
🌏
🌐
🏌
⛳
🦍
💧
🌢
💦
⬛
⬜
⬤
◯
📉
📊
🐸
😀
😬
😁
🧗
🐽
🤵
🎸
🤸
🎃
🏋
🍔
🐹
🤾
🤷
🎩
📢
🔈
🕨
🕪
☝
👆
🖞
🖠
🖢
⚡
🚁
🌿
🦔
⬢
⬡
🌺
🏒
🏑
👨
🚹
🏥
⌚
🌭
🏨
🏩
🙌
₴
∃
∄
🏝
🖼
🏢
🖨
🖶
🗂
∞
ℹ
💁
🛈
😇
😟
∮
∬
∭
∰
∫
∩
🛇
🙃
ι
Ι
🗾
👖
🎮
👰
😂
🃏
🤹
📰
🗞
🥋
♃
🕋
κ
Κ
☧
χ
Χ
👘
🥝
🐨
🥛
λ
Λ
🔦
👅
😛
😜
😝
🏮
🐇
🐰
🐆
💌
🌅
🌄
🌇
🗢
🦎
🗽
🦄
🔗
♌
₺
₤
🛏
📒
£
📕
💷
📖
🕮
📚
🚂
🛲
◊
🤪
🐺
🔍
🔎
🛷
🔅
🔆
🌔
🌖
🌛
☽
🌜
☾
🕶
😎
👓
😈
👺
🤼
🎰
🏪
🏬
🧙
🀄
🎽
✋
🖐
🖑
🤚
👐
🌽
🏠
🏡
🏚
🏘
♂
💼
🐧
🍊
🕹
🤓
🧥
⚭
💋
®
🕅
📑
🔖
🛠
⚒
🔨
😷
💆
🤬
🙅
🤣
🏅
🎖
📣
🍈
📝
🕎
🤥
☿
🧜
🚈
🚇
😋
🎤
🎙
🔬
🍯
🔞
◾
🚐
💽
⏲
🖀
🧐
🚝
⛰
🏔
🎢
🕌
🏍
🐑
🤶
μ
Μ
🔇
✖
💪
🏛
🎶
🎵
↑
∉
⊅
⇑
🏊
😏
🤢
🚢
🛳
∌
∤
🚯
↗
⇗
🌨
♆
😐
👃
↖
⇖
💒
🎄
𝅘𝅥
🥥
🚭
⊄
∦
👎
¬
🖓
🗅
♩
♪
🗈
📓
📔
♫
♬
🎝
🎜
🥘
🌑
🌚
↕
⇕
ν
Ν
☁
⛅
⛈
🌤
🌥
🌃
←
⇐
🌊
🍢
👁
🥚
👹
🐦
👌
🖏
🙆
🕉
ω
Ω
ο
Ο
👋
💅
🥇
☈
💻
🖥
👂
👯
∨
👍
🖒
🐻
👷
🛸
🗆
🗉
🗌
📄
🗏
📃
🗟
📟
🗍
🗐
🍞
🥖
☮
🎨
🌴
🥞
🐼
🤕
♾
♼
🦋
📦
∥
▱
▰
☂
🌂
⛱
🏞
∂
🎼
🕲
🚸
🛂
🍉
🍠
🥔
⛸
🤦
🤲
𝄻
🖳
🏻
🏼
🏽
🏾
🏿
🍑
🎣
😔
⬟
⬠
⛤
🎅
😣
₱
▫
▪
◽
⭑
⭒
φ
Φ
π
Π
🎹
⛏
💎
🚷
🚶
💊
🌲
🖌
🏓
♙
♟
♠
♤
🕱
🛤
🔫
🍕
🌱
🥡
🌕
🌝
😢
☔
⛆
✑
✒
♇
🌦
👝
🤝
✊
👊
🤛
🤜
·
‱
🍐
☠
🐟
🐠
🐡
♓
🌶
🗛
🗚
👮
🍏
🍎
⛽
🌉
🍿
🐖
🐷
📴
📵
📱
🖁
👛
🕫
🕬
🚪
🚮
″
🐔
🐙
🎎
‰
🐣
🐤
🐥
🌒
🌓
📋
🙏
′
🤴
👸
🔌
∏
📽
🙇
ψ
Ψ
◦
•
‣
📶
📍
📌
∀
∜
∛
√
📻
☢
😡
🍲
🍇
🐀
🗦
🗥
🗤
🗧
▭
▬
♲
♻
🗕
📏
📐
♛
🎓
🦊
😦
🙁
☹
📇
🦈
🖧
🍴
⏰
🦏
ρ
Ρ
😆
🌾
🍚
👗
🤖
♔
♚
🂮
𝅝
🏵
🏶
🌹
💄
😊
😳
📜
🙄
₹
🎗
🎀
↓
⇓
⌛
⏳
👜
♐
🍶
🥗
👡
🥪
😭
😶
😑
🛰
♄
🧖
🎷
🛴
🛵
♏
🗳
↘
⇘
§
💠
🤳
🚛
⛔
💉
🐍
⛎
₪
💺
σ
Σ
ς
🔔
🛎
🔕
🙈
🙊
🙉
🐒
🐵
🎿
⛷
∊
∍
🏂
↙
⇙
🌞
☉
🌣
☼
∑
🛌
😪
🔊
🔉
😌
𝄽
♨
🤨
😃
😅
☺
☻
😄
🤭
🐁
🐭
🖱
🖰
🖯
⊂
🍝
🖖
🏟
🗿
🥩
📾
🛑
⏹
🖊
🖋
🖉
🍭
😰
⊃
🏄
🍣
🕍
🎘
👕
🌮
🛢
🥁
🐿
🎋
🥧
τ
Τ
♉
🚕
🚖
🚡
🚠
☏
☎
✆
🕾
🕿
🔭
🌧
🎾
⛺
♁
🗣
🚄
🚅
🍵
🎭
🌡
🤒
θ
Θ
🎫
🎟
🐅
🐯
💨
™
🚻
🍅
🌪
🐢
♖
♜
🗼
🌻
🐾
🖲
🚜
🚟
🚆
🚊
🚋
😓
⏢
🚧
♣
♧
🍀
⊿
△
▲
🛆
🔱
😤
🚎
📎
🖇
🎺
🏆
🕳
🎑
🌷
👳
📺
∪
υ
Υ
♅
⚱
🏭
🐄
🐮
🂫
🧛
🚤
🚳
🛐
🌬
🐗
🍷
🥃
🔒
🔏
🔐
♒
😵
👚
📼
🍖
📳
✌
🖔
👴
👵
♍
🧓
🏙
🎻
🔩
🌌
⛵
🚓
🚔
🚗
🚘
🚙
🏎
🌋
🏐
🤮
🚵
🚃
🤽
🚾
🚽
🕸
₩
×
❌
❎
🗶
ξ
Ξ
¥
💴
👀
☯
🧘
🦓
ζ
Ζ
🧟
💤
Indices
₋
₍
₎
₊
₌
₀
₁
₂
₃
₄
₅
₆
₇
₈
₉
ₐ
ᵦ
ₑ
ᵧ
ₕ
ᵢ
ⱼ
ₖ
ᵪ
ₗ
ₘ
ₙ
ₒ
ₚ
ᵩ
ᵣ
ᵨ
ₛ
ₜ
ᵤ
ᵥ
ₓ
₋
₍
₎
₊
₌
₀
₁
₂
₃
₄
₅
₆
₇
₈
₉
→
…
·
/cm²
/dm²
/km²
/m²
/m³
/mm²
/µm²
⁻
⁽
⁾
⁺
⁼
⁰
¹
²
³
⁴
⁵
⁶
⁷
⁸
⁹
Corrections
sœur
sœurs
cœur
cœurs
a-t-elle
a-t-il
a-t-on
a-t-elle
a-t-il
a-t-on
abscisse
acompte
accroître
affaires
affirmer
agio
agios
agréer
aller
ailleurs
ailleurs
am²
am³
ambiguë
année
années
annuler
annotation
annotations
annuler
apparaître
appel
appels
apparaît
apparaître
appeler
apercevoir
apcodendre
après J.-C.
arithmétique
attrapper
au-delà
au-delà
aujourd’hui
aujourd’hui
aussi
aussitôt
authentique
authentiques
autorisation
avant J.-C.
barrage
beaucoup
bibliothèque
bientôt
bœuf
bœufs
bulletin
c’est-à-dire
cela
cela
cellule
certain
chacun
charrette
chariot
château
circonstanciel
clientèle
cm²
cm³
cent
commettre
concession
concessions
conclue
confidentiel
connaît
connaître
contentieux
contrôle
couleur
courriers
courir
créée
créer
crème
curriculum
d’État
d’État
dégrèvement
déjà
déjà
déjà
dépôt
désœuvrement
développer
deux
dictionnaire
dilemme
dilemmes
diplôme
disparaît
disparaître
dans
dont
des
due
dues
dus
E.-U.
effets
émission
entracte
enveloppe
envelopper
etc.
etc.
excellent
excellents
excellent
excellents
exigence
phalange
falloir
fichier
fichiers
filiale
filiale
financière
fois
flèche
fœtus
francophone
fuir
gérer
gestionnaire
gouffre
goût
grand-chose
grand-mère
grand-père
griffonner
haut
icône
imbécillité
inclus
incluse
indemniser
indépendant
innovation
intérêt
intéresser
intervalle
jamais
jusqu’à
jusqu’au
juste
l’Église
L’Église
l’État
L’État
l’Église
L’Église
l’État
L’État
langage
langages
leur
licence
licences
les
manœuvre
manœuvres
Méditerranée
mnémotechnique
moi
moins
modèle
mœurs
mourir
Noël
nœud
nœuds
nous
occuper
occurrence
occurrences
occuper
occurrence
occurrences
ODF
œcuménisme
œil
œnologie
œnologue
œnologues
œsophage
œuf
œufs
œuvre
œuvres
∞
pâque
Pâques
paraît
paraître
parallèle
parallèles
paranoïaque
parce que
parce que
pèlerin
périphérique
personnalité
personnel
plain-pied
prêt
problème
problèmes
professionnel
professionnelle
professionnelles
professionnels
professionnel
professionnelle
professionnelles
professionnels
quelqu'un
quelqu'un
raccourci
rappel
rappelle
rappeller
rappels
récépissé
reconnaît
reconnaître
réflexion
règlement
réglementation
régler
rehausser
remédier
rouvrir
ressentir
rythme
rythmes
réintroduire
rôle
sera-t-elle
sera-t-il
sera-t-il
sera-t-elle
sera-t-il
sera-t-il
sera-t-elle
sera-t-il
sera-t-on
sous-traitant
temps
toujours
trafic
très
valeur
verrouiller
veuillez
vœu
vœux
Voilà
volontiers
vous
vouloir
Unités
g·m²
m²·s
m³/s
dam²
dam³
dm²
dm³
Em²
Em³
fm²
fm³
Gm²
Gm³
hm²
hm³
km²
km³
m²
m³
mm²
Mm²
mm³
Mm³
nm²
nm³
pm²
Pm²
pm³
Pm³
Tm²
Tm³
ym²
Ym²
ym³
Ym³
zm²
Zm²
zm³
Zm³
µm²
µm³
Source : https://wiki.documentfoundation.org/UserProfile#User_profile_content.
Par défaut, il est difficile d'obtenir certains caractères sous Windows (contrairement à MacOS ou GNU/Linux), par exemple À
, É
, œ
, une espace insécable, …
eric.bugnet.fr
En utilisant Microsoft Keyboard Layout Creator, il a créé un layout basé sur le clavier fr-oss présent dans les distributions GNU/Linux.
Tous les détails sur la page : Un clavier pour écrire en français sous Windows É Ç Œ et trucs dans le genre... - Mon coin du web...
Il y partage notamment son fichier source. Pour ma part je m'en suis servi pour ajouter l'espace fine insécable avec Shift+Espace avant de reconstruire les fichiers d'installation (voir pièces-jointes).
Obtenir des infos sur une image docker
Commande
Attention, les actions se lisent de bas en haut.
docker history --format "{{.CreatedBy}}" --no-trunc <image>
Exemple
docker history --format "{{.CreatedBy}}" --no-trunc cthulhoo/ttrss-web-nginx
COPY nginx.conf /etc/nginx/nginx.conf # buildkit
HEALTHCHECK &{["CMD-SHELL" "curl --fail http://localhost/tt-rss/index.php || exit 1"] "0s" "0s" "0s" '\x00'}
/bin/sh -c #(nop) CMD ["nginx" "-g" "daemon off;"]
/bin/sh -c #(nop) STOPSIGNAL SIGQUIT
/bin/sh -c #(nop) EXPOSE 80
/bin/sh -c #(nop) ENTRYPOINT ["/docker-entrypoint.sh"]
/bin/sh -c #(nop) COPY file:09a214a3e07c919af2fb2d7c749ccbc446b8c10eb217366e5a65640ee9edcc25 in /docker-entrypoint.d
/bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7de297435e32af634f29f7132ed0550d342cad9fd20158258 in /docker-entrypoint.d
/bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b03c4e6c8c513ae014f691fb05d530257dfffd07035c1b75da in /docker-entrypoint.d
/bin/sh -c #(nop) COPY file:65504f71f5855ca017fb64d502ce873a31b2e0decd75297a8fb0a287f97acf92 in /
/bin/sh -c set -x && addgroup -g 101 -S nginx && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx && apkArch="$(cat /etc/apk/arch)" && nginxPackages=" nginx=${NGINX_VERSION}-r${PKG_RELEASE} nginx-module-xslt=${NGINX_VERSION}-r${PKG_RELEASE} nginx-module-geoip=${NGINX_VERSION}-r${PKG_RELEASE} nginx-module-image-filter=${NGINX_VERSION}-r${PKG_RELEASE} nginx-module-njs=${NGINX_VERSION}.${NJS_VERSION}-r${PKG_RELEASE} " && apk add --no-cache --virtual .checksum-deps openssl && case "$apkArch" in x86_64|aarch64) set -x && KEY_SHA512="e7fa8303923d9b95db37a77ad46c68fd4755ff935d0a534d26eba83de193c76166c68bfe7f65471bf8881004ef4aa6df3e34689c305662750c0172fca5d8552a *stdin" && wget -O /tmp/nginx_signing.rsa.pub https://nginx.org/keys/nginx_signing.rsa.pub && if [ "$(openssl rsa -pubin -in /tmp/nginx_signing.rsa.pub -text -noout | openssl sha512 -r)" = "$KEY_SHA512" ]; then echo "key verification succeeded!"; mv /tmp/nginx_signing.rsa.pub /etc/apk/keys/; else echo "key verification failed!"; exit 1; fi && apk add -X "https://nginx.org/packages/mainline/alpine/v$(egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" --no-cache $nginxPackages ;; *)
set -x && tempDir="$(mktemp -d)" && chown nobody:nobody $tempDir && apk add --no-cache --virtual .build-deps gcc libc-dev make openssl-dev pcre2-dev zlib-dev linux-headers libxslt-dev gd-dev geoip-dev perl-dev libedit-dev bash
alpine-sdk findutils && su nobody -s /bin/sh -c " export HOME=${tempDir} && cd ${tempDir} && curl -f -O https://hg.nginx.org/pkg-oss/archive/${NGINX_VERSION}-${PKG_RELEASE}.tar.gz && PKGOSSCHECKSUM=\"513952f1e0432e667a8e3afef791a2daa036911f35573c849712747f10418f3f5b8712faf75fcb87f91bfaf593622b1e1c4f38ad9fef830f4cae141357206ecd *${NGINX_VERSION}-${PKG_RELEASE}.tar.gz\" && if [ \"\$(openssl sha512 -r ${NGINX_VERSION}-${PKG_RELEASE}.tar.gz)\" = \"\$PKGOSSCHECKSUM\" ]; then echo \"pkg-oss tarball checksum verification succeeded!\"; else echo \"pkg-oss tarball checksum verification failed!\"; exit 1; fi && tar xzvf ${NGINX_VERSION}-${PKG_RELEASE}.tar.gz && cd pkg-oss-${NGINX_VERSION}-${PKG_RELEASE} && cd alpine && make all && apk index -o ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz ${tempDir}/packages/alpine/${apkArch}/*.apk && abuild-sign -k ${tempDir}/.abuild/abuild-key.rsa ${tempDir}/packages/alpine/${apkArch}/APKINDEX.tar.gz " && cp ${tempDir}/.abuild/abuild-key.rsa.pub /etc/apk/keys/ && apk del .build-deps && apk add -X ${tempDir}/packages/alpine/ --no-cache $nginxPackages ;; esac && apk del .checksum-deps && if [ -n "$tempDir" ]; then rm -rf "$tempDir"; fi && if [ -n "/etc/apk/keys/abuild-key.rsa.pub" ]; then rm -f /etc/apk/keys/abuild-key.rsa.pub; fi && if [ -n "/etc/apk/keys/nginx_signing.rsa.pub" ]; then rm -f /etc/apk/keys/nginx_signing.rsa.pub; fi && apk add --no-cache --virtual .gettext gettext && mv /usr/bin/envsubst /tmp/ && runDeps="$( scanelf --needed --nobanner /tmp/envsubst | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' | sort -u | xargs -r apk info --installed | sort -u )" && apk add --no-cache $runDeps && apk del .gettext && mv /tmp/envsubst /usr/local/bin/ && apk add --no-cache tzdata && apk add --no-cache curl ca-certificates && ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log && mkdir /docker-entrypoint.d
/bin/sh -c #(nop) ENV PKG_RELEASE=1
/bin/sh -c #(nop) ENV NJS_VERSION=0.7.6
/bin/sh -c #(nop) ENV NGINX_VERSION=1.23.1
/bin/sh -c #(nop) LABEL maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>
/bin/sh -c #(nop) CMD ["/bin/sh"]
/bin/sh -c #(nop) ADD file:2a949686d9886ac7c10582a6c29116fd29d3077d02755e87e111870d63607725 in /
Et pour obtenir une mise en page qui va bien, c'est à dire avec des retours à la ligne :
$ docker history --format "{{.CreatedBy}}" --no-trunc collabora/code:latest | perl -p -e 's/(?=[ ]{2,})(?<![ ])/\n/g'
CMD ["/start-collabora-online.sh"]
USER 100
EXPOSE map[9980/tcp:{}]
COPY /scripts/start-collabora-online.pl / # buildkit
COPY /scripts/start-collabora-online.sh / # buildkit
RUN |4 repo= type= nobrand= noinotifywait= /bin/sh -c apt-get update &&
apt-get -y install cpio tzdata libcap2-bin apt-transport-https gnupg2 ca-certificates curl &&
repourl="https://collaboraoffice.com/${repo:-repos}/CollaboraOnline/";
secret_key=$(cat /run/secrets/secret_key);
if [ "$type" = "cool" ] && [ -n ${secret_key+set} ]; then
echo "Based on the provided build arguments Collabora Online from customer repo will be used.";
repourl="${repourl}23.05/customer-deb-${secret_key}/";
elif [ "$type" = "key" ]; then
echo "Based on the provided build arguments license key enabled Collabora Online will be used.";
repourl="${repourl}23.05-key/";
else
echo "Based on the provided build arguments Collabora Online Development Edition will be used.";
repourl="${repourl}23.05-CODE/CODE-deb/";
fi &&
echo "deb [signed-by=/usr/share/keyrings/collaboraonline-release-keyring.gpg] ${repourl} /" > /etc/apt/sources.list.d/collabora.list &&
if [ "$repo" = "repos-snapshot" ]; then
curl https://www.collaboraoffice.com/downloads/gpg/collaboraonline-snapshot-keyring.gpg --output /usr/share/keyrings/collaboraonline-snapshot-keyring.gpg;
sed -i "s/collaboraonline-release-keyring/collaboraonline-snapshot-keyring/" /etc/apt/sources.list.d/collabora.list;
else
curl https://www.collaboraoffice.com/downloads/gpg/collaboraonline-release-keyring.gpg --output /usr/share/keyrings/collaboraonline-release-keyring.gpg;
fi &&
apt-get update &&
apt-get -y install coolwsd
collaboraoffice-dict-*
collaboraofficebasis-ar
collaboraofficebasis-bg
collaboraofficebasis-ca
collaboraofficebasis-cs
collaboraofficebasis-da
collaboraofficebasis-de
collaboraofficebasis-el
collaboraofficebasis-en-gb
collaboraofficebasis-en-us
collaboraofficebasis-eo
collaboraofficebasis-es
collaboraofficebasis-eu
collaboraofficebasis-fi
collaboraofficebasis-fr
collaboraofficebasis-gl
collaboraofficebasis-he
collaboraofficebasis-hr
collaboraofficebasis-hu
collaboraofficebasis-id
collaboraofficebasis-is
collaboraofficebasis-it
collaboraofficebasis-ja
collaboraofficebasis-ko
collaboraofficebasis-lo
collaboraofficebasis-nb
collaboraofficebasis-nl
collaboraofficebasis-oc
collaboraofficebasis-pl
collaboraofficebasis-pt
collaboraofficebasis-pt-br
collaboraofficebasis-ru
collaboraofficebasis-sk
collaboraofficebasis-sl
collaboraofficebasis-sq
collaboraofficebasis-sv
collaboraofficebasis-tr
collaboraofficebasis-uk
collaboraofficebasis-vi
collaboraofficebasis-zh-cn
collaboraofficebasis-zh-tw &&
if [ -z "$nobrand" ]; then
if [ "$type" = "cool" ] || [ "$type" = "key" ]; then
apt-get -y install collabora-online-brand;
else
apt-get -y install code-brand;
fi;
fi &&
if [ -z "$noinotifywait" ]; then
apt-get -y install inotify-tools psmisc;
fi &&
chown cool:cool /etc/coolwsd &&
rm -rf /var/lib/apt/* &&
rm -rf /etc/coolwsd/proof_key* # buildkit
ENV LC_CTYPE=C.UTF-8
ARG noinotifywait
ARG nobrand
ARG type
ARG repo
MAINTAINER Andras Timar <andras.timar@collabora.com>
/bin/sh -c #(nop)
CMD ["bash"]
/bin/sh -c #(nop) ADD file:95a4ddc3a846636c52c273cac4e2e0d75225cde59612235c1480201b14581d9a in /
Command Line Interface - Tips en vrac
Chercher les fichiers qui contiennent un (des) .
dans leur nom et le(s) supprimer
Toute la difficulté est de ne pas supprimer le point de l'extension…
"find -iname '*.avi' -exec rename -v 's/(?!^)\.(?!avi$)/ /g' {} \;"
Chercher les fichiers dans les sous-dossiers et le remonter dans le dossier
find . -maxdepth 2 -mindepth 2 -exec mv '{}' ./ \;
Connaître la date d'expiration d'un certificat TLS
read DOMAIN"?Domain to check:" ; echo | openssl s_client -connect "$DOMAIN":443 2>/dev/null | openssl x509 -noout -enddate ; unset DOMAIN
Poster en multilignes sur Mastodon avec cURL
curl https://<domain>/api/v1/statuses \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"status":"Première ligne.\nSeconde ligne…",
"in_reply_to_id":null,"media_ids":[],"sensitive":false,
"spoiler_text":"","visibility":"direct",
"poll":null,"language":"fr"}' \
| jq '.id'
Note…
<domain>
est le domaine de l'instance Mastodon ;<token>
est le jeton comportant au moins les droits en écriture ;"visibility":"direct"
n'adresse le message qu'au personne mentionnée.
Ce qui renvoie l'id du post.
Documentation : statuses API methods - Mastodon documentation.
Pour ajouter un émoji, on peut le copier depuis le navigateur puis le coller. Il y a sans doute une autre façon, mais je n'ai pas trop cherché et ça fonctionne comme ça !
Récupérer les réponses de ChatGPT en markdown
Le script est « en partie » écrit par ChatGPT lui-même…
Importer le fichier lib/turndown.browser.umd.js
de la bibliothèque mixmark-ioturndown 🛏 An HTML to Markdown converter written in JavaScript depuis le site https://unpkg.com/browse/turndown/ (actuellement ce lien) dans la console JavaScript du navigateur.
Version minifiée par JavaScript Minifier & Compressor Toptal®
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).TurndownService=n()}(this,function(){"use strict";function e(e,n){return Array(n+1).join(e)}var n,t=["ADDRESS","ARTICLE","ASIDE","AUDIO","BLOCKQUOTE","BODY","CANVAS","CENTER","DD","DIR","DIV","DL","DT","FIELDSET","FIGCAPTION","FIGURE","FOOTER","FORM","FRAMESET","H1","H2","H3","H4","H5","H6","HEADER","HGROUP","HR","HTML","ISINDEX","LI","MAIN","MENU","NAV","NOFRAMES","NOSCRIPT","OL","OUTPUT","P","PRE","SECTION","TABLE","TBODY","TD","TFOOT","TH","THEAD","TR","UL"];function r(e){return l(e,t)}var i=["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"];function o(e){return l(e,i)}var a=["A","TABLE","THEAD","TBODY","TFOOT","TH","TD","IFRAME","SCRIPT","AUDIO","VIDEO"];function l(e,n){return n.indexOf(e.nodeName)>=0}function u(e,n){return e.getElementsByTagName&&n.some(function(n){return e.getElementsByTagName(n).length})}var c={};function s(e){return e?e.replace(/(\n+\s*)+/g,"\n"):""}function f(e){for(var n in this.options=e,this._keep=[],this._remove=[],this.blankRule={replacement:e.blankReplacement},this.keepReplacement=e.keepReplacement,this.defaultRule={replacement:e.defaultReplacement},this.array=[],e.rules)this.array.push(e.rules[n])}function d(e,n,t){for(var r=0;r<e.length;r++){var i=e[r];if(p(i,n,t))return i}}function p(e,n,t){var r=e.filter;if("string"==typeof r){if(r===n.nodeName.toLowerCase())return!0}else if(Array.isArray(r)){if(r.indexOf(n.nodeName.toLowerCase())>-1)return!0}else if("function"==typeof r){if(r.call(e,n,t))return!0}else throw TypeError("`filter` needs to be a string, array, or function")}function h(e){var n=e.nextSibling||e.parentNode;return e.parentNode.removeChild(e),n}function g(e,n,t){return e&&e.parentNode===n||t(n)?n.nextSibling||n.parentNode:n.firstChild||n.nextSibling||n.parentNode}c.paragraph={filter:"p",replacement:function(e){return"\n\n"+e+"\n\n"}},c.lineBreak={filter:"br",replacement:function(e,n,t){return t.br+"\n"}},c.heading={filter:["h1","h2","h3","h4","h5","h6"],replacement:function(n,t,r){var i=Number(t.nodeName.charAt(1));if("setext"!==r.headingStyle||!(i<3))return"\n\n"+e("#",i)+" "+n+"\n\n";var o=e(1===i?"=":"-",n.length);return"\n\n"+n+"\n"+o+"\n\n"}},c.blockquote={filter:"blockquote",replacement:function(e){return"\n\n"+(e=(e=e.replace(/^\n+|\n+$/g,"")).replace(/^/gm,"> "))+"\n\n"}},c.list={filter:["ul","ol"],replacement:function(e,n){var t=n.parentNode;return"LI"===t.nodeName&&t.lastElementChild===n?"\n"+e:"\n\n"+e+"\n\n"}},c.listItem={filter:"li",replacement:function(e,n,t){e=e.replace(/^\n+/,"").replace(/\n+$/,"\n").replace(/\n/gm,"\n ");var r=t.bulletListMarker+" ",i=n.parentNode;if("OL"===i.nodeName){var o=i.getAttribute("start"),a=Array.prototype.indexOf.call(i.children,n);r=(o?Number(o)+a:a+1)+". "}return r+e+(n.nextSibling&&!/\n$/.test(e)?"\n":"")}},c.indentedCodeBlock={filter:function(e,n){return"indented"===n.codeBlockStyle&&"PRE"===e.nodeName&&e.firstChild&&"CODE"===e.firstChild.nodeName},replacement:function(e,n,t){return"\n\n "+n.firstChild.textContent.replace(/\n/g,"\n ")+"\n\n"}},c.fencedCodeBlock={filter:function(e,n){return"fenced"===n.codeBlockStyle&&"PRE"===e.nodeName&&e.firstChild&&"CODE"===e.firstChild.nodeName},replacement:function(n,t,r){for(var i,o=((t.firstChild.getAttribute("class")||"").match(/language-(\S+)/)||[null,""])[1],a=t.firstChild.textContent,l=r.fence.charAt(0),u=3,c=RegExp("^"+l+"{3,}","gm");i=c.exec(a);)i[0].length>=u&&(u=i[0].length+1);var s=e(l,u);return"\n\n"+s+o+"\n"+a.replace(/\n$/,"")+"\n"+s+"\n\n"}},c.horizontalRule={filter:"hr",replacement:function(e,n,t){return"\n\n"+t.hr+"\n\n"}},c.inlineLink={filter:function(e,n){return"inlined"===n.linkStyle&&"A"===e.nodeName&&e.getAttribute("href")},replacement:function(e,n){var t=n.getAttribute("href"),r=s(n.getAttribute("title"));return r&&(r=' "'+r+'"'),"["+e+"]("+t+r+")"}},c.referenceLink={filter:function(e,n){return"referenced"===n.linkStyle&&"A"===e.nodeName&&e.getAttribute("href")},replacement:function(e,n,t){var r,i,o=n.getAttribute("href"),a=s(n.getAttribute("title"));switch(a&&(a=' "'+a+'"'),t.linkReferenceStyle){case"collapsed":r="["+e+"][]",i="["+e+"]: "+o+a;break;case"shortcut":r="["+e+"]",i="["+e+"]: "+o+a;break;default:var l=this.references.length+1;r="["+e+"]["+l+"]",i="["+l+"]: "+o+a}return this.references.push(i),r},references:[],append:function(e){var n="";return this.references.length&&(n="\n\n"+this.references.join("\n")+"\n\n",this.references=[]),n}},c.emphasis={filter:["em","i"],replacement:function(e,n,t){return e.trim()?t.emDelimiter+e+t.emDelimiter:""}},c.strong={filter:["strong","b"],replacement:function(e,n,t){return e.trim()?t.strongDelimiter+e+t.strongDelimiter:""}},c.code={filter:function(e){var n=e.previousSibling||e.nextSibling,t="PRE"===e.parentNode.nodeName&&!n;return"CODE"===e.nodeName&&!t},replacement:function(e){if(!e)return"";e=e.replace(/\r?\n|\r/g," ");for(var n=/^`|^ .*?[^ ].* $|`$/.test(e)?" ":"",t="`",r=e.match(/`+/gm)||[];-1!==r.indexOf(t);)t+="`";return t+n+e+n+t}},c.image={filter:"img",replacement:function(e,n){var t=s(n.getAttribute("alt")),r=n.getAttribute("src")||"",i=s(n.getAttribute("title"));return r?"+")":""}},f.prototype={add:function(e,n){this.array.unshift(n)},keep:function(e){this._keep.unshift({filter:e,replacement:this.keepReplacement})},remove:function(e){this._remove.unshift({filter:e,replacement:function(){return""}})},forNode:function(e){var n;return e.isBlank?this.blankRule:(n=d(this.array,e,this.options))||(n=d(this._keep,e,this.options))||(n=d(this._remove,e,this.options))?n:this.defaultRule},forEach:function(e){for(var n=0;n<this.array.length;n++)e(this.array[n],n)}};var m,v="undefined"!=typeof window?window:{},A=!function e(){var n=v.DOMParser,t=!1;try{new n().parseFromString("","text/html")&&(t=!0)}catch(r){}return t}()?(m=function(){},!function e(){var n=!1;try{document.implementation.createHTMLDocument("").open()}catch(t){window.ActiveXObject&&(n=!0)}return n}()?m.prototype.parseFromString=function(e){var n=document.implementation.createHTMLDocument("");return n.open(),n.write(e),n.close(),n}:m.prototype.parseFromString=function(e){var n=new window.ActiveXObject("htmlfile");return n.designMode="on",n.open(),n.write(e),n.close(),n},m):v.DOMParser;function y(e,t){var i;return!function e(n){var t=n.element,r=n.isBlock,i=n.isVoid,o=n.isPre||function(e){return"PRE"===e.nodeName};if(!(!t.firstChild||o(t))){for(var a=null,l=!1,u=null,c=g(u,t,o);c!==t;){if(3===c.nodeType||4===c.nodeType){var s=c.data.replace(/[ \r\n\t]+/g," ");if((!a||/ $/.test(a.data))&&!l&&" "===s[0]&&(s=s.substr(1)),!s){c=h(c);continue}c.data=s,a=c}else if(1===c.nodeType)r(c)||"BR"===c.nodeName?(a&&(a.data=a.data.replace(/ $/,"")),a=null,l=!1):i(c)||o(c)?(a=null,l=!0):a&&(l=!1);else{c=h(c);continue}var f=g(u,c,o);u=c,c=f}a&&(a.data=a.data.replace(/ $/,""),a.data||h(a))}}({element:i="string"==typeof e?(n=n||new A).parseFromString('<x-turndown id="turndown-root">'+e+"</x-turndown>","text/html").getElementById("turndown-root"):e.cloneNode(!0),isBlock:r,isVoid:o,isPre:t.preformattedCode?N:null}),i}function N(e){return"PRE"===e.nodeName||"CODE"===e.nodeName}function E(e,n){var t,c,s,f;return e.isBlock=r(e),e.isCode="CODE"===e.nodeName||e.parentNode.isCode,e.isBlank=(t=e,!o(t)&&!l(c=t,a)&&/^\s*$/i.test(t.textContent)&&!u(s=t,i)&&!u(f=t,a)),e.flankingWhitespace=function e(n,t){if(n.isBlock||t.preformattedCode&&n.isCode)return{leading:"",trailing:""};var r,i,o=(r=n.textContent,i=r.match(/^(([ \t\r\n]*)(\s*))[\s\S]*?((\s*?)([ \t\r\n]*))$/),{leading:i[1],leadingAscii:i[2],leadingNonAscii:i[3],trailing:i[4],trailingNonAscii:i[5],trailingAscii:i[6]});return o.leadingAscii&&T("left",n,t)&&(o.leading=o.leadingNonAscii),o.trailingAscii&&T("right",n,t)&&(o.trailing=o.trailingNonAscii),{leading:o.leading,trailing:o.trailing}}(e,n),e}function T(e,n,t){var i,o,a;return"left"===e?(i=n.previousSibling,o=/ $/):(i=n.nextSibling,o=/^ /),i&&(3===i.nodeType?a=o.test(i.nodeValue):t.preformattedCode&&"CODE"===i.nodeName?a=!1:1!==i.nodeType||r(i)||(a=o.test(i.textContent))),a}var C=Array.prototype.reduce,R=[[/\\/g,"\\\\"],[/\*/g,"\\*"],[/^-/g,"\\-"],[/^\+ /g,"\\+ "],[/^(=+)/g,"\\$1"],[/^(#{1,6}) /g,"\\$1 "],[/`/g,"\\`"],[/^~~~/g,"\\~~~"],[/\[/g,"\\["],[/\]/g,"\\]"],[/^>/g,"\\>"],[/_/g,"\\_"],[/^(\d+)\. /g,"$1\\. "]];function k(e){if(!(this instanceof k))return new k(e);this.options=function e(n){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var i in r)r.hasOwnProperty(i)&&(n[i]=r[i])}return n}({},{rules:c,headingStyle:"setext",hr:"* * *",bulletListMarker:"*",codeBlockStyle:"indented",fence:"```",emDelimiter:"_",strongDelimiter:"**",linkStyle:"inlined",linkReferenceStyle:"full",br:" ",preformattedCode:!1,blankReplacement:function(e,n){return n.isBlock?"\n\n":""},keepReplacement:function(e,n){return n.isBlock?"\n\n"+n.outerHTML+"\n\n":n.outerHTML},defaultReplacement:function(e,n){return n.isBlock?"\n\n"+e+"\n\n":e}},e),this.rules=new f(this.options)}function b(e){var n=this;return C.call(e.childNodes,function(e,t){t=new E(t,n.options);var r="";return 3===t.nodeType?r=t.isCode?t.nodeValue:n.escape(t.nodeValue):1===t.nodeType&&(r=D.call(n,t)),S(e,r)},"")}function O(e){var n=this;return this.rules.forEach(function(t){"function"==typeof t.append&&(e=S(e,t.append(n.options)))}),e.replace(/^[\t\r\n]+/,"").replace(/[\t\r\n\s]+$/,"")}function D(e){var n=this.rules.forNode(e),t=b.call(this,e),r=e.flankingWhitespace;return(r.leading||r.trailing)&&(t=t.trim()),r.leading+n.replacement(t,e,this.options)+r.trailing}function S(e,n){var t,r=function e(n){for(var t=n.length;t>0&&"\n"===n[t-1];)t--;return n.substring(0,t)}(e),i=(t=n).replace(/^\n*/,""),o=Math.max(e.length-r.length,n.length-i.length);return r+"\n\n".substring(0,o)+i}return k.prototype={turndown:function(e){if(n=e,null==n||"string"!=typeof n&&(!n.nodeType||1!==n.nodeType&&9!==n.nodeType&&11!==n.nodeType))throw TypeError(e+" is not a string, or an element/document/fragment node.");if(""===e)return"";var n,t=b.call(this,new y(e,this.options));return O.call(this,t)},use:function(e){if(Array.isArray(e))for(var n=0;n<e.length;n++)this.use(e[n]);else if("function"==typeof e)e(this);else throw TypeError("plugin must be a Function or an Array of Functions");return this},addRule:function(e,n){return this.rules.add(e,n),this},keep:function(e){return this.rules.keep(e),this},remove:function(e){return this.rules.remove(e),this},escape:function(e){return R.reduce(function(e,n){return e.replace(n[0],n[1])},e)}},k});
Puis coller ce code :
{
const answerClass = 'prose';
// Crée une instance de TurndownService
const turndownService = new TurndownService({codeBlockStyle: 'fenced', strongDelimiter: '__'});
// Ajoute une règle pour les blocs de code
turndownService.addRule('codeBlock', {
filter: 'pre',
replacement: function (content) {
const regexTick = /^`|`\n+/gm;
const _content = content.replace('\n\n','').replace('Copy code\n','').replace(regexTick,'');
console.log('***', _content);
return '\n```' + _content + '\n```\n';
}
});
// Sélectionne toutes les balises <div> qui contiennent la classe
const answerElements = document.querySelectorAll('div.' + answerClass);
// Initialise une chaîne de caractères vide pour stocker les réponses en markdown
let markdown = '';
// Boucle à travers chaque élément de réponse
answerElements.forEach((answerElement) => {
// Convertit le contenu HTML de l'élément réponse en markdown
const answerHtml = answerElement.innerHTML.trim();
const answerMarkdown = turndownService.turndown(answerHtml);
// Ajoute le texte en markdown de l'élément réponse à la chaîne markdown
markdown += answerMarkdown + '\n\n';
});
// Affiche la chaîne markdown dans la console
console.log(markdown);
}
Il est possible que la classe de la réponse ait changé, il faudra l'adapter.
Version minifiée tout compris
{const answerClass='prose';!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).TurndownService=n()}(this,function(){"use strict";function e(e,n){return Array(n+1).join(e)}var n,t=["ADDRESS","ARTICLE","ASIDE","AUDIO","BLOCKQUOTE","BODY","CANVAS","CENTER","DD","DIR","DIV","DL","DT","FIELDSET","FIGCAPTION","FIGURE","FOOTER","FORM","FRAMESET","H1","H2","H3","H4","H5","H6","HEADER","HGROUP","HR","HTML","ISINDEX","LI","MAIN","MENU","NAV","NOFRAMES","NOSCRIPT","OL","OUTPUT","P","PRE","SECTION","TABLE","TBODY","TD","TFOOT","TH","THEAD","TR","UL"];function r(e){return a(e,t)}var i=["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"];function o(e){return a(e,i)}var l=["A","TABLE","THEAD","TBODY","TFOOT","TH","TD","IFRAME","SCRIPT","AUDIO","VIDEO"];function a(e,n){return n.indexOf(e.nodeName)>=0}function u(e,n){return e.getElementsByTagName&&n.some(function(n){return e.getElementsByTagName(n).length})}var c={};function s(e){return e?e.replace(/(\n+\s*)+/g,"\n"):""}function f(e){for(var n in this.options=e,this._keep=[],this._remove=[],this.blankRule={replacement:e.blankReplacement},this.keepReplacement=e.keepReplacement,this.defaultRule={replacement:e.defaultReplacement},this.array=[],e.rules)this.array.push(e.rules[n])}function d(e,n,t){for(var r=0;r<e.length;r++){var i=e[r];if(p(i,n,t))return i}}function p(e,n,t){var r=e.filter;if("string"==typeof r){if(r===n.nodeName.toLowerCase())return!0}else if(Array.isArray(r)){if(r.indexOf(n.nodeName.toLowerCase())>-1)return!0}else if("function"==typeof r){if(r.call(e,n,t))return!0}else throw TypeError("`filter` needs to be a string, array, or function")}function h(e){var n=e.nextSibling||e.parentNode;return e.parentNode.removeChild(e),n}function g(e,n,t){return e&&e.parentNode===n||t(n)?n.nextSibling||n.parentNode:n.firstChild||n.nextSibling||n.parentNode}c.paragraph={filter:"p",replacement:function(e){return"\n\n"+e+"\n\n"}},c.lineBreak={filter:"br",replacement:function(e,n,t){return t.br+"\n"}},c.heading={filter:["h1","h2","h3","h4","h5","h6"],replacement:function(n,t,r){var i=Number(t.nodeName.charAt(1));if("setext"!==r.headingStyle||!(i<3))return"\n\n"+e("#",i)+" "+n+"\n\n";var o=e(1===i?"=":"-",n.length);return"\n\n"+n+"\n"+o+"\n\n"}},c.blockquote={filter:"blockquote",replacement:function(e){return"\n\n"+(e=(e=e.replace(/^\n+|\n+$/g,"")).replace(/^/gm,"> "))+"\n\n"}},c.list={filter:["ul","ol"],replacement:function(e,n){var t=n.parentNode;return"LI"===t.nodeName&&t.lastElementChild===n?"\n"+e:"\n\n"+e+"\n\n"}},c.listItem={filter:"li",replacement:function(e,n,t){e=e.replace(/^\n+/,"").replace(/\n+$/,"\n").replace(/\n/gm,"\n ");var r=t.bulletListMarker+" ",i=n.parentNode;if("OL"===i.nodeName){var o=i.getAttribute("start"),l=Array.prototype.indexOf.call(i.children,n);r=(o?Number(o)+l:l+1)+". "}return r+e+(n.nextSibling&&!/\n$/.test(e)?"\n":"")}},c.indentedCodeBlock={filter:function(e,n){return"indented"===n.codeBlockStyle&&"PRE"===e.nodeName&&e.firstChild&&"CODE"===e.firstChild.nodeName},replacement:function(e,n,t){return"\n\n "+n.firstChild.textContent.replace(/\n/g,"\n ")+"\n\n"}},c.fencedCodeBlock={filter:function(e,n){return"fenced"===n.codeBlockStyle&&"PRE"===e.nodeName&&e.firstChild&&"CODE"===e.firstChild.nodeName},replacement:function(n,t,r){for(var i,o=((t.firstChild.getAttribute("class")||"").match(/language-(\S+)/)||[null,""])[1],l=t.firstChild.textContent,a=r.fence.charAt(0),u=3,c=RegExp("^"+a+"{3,}","gm");i=c.exec(l);)i[0].length>=u&&(u=i[0].length+1);var s=e(a,u);return"\n\n"+s+o+"\n"+l.replace(/\n$/,"")+"\n"+s+"\n\n"}},c.horizontalRule={filter:"hr",replacement:function(e,n,t){return"\n\n"+t.hr+"\n\n"}},c.inlineLink={filter:function(e,n){return"inlined"===n.linkStyle&&"A"===e.nodeName&&e.getAttribute("href")},replacement:function(e,n){var t=n.getAttribute("href"),r=s(n.getAttribute("title"));return r&&(r=' "'+r+'"'),"["+e+"]("+t+r+")"}},c.referenceLink={filter:function(e,n){return"referenced"===n.linkStyle&&"A"===e.nodeName&&e.getAttribute("href")},replacement:function(e,n,t){var r,i,o=n.getAttribute("href"),l=s(n.getAttribute("title"));switch(l&&(l=' "'+l+'"'),t.linkReferenceStyle){case"collapsed":r="["+e+"][]",i="["+e+"]: "+o+l;break;case"shortcut":r="["+e+"]",i="["+e+"]: "+o+l;break;default:var a=this.references.length+1;r="["+e+"]["+a+"]",i="["+a+"]: "+o+l}return this.references.push(i),r},references:[],append:function(e){var n="";return this.references.length&&(n="\n\n"+this.references.join("\n")+"\n\n",this.references=[]),n}},c.emphasis={filter:["em","i"],replacement:function(e,n,t){return e.trim()?t.emDelimiter+e+t.emDelimiter:""}},c.strong={filter:["strong","b"],replacement:function(e,n,t){return e.trim()?t.strongDelimiter+e+t.strongDelimiter:""}},c.code={filter:function(e){var n=e.previousSibling||e.nextSibling,t="PRE"===e.parentNode.nodeName&&!n;return"CODE"===e.nodeName&&!t},replacement:function(e){if(!e)return"";e=e.replace(/\r?\n|\r/g," ");for(var n=/^`|^ .*?[^ ].* $|`$/.test(e)?" ":"",t="`",r=e.match(/`+/gm)||[];-1!==r.indexOf(t);)t+="`";return t+n+e+n+t}},c.image={filter:"img",replacement:function(e,n){var t=s(n.getAttribute("alt")),r=n.getAttribute("src")||"",i=s(n.getAttribute("title"));return r?"+")":""}},f.prototype={add:function(e,n){this.array.unshift(n)},keep:function(e){this._keep.unshift({filter:e,replacement:this.keepReplacement})},remove:function(e){this._remove.unshift({filter:e,replacement:function(){return""}})},forNode:function(e){var n;return e.isBlank?this.blankRule:(n=d(this.array,e,this.options))||(n=d(this._keep,e,this.options))||(n=d(this._remove,e,this.options))?n:this.defaultRule},forEach:function(e){for(var n=0;n<this.array.length;n++)e(this.array[n],n)}};var m,v="undefined"!=typeof window?window:{},y=!function e(){var n=v.DOMParser,t=!1;try{new n().parseFromString("","text/html")&&(t=!0)}catch(r){}return t}()?(m=function(){},!function e(){var n=!1;try{document.implementation.createHTMLDocument("").open()}catch(t){window.ActiveXObject&&(n=!0)}return n}()?m.prototype.parseFromString=function(e){var n=document.implementation.createHTMLDocument("");return n.open(),n.write(e),n.close(),n}:m.prototype.parseFromString=function(e){var n=new window.ActiveXObject("htmlfile");return n.designMode="on",n.open(),n.write(e),n.close(),n},m):v.DOMParser;function A(e,t){var i;return!function e(n){var t=n.element,r=n.isBlock,i=n.isVoid,o=n.isPre||function(e){return"PRE"===e.nodeName};if(!(!t.firstChild||o(t))){for(var l=null,a=!1,u=null,c=g(u,t,o);c!==t;){if(3===c.nodeType||4===c.nodeType){var s=c.data.replace(/[ \r\n\t]+/g," ");if((!l||/ $/.test(l.data))&&!a&&" "===s[0]&&(s=s.substr(1)),!s){c=h(c);continue}c.data=s,l=c}else if(1===c.nodeType)r(c)||"BR"===c.nodeName?(l&&(l.data=l.data.replace(/ $/,"")),l=null,a=!1):i(c)||o(c)?(l=null,a=!0):l&&(a=!1);else{c=h(c);continue}var f=g(u,c,o);u=c,c=f}l&&(l.data=l.data.replace(/ $/,""),l.data||h(l))}}({element:i="string"==typeof e?(n=n||new y).parseFromString('<x-turndown id="turndown-root">'+e+"</x-turndown>","text/html").getElementById("turndown-root"):e.cloneNode(!0),isBlock:r,isVoid:o,isPre:t.preformattedCode?N:null}),i}function N(e){return"PRE"===e.nodeName||"CODE"===e.nodeName}function E(e,n){var t,c,s,f;return e.isBlock=r(e),e.isCode="CODE"===e.nodeName||e.parentNode.isCode,e.isBlank=!o(t=e)&&!a(c=t,l)&&/^\s*$/i.test(t.textContent)&&!u(s=t,i)&&!u(f=t,l),e.flankingWhitespace=function e(n,t){if(n.isBlock||t.preformattedCode&&n.isCode)return{leading:"",trailing:""};var r,i,o={leading:(i=(r=n.textContent).match(/^(([ \t\r\n]*)(\s*))[\s\S]*?((\s*?)([ \t\r\n]*))$/))[1],leadingAscii:i[2],leadingNonAscii:i[3],trailing:i[4],trailingNonAscii:i[5],trailingAscii:i[6]};return o.leadingAscii&&T("left",n,t)&&(o.leading=o.leadingNonAscii),o.trailingAscii&&T("right",n,t)&&(o.trailing=o.trailingNonAscii),{leading:o.leading,trailing:o.trailing}}(e,n),e}function T(e,n,t){var i,o,l;return"left"===e?(i=n.previousSibling,o=/ $/):(i=n.nextSibling,o=/^ /),i&&(3===i.nodeType?l=o.test(i.nodeValue):t.preformattedCode&&"CODE"===i.nodeName?l=!1:1!==i.nodeType||r(i)||(l=o.test(i.textContent))),l}var C=Array.prototype.reduce,R=[[/\\/g,"\\\\"],[/\*/g,"\\*"],[/^-/g,"\\-"],[/^\+ /g,"\\+ "],[/^(=+)/g,"\\$1"],[/^(#{1,6}) /g,"\\$1 "],[/`/g,"\\`"],[/^~~~/g,"\\~~~"],[/\[/g,"\\["],[/\]/g,"\\]"],[/^>/g,"\\>"],[/_/g,"\\_"],[/^(\d+)\. /g,"$1\\. "]];function k(e){if(!(this instanceof k))return new k(e);this.options=function e(n){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var i in r)r.hasOwnProperty(i)&&(n[i]=r[i])}return n}({},{rules:c,headingStyle:"setext",hr:"* * *",bulletListMarker:"*",codeBlockStyle:"indented",fence:"```",emDelimiter:"_",strongDelimiter:"**",linkStyle:"inlined",linkReferenceStyle:"full",br:" ",preformattedCode:!1,blankReplacement:function(e,n){return n.isBlock?"\n\n":""},keepReplacement:function(e,n){return n.isBlock?"\n\n"+n.outerHTML+"\n\n":n.outerHTML},defaultReplacement:function(e,n){return n.isBlock?"\n\n"+e+"\n\n":e}},e),this.rules=new f(this.options)}function b(e){var n=this;return C.call(e.childNodes,function(e,t){t=new E(t,n.options);var r="";return 3===t.nodeType?r=t.isCode?t.nodeValue:n.escape(t.nodeValue):1===t.nodeType&&(r=O.call(n,t)),S(e,r)},"")}function D(e){var n=this;return this.rules.forEach(function(t){"function"==typeof t.append&&(e=S(e,t.append(n.options)))}),e.replace(/^[\t\r\n]+/,"").replace(/[\t\r\n\s]+$/,"")}function O(e){var n=this.rules.forNode(e),t=b.call(this,e),r=e.flankingWhitespace;return(r.leading||r.trailing)&&(t=t.trim()),r.leading+n.replacement(t,e,this.options)+r.trailing}function S(e,n){var t,r=function e(n){for(var t=n.length;t>0&&"\n"===n[t-1];)t--;return n.substring(0,t)}(e),i=(t=n).replace(/^\n*/,""),o=Math.max(e.length-r.length,n.length-i.length);return r+"\n\n".substring(0,o)+i}return k.prototype={turndown:function(e){if(null==(n=e)||"string"!=typeof n&&(!n.nodeType||1!==n.nodeType&&9!==n.nodeType&&11!==n.nodeType))throw TypeError(e+" is not a string, or an element/document/fragment node.");if(""===e)return"";var n,t=b.call(this,new A(e,this.options));return D.call(this,t)},use:function(e){if(Array.isArray(e))for(var n=0;n<e.length;n++)this.use(e[n]);else if("function"==typeof e)e(this);else throw TypeError("plugin must be a Function or an Array of Functions");return this},addRule:function(e,n){return this.rules.add(e,n),this},keep:function(e){return this.rules.keep(e),this},remove:function(e){return this.rules.remove(e),this},escape:function(e){return R.reduce(function(e,n){return e.replace(n[0],n[1])},e)}},k});let e=new TurndownService({codeBlockStyle:"fenced",strongDelimiter:"__"});e.addRule("codeBlock",{filter:"pre",replacement:function(e){let n=e.replace("\n\n","").replace("Copy code\n","").replace(/^`|`\n+/gm,"");return console.log("***",n),"\n```"+n+"\n```\n"}});let n=document.querySelectorAll("div."+answerClass),t="";n.forEach(n=>{let r=n.innerHTML.trim(),i=e.turndown(r);t+=i+"\n\n"}),console.log(t)}
Obtenir les request headers avec curl
curl -s -D - -o /dev/null <url>
-s
: Avoid showing progress bar-D -
: Dump headers to a file, but-
sends it to stdout-o /dev/null
: Ignore response body
Source : How to display request headers with command line curl - Stack Overflow
Astuces dans la console de navigateur
Lister les aliases dans Mailo
{
const aliases = Array.from(document.querySelectorAll(".cl_lst_td_elt")).map(el => el.textContent).join('\n');
console.log(aliases);
}
Lister les nouveautés de GitLab-CE
Entrer les lignes suivantes dans la console Javascript du navigateur
{
const version = document.querySelector("h1").textContent;
const wishesSections = [
"top-feature",
"primary-features",
"secondary-features",
];
const availableData =
'[data-original-title="Available in GitLab self-managed Free"]';
const notAvailable =
'[data-original-title="Not available in GitLab self-managed Free"]';
const [topFeatures, primaryFeatures, secondaryFeatures] = Array.from(
document.querySelectorAll(".content > section")
).filter((el) => wishesSections.includes(el.id));
const nestedElement = (el, overload, linkEl = "previousElementSibling") => {
const paths = overload.split(".");
let result = el.parentNode.parentNode.parentNode;
const doc =
result.parentNode.lastElementChild.firstElementChild.firstElementChild
.href;
const docLink = doc ? `[_(doc)_](${doc})` : "";
for (path of paths) {
result = result[path];
}
const link = result[linkEl];
return [`- [${result.textContent}](${link.href}) ${docLink}`];
};
const hideElements = (el, overload, linkEl = false) => {
const paths = overload.split(".");
let result = el.parentNode.parentNode.parentNode;
for (path of paths) {
result = result[path];
}
linkEl && result.previousElementSibling.style.display = "none";
result.style.display = "none";
};
Array.from(topFeatures.querySelectorAll(notAvailable)).forEach((el) =>
hideElements(el, "parentNode")
);
Array.from(primaryFeatures.querySelectorAll(notAvailable)).forEach((el) =>
hideElements(el, "parentNode.parentNode", true)
);
Array.from(secondaryFeatures.querySelectorAll(notAvailable)).forEach((el) =>
hideElements(el, "parentNode")
);
const primaryAvailable = Array.from(
primaryFeatures.querySelectorAll(availableData)
).map((el) =>
nestedElement(
el,
"parentNode.parentNode.previousElementSibling.firstElementChild.lastElementChild"
)
);
const secondaryAvailable = Array.from(
secondaryFeatures.querySelectorAll(availableData)
).map((el) => nestedElement(el, "previousElementSibling.lastElementChild"));
const finalResult = []
.concat(version, primaryAvailable, secondaryAvailable)
.join("\n");
console.log(finalResult);
const copyButton = document.createElement("button");
const defaultOpacity = "0.4";
copyButton.style.position = "fixed";
copyButton.style.margin = "20px";
copyButton.style.bottom = "0";
copyButton.style.zIndex = "10";
copyButton.style.backgroundColor = "teal";
copyButton.style.color = "wheat";
copyButton.style.fontSize = "1.5em";
copyButton.style.fontWeight = "bold";
copyButton.style.borderRadius = "10px";
copyButton.style.transition = "all 0.4s 0.1s ease-in";
copyButton.style.opacity = defaultOpacity;
copyButton.onmouseover = function () {
this.style.opacity = "1";
this.style.boxShadow = "black -3px 2px 6px";
this.style.transform = "translate(3px, -2px)";
};
copyButton.onmouseleave = function () {
this.style.opacity = defaultOpacity;
this.style.boxShadow = "unset";
this.style.transform = "translate(-3px, 2px)";
};
copyButton.innerHTML = "Copier la liste<br><em>Community Edition</em>";
document.body.insertBefore(copyButton, document.body.firstChild);
const copyFunction = () => {
navigator.clipboard.writeText(finalResult).then(
() => {
console.log("Données copiées dans le presse-papier.");
},
(e) => {
console.error("Les données ne sont pas copiées…", e);
}
);
document.execCommand("copy");
};
copyButton.addEventListener("click", copyFunction);
}
Version Bookmarklet
Pour une utilisation régulière, il faut ajouter un marque-page, puis remplacer l'URL par le code suivant :
javascript: const version = document.querySelector("h1").textContent; const wishesSections = [ "top-feature", "primary-features", "secondary-features", ]; const availableData = '[data-original-title="Available in GitLab self-managed Free"]'; const notAvailable = '[data-original-title="Not available in GitLab self-managed Free"]'; const [topFeatures, primaryFeatures, secondaryFeatures] = Array.from( document.querySelectorAll(".content > section") ).filter((el) => wishesSections.includes(el.id)); const nestedElement = (el, overload, linkEl = "previousElementSibling") => { const paths = overload.split("."); let result = el.parentNode.parentNode.parentNode; const doc = result.parentNode.lastElementChild.firstElementChild.firstElementChild.href; const docLink = doc ? `[_(doc)_](${doc})` : ""; for (path of paths) { result = result[path]; } const link = result[linkEl]; return [`- [${result.textContent}](${link.href}) ${docLink}`]; }; const hideElements = (el, overload, linkEl = false) => { const paths = overload.split("."); let result = el.parentNode.parentNode.parentNode; for (path of paths) { result = result[path]; } if (linkEl) {result.previousElementSibling.style.display = "none"}; result.style.display = "none"; }; Array.from(topFeatures.querySelectorAll(notAvailable)).forEach((el) => hideElements(el, "parentNode") ); Array.from(primaryFeatures.querySelectorAll(notAvailable)).forEach((el) => hideElements(el, "parentNode.parentNode", true) ); Array.from(secondaryFeatures.querySelectorAll(notAvailable)).forEach((el) => hideElements(el, "parentNode") ); const primaryAvailable = Array.from( primaryFeatures.querySelectorAll(availableData) ).map((el) => nestedElement( el, "parentNode.parentNode.previousElementSibling.firstElementChild.lastElementChild" ) ); const secondaryAvailable = Array.from( secondaryFeatures.querySelectorAll(availableData) ).map((el) => nestedElement(el, "previousElementSibling.lastElementChild")); const finalResult = [] .concat(version, primaryAvailable, secondaryAvailable) .join("\n"); console.log(finalResult); const copyButton = document.createElement("button"); const defaultOpacity = "0.4"; copyButton.style.position = "fixed"; copyButton.style.margin = "20px"; copyButton.style.bottom = "0"; copyButton.style.zIndex = "10"; copyButton.style.backgroundColor = "teal"; copyButton.style.color = "wheat"; copyButton.style.fontSize = "1.5em"; copyButton.style.fontWeight = "bold"; copyButton.style.borderRadius = "10px"; copyButton.style.transition = "all 0.4s 0.1s ease-in"; copyButton.style.opacity = defaultOpacity; copyButton.onmouseover = function () { this.style.opacity = "1"; this.style.boxShadow = "black -3px 2px 6px"; this.style.transform = "translate(3px, -2px)"; }; copyButton.onmouseleave = function () { this.style.opacity = defaultOpacity; this.style.boxShadow = "unset"; this.style.transform = "translate(-3px, 2px)"; }; copyButton.innerHTML = "Copier la liste<br><em>Community Edition</em>"; document.body.insertBefore(copyButton, document.body.firstChild); const copyFunction = () => { navigator.clipboard.writeText(finalResult).then( () => { console.log("Donn%C3%A9es copi%C3%A9es dans le presse-papier."); }, (e) => { console.error("Les donn%C3%A9es ne sont pas copi%C3%A9es%E2%80%A6", e); } ); document.execCommand("copy"); }; copyButton.addEventListener("click", copyFunction);
Ensuite, le fait de cliquer sur le marque-page activera le script.
En ajoutant comme seul mot-clé : bm_gitlab
, cela me permet d'entrer ce mot-clé lorsque je suis sur la page de release de GitLab pour lancer directement le script.
Résultat
Exemple avec la page GitLab 16.0 released.
Les éléments ne correspondant pas à Self-Managed
Free
sont masqués sur la page.
Un bouton apparaît permettant de copier la liste suivante dans le presse-papier :
GitLab 16.0 Release
- Comment templates (doc)
- Update your fork from the GitLab UI (doc)
- New Web IDE experience now generally available (doc)
- Token rotation API (doc)
- Authenticate with Jira personal access tokens (doc)
- Import collaborators as an additional item to import (doc)
- Opt in to a new navigation experience (doc)
- Add or resolve to-do items on tasks, objectives, and key results (doc)
- GitLab Pages unique subdomains (doc)
- Pick custom colors for labels (doc)
- Real-time merge request updates (doc)
- Configurable maximum number of included CI/CD configuration files (doc)
- Create an instance runner in the Admin Area as a user (doc)
- GitLab Runner 16.0 (doc)
- REST API endpoint to create a runner (doc)
- Trigger job mirror status of downstream pipeline when cancelled (doc)
- Import Maven/Gradle packages by using CI/CD pipelines (doc)
- Placeholder for issue description in Service Desk automated replies (doc)
- Faster, easier Scala scanning in SAST (doc)
- SAST analyzer updates (doc)
- Option to disable followers (doc)
- Self-managed GitLab uses two database connections (doc)
- Filter GitHub repositories to import (doc)
- Limit session length for users (doc)
- Add emoji reactions on tasks, objectives and key results (doc)
- Change work item type from quick action (doc)
- Reorder child records for tasks, objectives and key results (doc)
- CI/CD components (doc)
- Create a group runner as a user (doc)
- Create project runners as a user (doc)
- Per-cache fallback cache keys in CI/CD pipelines (doc)
- Rate Limit for the projects/:id/jobs API endpoint reduced (doc)
- Download packages from the Maven Registry with Scala (doc)
- Display message when deploy freeze is active (doc)
- Secret Detection updates (doc)
- GitLab chart improvements (doc)
- Omnibus improvements (doc)
- Mark to-do items completed by other group or project owners Done (doc)
- Rate limit for unauthenticated users of the Projects List API (doc)
- Additional Registration Features available to Free users (doc)
Lister les mises à jour de WordPress
Entrer les lignes suivantes dans la console Javascript du navigateur
{
const names={plugins: "Extensions", themes: "Thèmes", translations: "Traductions"};
let result="";
const getUpgrades = (name) => {
const elements = Array.from(document.querySelectorAll(`[name=\"upgrade-${name}\"] .plugin-title > p > strong`));
if (!elements.length) {
return "";
};
const textContent = elements.map(el => `- ${el.textContent}`).join('\n');
return `${names[name]} :\n${textContent}\n`;
};
for (name in names) {
result = result.concat(getUpgrades(name));
};
console.log(result);
const copyButton = document.createElement("button");
const defaultOpacity = "0.4";
copyButton.style.position = "fixed";
copyButton.style.margin = "20px";
copyButton.style.bottom = "0";
copyButton.style.zIndex = "10";
copyButton.style.backgroundColor = "teal";
copyButton.style.color = "wheat";
copyButton.style.fontSize = "1.5em";
copyButton.style.fontWeight = "bold";
copyButton.style.borderRadius = "10px";
copyButton.style.transition = "all 0.4s 0.1s ease-in";
copyButton.style.opacity = defaultOpacity;
copyButton.onmouseover = function () {
this.style.opacity = "1";
this.style.boxShadow = "black -3px 2px 6px";
this.style.transform = "translate(3px, -2px)";
};
copyButton.onmouseleave = function () {
this.style.opacity = defaultOpacity;
this.style.boxShadow = "unset";
this.style.transform = "translate(-3px, 2px)";
};
copyButton.innerHTML = "Copier la liste";
document.body.insertBefore(copyButton, document.body.firstChild);
const copyFunction = () => {
navigator.clipboard.writeText(result).then(
() => {
console.log("Données copiées dans le presse-papier.");
},
(e) => {
console.error("Les données ne sont pas copiées…", e);
}
);
};
copyButton.addEventListener("click", copyFunction);
}
Version Bookmarklet
Pour une utilisation régulière, il faut ajouter un marque-page, puis remplacer l'URL par le code suivant :
javascript: const names={plugins: "Extensions", themes: "Thèmes", translations: "Traductions"}; let result=""; const getUpgrades = (name) => { const elements = Array.from(document.querySelectorAll(`[name=\"upgrade-${name}\"] .plugin-title > p > strong`));if (!elements.length) {return "";};const textContent = elements.map(el => `- ${el.textContent}`).join('\n');return `${names[name]} :\n${textContent}\n`;};for (name in names) {result = result.concat(getUpgrades(name));};console.log(result);const copyButton = document.createElement("button");const defaultOpacity = "0.4";copyButton.style.position = "fixed";copyButton.style.margin = "20px";copyButton.style.bottom = "0";copyButton.style.zIndex = "10";copyButton.style.backgroundColor = "teal";copyButton.style.color = "wheat";copyButton.style.fontSize = "1.5em";copyButton.style.fontWeight = "bold";copyButton.style.borderRadius = "10px";copyButton.style.transition = "all 0.4s 0.1s ease-in";copyButton.style.opacity = defaultOpacity;copyButton.onmouseover = function () {this.style.opacity = "1";this.style.boxShadow = "black -3px 2px 6px";this.style.transform = "translate(3px, -2px)";};copyButton.onmouseleave = function () {this.style.opacity = defaultOpacity;this.style.boxShadow = "unset";this.style.transform = "translate(-3px, 2px)";};copyButton.innerHTML = "Copier la liste";document.body.insertBefore(copyButton, document.body.firstChild);const copyFunction = () => {navigator.clipboard.writeText(result).then(() => {console.log("Données copiées dans le presse-papier.");},(e) => {console.error("Les données ne sont pas copiées…", e);});};copyButton.addEventListener("click", copyFunction);
Ensuite, le fait de cliquer sur le marque-page activera le script.
En ajoutant comme seul mot-clé : bm_wp
, cela me permet d'entrer ce mot-clé lorsque je suis sur la page de mise à jour de WordPress pour lancer directement le script.
Exporter des données du DOM dans un fichier .csv
{
let type = "text/csv;charset=utf-8"
const rows = Array.from(document.getElementsByTagName('tr')).map(el => `${el.children[0].textContent},${el.children[1].textContent}`).join('\n');
const blob = new Blob([rows], {type: type});
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl);
}
À adapter évidemment suivant les éléments à sélectionner dans la variable rows
.
Yt-dlp dans France.tv
{
const maxWidth = 1000;
const shebang = "#!/bin/sh\n";
const createTmpFile = "tempFile=$(mktemp)\n";
const autoClean = '\n\nwhile read line; do\nsed -i '' -e "${line}s/^/#/" script.sh\ndone < "${tempFile}"';
class Video {
constructor(video) {
const getElContent = (parent, selector) => parent.querySelector(selector).textContent.trim()
const title = getElContent(video, '.c-card-16x9__title');
const subtitle = getElContent(video, '.c-card-16x9__subtitle');
this.title = `${title} - ${subtitle}`;
this.link = video.firstChild.href;
}
dlp() {
const cli = `[ ! -e "${this.title}" ] && yt-dlp -w -f "b[width<${maxWidth}]/bv[width<${maxWidth}]+ba" -o "${this.title}.%(ext)s" ${this.link} && grep -nF "${this.title}" script.sh | awk -F ':' '{print $1;}' >> "$tempFile"`
return cli;
}
}
const videos = Array.from(document.querySelectorAll(".c-wall__item")).map((video) => (new Video(video)).dlp()).sort().filter((el,i,a) => i===a.indexOf(el)).join('\n');
const result = shebang.concat(createTmpFile, videos, autoClean);
console.log(result);
}
Supprimer plusieurs tickets d'un coup sur GitLab
But
Avoir des cases à cocher pour sélectionner les tickets que l'on souhaite supprimer.
À ce jour il n'est pas possible de les supprimer en série avec le Bulk edit
.
Script
Entrer dans la console des outils de développement le script suivant :
{
const deleteIssue = async (projectId, issueId) => {
fetch(
`https://<GITLAB_URL>/api/v4/projects/${projectId}/issues/${issueId}`,
{
method: "DELETE",
headers: {
"PRIVATE-TOKEN": "<PRIVATE_TOKEN>",
},
}
);
};
const issuesLi = Array.from(document.querySelectorAll("ul.issues-list > li"));
const issuesNb = Array.from(
document.getElementsByClassName("issuable-reference")
).map((el) => parseInt(el.innerText.trim().slice(1)));
const projectId = document.body.dataset.projectId;
console.log("Project ID:", projectId);
issuesLi.forEach((li, id) => {
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.className = "delete";
checkbox.style.marginRight = "1em";
checkbox.value = issuesNb[id];
li.insertBefore(checkbox, li.firstChild);
});
const deleteButton = document.createElement("button");
deleteButton.style.position = "fixed";
deleteButton.style.margin = "20px";
deleteButton.style.bottom = "20px";
deleteButton.style.zIndex = "1000";
deleteButton.style.backgroundColor = "darkred";
deleteButton.style.color = "wheat";
deleteButton.style.fontSize = "1.5em";
deleteButton.style.fontWeight = "bold";
deleteButton.style.borderRadius = "10px";
deleteButton.style.transition = "all 0.4s 0.1s ease-in";
deleteButton.onmouseover = function () {
this.style.boxShadow = "black -3px 2px 6px";
this.style.transform = "translate(3px, -2px)";
};
deleteButton.onmouseleave = function () {
this.style.boxShadow = "unset";
this.style.transform = "translate(-3px, 2px)";
};
deleteButton.innerHTML = "Supprimer les tickets";
document.body.insertBefore(deleteButton, document.body.firstChild);
const deleteFunction = () => {
const selectedCheckboxes = document.querySelectorAll(
"input:checked.delete"
);
selectedCheckboxes.forEach((el) => deleteIssue(projectId, el.value));
};
deleteButton.addEventListener("click", deleteFunction);
}
TODO
Ajouter le rechargement automatique à la fin de la suppression…
Adapter les valeurs :
-
<GITLAB_URL>
, l'URL de l'instance GitLab. -
<PRIVATE_TOKEN>
, la clé privée permettant les actions par l'API. Il faut être administrateur ou propriétaire du projet.
Utilisation
- Lancer le script avec les touches ctrl+⏎ (ou ⌘+⏎).
- Cocher les cases des tickets que l'on souhaite supprimer.
- Cliquer sur le bouton
Supprimer les tickets
.
Attention : Il n'y a pas de confirmation avant la suppression.
Il est possible d'en faire un bookmarklet en supprimant tous les retours à la ligne, ajouter javascript:
au départ puis coller tout ça dans un lien de marque-page du navigateur.
Obtenir l'URL pour l'abonnement d'agendas et de contacts iCloud
En gros, il faut aller sur icloud.com, se connecter à son compte, obtenir l'URL appelé quand on clique sur un nom d'agenda ou lorsqu'on rafraîchit la page de contacts. Il faut copier l'URL de la requête XHR.
Ensuite, utliser les scripts suivants (zsh sur MacOS)…
Agendas
read URL"?XHR URL ? " ; \
iCloud_SER=$(echo "$URL" | ggrep -Po '(?<=https:\/\/).*(?=-calendarws\.icloud\.com)') ; \
iCloud_CAL=$(echo "$URL" | ggrep -Po '(?<=ca\/collections\/).*(?=\?)') ; \
iCloud_ID=$(echo "$URL" | ggrep -Po '(?<=&dsid\=)\d*(?=&?)') ; \
echo "\n\nhttps://$iCloud_SER-caldav.icloud.com/$iCloud_ID/calendars/$iCloud_CAL/" ; \
unset URL iCloud_SER iCloud_CAL iCloud_ID
Source : Thunderbird iCloud calendar sync • my2cents
Contacts
read URL"?XHR URL ? " ; \
iCloud_SER=$(echo "$URL" | ggrep -Po '(?<=https:\/\/).*(?=-contactsws\.icloud\.com)') ; \
iCloud_ID=$(echo "$URL" | ggrep -Po '(?<=&dsid\=)\d*(?=&?)') ; \
echo "\n\nhttps://$iCloud_SER-contacts.icloud.com/$iCloud_ID/carddavhome/card/" ; \
unset URL iCloud_SER iCloud_ID
Claviers US
Source : British and American keyboards - Wikipedia.