Compare commits

...

6 Commits

  1. 80
      edit_bookmarks_dmenu.sh
  2. 60
      interface_dmenu.sh
  3. 66
      script.js
  4. 139
      signet.sh
  5. 196
      style.css

80
edit_bookmarks_dmenu.sh

@ -1,80 +0,0 @@
#!/bin/sh
# needs a better name
# - - - - - - - - - - - - - - - - ARGS - - - - - - - - - - - - - - - - -
show_help() {
echo "Usage:"
echo "1. Copy the desired Url to your clipboard"
echo "2. ./edit_bookmarks_dmenu.sh BOOKMARKS"
echo "Options:"
echo " --help Display this help message"
exit 1
}
if [ "$#" -eq 0 ]; then
echo "Nothing happened, I need a file of bookmarks to edit."
show_help
fi
while [ "$#" -gt 0 ]; do
case "$1" in
--help)
show_help
;;
-*)
echo "Error: Unknown option: $1" >&2
show_help
;;
esac
shift
done
dmenu_style() {
local font='junicode-18'
local normal_bg='#000000'
local normal_fg='#FFFFFF'
local selected_bg='#AAAAAA'
local selected_fg='#000000'
echo "-fn $font -nb $normal_bg -nf $normal_fg -sb $selected_bg -sf $selected_fg"
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --
# TODO : process multiple files of BOOKMARKS at once
BOOKMARKS=$1
URL=$(xclip -o -selection clipboard)
# The curl for Name: is a blocking process and will pause the programm
# in case internet shuts :^)
# TODO :
# add description, tags and color in one field with symbols such as :
# § this is a description. § comma, separated, tags § color
# If the given string ressembles to a url, continue.
# https://stackoverflow.com/questions/21115121/how-to-test-if-string-matches-a-regex-in-posix-shell-not-bash
# URL_REGEX="^(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]*[-A-Za-z0-9+&@#/%=~_|]"
if printf "$URL" | grep -q http; then
# TODO : incrementing id replacing <ol> list counter
#PREV_URL_COUNT=$(grep "URL: " $BOOKMARKS | wc -l)
#ID: $((PREV_URL_COUNT + 1))
# TODO : add the bookmark in reverse, last in first first on the stack
# maybe using tac instead of cat ?
cat <<- EOF >> $BOOKMARKS
URL: $(printf $URL)
Name: $(curl $URL | awk -v RS='</title>' '\
/<title>/ {gsub(/.*<title>/, ""); print}\
' | tr -d '\n')
Description: $(printf "" | dmenu -p "Enter a description: " $(dmenu_style))
Tags: $(printf "" | dmenu -p "Enter comma separated tags: " $(dmenu_style))
Date: $(date +%s)
EOF
else
printf "Text in clipboard is not a url"
exit
fi
# what we used to need htmlq for :
# name=$(curl $url | ~/.cargo/bin/htmlq title --text | sed -r '/^\s*$/d' | sed 's/^ *//g')

60
interface_dmenu.sh

@ -0,0 +1,60 @@
#!/bin/bash
# - - - - - - - - - - - - - - - - ARGS - - - - - - - - - - - - - - - - -
show_help() {
printf "
Usage:
1. Copy the desired URL to your clipboard
2. ./interface_dmenu.sh BOOKMARKS
Options:
--help Display this help message"
exit 1
}
if [ "$#" -eq 0 ]; then
printf "Nothing happened, I need a file of bookmarks to edit."
show_help
fi
while [ "$#" -gt 0 ]; do
case "$1" in
--help)
show_help
;;
-*)
printf "Error: Unknown option: $1" >&2
show_help
;;
esac
shift
done
dmenu_style() {
local font='junicode-18'
local normal_bg='#000000'
local normal_fg='#FFFFFF'
local selected_bg='#AAAAAA'
local selected_fg='#000000'
echo "-fn $font -nb $normal_bg -nf $normal_fg -sb $selected_bg -sf $selected_fg"
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --
URL=$(xclip -o -selection clipboard)
if [ "${URL#"http"}" != "$URL" ]; then
DESC=$(dmenu -p "$URL · description →" $(dmenu_style))
TAGS=$(dmenu -p "$URL · $DESC · tags →" $(dmenu_style))
cat <<- EOF > signet
URL: $URL
Description: $DESC
Tags: $TAGS
Date: $(date +%g/%m/%d)
EOF
./edit.sh
else
printf "Text in clipboard is not a url"
exit
fi

66
script.js

@ -1,59 +1,19 @@
//document.addEventListener("keydown", function(event) { const textarea = document.querySelector('textarea')
// var keyPressed = event.key.toLowerCase();
// function updateValue(e) {
// if (keyPressed === 'p') { let val = textarea.value.toLowerCase()
// const val = Math.round(Math.random()*255) document.querySelectorAll('.signets tr').forEach((e) => {
// document.querySelector('body').style.background = `rgba(${val},${val /2},${val})` var listItemText = e.innerHTML.toLowerCase();
// console.log("The 'P' key was pressed"); listItemText.includes(val) ?
// } e.classList.remove('hidden') : e.classList.add('hidden')
//}); })
// Barre de recherche
$(document).ready(function () {
$('li').addClass('active')
$('textarea').on('input', function () {
var userInput = $(this).val().toLowerCase();
$('li').each(function () {
var listItemText = $(this).text().toLowerCase();
if (listItemText.includes(userInput)) {
$(this).addClass('active');
} else {
$(this).removeClass('active');
}
});
});
});
// On convertit les dates au format AA-MM-JJ
function formatDateFromEpoch(epochTime) {
const date = new Date(epochTime * 1000);
const YY = date.getFullYear().toString()
const MM = ('0' + (date.getMonth() + 1)).slice(-2)
const DD = ('0' + date.getDate()).slice(-2)
if(epochTime == ''){
return `N/A`;
}
return `${YY}/${MM}/${DD}`;
} }
const dates = document.querySelectorAll('h4') document.addEventListener("DOMContentLoaded", function(event) {
dates.forEach((date) => { textarea.addEventListener("input", updateValue);
date.innerHTML= formatDateFromEpoch(date.innerHTML)
})
// On cache les descriptions si elles sont vides
$('h2').each(function() {
$(this).html() == '' ? $(this).hide() : $(this).show()
}) })
// On colore les entrées qui ont un attribut 'color' document.querySelectorAll('[color]').forEach((e) => {
$('[color]').each(function() { e.style.background = `linear-gradient(var(--background), ${e.getAttribute('color')} `
$(this).css('background', `linear-gradient(var(--background), ${$(this).attr('color')} `)
}) })

139
signet.sh

@ -31,7 +31,7 @@ while [ "$#" -gt 0 ]; do
if [ -f "$1" ]; then if [ -f "$1" ]; then
break break
else else
echo "The file you provided doesn't seam to exist : $1" echo "The file provided doesn't seem to exist : $1"
exit 1 exit 1
fi fi
;; ;;
@ -40,77 +40,102 @@ while [ "$#" -gt 0 ]; do
done done
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --
# I thought about using recutils db from GNU but went back to plain text blanklineRecords_to_html()
# DB=BOOKMARKS.rec {
DB=$1
cat <<- EOF
<!DOCTYPE html>
<html>
<head>
<title>⛵ → $(date "+%g-%m-%d, %H:%M")</title>
<script defer src="jquery-3.7.1.slim.min.js"></script>
<script defer src="script.js"></script>
<link rel="stylesheet" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<div id="cc"></div>
<textarea autofocus></textarea>
<nav>
$(
awk '/Tags: ./ {print tolower($0)}' $DB |\
sed -e 's/tags: //' -e 's/,/\n/g' | sed 's/^ //g' |\
sort | uniq -c | sort -nr |\
awk '{print "<p count=\"" $1 "\">" $2 "</p>"}'
)
</nav>
<ol>
$(
awk -v RS= '!/Tags: .*hide/ {print $0 "\n"}' $DB |\
awk -v RS= ' awk -v RS= '
{ {
if ($0 != "") { if ($0 != "") {
id=""
URL=""
DESC=""
TAGS=""
DATE=""
color=""
split($0, lines, "\n") split($0, lines, "\n")
color = ""
for (i in lines) { for (i in lines) {
if(lines[i] ~ /^[0-9]+$/ ) {
id=lines[i]
}
split(lines[i], parts, ": ") split(lines[i], parts, ": ")
field = parts[1] field = parts[1]
value = parts[2] value = parts[2]
if (field == "Color") {
color = value
}
vals[i] = value
}
URL=vals[1]
NAME=vals[2]
DESC=vals[3]
TAGS=vals[4]
DATE=vals[5]
print "<li>" if(field ~ /^Color/ ) {color=value}
print "<a href=\"" URL "\">" if(field ~ /^URL/ ) {URL=value }
if(field ~ /^Name/ ) {NAME=value }
if(field ~ /^Description/ ) {DESC=value }
if(field ~ /^Tags/ ) {TAGS=value }
if(field ~ /^Date/ ) {DATE=value }
if (color != "") {
print "<section color=\"" color "\">"
}
else {
print "<section>"
} }
print "<h4>" DATE "</h4>" \ if(color != ""){
"<h1>" NAME "</h1>" \ printf "<tr color=\"%s\">", color
"<h5>" URL "</h5>" \ }
"<h2>" DESC "</h2>" \ else{
"<h3>" TAGS "</h3>" printf "%s", "<tr>"
}
printf "<td class=\"id\">%d</td>", id
print "</section>" printf "<td><a href=\"%s\">%s</a>\n", URL, NAME
print "</a>" if(DESC != "") {printf "<p class=\"desc\">%s</p>\n", DESC}
print "</li>" printf "</td>"
printf "<td><p class=\"tags\">%s</p></td>\n", TAGS
printf "<td><date>%s</date></td>\n", DATE
print "</tr>"
} }
} ' } '
}
DB=$1
cat <<- EOF
<!DOCTYPE html>
<html>
<head>
<title>⛵ → $(date "+%g-%m-%d, %H:%M")</title>
<link rel="stylesheet" href="style.css">
<script defer src="script.js"></script>
<meta charset="utf-8" />
</head>
<body>
<p>liens épinglés</p>
<table class="PIN">
$(
cat $DB |\
awk -v RS= '/PIN/ {print $0 "\n"}' | blanklineRecords_to_html
)
</table>
<hr>
<textarea rows="1" autofocus placeholder="filtrer..."></textarea>
<hr>
<details>
<summary>tags</summary>
<nav>
$(
awk '/Tags: ./ {print tolower($0)}' $DB |\
sed -e 's/tags: //' -e 's/,/\n/g' | sed 's/^ //g' |\
sort | uniq -cd | sort -nr |\
awk '{print "<button count=\"" $1 "\">" $2 "</button>"}'
)
</nav>
</details>
<hr>
<table class="signets">
<thead><tr>
<td>#</td>
<td>Title, URL, description</td>
<td>tags</td>
<td>y/m/d<rtd>
</tr></thead>
$(
cat $DB |\
blanklineRecords_to_html
) )
</ol> </table>
<footer></footer> <footer></footer>
</body> </body>
</html> </html>

196
style.css

@ -1,24 +1,15 @@
/* h1 Name :root{
* h2 Description --font-size:12px;
* h3 Tags --line-height:16px;
* h4 Date --gap:2px;
* h5 Url --height:calc(var(--line-height) + var(--gap) * 2);
*/
:root {
--font-size:22px;
--font-size-s:calc(var(--font-size) / 1.5);
--line-height:24px;
--date-width:10ch;
--gutter:0px;
--padding:2px;
--height:auto; --height:auto;
--color:black; --width-number:2em;
--selection:purple; --background:#FEFEFE;
--background:#FFF; --link:purple;
--background-2:#FEFEFE; --text:black;
--background-bottom:black; --selection:lightyellow
} }
/* https://github.com/psb1558/Junicode-font/releases */
@font-face { @font-face {
font-family: Junicode; font-family: Junicode;
src: url("Junicode-CondLight.otf") format("opentype"); src: url("Junicode-CondLight.otf") format("opentype");
@ -32,158 +23,53 @@
font-family: Junicode, serif; font-family: Junicode, serif;
font-variant-numeric: lining-nums; font-variant-numeric: lining-nums;
} }
h1,h2,h3,h4,h5,p, a {
text-wrap:wrap;
word-break: break-word;
line-height:var(--line-height);
padding:0;
margin:0;
font-weight:normal;
font-size:var(--font-size);
}
h1,h2,h3,h5 {
display:inline;
}
nav, section, textarea {
padding: var(--padding) 0;
}
a{
width:100%;
display:block;
color:var(--color);
text-decoration:none;
margin:auto;
textarea {width:100%;padding:0;margin:0;
border:1px dotted black;
height:var(--height)
} }
h5 {
text-decoration:underline }
li:hover a {
color:var(--selection)}
.PIN date, .PIN .tags, .PIN .id {display:none}
tr a{color:var(--text); text-decoration:none}
tr a::after{
margin-left:5px; content:attr(href); color:var(--link);
text-decoration:underline}
textarea{ li:hover a::after{display:block}
position:fixed;
top:0;
left:5px;
z-index:10;
width:calc(100vw - 10px);
font-size:var(--font-size);
height:calc(var(--line-height) + var(--padding));
}
ol {
margin:0;
display:flex;
gap:var(--gutter);
flex-direction:column-reverse;
} tbody tr:hover {background:var(--selection)}
body {
td {line-height:var(--line-height);
height:var(--height);
border-bottom: 1px solid black;
padding: var(--gap) 5px;
word-break:break-word;
} }
footer {
height:100vh;
margin-top:50vh;
background:linear-gradient( var(--background), var(--background-bottom));
width:calc(100% + 20px - 2px);
margin-left:-10px;
margin-bottom:-10px;
overflow:hidden;
}
li {
font-size:var(--font-size);
color:rgba(0,0,0,0);
height:0;
overflow:hidden
}
li * {opacity:0}
.active:nth-of-type(2n){
background:var(--background-2);
table {
border-collapse:collapse;
border: 1px dotted black;
} }
li,textarea, nav {
box-sizing:border-box;
border:none;
} hr{ border:none;
.active * {opacity:1}
.active {
border-bottom: 1px solid black; border-bottom: 1px solid black;
height:var(--height);
display:list-item;
color:var(--color);
overflow:visible;
}
h1,h2,a {
}
h3{
opacity:.5
}
section{
padding-right:var(--date-width);
height:calc(var(--font-size) + 2px) ;
overflow:hidden;
} }
section:hover{
height:auto
}
section:hover h1, h2, h3, h5{
display:inline
}
h1 {order: 0;
}
h2 {
font-style:italic}
h5,h2,h3,h4 {
order:3
}
h3::before, h2::before, h1::after{content:'\00a0·\00a0';}
h4 {
width:var(--date-width);
width:fit-content;
text-align: right;
button::after {
content:" "attr(count);
position:absolute; position:absolute;
right:10px; transform:translate(1px, -5px)
} }
html{background:white}
nav p {display:inline;
}
nav p:not(:first-of-type)::before{
content:'· '
}
nav p::after{
font-size:var(--font-size-s);
display:inline-block;
transform:translateY(-7px);
content:'\00a0(' attr(count) ')'
}
nav {
border-top: 1px solid black;
border-bottom: 1px solid black;
margin-top:calc(var(--line-height) + 1px + var(--padding));
height:calc(var(--line-height) + var(--padding) * 2);
overflow:hidden;
} button{background:transparent;border:none}
nav:hover {height:auto}
#cc {
display:absolute;
position:fixed;
top:0;
left:0;
z-index:10;
height:100vh;
width:100vw;
pointer-events:none;
background:linear-gradient(0deg, yellow, ivory);
mix-blend-mode:multiply;
/* A color correction pass, enable it by removing this line ↓ */ p{margin:0;display:inline}
display:none .desc {opacity:.5}
}
td:last-of-type {text-align:center;min-width:8ch}
td:first-of-type {text-align:center;width:4ch}
td:nth-of-type(3) {text-align:center}
.hidden{display:none}
tr,table {min-width:100%}

Loading…
Cancel
Save