Git Product home page Git Product logo

static-marks's Introduction

Static Marks

Build npm license

Convert your plain bookmark files into a static web app.

YAML to App diagram

  • Share your bookmarks app via a single self-contained HTML file.
  • Use with any modern browser.
  • Import bookmarks from Chrome, Firefox or Pocket.
  • It's free and open source.

🔖 View Live Demo

Demo

Static Marks Screencast

Features

  • Use custom browser search engines with a ?search=%s URL param (example).
    • In Firefox, right-click the Static Marks search field and select "Add a Keyword for this Search".
  • Use custom web page templates. If you don't like the default UI, provide your own (example based on this template).
  • Dark Mode.

Quickstart

npm install -g static-marks
  • Create a plain text bookmarks.yml YAML file containing your bookmarks. Alternatively, import your existing browser bookmarks:
static-marks import browser-bookmarks.html > bookmarks.yml
  • Build your bookmarks app:
static-marks build bookmarks.yml > bookmarks.html
  • Open bookmarks.html in your browser.

Installation

This tool requires Node.js version 12+.

  • As a globally available CLI tool:
npm install -g static-marks
  • As a local dependency in your project:
npm install --save static-marks
  • Without installing:
npx static-marks <command>

Usage

static-marks [options] <command>

Options:
  -V, --version               output the version number
  -h, --help                  output usage information

Commands:
  build [options] <files...>  build bookmarks app
  import [options] <file>     import bookmarks from chrome, firefox or pocket
  report <files...>           report bookmarks

Run static-marks <command> --help to view the usage of a specific command.

Build bookmarks app

static-marks build [options] <files...>

Options:
  -o, --output [file]     output to a file (use stdout by default)
  -t, --title [title]     set document title
  --template-file [file]  use a custom web page template

Examples:

static-marks build -o bookmarks.html bookmark.yml  # Single file
static-marks build bookmarks.yml > bookmarks.html  # Alt. notation
static-marks build f1.yml f2.yml > bookmarks.html  # Multiple files
static-marks build files/* > bookmarks.html        # All files at path

Import bookmarks

static-marks import [options] <file>

Options:
  -o, --output [file]  output to a file (use stdout by default)

Examples:

static-marks import exported.html > imported.yml
static-marks import -o imported.yml exported.html

View a report for your bookmarks

Currently, the report contains only the total bookmarks count. In the future, it might be used for detecting duplicate and dead links.

static-marks report [options] <files...>

Examples:

static-marks report bookmarks.yml
static-marks report files/*

File format

Bookmark files are written in YAML. There are multiple levels of hierarchy:

Collection:
  - Bucket:
      - Link: https://example.com

A link URL can be expressed either as an item property or as a child item:

- Link 1: https://example.com
- Link 2:
    - https://example.com

Notes and nested links are added as children of a link (the first element is the link URL). If the text is a valid-formatted URL it will be automatically converted to a link:

- Link with notes:
    - https://example.com
    - This is a text note
    - Link note: https://example.com
    - https://example.net

First-level notes can be used to describe or structure a bucket:

- Bucket:
    - Link 1: https://example.com
    - Carpe diem!

Here's a complete example:

Collection:
  - Bucket:
      - Link 1: https://example.com
      - Link 2:
          - https://example.com
      - Link with notes:
          - https://example.com
          - This is a text note
          - Link note: https://example.com
      - First-level note

There is an optional 1st level hierarchy level available when you provide more than one bookmark file to static-marks. When passing multiple files, a header menu will be displayed to toggle between individual files and all bookmarks.

# file toggle menu not necessary/not available
static-marks build file1.yaml

# file toggle menu available
static-marks build file1.yaml file2.yaml

Troubleshooting

Encoding issues

You can use both > to pipe the results of a static-marks command or the -o to provide an explicit output file. There might be cases where the > variant doesn't play well with the shell encoding, though.

See #46 for more information.

Using Static Marks with Gitlab Pages

You can leverage GitLab Pages to host your Static Marks instance. Check out the example repository and a live demo.

  1. Create a new GitLab repository.
  2. Include the example .gitlab-ci.yml file in the root directory.
  3. Add all your bookmark *.yml files in a bookmarks directory.

After every push to the master branch, your Static Marks page will be rebuilt. By default, it will be available at https://<USERNAME>.gitlab.io/<PROJECTNAME>.

Development and Contribution

The frontend part of Static Mark is maintained in another repository, where a template file (_template.html) is being generated. This approach makes it possible to include the whole application and user-defined bookmarks in a single HTML file.

If you want to provide any frontend-related changes, please create a PR in the other repository. Changes to the core CLI application are handled here instead.

Contributors

Thanks goes to these wonderful people:

darekkay gaerfield kaushalyap k-kalinowski g33k247 dzmitry-lahoda diegombeltran veerreshr nausher acer123acer123
jflip e-minguez iaeiou Jiehong RishiKumarRay overflowy

This project follows the all-contributors specification to acknowledge all contributions.

License

This project and its contents are open source under the MIT license.

static-marks's People

Contributors

acer123acer123 avatar allcontributors[bot] avatar darekkay avatar jflip avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

static-marks's Issues

List duplicate links in the report

The report command introduced in 2.1.0 returns the total number of links. This command should be improved to also find and list all duplicate links. There might be valid use cases for having duplicate links, so there should be a flag to disable this feature within report command (e.g. --no-duplicates).

[Request] Add icons to bookmarks links

Hi,

instead of the standard svg icon beside the link bookmark-svg

I would like to have (as other users) the ability to change it to a local or remote icon file.

That would help a lot as an icon ico is more speaking than a text.

Before: After:
static-marks-before static-marks-after

Suggestion of formating

Collection:
  - Bucket:
      - url: https://example.com/
      - ico: example.png

or (google favicon api)

Collection:
  - Bucket:
      - url: https://example.com/
      - ico: https://www.google.com/s2/favicons?domain=${domain}&sz=${size}

or (base64)

Collection:
  - Bucket:
      - url: https://example.com/
      - ico: data:image/png;base64,...

Anything that works is welcome.

// update

Here https://github.com/maximtrp/tab a lite similar project by @maximtrp with icons integration capability.

In search for ultimate bookmarks view

I have tried static-marks. And it does not work for me.

I have 10K bookmarks. I use tags, I do not use directories to split them. So tagless view does not work for me.

Are you aware of any view with tag cloud and hierarchical tag faceting and local search build in? So I can export my knowledge graph for ease of search and use.

I would like to share my knowledge with people by giving them links to tagged searches on my jamstack.

Open links in new tab?

Hi,
sorry for the question, I use this for some time now but did update to the current version just some weeks ago. Sometime the default behavior was to open links in new tabs or windows - has this changed, can I get this back somehow?

Thanks

Treat notes starting with "http" as links

There are currently two types of notes: text notes and link notes (nested links).

Example bookmarks file:

Collection:
  - Bucket:
    - Link:
      - https://example.com
      - Text note
      - Link note: https://example.com
      - https://example.com

The current result:

image

It would be nice to turn text notes automatically into clickable links if they start with http (or maybe even other supported protocols).

Support non-HTML templates

Static Marks supports custom templates. The logic is not flexible, though. It depends on the way the default template (Static Marks App) works: bookmarks are injected as plain text and require the template to use JavaScript to access them.

The logic should be adjusted to support transforming bookmarks into any other format. This will also open up the project and simplify migrating to other projects. An opinionated template language (e.g. ejb, handlebars or nunjucks) can be predefined.

Related: #44

Github running problem

Hi. I currently use github to run the project. I want to specify a template, but the template has not been effective, what is the reason?

template.html Uploaded project

Configuration:

  - name: Install and Build 🔧
    run: |
      npm install static-marks
      mkdir build
      ./node_modules/.bin/static-marks build --template-file template.html *.yml > build/index.html 

Build File Doesn't Render Properly

I've installed static marks. I exported my Chrome bookmarks to an html file. I can open that file in a browser and it renders fine.

The import to static marks works fine (no errors are thrown).

The build *.yml to *.html also appears to work fine and throws no errors.

When I open the build bookmarks.html file, it does not render properly like your demo page (except for the header).

What am I doing wrong?

Screenshot_20190513_175446

First-level notes should not count as bookmarks

The test/examples/definitions.yml file contains 10 links and one first-level note ("First level note"). However, running static-marks report returns 11, because the note currently counts as a link.

Actual:

expected cli output

Expected:

actual cli output

How to modify the title?

Modified the template file, but it will be replaced by the default

Environment: github-page

template part code:
`

<script>var injected="%INJECTED%"</script>
<title>Bookmarks</title>
<script>(function() {
  document.documentElement.dataset.theme = localStorage.getItem("theme")
    || (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "default");
})();</script>
<script type="module" crossorigin>var Mc=Object.defineProperty,Oc=Object.defineProperties;var Fc=Object.getOwnPropertyDescriptors;var ir=Object.getOwnPropertySymbols;var Zi=Object.prototype.hasOwnProperty,bi=Object.prototype.propertyIsEnumerable;var Ji=(e,t,n)=>t in e?Mc(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Rt=(e,t)=>{for(var n in t||(t={}))Zi.call(t,n)&&Ji(e,n,t[n]);if(ir)for(var n of ir(t))bi.call(t,n)&&Ji(e,n,t[n]);return e},Ml=(e,t)=>Oc(e,Fc(t));var Ol=(e,t)=>{var n={};for(var r in e)Zi.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&ir)for(var r of ir(e))t.indexOf(r)<0&&bi.call(e,r)&&(n[r]=e[r]);return n};window.regeneratorRuntime=void 0;const Ic=function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))r(l);new MutationObserver(l=>{for(const o of l)if(o.type==="childList")for(const i of o.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&r(i)}).observe(document,{childList:!0,subtree:!0});function n(l){const o={};return l.integrity&&(o.integrity=l.integrity),l.referrerpolicy&&(o.referrerPolicy=l.referrerpolicy),l.crossorigin==="use-credentials"?o.credentials="include":l.crossorigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(l){if(l.ep)return;l.ep=!0;const o=n(l);fetch(l.href,o)}};Ic();var R={exports:{}},M={};/**

`

Too large size of bookmark-file

Hi Darek

thanks for Static Marks.
I've noticed that my output file is quite large for a few html links, approx. 200 kb.
This could be a problem on small data plans and mobile use, although some of the content might be cached on the mobile.
I have 60+ links in several boxes, however, I wouldn't need the search bar. Also, I don't need the collapse/expand feature for links.
The output file should not be as big as 200 kb, and I think a static html file could be much smaller in file size.

Is it possible to create a more simple static bookmark file, e.g. with command line arguments?

Greetings,
Heiko

[feature] improve the ease with which the search field can be added as a search engine in the browser (firefox)

Hi,

Today, the documentation says that the bookmarks can be used as a search engine by using https://darekkay.com/static-marks/demo/default.html?search=%s.

Which is great (really!)

However, when right-clicking on the search field, the browser does not seem to allow you to do that automatically, even though it should (here, with Firefox 96).

There is a way to fix that easily, though: by converting the <div class="filter" role="search"> to a form, and giving a name to the input field:

<form class="filter" role="search">
  <div class="filter-button empty">
    <button type="button" class="btn-unstyled" aria-label="Clear filter" disabled="">
      <div class="icon icon-search"></div>
    </button>
  </div>
  <input aria-label="Search everywhere" type="search" class="input" placeholder="Search everywhere..." name="search">
</form>

(No visual change for the user).

With this, (in Firefox), you can right-click the search field, and select "Add a keyword for this search", and it will smartly understand that you want to use https://darekkay.com/static-marks/demo/default.html?search=%s as the search term.

This feature has been removed in Chrome for a few years already, so this won't help there.

File collapsing and file order

Hello, and first of all, congratulations. I love your idea.

I've been using it for a while and I really like it. I wonder how hard implementing file collapse and file order would be. That way you would be able to hide one of the files in case it's full of links (for instance, awesome.yml), and also, establish which file should be first. Currently, I'm not sure which sort order uses.

I'm not a front developer, so I'm not sure I could help, but, I think it could be possible by modifying template file, couldn't it?

Nested hierarchy levels?

I try to understand the YAML syntax. In your demo ur'e using nested Links inside a sub-menu (Icons->Font Awesome). Can you provide the YAML syntax or the source for that?
Regards

Importing Bookmark Export HTML file from Raindrop.io doesn't show any URLs

I exported my bookmarks from raindrop.io as an HTML export.
The format used is similar to the one used by Google Bookmarks ( See sample below).

But Static marks did not pick up these bookmarks, the generated yml file is empty (also below).

Sample record from the exported HTML file

<DT><H3 ADD_DATE="0" LAST_MODIFIED="0">Speed Dial</H3>
<DL><p>
</DL><p>
<DT><H3 ADD_DATE="0" LAST_MODIFIED="0">Unsorted</H3>
<DL><p>
<DT><A HREF="https://www.readthistwice.com/person/paul-graham" ADD_DATE="1596669210" LAST_MODIFIED="1596669220" TAGS="Read Later,books,fun,interesting">89 books Paul Graham recommended</A>
<DD>(Updated 2020) The most up to date and comprehensive list of 89 verified book recommendations from Paul Graham. Includes quotes and sources.

sample_ bookmarks.yml file


Imported:
  - root: []


This software looked quite promising as I was hoping to store my bookmarks locally/my own cloud.
But looks like I'm facing issues getting started/importing bookmarks.

Add Dark Mode

Prerequesites:

  • CSS colors should be refactored into CSS custom properties
  • SVGs have to be moved out of CSS (base64) into the markup to allow changing their colors. To keep the markup size small, the SVGs should probably be reused via <use> (MDN).

TODO:

  • Define dark theme, probably based on this.
  • Add theme switcher

All changes have to be done in this repository.

Force dark mode?

I use dark colour schemes on all of my devices.

On some of them, the prefers-colour-scheme: dark handling doesn’t work (or only works after a refresh). I believe this is due to bugs outside of my control in the system or browser software.

Is there a way to hardcode my static marks page to always use the dark theme?

Error unclear if column is forgotten

Issue

When running static mark, the following error occurs:

static-marks build --title 'Personal Bookmarks' ./bookmarks.yml > ./html/index.html
× Could not convert YAML file: /Users/username/dev/personal-static-files/bookmarks.yml
  bucket[bucketName].map is not a function
× Process aborted: at least one YAML file is malformed.

This happens because I forgot 1 level, and can be reproduced with the following yml file:

Section:
  - test: http://github.com

The problem is that it's expecting a level in between to name the column, but I didn't realise, and I thought the error must be coming from characters to to escape in the url or to quote something to make it a valid yaml.

The fix is simple, but unrelated to the yaml being mal formatted:

Section:
  - Column:
    - test: http://github.com

Expected behaviour

The error message should be more accurate, as in this case the yaml file is not malformed, but its structure is not the one expected, and the message bucket[bucketName].map is not a function is meaningless to the user.

Instead, it should be detected that a level is missing, or something, and tell the user about it, maybe with an example.

Header's menu not present

Hi,

In the demo, the header has 2 div classes: a filter and a menu.

However, when using version 2.3.0, only the filter div is present, and the menu is not present at all.

No custom template is used.

Environment:

node 16, installed with yarn (yarn add global static-marks).

Screenshot of the issue:

image

Screenshot of the demo that is correctly:

image

Non-minified version of default template

Hi,

is it possible to provide non-minified version of the default page template provided with static-marks? I'd like to add autofocus to the search input and the current minified version doesn't lend itself to such modifications ;)

static-marks returns no error when it failed to parse the yml-file

Given the following bookmarks-yaml-file:

test:
  - duckduckgo: https://duckduckgo.com/
    - more duck: https://duckduckgo.com/

static-marks will output an error (which is absolutely fine), but the return value is still '0':
image

Further information: Within an automatic build, this will result in a html-file containing no links whereas the build just runs fine. This finally results in overwriting a fine version of a page with an empty one.

Implicit labels for links

A suggestion that would help users like myself that tend to remove the labels from links in bookmark bars and rely on favicons like so
image

While this makes for a nice and clean bookmark bar it kind of messes with this project and has a result like this
image

My suggestion would be that when creating the .yml file, if no label exists for the link, just use the link as an 'implicit' label.
So instead of

We'd have the output

Would love to give this a go if you think it is a good idea 👍

Warning about 2 severe vulnerabilities after 'npm install'

Hello there,

I get this warning from npm after a fresh install following the documentation:

4 vulnerabilities (2 low, 2 high)

More informations with npm audit report

$ npm audit
axios  <0.21.1
Severity: high
Server-Side Request Forgery - https://npmjs.com/advisories/1594
fix available via `npm audit fix --force`
Will install [email protected], which is a breaking change
node_modules/axios
  static-marks  *
  Depends on vulnerable versions of axios
  Depends on vulnerable versions of mkdirp
  node_modules/static-marks

minimist  <0.2.1 || >=1.0.0 <1.2.3
Prototype Pollution - https://npmjs.com/advisories/1179
fix available via `npm audit fix --force`
Will install [email protected], which is a breaking change
node_modules/minimist
  mkdirp  0.4.1 - 0.5.1
  Depends on vulnerable versions of minimist
  node_modules/mkdirp
    static-marks  *
    Depends on vulnerable versions of axios
    Depends on vulnerable versions of mkdirp
    node_modules/static-marks

4 vulnerabilities (2 low, 2 high)

How to reproduce?

run npm install static-marks, that's all

My setup:

Debian 10, static-marks 2.2.4
and

$ npm version
npm version
{
  npm: '7.5.1',
  node: '15.8.0',
  v8: '8.6.395.17-node.23',
  uv: '1.40.0',
  zlib: '1.2.11',
  brotli: '1.0.9',
  ares: '1.17.1',
  modules: '88',
  nghttp2: '1.42.0',
  napi: '7',
  llhttp: '2.1.3',
  openssl: '1.1.1i',
  cldr: '38.1',
  icu: '68.2',
  tz: '2020d',
  unicode: '13.0'
}

Workaround

run npm audit fix --force

Provide built-in templates

Based on #43, I thought it would be a good idea to provide build-in templates. Currently, I can either use the default app or provide a custom template via --template-file parameter. There is an example template for others to apply or to use as inspiration to create custom templates. However, it would be nice to provide built-in templates so that it's not required to set anything up locally, e.g.:

static-marks build --template default [...]
static-marks build --template minimal [...]

The Open All button should display a message on hover

Hi,

The "open all" button for each category has an aria-label, which is great, but is missing a title:

<button type="button" class="btn-unstyled" aria-label="Open all links from this bucket" tabindex="-1">
  <div class="icon icon-open-all"></div>
</button>

Having a title would allow a on-hover element to be shown for sighter users:

<button type="button" class="btn-unstyled" aria-label="Open all links from this bucket" tabindex="-1" title="Open all links from this bucket">
  <div class="icon icon-open-all"></div>
</button>

Adding bookmarks using Apple Shortcuts

I'm thinking of ways to make it easier to add new bookmarks to mybookmarks.yml file from within the browser itself (just like one normally does). My first idea was to write a Shortcut action (or use Keyboard Maestro) that executes a shell script that appends a line to the file, like so:

Unsorted:
  - These bookmarks have been added via the shortcut:
      - Darek's website: https://darekkay.com/static-marks/

After doing...

echo "      - New bookmark: https://www.example.com/" | tee -a bookmarks.yml

Note: with Apple Shortcuts or KM it's pretty easy to get the page title and URL of the active page in Chrome or Safari.

You'll get this:

Unsorted:
  - These bookmarks have been added via the shortcut:
      - Darek's website: https://darekkay.com/static-marks/
      - New bookmark: https://www.example.com/

And the same shortcut action could then also rebuild the bookmarks.html file. And then, periodically, I would just open the YAML file to move and organise the newly added bookmarks.

Or am I totally overthinking it? I haven't built it yet, so I'd like to hear what you think.

On mobile: move search bar to the bottom

Hello there,

On mobile, the "Search everywhere..." search bar is located at the top, which is nice, but is a bit far for most people's fingers.

Today, mobile browsers even have the url bar at the bottom for reachability purposes.

Would it be possible to have the search bar be sticky at the bottom on the viewport instead of at the top?

Basically having bottom: 0 instead of top: 0 for header and setting top: 0 instead of top: 60px for main in the css.

WDYT?

TypeError: args.flatMap is not a function

Hello Everyone, I'm trying to build my file and I receive the following error:

kmarks$ static-marks build demo.yml > bookmarks2.html
/usr/local/lib/node_modules/static-marks/bin/build/index.js:9
.flatMap((file) => glob.sync(file, { realpath: true }))
^

TypeError: args.flatMap is not a function
at Object.build [as run] (/usr/local/lib/node_modules/static-marks/bin/build/index.js:9:6)
at Command.program.command.description.option.option.option.action (/usr/local/lib/node_modules/static-marks/bin/cli.js:23:38)
at Command.listener (/usr/local/lib/node_modules/static-marks/node_modules/commander/index.js:370:29)
at Command.emit (events.js:198:13)
at Command.parseArgs (/usr/local/lib/node_modules/static-marks/node_modules/commander/index.js:892:12)
at Command.parse (/usr/local/lib/node_modules/static-marks/node_modules/commander/index.js:642:21)
at cli (/usr/local/lib/node_modules/static-marks/bin/cli.js:59:11)
at Object. (/usr/local/lib/node_modules/static-marks/bin/static-marks.js:6:1)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)

I'm using the Ubuntu 20.04, and I got the same error in the Docker setup.
I'm using the demofiles from https://github.com/darekkay/static-marks/tree/master/docs/examples/bookmarks

Any idea what can cause this? Thanks in advanced,

Autofocus search field

It would be nice to have the search field autofocused

  • on page load
  • after pressing the X button to clear the search input

This use case was also described in #6.

As this affects the UI, the implementation has to be done in darekkay/static-marks-app.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.