jekyll-sqlite
Advanced tools
+3
-1
| PATH | ||
| remote: . | ||
| specs: | ||
| jekyll-sqlite (0.1.0) | ||
| jekyll-sqlite (0.1.1) | ||
| sqlite3 (~> 1.6) | ||
@@ -35,2 +35,3 @@ | ||
| sqlite3 (1.6.2-aarch64-linux) | ||
| sqlite3 (1.6.2-x86_64-linux) | ||
| unicode-display_width (2.4.2) | ||
@@ -40,2 +41,3 @@ | ||
| aarch64-linux | ||
| x86_64-linux | ||
@@ -42,0 +44,0 @@ DEPENDENCIES |
@@ -8,3 +8,2 @@ # frozen_string_literal: true | ||
| class Error < StandardError; end | ||
| # Your code goes here... | ||
| end |
@@ -16,10 +16,68 @@ # frozen_string_literal: true | ||
| # Get the root of where we are generating the data | ||
| def get_root(root, name) | ||
| name.split(".")[0..-2].each do |p| | ||
| root = root[p] | ||
| end | ||
| root | ||
| end | ||
| def gen_hash_data(root, db, _query) | ||
| root ||= {} | ||
| root[name] = db.execute(config["query"]) | ||
| root[name].size | ||
| end | ||
| def gen_nested_data(item, db, query, name) | ||
| item[name] = [] | ||
| db.prepare(query) do |stmt| | ||
| # We bind params, ignoring any errors | ||
| # Since there's no way to get required params | ||
| # From a statement | ||
| item.each do |key, value| | ||
| stmt.bind_param key, value | ||
| rescue StandardError # rubocop:disable Lint/SuppressedException | ||
| end | ||
| stmt.execute.each { |d| item[name] << d } | ||
| end | ||
| item[name].size | ||
| end | ||
| def array_gen(root, config, name, db) | ||
| count = 0 | ||
| root.each do |item| | ||
| # TODO: Add support for binding Arrays as well. | ||
| if item.is_a? Hash | ||
| count += gen_nested_data(item, db, config["query"], name) | ||
| else | ||
| Jekyll.logger.info "Jekyll SQLite:", "Item is not a hash for #{name}. Unsupported configuration" | ||
| end | ||
| end | ||
| count | ||
| end | ||
| def gen_data(root, config, name, db) | ||
| count = 0 | ||
| if root.nil? || (root.is_a? Hash) | ||
| count = gen_hash_data(root, db, config["query"]) | ||
| elsif root.is_a? Array | ||
| count = array_gen(root, config, name, db) | ||
| end | ||
| count | ||
| end | ||
| def get_tip(name) | ||
| name.split(".")[-1] | ||
| end | ||
| def generate(site) | ||
| site.config["sqlite"].each do |name, config| | ||
| site.config["sqlite"].each do |config| | ||
| name = config["data"] | ||
| SQLite3::Database.new config["file"], readonly: true do |db| | ||
| Jekyll.logger.info "Jekyll SQLite:", "Starting to load #{name}" | ||
| fast_setup db | ||
| db.results_as_hash = config.fetch("results_as_hash", true) | ||
| site.data[name] = db.execute(config["query"]) | ||
| Jekyll.logger.info "Jekyll SQLite:", "Loaded #{name}. Count=#{site.data[name].size}" | ||
| root = get_root(site.data, name) | ||
| count = gen_data(root, config, get_tip(name), db) | ||
| Jekyll.logger.info "Jekyll SQLite:", "Loaded #{name}. Count=#{count}. as_hash=#{db.results_as_hash}" | ||
| end | ||
@@ -26,0 +84,0 @@ end |
@@ -5,4 +5,4 @@ # frozen_string_literal: true | ||
| module Sqlite | ||
| VERSION = "0.1.0" | ||
| VERSION = "0.1.1" | ||
| end | ||
| end |
+92
-23
@@ -1,5 +0,7 @@ | ||
| # Jekyll SQlite plugin | ||
| # Jekyll SQLite plugin | ||
| A Jekyll generator plugin to lets you use SQLite database instead of data files as a data source. | ||
| A Jekyll generator plugin to lets you use SQLite database instead of data files as a data source. It lets you easily create APIs and websites from a SQLite database, by linking together a database file, your template, and the relevant queries. | ||
| It additionally supports nested queries, so that you can use the rows of `site.data.items` as bind_params for your nested query. | ||
| [](https://github.com/captn3m0/jekyll-sqlite/actions/workflows/main.yml) [](https://badge.fury.io/rb/jekyll-sqlite) | ||
@@ -9,3 +11,3 @@ | ||
| Add this line to your site's Gemfile: | ||
| Add this line to your site's `Gemfile`: | ||
@@ -20,3 +22,3 @@ ```ruby | ||
| plugins: | ||
| - jekyll-sqlite | ||
| - jekyll_sqlite | ||
| ``` | ||
@@ -26,15 +28,2 @@ | ||
| ## Installation | ||
| TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org. | ||
| Install the gem and add to the application's Gemfile by executing: | ||
| $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG | ||
| If bundler is not being used to manage dependencies, install the gem by executing: | ||
| $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG | ||
| ## Usage | ||
@@ -46,11 +35,15 @@ | ||
| ... | ||
| # These are run in sequence, so any nested data can work well. | ||
| sqlite: | ||
| members: | ||
| - data: members | ||
| file: _db/users.db | ||
| sql: SELECT * FROM members ORDER by created_at DESC | ||
| query: SELECT * FROM members ORDER by created_at DESC | ||
| # You can use `results_as_hash` to switch between array or hash results (default). | ||
| verified: | ||
| - data: verified | ||
| results_as_hash: false # default true | ||
| file: _db/users.db | ||
| sql: SELECT username, email FROM members WHERE verified=1 | ||
| query: SELECT username, email FROM members WHERE verified=1 | ||
| - data: members.posts | ||
| file: _db/posts.db | ||
| query: SELECT * FROM posts WHERE user_id = :id | ||
| ``` | ||
@@ -61,4 +54,9 @@ | ||
| ```liquid | ||
| {% for user in site.data.members %} | ||
| - {{user.username}} | ||
| {% for member in site.data.members %} | ||
| - {{member.username}} | ||
| # Your Posts | ||
| {% for post in member.posts %} | ||
| {{post}} | ||
| {% endfor %} | ||
| {% endfor %} | ||
@@ -72,2 +70,73 @@ | ||
| ## Generating Pages | ||
| It works well with the `datapage_gen` plugin: | ||
| See the [datapage_gen](https://github.com/avillafiorita/jekyll-datapage_gen) docs for more details. | ||
| Here's a sample configuration: | ||
| ```yaml | ||
| # This will automatically generate a file for each restaurant | ||
| # restaurants/#{id}.html file | ||
| # with the layout `_layouts/restaurant.html` | ||
| # and page.id, page.name, page.active set | ||
| # and page.title set to restaurant name | ||
| sqlite: | ||
| restaurants: | ||
| file: _db/reviews.db | ||
| sql: SELECT id, name, last_review_date > 1672531200 as active, address FROM restaurants; | ||
| page_gen: | ||
| - data: restaurants | ||
| template: restaurant | ||
| name: id | ||
| title: name | ||
| filter: active | ||
| ``` | ||
| ## Nested Queries | ||
| You can use the rows of `site.data.items` as bind_params for your nested query. For this to work against | ||
| data generated by the plugin, the configuration order must be correct, so you need `site.data.items` above `site.data.items.nested` in your configuration. | ||
| Say you have a YAML file defining your items (`data/items.yaml`): | ||
| ```yaml | ||
| - id: 31323952-2708-42dc-a995-6006a23cbf00 | ||
| name: Item 1 | ||
| - id: 5c8e67a0-d490-4743-b5b8-8e67bd1f95a2 | ||
| name: Item 2 | ||
| ``` | ||
| and the prices for the items in your SQLite database, the following configuration will enrich the `items` array with the price: | ||
| ```yaml | ||
| sql: | ||
| - data: site.data.items.meta | ||
| query: SELECT price,author FROM pricing WHERE id =:id | ||
| ``` | ||
| This would allow the following Liquid loop to be written: | ||
| ```liquid | ||
| {% for item in site.data.items %} | ||
| {{item.meta.price}}, {{item.meta.author}} | ||
| {% endfor %} | ||
| ``` | ||
| This works well with `results_as_configuration` as well. | ||
| ```yaml | ||
| sql: | ||
| - data: site.data.items.meta | ||
| query: SELECT price,author FROM pricing WHERE id =:id | ||
| results_as_hash: false | ||
| ``` | ||
| The following also renders the price and author: | ||
| ```liquid | ||
| {% for item in site.data.items %} | ||
| {{item.meta[0]}}, {{item.meta[1]}} | ||
| {% endfor %} | ||
| ``` | ||
| ## Development | ||
@@ -74,0 +143,0 @@ |