v2 : no more dependy to jquery, signet generates <table> instead of <ol>

This commit is contained in:
clemtre 2024-03-22 14:18:59 +01:00
parent dd65be059f
commit 8abd7f50d1
5 changed files with 204 additions and 353 deletions

View File

@ -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 Executable file
View File

@ -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

View File

@ -1,59 +1,19 @@
//document.addEventListener("keydown", function(event) {
// var keyPressed = event.key.toLowerCase();
//
// if (keyPressed === 'p') {
// const val = Math.round(Math.random()*255)
// document.querySelector('body').style.background = `rgba(${val},${val /2},${val})`
// console.log("The 'P' key was pressed");
// }
//});
const textarea = document.querySelector('textarea')
// 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}`;
function updateValue(e) {
let val = textarea.value.toLowerCase()
document.querySelectorAll('.signets tr').forEach((e) => {
var listItemText = e.innerHTML.toLowerCase();
listItemText.includes(val) ?
e.classList.remove('hidden') : e.classList.add('hidden')
})
}
const dates = document.querySelectorAll('h4')
dates.forEach((date) => {
date.innerHTML= formatDateFromEpoch(date.innerHTML)
document.addEventListener("DOMContentLoaded", function(event) {
textarea.addEventListener("input", updateValue);
})
// 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'
$('[color]').each(function() {
$(this).css('background', `linear-gradient(var(--background), ${$(this).attr('color')} `)
document.querySelectorAll('[color]').forEach((e) => {
e.style.background = `linear-gradient(var(--background), ${e.getAttribute('color')} `
})

141
signet.sh
View File

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

212
style.css
View File

@ -1,24 +1,15 @@
/* h1 Name
* h2 Description
* h3 Tags
* h4 Date
* h5 Url
*/
:root {
--font-size:22px;
--font-size-s:calc(var(--font-size) / 1.5);
--line-height:24px;
--date-width:10ch;
--gutter:0px;
--padding:2px;
:root{
--font-size:12px;
--line-height:16px;
--gap:2px;
--height:calc(var(--line-height) + var(--gap) * 2);
--height:auto;
--color:black;
--selection:purple;
--background:#FFF;
--background-2:#FEFEFE;
--background-bottom:black;
--width-number:2em;
--background:#FEFEFE;
--link:purple;
--text:black;
--selection:lightyellow
}
/* https://github.com/psb1558/Junicode-font/releases */
@font-face {
font-family: Junicode;
src: url("Junicode-CondLight.otf") format("opentype");
@ -32,158 +23,53 @@
font-family: Junicode, serif;
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{
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;
li:hover a::after{display:block}
}
body {
tbody tr:hover {background:var(--selection)}
}
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);
}
li,textarea, nav {
box-sizing:border-box;
border:none;
}
.active * {opacity:1}
.active {
border-bottom: 1px solid black;
td {line-height:var(--line-height);
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;
position:absolute;
right:10px;
}
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;
}
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 ↓ */
display:none
padding: var(--gap) 5px;
word-break:break-word;
}
table {
border-collapse:collapse;
border: 1px dotted black;
}
hr{ border:none;
border-bottom: 1px solid black;
}
button::after {
content:" "attr(count);
position:absolute;
transform:translate(1px, -5px)
}
button{background:transparent;border:none}
p{margin:0;display:inline}
.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%}