@ -32,6 +32,8 @@ steps:
|
||||
from_secret: server_pass
|
||||
API_TOKEN:
|
||||
from_secret: api_token
|
||||
STRIPE_LIVE_KEY:
|
||||
from_secret: stripe_live_key
|
||||
privileged: false
|
||||
volumes:
|
||||
- name: jekyll
|
||||
|
2
COPYING
@ -18,7 +18,7 @@
|
||||
|
||||
# We are open to granting a more permissive (such as MIT or Apache 2.0) license to SharpeTronics, Inc.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please contact
|
||||
# info@sharpetronics.com if you are interested.
|
||||
# info@sharpetronics.com.
|
||||
|
||||
# If you would like to contribute to this code, please follow GPLv3 guidelines.
|
||||
# as an example, after making changes to the software (Called a Fork) and credit the original copyright holder as the creator with your credit added to theirs.
|
||||
|
27
Gemfile
@ -17,19 +17,22 @@ gem "jekyll", "~> 4.2.2"
|
||||
# If you have any plugins, put them here!
|
||||
|
||||
group :jekyll_plugins do
|
||||
gem "webrick", "~> 1.7" # dep for Jekyll 4.2.2; Ruby 3 doesn't have webrick by default anymore.
|
||||
gem "json", "~> 2.1" # dep for json
|
||||
gem "faraday" # a simple, but flexible HTTP client library, with support for multiple backends.
|
||||
gem "httpx" # swiss army knife of Ruby for HTTP
|
||||
gem 'faraday-multipart' # send with UDP; No encoding of the data
|
||||
#gem 'faraday-http-cache' # caching may be an upgrade at later date if needed
|
||||
|
||||
gem "jekyll-feed", "~> 0.12"
|
||||
gem "jekyll-menus"
|
||||
gem "jekyll-tagging"
|
||||
gem "jekyll-archives"
|
||||
gem "jekyll-paginate-v2"
|
||||
gem 'jekyll-feed', '~> 0.12'
|
||||
gem 'jekyll-menus'
|
||||
gem 'jekyll-tagging'
|
||||
gem 'jekyll-archives'
|
||||
gem 'jekyll-paginate-v2'
|
||||
end
|
||||
|
||||
group :dev_plugins do
|
||||
gem 'webrick', '~> 1.7' # dep for Jekyll 4.2.2; Ruby 3 doesn't have webrick by default anymore.
|
||||
gem 'json', '~> 2.1' # dep for json
|
||||
gem 'faraday' # a simple, but flexible HTTP client library, with support for multiple backends.
|
||||
gem 'httpx' # swiss army knife of Ruby for HTTP
|
||||
gem 'faraday-multipart' # send with UDP; No encoding of the data
|
||||
gem 'stripe' # integrating Stripe payments with Jekyll
|
||||
gem 'rails' # must use Rails for .blank support
|
||||
#gem 'faraday-http-cache' # caching may be an upgrade at later date
|
||||
end
|
||||
|
||||
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
|
||||
|
118
Gemfile.lock
@ -1,13 +1,71 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (6.0.6)
|
||||
actionpack (= 6.0.6)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (6.0.6)
|
||||
actionpack (= 6.0.6)
|
||||
activejob (= 6.0.6)
|
||||
activerecord (= 6.0.6)
|
||||
activestorage (= 6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
mail (>= 2.7.1)
|
||||
actionmailer (6.0.6)
|
||||
actionpack (= 6.0.6)
|
||||
actionview (= 6.0.6)
|
||||
activejob (= 6.0.6)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (6.0.6)
|
||||
actionview (= 6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
rack (~> 2.0, >= 2.0.8)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (6.0.6)
|
||||
actionpack (= 6.0.6)
|
||||
activerecord (= 6.0.6)
|
||||
activestorage (= 6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
activejob (6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
activerecord (6.0.6)
|
||||
activemodel (= 6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
activestorage (6.0.6)
|
||||
actionpack (= 6.0.6)
|
||||
activejob (= 6.0.6)
|
||||
activerecord (= 6.0.6)
|
||||
marcel (~> 1.0)
|
||||
activesupport (6.0.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
zeitwerk (~> 2.2, >= 2.2.2)
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
builder (3.2.4)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.1.10)
|
||||
crass (1.0.6)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0)
|
||||
erubi (1.11.0)
|
||||
eventmachine (1.2.7)
|
||||
faraday (2.3.0)
|
||||
faraday-net_http (~> 2.0)
|
||||
@ -17,6 +75,8 @@ GEM
|
||||
faraday-net_http (2.0.3)
|
||||
ffi (1.15.5)
|
||||
forwardable-extended (2.6.0)
|
||||
globalid (1.0.0)
|
||||
activesupport (>= 5.0)
|
||||
http-2-next (0.5.0)
|
||||
http_parser.rb (0.6.0)
|
||||
httpx (0.20.3)
|
||||
@ -61,12 +121,55 @@ GEM
|
||||
listen (3.7.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
loofah (2.19.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
marcel (1.0.2)
|
||||
mercenary (0.4.0)
|
||||
method_source (1.0.0)
|
||||
mini_mime (1.1.2)
|
||||
minitest (5.16.3)
|
||||
multipart-post (2.2.3)
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.13.8-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
nuggets (1.6.0)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (4.0.7)
|
||||
racc (1.6.0)
|
||||
rack (2.2.4)
|
||||
rack-test (2.0.2)
|
||||
rack (>= 1.3)
|
||||
rails (6.0.6)
|
||||
actioncable (= 6.0.6)
|
||||
actionmailbox (= 6.0.6)
|
||||
actionmailer (= 6.0.6)
|
||||
actionpack (= 6.0.6)
|
||||
actiontext (= 6.0.6)
|
||||
actionview (= 6.0.6)
|
||||
activejob (= 6.0.6)
|
||||
activemodel (= 6.0.6)
|
||||
activerecord (= 6.0.6)
|
||||
activestorage (= 6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 6.0.6)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.4.3)
|
||||
loofah (~> 2.3)
|
||||
railties (6.0.6)
|
||||
actionpack (= 6.0.6)
|
||||
activesupport (= 6.0.6)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.20.3, < 2.0)
|
||||
rake (13.0.6)
|
||||
rb-fsevent (0.11.1)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
@ -76,8 +179,17 @@ GEM
|
||||
safe_yaml (1.0.5)
|
||||
sassc (2.4.0)
|
||||
ffi (~> 1.9)
|
||||
sprockets (4.1.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.4.2)
|
||||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
sprockets (>= 3.0.0)
|
||||
stripe (7.1.0)
|
||||
terminal-table (2.0.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thor (1.2.1)
|
||||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.9)
|
||||
thread_safe (~> 0.1)
|
||||
@ -86,6 +198,10 @@ GEM
|
||||
unicode-display_width (1.8.0)
|
||||
wdm (0.1.1)
|
||||
webrick (1.7.0)
|
||||
websocket-driver (0.7.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
zeitwerk (2.6.0)
|
||||
|
||||
PLATFORMS
|
||||
x86_64-linux-musl
|
||||
@ -101,6 +217,8 @@ DEPENDENCIES
|
||||
jekyll-paginate-v2
|
||||
jekyll-tagging
|
||||
json (~> 2.1)
|
||||
rails
|
||||
stripe
|
||||
tzinfo (~> 1.2)
|
||||
tzinfo-data
|
||||
wdm (~> 0.1.1)
|
||||
|
4
LICENSE
@ -1,4 +1,4 @@
|
||||
# This software gathers all collection types from an API and saves that data into Jekyll _data/ folder.
|
||||
# This software is coded in Ruby and gathers all collection types from an API and saves that data into the Jekyll _data/.. folder; a including, secure integration that allows for Ecommerce with Stripe.
|
||||
# Copyright (C) SharpeTronics, Inc. 2013-2023
|
||||
|
||||
# Author(s): Charles Sharpe(@odinzu_me)
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
# We are open to granting a more permissive (such as MIT or Apache 2.0) license to SharpeTronics, Inc.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please contact
|
||||
# info@sharpetronics.com if you are interested.
|
||||
# info@sharpetronics.com.
|
||||
|
||||
# If you would like to contribute to this code, please follow GPLv3 guidelines.
|
||||
# as an example, after making changes to the software (Called a Fork) and credit the original copyright holder as the creator with your credit added to theirs.
|
||||
|
10
README.md
@ -17,10 +17,10 @@ No proprietary operating system dependencies required, only Docker Engine super
|
||||
* SharpeTronics Pages ready (free static hosting).
|
||||
* Drone CI / CD system.
|
||||
* Backups for restoring to previous states.
|
||||
* Headless CMS with superpowers!
|
||||
* Headless CMS with Strapi superpowers!
|
||||
* Ease of use for editors and writers.
|
||||
* Distributed CDN with automatic HTTPS (Cloudflare).
|
||||
* Secure ecommerce shopping.
|
||||
* Secure Ecommerce shopping with Stripe.
|
||||
* International Multi-language
|
||||
|
||||
# Jekyll Plugins
|
||||
@ -59,8 +59,8 @@ No proprietary operating system dependencies required, only Docker Engine super
|
||||
* Stripe https://stripe.com/docs
|
||||
* SharpeTronics Custom Ruby Plugin (License: GPLv3)
|
||||
|
||||
## Socials
|
||||
## Socials
|
||||
* Discord: https://discord.gg/TUZ6P7BV
|
||||
* Twitter: https://nitter.privacydev.net/sharpetronics
|
||||
* Twitter: https://twitter.com/sharpetronics
|
||||
* Email: info@sharpetronics.com
|
||||
* Telegram: https://t.me/+oFUwKSn3frgzZDFh
|
||||
* Telegram: https://t.me/+oFUwKSn3frgzZDFh
|
||||
|
50
_config.yml
@ -49,31 +49,36 @@ feed:
|
||||
- legal
|
||||
- devops
|
||||
|
||||
# ===================================================================================
|
||||
# teh API dashboard configuration
|
||||
api:
|
||||
# Your API endpoint
|
||||
# ecommerce integration with Stripe
|
||||
stripe:
|
||||
# The Stripe Jekyll configuration
|
||||
enabled: true # sometimes we don't need ecommerce integration; defaults to false
|
||||
reset_stripe_db: false # when set true, it will delete all remote Stripe products and resubmit the products from CMS interface; caution! used for cleaning a Stripe db.
|
||||
|
||||
# uri format: [endpoint]+[endpoint_ext]+[endpoint_param]
|
||||
endpoint: https://dash.sharpetronics.com # url to api; no trailing slash
|
||||
endpoint_ext: /api/ # (optional) the extension of endpoint e.g. https://www.example.com/api/
|
||||
endpoint_query: ?populate=* # (optional) e.g. force retrieve all json data
|
||||
output: true # when true (global), new or modified images are downloaded from each collection type
|
||||
local_media_dir: uploads/ # a placeholder example
|
||||
endpoint_param: ?populate=* # (optional) e.g. populate all json data; does not affect endpoint_uploads.
|
||||
endpoint_uploads: uploads # optional, no use at the moment; the location of all media files on api; this is required for downloading images
|
||||
|
||||
local_media_dir: uploads/ # where to cache the images
|
||||
cache_images: true # when true (global), new or modified images are downloaded from endpoint_uploads; note: Docker is also caching downloaded images.
|
||||
|
||||
collections:
|
||||
# Example for a "posts" collection
|
||||
posts: # required
|
||||
# Collection name used to construct the url requested. Example: type `foo` would generate the following url `http://localhost:1337/foo`.
|
||||
type: posts # used for directory creation and organizing files
|
||||
filepath: '_data/posts/index.json' # a placeholder example
|
||||
# Permalink used to generate the output files (eg. /posts/:id).
|
||||
# permalink: /blog/:id/
|
||||
# output: false
|
||||
# Example for a "products" collection
|
||||
#products:
|
||||
# Collection name (optional). Used to construct the url requested. Example: type `foo` would generate the following url `http://localhost:1337/foo`.
|
||||
#type: products # a placeholder example
|
||||
#path: '_data/products/index.json' # a placeholder example
|
||||
# Permalink used to generate the output files (eg. /posts/:id).
|
||||
# permalink: /blog/:id/
|
||||
# output: false
|
||||
# the "posts" collection
|
||||
posts: # required
|
||||
# Collection name used to construct the url requested. Example: type `foo` would generate the following url `http://localhost:1337/foo`.
|
||||
type: posts # required; used for directory creation and organizing files
|
||||
filepath: '_data/posts/index.json' # the filepath for posts json hash
|
||||
# the "products" collection
|
||||
products: # optional?
|
||||
# Collection name (optional). Used to construct the url requested. Example: type `foo` would generate the following url `http://localhost:1337/foo`.
|
||||
type: products # required; used for directory creation and organizing files
|
||||
filepath: '_data/products/index.json' # the filepath for products json hash
|
||||
# ===================================================================================
|
||||
|
||||
# Collection configuration
|
||||
# These collections will sort types of products and loop through that
|
||||
@ -83,7 +88,7 @@ collections_dir: collections
|
||||
|
||||
collections:
|
||||
products:
|
||||
output: true
|
||||
output: true # true or false
|
||||
permalink: /products/:path/
|
||||
|
||||
permalink: "/blog/:categories/:year/:month/:day/:title/" # Built in options include: date, pretty, ordinal, weekdate, none; learn more here: https://jekyllrb.com/docs/permalinks/
|
||||
@ -104,7 +109,6 @@ sass:
|
||||
|
||||
# Site configuration for the Jekyll v2 Pagination gem
|
||||
pagination:
|
||||
|
||||
# Site-wide kill switch, disabled here it doesn't run at all
|
||||
enabled: true
|
||||
# Set to 'true' to enable pagination debugging. This can be enabled in the site config or only for individual pagination pages
|
||||
@ -114,7 +118,7 @@ pagination:
|
||||
# How many objects per paginated page, used to be `paginate` (default: 0, means all)
|
||||
per_page: 9
|
||||
# The permalink structure for the paginated pages (this can be any level deep)
|
||||
permalink: '/:num/' # Pages are index.html inside this folder (default)
|
||||
permalink: ':num/' # Pages are index.html inside this folder (default)
|
||||
#permalink: '/page/:num.html' # Pages are simple html files
|
||||
#permalink: '/page/:num' # Pages are html files, linked jekyll extensionless permalink style.
|
||||
|
||||
|
@ -5,8 +5,8 @@ Charles:
|
||||
last_name: "Sharpe"
|
||||
site: "https://www.csharpe.me"
|
||||
avatar: "/uploads/authors/c-avatar.webp" #Size of avatar_image 36x36
|
||||
bio: "Independent Full-Stack Web Developer; curious about Astronomy, Information Technology, Privacy, Permaculture, Philosophy & Consciousness."
|
||||
email: "charles.sharpee@gmail.com"
|
||||
bio: "A Stack Architect; curious about Astronomy, Information Technology, Privacy, Permaculture, Philosophy & Consciousness."
|
||||
email: "info@sharpetronics.com"
|
||||
# Twitter nick for use in Twitter cards and follow button.
|
||||
twitter: "csharpe_me" # if no twitter in this config, the twitter follow button will be removed
|
||||
# GitHub nick for use in follow button in author block.
|
||||
@ -14,12 +14,8 @@ Charles:
|
||||
social:
|
||||
- title: "github"
|
||||
url: "https://github.com/csharpee"
|
||||
- title: "linkedin"
|
||||
url: "https://www.linkedin.com/in/EXAMPLE"
|
||||
- title: "youtube"
|
||||
url: "https://www.youtube.com/channel/EXAMPLE"
|
||||
- title: "facebook"
|
||||
url: "https://www.facebook.com/EXAMPLE"
|
||||
- title: "twitter"
|
||||
url: "https://www.twitter.com/odinzu_me"
|
||||
|
||||
|
||||
Dexter:
|
||||
|
@ -1,15 +0,0 @@
|
||||
title: Cup
|
||||
url: /products/2020-06-03-cup/
|
||||
id: 201806
|
||||
sku: 202055478373
|
||||
image: assets/images/Peppermint-Lip-Balm.jpg
|
||||
description: Our all natural Peppermint lip balm was a great hit with our family & friends. We hope you enjoy it too!
|
||||
excerpt: Our BEST SELLING lip balm - you'll love it!
|
||||
category: Lip Balm
|
||||
tag: Health
|
||||
quantity: 14
|
||||
price: 125.00
|
||||
weight: Peppermint
|
||||
format: Physical
|
||||
material: Wood, Steel
|
||||
dimension: 15in x 35in
|
1
_data/products/index.json
Normal file
@ -1,15 +0,0 @@
|
||||
title: Dragon
|
||||
url: /products/2017-02-03-dragon/
|
||||
id: 201806
|
||||
sku: 202055478373
|
||||
image: assets/images/Peppermint-Lip-Balm.jpg
|
||||
description: Our all natural Peppermint lip balm was a great hit with our family & friends. We hope you enjoy it too!
|
||||
excerpt: Our BEST SELLING lip balm - you'll love it!
|
||||
category: Lip Balm
|
||||
tag: Health
|
||||
quantity: 14
|
||||
price: 5.00
|
||||
weight: Peppermint
|
||||
format: Physical
|
||||
material: Wood, Steel
|
||||
dimension: 15in x 35in
|
@ -9,18 +9,20 @@ pagination:
|
||||
|
||||
<section id="main" class="wrapper style1">
|
||||
<div class="inner">
|
||||
<!-- Shopping Cart -->
|
||||
{% unless page.layout == "posts" %}
|
||||
<!-- The back button on a single post -->
|
||||
<section class="row product-cart journal">
|
||||
<div class="col-12">
|
||||
<a href="{{site.url}}/blog"><h5 class="button back">< Go Back</h5></a>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
{% endunless %}
|
||||
|
||||
<!-- Title -->
|
||||
<header class="major special journal">
|
||||
<div class="hero"> <img class="image fit" src="{{ page.banner_image }}" alt="{{ page.banner_image_alt }}"> </div>
|
||||
<h1>{{ page.title }}</h1>
|
||||
<p>{{ page.sub_title }}</p>
|
||||
<p>{{ page.subheading }}</p>
|
||||
</header>
|
||||
<!-- Content -->
|
||||
<div class="content">
|
||||
|
@ -16,7 +16,7 @@ layout: post
|
||||
|
||||
<div class="title">
|
||||
<h2><a href="{{ post.url | absolute_url }}">{{ post.title }}</a></h2>
|
||||
<p>{{ post.sub_heading }}</p>
|
||||
<p>{{ post.subheading }}</p>
|
||||
</div>
|
||||
{% assign author = site.data.authors[post.author] %}
|
||||
{%- include author_card.html -%}
|
||||
@ -30,7 +30,7 @@ layout: post
|
||||
<li><b>{{ post.category }}</b></li>
|
||||
<li><b>Tags: </b>{{ post.tags }}</li>
|
||||
<!-- <li class="icon solid fa-heart">144</li> -->
|
||||
<li><a href="{{ post.url | absolute_url }}" class="icon solid fa-comment">88</a></li>
|
||||
<li><a href="{{ post.url | absolute_url }}" class="icon solid fa-comment">43</a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
</article>
|
||||
|
@ -26,7 +26,7 @@ pagination:
|
||||
<!-- Page Heading -->
|
||||
<header class="major special">
|
||||
<h1>{{ page.title }}</h1>
|
||||
<p>{{ page.sub_heading }}</p>
|
||||
<p>{{ page.subheading }}</p>
|
||||
</header>
|
||||
<!-- Main Body Content -->
|
||||
<div class="content">
|
||||
|
@ -1,9 +1,9 @@
|
||||
# This software gathers all collection types from an API and saves that data into Jekyll _data/ folder.
|
||||
# This software gathers all collection types from an API or headless CMS, then saves that data into the Jekyll _data/ folder.
|
||||
# Copyright (C) SharpeTronics, Inc. 2013-2023
|
||||
|
||||
# Author(s): Charles Sharpe(@odinzu_me)
|
||||
# Author(s): Charles Sharpe(@odinzu_me) aka SharpeTronics, Inc.
|
||||
# License: GPLv3
|
||||
# Version: 1
|
||||
# Version: 1.3
|
||||
|
||||
# This is Free Software released under GPLv3. Any misuse of this software
|
||||
# will be followed up with GPL enforcement via Software Freedom Law Center:
|
||||
@ -18,8 +18,8 @@
|
||||
# Dependencies downloaded as part of the build process may be covered by other open-source licenses.
|
||||
|
||||
# We are open to granting a more permissive (such as MIT or Apache 2.0) license to SharpeTronics, Inc.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please contact
|
||||
# info@sharpetronics.com if you are interested.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please email
|
||||
# info@sharpetronics.com.
|
||||
|
||||
# If you would like to contribute to this code, please follow GPLv3 guidelines.
|
||||
# as an example, after making changes to the software (Called a Fork) and credit the original copyright holder as the creator with your credit added to theirs.
|
||||
@ -31,34 +31,24 @@ require 'faraday' # https://lostisland.github.io/faraday/usage/
|
||||
require 'httpx/adapters/faraday' # https://honeyryderchuck.gitlab.io/httpx/
|
||||
require 'addressable/uri' # https://github.com/sporkmonger/addressable If you need to normalize URIs, e.g. http://www.詹姆斯.com/
|
||||
require 'faraday/multipart' # https://github.com/lostisland/faraday-multipart
|
||||
require 'active_support/core_ext/object/blank' # load only the specific extension for .blank? support
|
||||
|
||||
Jekyll.logger.debug "A Ruby bot be building this...[*_-]\n".green.bold
|
||||
Jekyll.logger.debug "A SharpeTronics bot be building this...[*_-]\n".green.bold
|
||||
# prepare uri & load _config.yml into config_yml object
|
||||
config_yml = "_config.yml"
|
||||
f = YAML.load(File.read(config_yml.to_s)) # r - read file
|
||||
api_endpoint = f['api']['endpoint']
|
||||
endpoint_query = f['api']['endpoint_query']
|
||||
endpoint_param = f['api']['endpoint_param']
|
||||
endpoint_ext = f['api']['endpoint_ext']
|
||||
Jekyll.logger.debug "DEBUG: API_ENDPDOINT for GET COLLECTIONS: " "#{api_endpoint}".to_s.yellow.bold
|
||||
|
||||
# create directory _data/posts/ if doesn't exist
|
||||
if not Dir.exist?(f['api']['collections']['posts']['type'].to_s)
|
||||
puts "folder does not exist, let's create a new folder in Jekyll called: _data/posts/ ".yellow
|
||||
Dir.mkdir (f['api']['collections']['posts']['type'].to_s)
|
||||
end
|
||||
# create file.json if doesn't exist
|
||||
if not File.exist?(f['api']['collections']['posts']['filepath'])
|
||||
puts "file does not exist, let's create a new file".yellow.bold
|
||||
File.write(f['api']['collections']['posts']['filepath'], 'A Ruby bot be building this...[*_-]\n')
|
||||
end
|
||||
|
||||
# authenticated or public API data
|
||||
# import API_TOKEN from the environment. e.g. export API_TOKEN=example
|
||||
api_token = ENV['API_TOKEN']
|
||||
# check if api_token is auth or unauth
|
||||
if api_token === nil
|
||||
if "#{api_token}".blank?
|
||||
# logs data to screen
|
||||
puts "ENV DEBUG: API_TOKEN FAILED! Testing a public request without a bearer token... ".red
|
||||
puts "TOKEN MISSING! Testing a public request without a bearer token... ".red
|
||||
options = {
|
||||
headers: ""
|
||||
}
|
||||
@ -80,34 +70,55 @@ if api_token === nil
|
||||
Jekyll.logger.debug "HTTP DEBUG: BULIDING CONNECTION: #{api_builder}".to_s.yellow.bold
|
||||
# logs auth status to screen
|
||||
puts ""
|
||||
puts "API_TOKEN SUCCESS! Getting the authenticated data...".green
|
||||
puts "API_DATABASE TOKEN SUCCESS! Getting the authenticated data...".cyan.bold
|
||||
puts ""
|
||||
end # close if/else
|
||||
|
||||
# TODO: add ['products'] collection
|
||||
# parses through local Jekyll _config.yml file and gets collection `type`
|
||||
#products_path = "[:site].config['api']['collections']['products']['type']"
|
||||
posts_path = f['api']['collections']['posts']['type']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: JEKYLL CONFIG TYPE PATH: " "#{posts_path}".to_s.yellow.bold
|
||||
products_type = f['api']['collections']['products']['type']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: JEKYLL CONFIG PRODUCTS PATH: " "#{products_type}".to_s.yellow
|
||||
|
||||
# populate all data to have image data available in Strapi
|
||||
# TODO: update this to work with any URL API in _config.yml; e.g. some API's don't need static /api like Strapi CMS
|
||||
uri = "#{api_endpoint}#{endpoint_ext}#{posts_path}#{endpoint_query}"
|
||||
Jekyll.logger.debug "HTTP DEBUG: URI: " "#{uri}".to_s.yellow
|
||||
posts_type = f['api']['collections']['posts']['type']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: JEKYLL CONFIG POSTS PATH: " "#{posts_type}".to_s.yellow.bold
|
||||
|
||||
# the actual GET with header data; retrieve all json data from API
|
||||
api_connect = api_builder.get(uri)
|
||||
Jekyll.logger.debug "HTTP DEBUG: THE COLLECTION IS: #{posts_path} WITH STATUS CODE: #{api_connect.status}".to_s.yellow.bold
|
||||
# store filepath config options
|
||||
posts_filepath = f['api']['collections']['posts']['filepath']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: JEKYLL CONFIG POSTS FILEPATH: " "#{posts_filepath}".to_s.yellow.bold
|
||||
|
||||
# api request variable passing uri and storing inside response var
|
||||
# response = api_request(uri)
|
||||
json_data = api_connect.body
|
||||
Jekyll.logger.debug "HTTP DEBUG: IS JSON DATA EMPTY? #{json_data.empty?}".to_s.yellow
|
||||
#Jekyll.logger.debug "DEBUG: STOUT JSON DATA: #{json_data}".to_s.yellow.bold
|
||||
products_filepath = f['api']['collections']['products']['filepath']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: JEKYLL CONFIG PRODUCTS FILEPATH: " "#{products_filepath}".to_s.yellow
|
||||
|
||||
# opens the file and writes the data to the file
|
||||
Jekyll.logger.debug "WRITING RAW JSON DATA TO FILE...".yellow.bold
|
||||
File.write('./_data/posts/index.json', JSON.dump(json_data))
|
||||
# build the resource link & populate posts json data
|
||||
uri_posts = "#{api_endpoint}#{endpoint_ext}#{posts_type}#{endpoint_param}"
|
||||
Jekyll.logger.debug "HTTP DEBUG: POSTS URI: " "#{uri_posts}".to_s.yellow.bold
|
||||
# build the resource link & populate posts json data
|
||||
uri_products = "#{api_endpoint}#{endpoint_ext}#{products_type}#{endpoint_param}"
|
||||
Jekyll.logger.debug "HTTP DEBUG: PRODUCTS URI: " "#{uri_products}".to_s.yellow
|
||||
|
||||
# the actual GET with header data; retrieve all product and posts json data from API
|
||||
posts_api_connect = api_builder.get(uri_posts)
|
||||
Jekyll.logger.debug "HTTP DEBUG: THE COLLECTION is: #{posts_type} with STATUS CODE: #{posts_api_connect.status}".to_s.cyan.bold
|
||||
|
||||
products_api_connect = api_builder.get(uri_products)
|
||||
Jekyll.logger.debug "HTTP DEBUG: THE COLLECTION is: #{products_type} with STATUS CODE: #{products_api_connect.status}".to_s.cyan.bold
|
||||
|
||||
# store all data into the body of the api
|
||||
posts_json_data = posts_api_connect.body
|
||||
Jekyll.logger.debug "HTTP DEBUG: IS POST JSON DATA EMPTY? #{posts_json_data.empty?}".to_s.yellow
|
||||
|
||||
products_json_data = products_api_connect.body
|
||||
Jekyll.logger.debug "HTTP DEBUG: IS PRODUCT JSON DATA EMPTY? #{products_json_data.empty?}".to_s.yellow
|
||||
|
||||
# opens the posts file and writes the data to the file
|
||||
Jekyll.logger.debug "WRITING RAW POSTS JSON DATA TO FILE...".yellow.bold
|
||||
File.write(posts_filepath, JSON.dump(posts_json_data))
|
||||
puts ""
|
||||
Jekyll.logger.debug "SUCCESS! JSON FILE DOWNLOADED...".green
|
||||
Jekyll.logger.debug "SUCCESS! JSON POSTS FILE DOWNLOADED...".cyan.bold
|
||||
puts ""
|
||||
|
||||
# opens the products file and writes the data to the file
|
||||
Jekyll.logger.debug "WRITING RAW PRODUCTS JSON DATA TO FILE...".yellow.bold
|
||||
File.write(products_filepath, JSON.dump(products_json_data))
|
||||
puts ""
|
||||
Jekyll.logger.debug "SUCCESS! JSON PRODUCTS FILE DOWNLOADED...".cyan.bold
|
||||
puts ""
|
||||
|
@ -1,192 +0,0 @@
|
||||
# This software gathers all collection types from an API and saves that data into Jekyll _data/ folder.
|
||||
# Copyright (C) SharpeTronics, Inc. 2013-2023
|
||||
|
||||
# Author(s): Charles Sharpe(@odinzu_me)
|
||||
# License: GPLv3
|
||||
# Version: 1
|
||||
|
||||
# This is Free Software released under GPLv3. Any misuse of this software
|
||||
# will be followed up with GPL enforcement via Software Freedom Law Center:
|
||||
# https://www.softwarefreedom.org/
|
||||
|
||||
# If you incorporate or include any code from SharpeTronics, Inc., your
|
||||
# code must be licensed as GPLv3 (not GPLv2 or MIT)
|
||||
|
||||
# The GPLv3 software license applies to the code directly included in this source distribution.
|
||||
# See the LICENSE & COPYING file for full information.
|
||||
|
||||
# Dependencies downloaded as part of the build process may be covered by other open-source licenses.
|
||||
|
||||
# We are open to granting a more permissive (such as MIT or Apache 2.0) license to SharpeTronics, Inc.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please contact
|
||||
# info@sharpetronics.com if you are interested.
|
||||
|
||||
# If you would like to contribute to this code, please follow GPLv3 guidelines.
|
||||
# as an example, after making changes to the software (Called a Fork) and credit the original copyright holder as the creator with your credit added to theirs.
|
||||
|
||||
require 'fileutils' # https://ruby-doc.org/stdlib-2.4.1/libdoc/fileutils/rdoc/FileUtils.html
|
||||
require 'json' # https://ruby-doc.org/stdlib-3.0.2/libdoc/json/rdoc/JSON.html
|
||||
require 'yaml' # load jekyll yaml config
|
||||
|
||||
module Jekyll
|
||||
# initialize variables
|
||||
product_path = "collections/_products/"
|
||||
post_path = "collections/_posts/"
|
||||
file_ending = ".md"
|
||||
|
||||
# load _config.yml
|
||||
config_yml = "_config.yml"
|
||||
f = YAML.load(File.read(config_yml.to_s)) # r - read file
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Is config empty? " "#{config_yml.empty?}".to_s.yellow
|
||||
|
||||
# set filepath, load the json, then parse through json file in _data/posts/index.json
|
||||
json_post_path = f['api']['collections']['posts']['filepath']
|
||||
# must read data into memory before parsing file
|
||||
read_json = File.read(json_post_path) # read json for all posts
|
||||
#json_product_path = f['api']['collections']['products']['path']
|
||||
# TODO: update for products also
|
||||
parsed_file = JSON.parse(read_json.to_s) # returns a hash
|
||||
|
||||
# cache / check and download all collection post data
|
||||
collection_ids = parsed_file["data"]
|
||||
# loop through each collection id
|
||||
collection_ids.each do |id|
|
||||
#puts "#{id}".yellow # output collection id for debug
|
||||
|
||||
# store json specific data for each post
|
||||
# check if title date is empty
|
||||
if id["attributes"]["title"] === nil
|
||||
Jekyll.logger.debug "ERROR: title is empty; does API post have title?".to_s.red
|
||||
else
|
||||
title = id["attributes"]["title"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Title: " "#{title}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# store slug into object
|
||||
slug = id["attributes"]["slug"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Slug: " "#{slug}".to_s.yellow
|
||||
|
||||
# check if sub_heading data is empty
|
||||
if id["attributes"]["subheading"] === nil
|
||||
Jekyll.logger.debug "ERROR: subheading is empty; does API post have subheading?".to_s.red
|
||||
else
|
||||
sub_heading = id["attributes"]["subheading"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Subheading: " "#{sub_heading}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# check if date data is empty
|
||||
if id["attributes"]["date"] === nil
|
||||
Jekyll.logger.debug "ERROR: date is empty; does API post have date?".to_s.red
|
||||
else
|
||||
date = id["attributes"]["date"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Date: " "#{date}".to_s.yellow
|
||||
end
|
||||
|
||||
# check if layout data is empty
|
||||
if id["attributes"]["layout"] === nil
|
||||
Jekyll.logger.debug "ERROR: layout is empty; does API post have layout?".to_s.red
|
||||
else
|
||||
layout = id["attributes"]["layout"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Layout: " "#{layout}".to_s.yellow.bold
|
||||
end
|
||||
# check if author data is empty
|
||||
puts "#{id}"
|
||||
if "#{id["attributes"]["author"]}".empty? || nil
|
||||
Jekyll.logger.debug "ERROR: author is empty; does API post have author?".to_s.red
|
||||
else
|
||||
author = id["attributes"]["author"]["data"]["attributes"]["name"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Author: " "#{author}".to_s.yellow
|
||||
end
|
||||
|
||||
# check if image data is empty
|
||||
if "#{id["attributes"]["image"]}".empty? || nil || "#{id["attributes"]["image"]["data"]}".empty?
|
||||
Jekyll.logger.debug "ERROR: banner_image url is empty; does API post have banner image url?".to_s.red
|
||||
else
|
||||
banner_image = id["attributes"]["image"]["data"]["attributes"]["url"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Banner Image: " "#{banner_image}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# check if banner_image_alt data is empty
|
||||
if id["attributes"]["image_alt"] === nil
|
||||
Jekyll.logger.debug "ERROR: banner_image_alt is empty; does API post have banner_image_alt?".to_s.red
|
||||
else
|
||||
banner_image_alt = id["attributes"]["image_alt"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Banner Image Alt-text: " "#{banner_image_alt}".to_s.yellow
|
||||
end
|
||||
|
||||
# check if tags data is empty
|
||||
if "#{id["attributes"]["tags"]}".empty? || nil
|
||||
Jekyll.logger.debug "ERROR: tags is empty; does API post have tags?".to_s.red
|
||||
else
|
||||
# an array for storing multiple input
|
||||
tags = id["attributes"]["tags"]["data"]
|
||||
# loop through all tags
|
||||
tags.each do |tag|
|
||||
puts ""
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Tag(s): " "#{tag}".to_s.yellow
|
||||
end
|
||||
puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
# check if category data is empty
|
||||
if "#{id["attributes"]["category"]}".empty? || nil
|
||||
Jekyll.logger.debug "ERROR: category is empty; does API post have a category?".to_s.red
|
||||
else
|
||||
category = id["attributes"]["category"]["data"]["attributes"]["name"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Category: " "#{category}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# check if content data is empty
|
||||
if id["attributes"]["content"] === nil
|
||||
Jekyll.logger.debug "ERROR: content is empty; does API post have content?".to_s.red
|
||||
else
|
||||
content = id["attributes"]["content"]
|
||||
Jekyll.logger.debug "DOCUMENT DEBUG: Collection Raw Content: " "#{content}".to_s.yellow
|
||||
end
|
||||
|
||||
# create the filename
|
||||
file_name = "#{date}-#{slug}#{file_ending}"
|
||||
|
||||
# let us put humpty dumpty back together again!
|
||||
# create a new collection type post *.md
|
||||
p = File.open( "#{post_path}#{file_name}","w" )
|
||||
|
||||
# file content in Jekyll yaml formatting
|
||||
p.puts "---"
|
||||
p.puts "layout: #{layout}"
|
||||
p.puts "date: #{date}"
|
||||
p.puts "author: #{author}"
|
||||
p.puts "banner_image: #{banner_image}" # the banner images are downloaded from API in image-filter.rb.
|
||||
p.puts "banner_image_alt: #{banner_image_alt}"
|
||||
p.puts "title: #{title}"
|
||||
|
||||
if sub_heading != nil
|
||||
p.puts "sub_heading: #{sub_heading}"
|
||||
end
|
||||
# add tags without json formatting in pretty format
|
||||
p.print "tags: " # pretty debug
|
||||
|
||||
if "#{id["attributes"]["tags"]}".empty? || nil
|
||||
Jekyll.logger.debug "ERROR: tags is empty; does API post have tags?".to_s.red
|
||||
else
|
||||
tags = id["attributes"]["tags"]["data"]
|
||||
# loop through all tags
|
||||
tags.each do |tag|
|
||||
p.print tag["attributes"]["tag"]
|
||||
p.print ", "
|
||||
end
|
||||
p.puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
if "#{id["attributes"]["category"]}".empty? || nil
|
||||
Jekyll.logger.debug "ERROR: category is empty; does API post have a category?".to_s.red
|
||||
else
|
||||
category = id["attributes"]["category"]["data"]["attributes"]["name"]
|
||||
p.puts "category: " "#{category}"
|
||||
end
|
||||
|
||||
p.puts "---" # close .yaml file frontmatter
|
||||
p.puts "#{content}" # write post content
|
||||
p.close # close the file; stop writing
|
||||
end
|
||||
end
|
203
_plugins/jekyll-api/lib/b-generate-posts.rb
Normal file
@ -0,0 +1,203 @@
|
||||
# This software generates mardown formatted posts from json data.
|
||||
# Copyright (C) SharpeTronics, Inc. 2013-2023
|
||||
|
||||
# Author(s): Charles Sharpe(@odinzu_me) aka SharpeTronics, Inc.
|
||||
# License: GPLv3
|
||||
# Version: 1.3
|
||||
|
||||
# This is Free Software released under GPLv3. Any misuse of this software
|
||||
# will be followed up with GPL enforcement via Software Freedom Law Center:
|
||||
# https://www.softwarefreedom.org/
|
||||
|
||||
# If you incorporate or include any code from SharpeTronics, Inc., your
|
||||
# code must be licensed as GPLv3 (not GPLv2 or MIT)
|
||||
|
||||
# The GPLv3 software license applies to the code directly included in this source distribution.
|
||||
# See the LICENSE & COPYING file for full information.
|
||||
|
||||
# Dependencies downloaded as part of the build process may be covered by other open-source licenses.
|
||||
|
||||
# We are open to granting a more permissive (such as MIT or Apache 2.0) license to SharpeTronics, Inc.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please email
|
||||
# info@sharpetronics.com.
|
||||
|
||||
# If you would like to contribute to this code, please follow GPLv3 guidelines.
|
||||
# as an example, after making changes to the software (Called a Fork) and credit the original copyright holder as the creator with your credit added to theirs.
|
||||
|
||||
require 'fileutils' # https://ruby-doc.org/stdlib-2.4.1/libdoc/fileutils/rdoc/FileUtils.html
|
||||
require 'json' # https://ruby-doc.org/stdlib-3.0.2/libdoc/json/rdoc/JSON.html
|
||||
require 'yaml' # load Jekyll yaml config
|
||||
require 'active_support/core_ext/object/blank' # load only the specific extension for .blank? support
|
||||
|
||||
module Jekyll
|
||||
# initialize variables
|
||||
jekyll_post_path = "collections/_posts/"
|
||||
file_ending = ".md"
|
||||
|
||||
# searches for _config.yml file in the root / of the Jekyll project.
|
||||
config_yml = "_config.yml"
|
||||
f = YAML.load(File.read(config_yml.to_s)) # r - read file
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Is the _config.yml available? " "#{f}".to_s.magenta.bold
|
||||
|
||||
# set filepath, load the json, then parse through json file
|
||||
json_post_path = f['api']['collections']['posts']['filepath']
|
||||
|
||||
# must read data into memory before parsing file
|
||||
read_posts_json = File.read(json_post_path) # read json for all posts
|
||||
|
||||
# parse through json files
|
||||
parsed_posts_file = JSON.parse(read_posts_json.to_s) # returns a hash
|
||||
|
||||
# cache / verify and download each post data
|
||||
post_ids = parsed_posts_file["data"]
|
||||
# loop through each post id
|
||||
post_ids.each do |id|
|
||||
|
||||
# get post modify time; it is cached in the Jekyll container
|
||||
updatedAt = id["attributes"]["updatedAt"]
|
||||
|
||||
# store json specific data for each post
|
||||
# determine if heading is blank or null.
|
||||
if "#{id["attributes"]["title"]}".blank? || "#{id["attributes"]["title"]}".empty?
|
||||
Jekyll.logger.debug "ERROR: the post title is missing; does the post have a heading?".to_s.red
|
||||
else
|
||||
title = id["attributes"]["title"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Title: " "#{title}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# store slug into object (object is auto generated with Strapi plugin)
|
||||
slug = id["attributes"]["slug"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Slug: " "#{slug}".to_s.yellow
|
||||
|
||||
# determine if subheading is blank or null.
|
||||
if "#{id["attributes"]["subheading"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the subheading is missing; does post [" "#{title}] have a subheading?".to_s.red
|
||||
else
|
||||
subheading = id["attributes"]["subheading"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Subheading: " "#{subheading}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if date is blank or null.
|
||||
if "#{id["attributes"]["date"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the date is missing; does post [" "#{title}] have a date?".to_s.red
|
||||
else
|
||||
date = id["attributes"]["date"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Date: " "#{date}".to_s.yellow
|
||||
end
|
||||
|
||||
# determine if layout is blank or null.
|
||||
if "#{id["attributes"]["layout"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the layout is missing; does post [" "#{title}] have a layout?".to_s.red
|
||||
else
|
||||
layout = id["attributes"]["layout"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Layout: " "#{layout}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if author data is blank or null.
|
||||
if "#{id["attributes"]["author"]["data"]}".blank? || "#{id["attributes"]["author"]["data"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the author is missing; does post [" "#{title}] have a author?".to_s.red
|
||||
else
|
||||
author = id["attributes"]["author"]["data"]["attributes"]["name"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Author: " "#{author}".to_s.yellow
|
||||
end
|
||||
|
||||
# determine if banner_image is blank or null.
|
||||
if "#{id["attributes"]["banner_image"]["data"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the banner_image url is missing; does post [" "#{title}] have a banner image url?".to_s.red
|
||||
else
|
||||
banner_image = id["attributes"]["banner_image"]["data"]["attributes"]["url"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Banner image: " "#{banner_image}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if gallery is blank or null, then loop through data.
|
||||
if "#{id["attributes"]["gallery"]["data"]}".blank? || "#{id["attributes"]["gallery"]["data"]}".empty?
|
||||
Jekyll.logger.debug "WARNING: the gallery data is missing".to_s.magenta
|
||||
else
|
||||
# we only need the urls for each image to prep for download
|
||||
gallery_images = id["attributes"]["gallery"]["data"]
|
||||
# loop through each product image.
|
||||
gallery_images.each do |image|
|
||||
puts ""
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Gallery image url(s): " "#{image["attributes"]["url"]}".to_s.yellow.bold
|
||||
end
|
||||
puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
# determine if banner_image_description is blank or null.
|
||||
if "#{id["attributes"]["banner_image_description"]}".blank?
|
||||
Jekyll.logger.debug "WARNING: the banner_image_description is missing; does post [" "#{title}] have a banner_image_description?".to_s.yellow
|
||||
else
|
||||
banner_image_description = id["attributes"]["banner_image_description"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Banner image desc: " "#{banner_image_description}".to_s.yellow
|
||||
end
|
||||
|
||||
# determine if tags data is blank or null, then loop through data.
|
||||
if "#{id["attributes"]["tags"]["data"]}".blank? || "#{id["attributes"]["tags"]["data"]}".empty?
|
||||
Jekyll.logger.debug "ERROR: the tags are missing; does post [" "#{title}] have tags?".to_s.red
|
||||
else
|
||||
# an array for storing multiple inputs
|
||||
tags = id["attributes"]["tags"]["data"]
|
||||
# loop through each post tag.
|
||||
tags.each do |tag|
|
||||
puts ""
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Tag(s): " "#{tag["attributes"]["tag"]}".to_s.yellow
|
||||
end
|
||||
puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
# determine if category data is blank or null; only one category per post.
|
||||
if "#{id["attributes"]["category"]["data"]}".blank? || "#{id["attributes"]["category"]["data"]}".empty?
|
||||
Jekyll.logger.debug "ERROR: the category is missing; does post [" "#{title}] have a category?".to_s.red
|
||||
else
|
||||
category = id["attributes"]["category"]["data"]["attributes"]["name"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Category: " "#{category}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if post content is blank or null.
|
||||
if "#{id["attributes"]["content"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the the content is missing; does post [" "#{title}] have a descrption?".to_s.red
|
||||
else
|
||||
content = id["attributes"]["content"]
|
||||
Jekyll.logger.debug "::DOCUMENT POST DEBUG:: Raw Content: " "#{content}".to_s.yellow
|
||||
end
|
||||
|
||||
# create the filename
|
||||
file_name = "#{date}-#{slug}#{file_ending}"
|
||||
|
||||
# let us put humpty dumpty back together again!
|
||||
# create a new collection type post *.md
|
||||
p = File.open( "#{jekyll_post_path}#{file_name}","w" )
|
||||
|
||||
# create document.md content in Jekyll yaml formatting
|
||||
p.puts "---"
|
||||
p.puts "updatedAt: #{updatedAt}"
|
||||
p.puts "layout: #{layout}"
|
||||
p.puts "title: #{title}"
|
||||
p.puts "subheading: #{subheading}"
|
||||
p.puts "slug: #{slug}"
|
||||
p.puts "date: #{date}"
|
||||
p.puts "author: #{author}"
|
||||
p.puts "banner_image: #{banner_image}" # the banner images are downloaded from API in image-filter.rb.
|
||||
p.puts "banner_image_description: #{banner_image_description}"
|
||||
p.puts "category: " "#{category}"
|
||||
|
||||
# add tags without json formatting in pretty format
|
||||
p.print "tags: " # pretty debug
|
||||
# loop & gather tags from one post
|
||||
if "#{id["attributes"]["tags"]}".blank? || "#{id["attributes"]["tags"]}".empty?
|
||||
Jekyll.logger.debug "WRITING ERROR: the tags are missing; does post [" "#{title}] have any tags?".to_s.red
|
||||
else
|
||||
tags = id["attributes"]["tags"]["data"]
|
||||
# loop through all tags
|
||||
tags.each do |tag|
|
||||
p.print tag["attributes"]["tag"]
|
||||
p.print ", "
|
||||
end
|
||||
p.puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
p.puts "---" # close .yaml file frontmatter
|
||||
p.puts "#{content}" # write post content
|
||||
p.close # close the file; stop writing
|
||||
end
|
||||
end
|
379
_plugins/jekyll-api/lib/b-generate-products.rb
Normal file
@ -0,0 +1,379 @@
|
||||
# This software generates mardown formatted products from json data.
|
||||
# Copyright (C) SharpeTronics, Inc. 2013-2023
|
||||
|
||||
# Author(s): Charles Sharpe(@odinzu_me) aka SharpeTronics, Inc.
|
||||
# License: GPLv3
|
||||
# Version: 1.3
|
||||
|
||||
# This is Free Software released under GPLv3. Any misuse of this software
|
||||
# will be followed up with GPL enforcement via Software Freedom Law Center:
|
||||
# https://www.softwarefreedom.org/
|
||||
|
||||
# If you incorporate or include any code from SharpeTronics, Inc., your
|
||||
# code must be licensed as GPLv3 (not GPLv2 or MIT)
|
||||
|
||||
# The GPLv3 software license applies to the code directly included in this source distribution.
|
||||
# See the LICENSE & COPYING file for full information.
|
||||
|
||||
# Dependencies downloaded as part of the build process may be covered by other open-source licenses.
|
||||
|
||||
# We are open to granting a more permissive (such as MIT or Apache 2.0) license to SharpeTronics, Inc.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please email
|
||||
# info@sharpetronics.com.
|
||||
|
||||
# If you would like to contribute to this code, please follow GPLv3 guidelines.
|
||||
# as an example, after making changes to the software (Called a Fork) and credit the original copyright holder as the creator with your credit added to theirs.
|
||||
|
||||
require 'fileutils' # https://ruby-doc.org/stdlib-2.4.1/libdoc/fileutils/rdoc/FileUtils.html
|
||||
require 'json' # https://ruby-doc.org/stdlib-3.0.2/libdoc/json/rdoc/JSON.html
|
||||
require 'yaml' # load Jekyll yaml config
|
||||
require 'active_support/core_ext/object/blank' # load only the specific extension for .blank? support
|
||||
require 'date' # https://github.com/ruby/date
|
||||
|
||||
module Jekyll
|
||||
# initialize variables
|
||||
jekyll_product_path = "collections/_products/"
|
||||
file_ending = ".md"
|
||||
|
||||
# load _config.yml
|
||||
config_yml = "_config.yml"
|
||||
f = YAML.load(File.read(config_yml.to_s)) # r - read file
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Is config empty? " "#{config_yml.blank?}".to_s.magenta.bold
|
||||
|
||||
# is Stripe turned on in site _config.yml file?
|
||||
stripe_enabled = f['api']['stripe']['enabled']
|
||||
Jekyll.logger.debug "ENV DEBUG: Is Stripe enabled? " "#{stripe_enabled}".to_s.yellow.bold
|
||||
|
||||
# if Stripe is enabled in _config.yml, then generate products
|
||||
if "#{stripe_enabled}" === "true"
|
||||
|
||||
# set filepath, load the json, then parse through json file
|
||||
json_product_path = f['api']['collections']['products']['filepath']
|
||||
|
||||
# must read data into memory before parsing file
|
||||
read_products_json = File.read(json_product_path) # read json for all products
|
||||
|
||||
# parse through json files
|
||||
parsed_products_file = JSON.parse(read_products_json.to_s) # returns a hash
|
||||
|
||||
# cache / verify and download each product data
|
||||
product_ids = parsed_products_file["data"]
|
||||
# loop through each collection id
|
||||
product_ids.each do |id|
|
||||
# store json specific data for each product
|
||||
# determine if stripe_id is blank or null.; this unique identifier is used for Stripe product ids also.
|
||||
# this allows overwriting Stripe id and syncronizes ids created from CMS API.
|
||||
if "#{id}".blank?
|
||||
Jekyll.logger.debug "ERROR: the product id is missing;".to_s.red
|
||||
else
|
||||
stripe_id = id["id"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Does the JSON data exist? " "#{stripe_id}".to_s.yellow
|
||||
end
|
||||
|
||||
# determine if heading is blank or null.
|
||||
if "#{id["attributes"]["heading"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the product heading is missing; does product [" "#{heading}] have a heading?".to_s.red
|
||||
else
|
||||
heading = id["attributes"]["heading"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Heading: " "#{heading}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# store slug into object (object is auto generated with Strapi plugin)
|
||||
slug = id["attributes"]["slug"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Slug: " "#{slug}".to_s.yellow
|
||||
|
||||
# determine if subheading is blank or null.
|
||||
if "#{id["attributes"]["subheading"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the subheading is missing; does product [" "#{heading}] have a subheading?".to_s.red
|
||||
else
|
||||
subheading = id["attributes"]["subheading"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Subheading: " "#{subheading}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if date is blank or null.
|
||||
if "#{id["attributes"]["date"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the date is missing; does product [" "#{heading}] have a date?".to_s.red
|
||||
else
|
||||
date = id["attributes"]["date"]
|
||||
# store build times of local products with Stripe metadata
|
||||
# on update too Stripe, updates the Stripe updatedAt time creating an infinite loop; we must have a static local time for each product that doesn't change on pushing to Stripe API
|
||||
# NOTE: this time needs to be local product data and doesn't come from Strapi CMS API.
|
||||
local_cms_time = DateTime.strptime(id['attributes']['updatedAt'], '%Y-%m-%dT%H:%M:%S')
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Date: " "#{date}".to_s.yellow
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Build_Time: " "#{local_cms_time}".to_s.yellow
|
||||
end
|
||||
|
||||
# determine if layout is blank or null.
|
||||
if "#{id["attributes"]["layout"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the layout is missing; does product [" "#{heading}] have a layout?".to_s.red
|
||||
else
|
||||
layout = id["attributes"]["layout"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Layout: " "#{layout}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if author data is blank or null.
|
||||
if "#{id["attributes"]["author"]["data"]}".blank? || "#{id["attributes"]["author"]["data"]}".empty?
|
||||
Jekyll.logger.debug "ERROR: the author is missing; does product [" "#{heading}] have a author?".to_s.red
|
||||
else
|
||||
author = id["attributes"]["author"]["data"]["attributes"]["name"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Author: " "#{author}".to_s.yellow
|
||||
end
|
||||
|
||||
# determine if banner_image is blank or null.
|
||||
if "#{id["attributes"]["banner_image"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the banner_image url is missing; does product [" "#{heading}] have a banner image url?".to_s.red
|
||||
else
|
||||
banner_image = id["attributes"]["banner_image"]["data"]["attributes"]["url"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Banner image: " "#{banner_image}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if gallery is blank or null, then loop through data.
|
||||
if "#{id["attributes"]["gallery"]["data"]}".blank? || "#{id["attributes"]["gallery"]["data"]}".empty?
|
||||
Jekyll.logger.debug "WARNING: the gallery data is missing".to_s.magenta
|
||||
else
|
||||
# we only need the urls for each image to prep for download
|
||||
gallery_images = id["attributes"]["gallery"]["data"]
|
||||
# loop through each product image.
|
||||
gallery_images.each do |image|
|
||||
puts ""
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Gallery image url(s): " "#{image["attributes"]["url"]}".to_s.yellow.bold
|
||||
end
|
||||
puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
# determine if banner_image_description is blank or null.
|
||||
if "#{id["attributes"]["banner_image_description"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the banner_image_description is missing; does product [" "#{heading}] have a banner_image_description?".to_s.red
|
||||
else
|
||||
banner_image_description = id["attributes"]["banner_image_description"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Banner image desc: " "#{banner_image_description}".to_s.yellow
|
||||
end
|
||||
|
||||
# determine if tags data is blank or null, then loop through data.
|
||||
if "#{id["attributes"]["tags"]["data"]}".blank? || "#{id["attributes"]["tags"]["data"]}".empty?
|
||||
Jekyll.logger.debug "ERROR: the tags is missing; does product [" "#{heading}] have tags?".to_s.red
|
||||
else
|
||||
# an array for storing multiple inputs
|
||||
tags = id["attributes"]["tags"]["data"]
|
||||
# loop through each product tag.
|
||||
tags.each do |tag|
|
||||
puts ""
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Tag(s): " "#{tag["attributes"]["tag"]}".to_s.yellow
|
||||
end
|
||||
puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
# determine if category data is blank or null; only one category per product andor post.
|
||||
if "#{id["attributes"]["category"]["data"]}".blank? || "#{id["attributes"]["category"]["data"]}".empty?
|
||||
Jekyll.logger.debug "ERROR: the category is missing; does product [" "#{heading}] have a category?".to_s.red
|
||||
else
|
||||
category = id["attributes"]["category"]["data"]["attributes"]["name"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Category: " "#{category}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product description is blank or null.
|
||||
if "#{id["attributes"]["description"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the the description is missing; does product [" "#{heading}] have a descrption?".to_s.red
|
||||
else
|
||||
description = id["attributes"]["description"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Raw Content: " "#{description}".to_s.yellow
|
||||
end
|
||||
|
||||
# determine if is_featured is blank or null.
|
||||
if "#{id["attributes"]["is_featured"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the is_featured is missing; is product " "#{heading} featured?".to_s.red
|
||||
else
|
||||
is_featured = id["attributes"]["is_featured"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: is_featured: " "#{is_featured}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if is_software is blank or null.
|
||||
if "#{id["attributes"]["is_software"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the is_software is missing; is product " "#{heading} software?".to_s.red
|
||||
else
|
||||
is_software = id["attributes"]["is_software"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: is_software: " "#{is_software}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if is_shippable is blank or null.
|
||||
if "#{id["attributes"]["is_shippable"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the is_shippable is missing; is product " "#{heading} shippable?".to_s.red
|
||||
else
|
||||
is_shippable = id["attributes"]["is_shippable"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: is_shippable: " "#{is_shippable}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if unit_price is blank or null.
|
||||
if "#{id["attributes"]["unit_price"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the amount is missing; does product [" "#{heading}] have a price?".to_s.red
|
||||
else
|
||||
unit_price = id["attributes"]["unit_price"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: unit_price: $" "#{unit_price}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product quantity is blank or null.
|
||||
if "#{id["attributes"]["quantity"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the quantity is missing; does product [" "#{heading}] have a quantity?".to_s.red
|
||||
else
|
||||
quantity = id["attributes"]["quantity"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: quantity: " "#{quantity}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product weight is blank or null.
|
||||
if "#{id["attributes"]["weight"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the weight is missing; does product [" "#{heading}] have a weight?".to_s.red
|
||||
else
|
||||
weight = id["attributes"]["weight"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: weight: " "#{weight}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product package_dimensions is blank or null.
|
||||
if "#{id["attributes"]["package_dimensions"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the package_dimensions is missing; does product [" "#{heading}] have a package_dimensions?".to_s.red
|
||||
else
|
||||
package_dimensions = id["attributes"]["package_dimensions"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: package_dimensions: " "#{package_dimensions}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product material_type is blank or null.
|
||||
if "#{id["attributes"]["material_type"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the material_type is missing; does product [" "#{heading}] have a material_type?".to_s.red
|
||||
else
|
||||
material_type = id["attributes"]["material_type"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: material_type: " "#{material_type}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product tax_code is blank or null.
|
||||
if "#{id["attributes"]["tax_code"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the tax_code is missing; does product [" "#{heading}] have a tax_code?".to_s.red
|
||||
else
|
||||
tax_code = id["attributes"]["tax_code"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: tax_code: " "#{tax_code}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product webpage_url is blank or null.
|
||||
if "#{id["attributes"]["webpage_url"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the webpage_url is missing; does product [" "#{heading}] have a webpage_url?".to_s.red
|
||||
else
|
||||
webpage_url = id["attributes"]["webpage_url"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: webpage_url: " "#{webpage_url}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product shipping_price is blank or null.
|
||||
if "#{id["attributes"]["shipping_price"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the shipping_price is missing; does product [" "#{heading}] have a shipping_price?".to_s.red
|
||||
else
|
||||
shipping_price = id["attributes"]["shipping_price"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: shipping_price: " "#{shipping_price}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product currency_type is blank or null.
|
||||
if "#{id["attributes"]["currency_type"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the currency_type is missing; does product [" "#{heading}] have a currency_type?".to_s.red
|
||||
else
|
||||
currency_type = id["attributes"]["currency_type"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: currency_type: " "#{material_type}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# determine if product shipping_rates is blank or null.
|
||||
if "#{id["attributes"]["shipping_rates"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the shipping_rates is missing; does product [" "#{heading}] have shipping_rates?".to_s.red
|
||||
else
|
||||
shipping_rates = id["attributes"]["shipping_rates"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: shipping_rates: " "#{shipping_rates}".to_s.yellow.bold
|
||||
#placeholder for looping through each shipping rate option
|
||||
end
|
||||
|
||||
# determine if product shipping_companies is blank or null.
|
||||
if "#{id["attributes"]["shipping_companies"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the shipping_companies is missing; does product [" "#{heading}] have shipping_companies?".to_s.red
|
||||
else
|
||||
shipping_companies = id["attributes"]["shipping_companies"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: shipping_companies: " "#{shipping_companies}".to_s.yellow.bold
|
||||
#placeholder for looping through each shipping_companies option
|
||||
end
|
||||
|
||||
# determine if product country_origin is blank or null.
|
||||
if "#{id["attributes"]["country_origin"]}".blank?
|
||||
Jekyll.logger.debug "ERROR: the country_origin is missing; does product [" "#{heading}] have a country_origin?".to_s.red
|
||||
else
|
||||
country_origin = id["attributes"]["country_origin"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: country_origin: " "#{country_origin}".to_s.yellow.bold
|
||||
end
|
||||
|
||||
# create the filename
|
||||
file_name = "#{date}-#{slug}#{file_ending}"
|
||||
|
||||
# let us put humpty dumpty back together again!
|
||||
# create a new collection type post *.md
|
||||
p = File.open( "#{jekyll_product_path}#{file_name}","w" )
|
||||
|
||||
# create document.md content in Jekyll yaml formatting
|
||||
p.puts "---"
|
||||
p.puts "stripe_id: #{stripe_id}"
|
||||
p.puts "metadata: #{local_cms_time}"
|
||||
p.puts "layout: #{layout}"
|
||||
p.puts "heading: #{heading}"
|
||||
p.puts "subheading: #{subheading}"
|
||||
p.puts "slug: #{slug}"
|
||||
p.puts "date: #{date}"
|
||||
p.puts "author: #{author}"
|
||||
p.puts "banner_image: #{banner_image}" # the banner images are downloaded from API in image-filter.rb.
|
||||
p.puts "banner_image_description: #{banner_image_description}"
|
||||
p.puts "category: " "#{category}"
|
||||
|
||||
# add gallery images without json formatting in pretty format
|
||||
p.print "gallery: \n" # pretty debug
|
||||
# loop & gather gallery images from one product
|
||||
if "#{id["attributes"]["gallery"]["data"]}".blank?
|
||||
Jekyll.logger.debug "WRITING ERROR: the gallery images are missing; does product [" "#{heading}] have any gallery images?".to_s.red
|
||||
else
|
||||
gallery = id["attributes"]["gallery"]["data"]
|
||||
# loop through all tags
|
||||
gallery.each do |gallery_image|
|
||||
p.print " - image_path: " "#{gallery_image["attributes"]["url"]} \n"
|
||||
p.print " title: " "#{gallery_image["attributes"]["hash"]} \n"
|
||||
end
|
||||
p.puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
# add tags without json formatting in pretty format
|
||||
p.print "tags: " # pretty debug
|
||||
# loop & gather tags from one product
|
||||
if "#{id["attributes"]["tags"]["data"]}".blank?
|
||||
Jekyll.logger.debug "WRITING ERROR: the tags are missing; does product [" "#{heading}] have any tags?".to_s.red
|
||||
else
|
||||
tags = id["attributes"]["tags"]["data"]
|
||||
# loop through all tags
|
||||
tags.each do |tag|
|
||||
p.print
|
||||
p.print tag["attributes"]["tag"]
|
||||
p.print ", "
|
||||
end
|
||||
p.puts "" # pretty debug spacing
|
||||
end
|
||||
|
||||
p.puts "webpage_url: #{webpage_url}"
|
||||
p.puts "is_featured: #{is_featured}"
|
||||
p.puts "is_software: #{is_software}"
|
||||
p.puts "is_shippable: #{is_shippable}"
|
||||
p.puts "currency_type: #{currency_type}"
|
||||
p.puts "country_origin: #{country_origin}"
|
||||
p.puts "unit_price: #{unit_price}"
|
||||
p.puts "quantity: #{quantity}"
|
||||
p.puts "package_dimensions: #{package_dimensions}"
|
||||
p.puts "material_type: #{material_type}"
|
||||
p.puts "weight: #{weight}"
|
||||
p.puts "tax_code: #{tax_code}"
|
||||
p.puts "shipping_price: #{shipping_price}"
|
||||
p.puts "shipping_rates: #{shipping_rates}"
|
||||
p.puts "shipping_company: #{shipping_companies}"
|
||||
|
||||
p.puts "---" # close .yaml file frontmatter
|
||||
p.puts "#{description}" # write product description
|
||||
p.close # close the file; stop writing
|
||||
end
|
||||
else
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Stripe is disabled in the _config.yml"
|
||||
end
|
||||
end
|
@ -1,9 +1,9 @@
|
||||
# This software gathers all collection types from an API and saves that data into Jekyll _data/ folder.
|
||||
# This software refactors static json image data and downloads unknown images for building a Jekyll web app.
|
||||
# Copyright (C) SharpeTronics, Inc. 2013-2023
|
||||
|
||||
# Author(s): Charles Sharpe(@odinzu_me)
|
||||
# Author(s): Charles Sharpe(@odinzu_me) aka SharpeTronics, Inc.
|
||||
# License: GPLv3
|
||||
# Version: 1
|
||||
# Version: 1.3
|
||||
|
||||
# This is Free Software released under GPLv3. Any misuse of this software
|
||||
# will be followed up with GPL enforcement via Software Freedom Law Center:
|
||||
@ -18,8 +18,8 @@
|
||||
# Dependencies downloaded as part of the build process may be covered by other open-source licenses.
|
||||
|
||||
# We are open to granting a more permissive (such as MIT or Apache 2.0) license to SharpeTronics, Inc.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please contact
|
||||
# info@sharpetronics.com if you are interested.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please email
|
||||
# info@sharpetronics.com.
|
||||
|
||||
# If you would like to contribute to this code, please follow GPLv3 guidelines.
|
||||
# as an example, after making changes to the software (Called a Fork) and credit the original copyright holder as the creator with your credit added to theirs.
|
||||
@ -29,6 +29,7 @@ require 'yaml' # load jekyll yaml config
|
||||
require 'faraday' # https://lostisland.github.io/faraday/usage/
|
||||
require 'faraday/multipart' # https://github.com/lostisland/faraday-multipart
|
||||
require 'httpx/adapters/faraday' # https://honeyryderchuck.gitlab.io/httpx/
|
||||
require 'active_support/core_ext/object/blank' # load only the specific extension for .blank? support
|
||||
|
||||
# load and verify _config.yml
|
||||
config_yml = "_config.yml"
|
||||
@ -36,97 +37,281 @@ f = YAML.load(File.read(config_yml.to_s)) # r - read file
|
||||
api_endpoint = f['api']['endpoint']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: API_ENDPDOINT: " "#{api_endpoint}".to_s.yellow
|
||||
media_dir = f['api']['local_media_dir']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: MEDIA DIR: " "#{media_dir}".to_s.yellow.bold
|
||||
output = f['api']['output']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: OUTPUT CONFIG: " "#{output}".to_s.yellow
|
||||
Jekyll.logger.debug "CONFIG DEBUG: MEDIA_DIR: " "#{media_dir}".to_s.yellow.bold
|
||||
cache_images = f['api']['cache_images']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: CACHED_IMAGES_DIR: " "#{cache_images}".to_s.yellow
|
||||
|
||||
# check if output is true or false in _config.yml
|
||||
if "#{output}" === "false" || nil
|
||||
Jekyll.logger.debug "CONFIG DEBUG: CONFIG FAILED TO LOAD".to_s.yellow
|
||||
# check if cache_images is true or false in _config.yml
|
||||
if "#{cache_images}" === "false" # "If A described a set, would B be a member of that set?" Jörg W Mittag
|
||||
Jekyll.logger.debug "CONFIG DEBUG: Downloading images is DISABLED in _config.yml.".to_s.yellow
|
||||
else
|
||||
# create image directory if doesn't exist
|
||||
# determine image directory filepath in _config.yml
|
||||
if not Dir.exist?(f['api']['local_media_dir'].to_s)
|
||||
Jekyll.logger.info "the image directory does not exist, I am going to create one".to_s.red
|
||||
Jekyll.logger.info "the Jekyll image directory does not exist, see _config_yml api --> local_media_dir.".to_s.red
|
||||
Dir.mkdir f['api']['local_media_dir'].to_s
|
||||
Jekyll.logger.info "CONFIG DEBUG: The local media directory is created at: #{f['api']['local_media_dir'].to_s}".to_s.yellow
|
||||
end
|
||||
|
||||
# All images are downloaded from EACH NEW collection
|
||||
# Each collection is parsed through the local _data json
|
||||
# Furthermore, the url is pieced together on each collection type like a post or product.
|
||||
# All images are downloaded from EACH NEW collection
|
||||
# Each collection is parsed through the local _data json
|
||||
# Furthermore, the url is pieced together on each collection type like a post or product.
|
||||
|
||||
# prepare http api connection
|
||||
api_builder = Faraday.new do |builder|
|
||||
# add by symbol, lookup from Faraday::Request,
|
||||
# Faraday::Response and Faraday::Adapter registries
|
||||
builder.adapter :httpx # must add adapter; default is Net:HTTP
|
||||
#builder.request :authorization, options
|
||||
builder.request :multipart
|
||||
# identical, but add the class directly instead of using lookups
|
||||
builder.use Faraday::Response::RaiseError
|
||||
end
|
||||
Jekyll.logger.debug "HTTP DEBUG: BULIDING CONNECTION: #{api_builder}".to_s.yellow
|
||||
# prepare http api connection; this is used for each collection type
|
||||
api_builder = Faraday.new do |builder|
|
||||
# add by symbol, lookup from Faraday::Request,
|
||||
# Faraday::Response and Faraday::Adapter registries
|
||||
builder.adapter :httpx # must add adapter; default is Net:HTTP
|
||||
#builder.request :authorization, options
|
||||
builder.request :multipart
|
||||
# identical, but add the class directly instead of using lookups
|
||||
builder.use Faraday::Response::RaiseError
|
||||
end # api_builder
|
||||
Jekyll.logger.debug "HTTP DEBUG: BULIDING CONNECTION: #{api_builder}".to_s.yellow
|
||||
|
||||
# load file, then parse through json file in _data/posts/index.json
|
||||
# add new collections here
|
||||
json_post_path = f['api']['collections']['posts']['filepath']
|
||||
Jekyll.logger.debug "JSON DEBUG: GET JSON CONFIG PATH: " "#{json_post_path}".to_s.yellow.bold
|
||||
# TODO: add product_path to parsed_json_file
|
||||
#json_product_path = f['api']['collections']['products']['path']
|
||||
#Jekyll.logger.debug "DEBUG: OUTPUT CONFIG: " "#{json_product_path}".to_s.yellow
|
||||
# begin sorting through PRODUCT json data
|
||||
# determine if using ecommerce integration, then prepare product images from sorting the json data.
|
||||
if f['api']['collections']['products']['type'] != 'products' # case sensitive
|
||||
Jekyll.logger.debug "CONFIG DEBUG: PRODUCTS FILEPATH IS MISSING IN JEKYLL _CONFIG.YML ".to_s.red.bold
|
||||
else
|
||||
# load filepath, then parse through json file in _data/posts/index.json
|
||||
json_product_path = f['api']['collections']['products']['filepath']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: PRODUCTS PATH: " "#{json_product_path}".to_s.yellow.bold
|
||||
|
||||
# TODO: add extra error log if file is missing
|
||||
read_json = File.read(json_post_path) # read json for all posts
|
||||
#Jekyll.logger.debug "DEBUG: READ JSON FILE: " "#{read_json}".to_s.yellow.bold # basic debug test
|
||||
read_product_json = File.read(json_product_path) # read json for all posts
|
||||
#Jekyll.logger.debug "DEBUG: READ JSON FILE: " "#{read_product_json}".to_s.yellow.bold # basic debug test
|
||||
|
||||
parsed_json_file = JSON.parse(read_json.to_s) # returns json hash
|
||||
Jekyll.logger.debug "JSON DEBUG: IS parsed_json_file EMPTY? " "#{parsed_json_file.empty?}".to_s.yellow # basic debug test
|
||||
parsed_product_json_file = JSON.parse(read_product_json.to_s) # returns json hash
|
||||
Jekyll.logger.debug "JSON DEBUG: IS PARSED_JSON_FILE MISSING? " "#{parsed_product_json_file.blank?}".to_s.magenta # basic debug test
|
||||
|
||||
# cache / check and download all collection image data
|
||||
collection_ids = parsed_json_file["data"]
|
||||
# loop through each collection id
|
||||
collection_ids.each do |id|
|
||||
#puts "#{id}".yellow # output collection id for debug
|
||||
# cache / check and download all PRODUCT image data
|
||||
product_collection_ids = parsed_product_json_file["data"]
|
||||
# loop through each product collection id
|
||||
product_collection_ids.each do |id|
|
||||
|
||||
# get image_url
|
||||
if "#{id["attributes"]["image"]}".to_s.empty? || nil || "#{id["attributes"]["image"]["data"]}".to_s.empty?
|
||||
Jekyll.logger.debug "ERROR: IMAGE DATA EMPTY for COLLECTION: " "#{id["attributes"]["title"]}".to_s.red # basic debug test
|
||||
else
|
||||
# set uri_path
|
||||
uri_path = "#{api_endpoint}""#{id["attributes"]["image"]["data"]["attributes"]["url"]}"
|
||||
Jekyll.logger.debug "HTTP DEBUG: URI_PATH:" "#{uri_path}".to_s.yellow.bold
|
||||
|
||||
# get file_name
|
||||
file_name = "#{id["attributes"]["image"]["data"]["attributes"]["hash"]}"
|
||||
|
||||
# prepare file
|
||||
file_ext = File.extname(uri_path) # get file extension from API
|
||||
Jekyll.logger.debug "FILE DEBUG: THE FILE EXTENSION NAME " "#{file_ext}".to_s.yellow.bold # basic debug test
|
||||
|
||||
# TODO: add image modified time to each API image
|
||||
#puts File.exist?(media_dir + file_name + file_ext) #debug if File exists
|
||||
if File.exist?(media_dir + file_name + file_ext) === false
|
||||
|
||||
# where the magic happens; download a new image
|
||||
image = api_builder.get(uri_path)
|
||||
Jekyll.logger.debug "DOWNLOADING... IMAGE URL IS: " "#{id["attributes"]["image"]["data"]["attributes"]["url"]}".to_s.green # basic debug test
|
||||
Jekyll.logger.debug "HTTP DEBUG: A NEW IMAGE HTTP(S) RESPONSE: " "#{image.status}\n" "#{image.headers}\n".to_s.yellow # debug http response status
|
||||
|
||||
# only save file if data exists
|
||||
file_exist = File.exist?(media_dir + file_name + file_ext) # file already exists? then, TODO: skip
|
||||
Jekyll.logger.debug "FILE DEBUG: DOES FILE ALREADY EXIST? " "#{file_exist}".to_s.yellow # basic debug test
|
||||
|
||||
# TODO: enable to work with Windows NTFS File Systems
|
||||
#file_ctime = File.ctime(media_dir + file_name + file_ext) # in NTFS (Windows) returns creation time (birthtime)
|
||||
#Jekyll.logger.debug "DEBUG: WHEN WAS FILE LAST MODIFIED? " "#{file_ctime}".to_s.yellow # basic debug test
|
||||
|
||||
c = File.open(file_name + file_ext, 'w') # w - Create an empty file for writing.
|
||||
c.write(image.body)
|
||||
c.close
|
||||
FileUtils.mv "#{c.path}", "#{media_dir}"
|
||||
Jekyll.logger.debug "FILE DEBUG: THE WHOLE FILE NAME " "#{file_name}" "#{file_ext}".to_s.yellow.bold # basic debug test
|
||||
# loop through gallery image data if exists
|
||||
if "#{id["attributes"]["gallery"]["data"]}".blank? || "#{id["attributes"]["gallery"]["data"]}".empty?
|
||||
Jekyll.logger.debug "GALLERY DEBUG: THE PRODUCT GALLERY DATA DOESN'T EXIST "
|
||||
else
|
||||
Jekyll.logger.debug "WARNING: FILE ALREADY EXISTS - SKIPPING".to_s.red.bold # basic debug test
|
||||
end
|
||||
end # end if output = true
|
||||
end
|
||||
end
|
||||
# we only need the urls for each image to prep for download
|
||||
product_gallery_images = id["attributes"]["gallery"]["data"]
|
||||
# loop through each product image.
|
||||
product_gallery_images.each do |image|
|
||||
|
||||
# prepare gallery_image_uri_path and store in a variable https://www.example.com/uploads/example.webp
|
||||
product_gallery_image_uri_path = "#{api_endpoint}""#{image["attributes"]["url"]}"
|
||||
Jekyll.logger.debug "PRODUCT FILE DEBUG: GALLERY IMAGE PATH: " "#{product_gallery_image_uri_path}".to_s.yellow
|
||||
|
||||
# prepare gallery_image_file_name and store in a variable
|
||||
product_gallery_image_file_name = "#{image["attributes"]["hash"]}"
|
||||
Jekyll.logger.debug "PRODUCT FILE DEBUG: GALLERY IMAGE FILE NAME: " "#{product_gallery_image_file_name}".to_s.yellow.bold
|
||||
|
||||
# prepare gallery_image_file_ext and store in a variable
|
||||
product_gallery_image_file_ext = "#{image["attributes"]["ext"]}" # get file extension from API
|
||||
Jekyll.logger.debug "PRODUCT FILE DEBUG: GALLERY IMAGE FILE EXT: " "#{product_gallery_image_file_ext}".to_s.yellow
|
||||
puts ""
|
||||
|
||||
|
||||
# if cached PRODUCT product_gallery_images exist, skip; else check modified time.
|
||||
#File.exist?(media_dir + product_gallery_image_file_name + product_gallery_image_file_ext)
|
||||
if File.exist?(media_dir + product_gallery_image_file_name + product_gallery_image_file_ext) === false
|
||||
|
||||
# where the magic happens; we finally download a new image
|
||||
gallery_download_image = api_builder.get(product_gallery_image_uri_path)
|
||||
Jekyll.logger.debug "DOWNLOADING... THE GALLERY PRODUCT IMAGE URI IS: " "#{product_gallery_image_uri_path}".to_s.cyan.bold # basic debug test
|
||||
Jekyll.logger.debug "HTTP DEBUG: A NEW GALLERY PRODUCT IMAGE HTTP(S) RESPONSE: " "#{gallery_download_image.status}\n" "#{gallery_download_image.headers}\n".to_s.yellow # debug http response status
|
||||
|
||||
# only save file if data exists
|
||||
file_exist_debug = File.exist?(media_dir + product_gallery_image_file_name + product_gallery_image_file_ext) # file already exists? then, TODO: skip
|
||||
Jekyll.logger.debug "FILE DEBUG: DOES GALLERY PRODUCT IMAGE ALREADY EXIST? " "#{file_exist_debug}".to_s.yellow # basic debug test
|
||||
|
||||
# TODO: enable to work with Windows NTFS File Systems
|
||||
#file_ctime = File.ctime(media_dir + file_name + file_ext) # in NTFS (Windows) returns creation time (birthtime)
|
||||
#Jekyll.logger.debug "DEBUG: WHEN WAS FILE LAST MODIFIED? " "#{file_ctime}".to_s.yellow # basic debug test
|
||||
|
||||
c = File.open(product_gallery_image_file_name + product_gallery_image_file_ext, 'w') # w - Create an empty file for writing.
|
||||
c.write(gallery_download_image.body) # write the download to local media_dir
|
||||
c.close # close the file
|
||||
FileUtils.mv "#{c.path}", "#{media_dir}" # move the file to custom path
|
||||
Jekyll.logger.debug "FILE DEBUG: THE WHOLE GALLERY PRODUCT IMAGE FILE NAME " "#{product_gallery_image_file_name}" "#{product_gallery_image_file_ext}".to_s.yellow.bold # basic debug test
|
||||
else
|
||||
Jekyll.logger.debug "PRODUCT GALLERY IMAGE ALREADY EXISTS - SKIPPING".to_s.magenta
|
||||
# get banner_image_uri_path from each PRODUCT
|
||||
if "#{id["attributes"]["banner_image"]["data"]}".blank? || "#{id["attributes"]["banner_image"]["data"]}".empty?
|
||||
Jekyll.logger.debug "ERROR: IMAGE DATA EMPTY for PRODUCT: " "#{id["attributes"]["name"]}".to_s.red # basic debug test
|
||||
else
|
||||
# set uri_path https://www.example.com/uploads/example.webp
|
||||
banner_image_uri_path = "#{api_endpoint}""#{id["attributes"]["banner_image"]["data"]["attributes"]["url"]}"
|
||||
Jekyll.logger.debug "PRODUCT FILE DEBUG: PRODUCT BANNER_IMAGE URI_PATH: " "#{banner_image_uri_path}".to_s.yellow
|
||||
|
||||
# get image_file_name
|
||||
banner_image_file_name = "#{id["attributes"]["banner_image"]["data"]["attributes"]["hash"]}"
|
||||
Jekyll.logger.debug "PRODUCT FILE DEBUG: PRODUCT BANNER_IMAGE URI_PATH: " "#{banner_image_file_name}".to_s.yellow.bold
|
||||
|
||||
# prepare filename
|
||||
banner_image_file_ext = "#{id["attributes"]["banner_image"]["data"]["attributes"]["ext"]}"
|
||||
Jekyll.logger.debug "PRODUCT FILE DEBUG: THE FILE EXTENSION NAME: " "#{banner_image_file_ext}".to_s.yellow # basic debug test
|
||||
|
||||
# if cached PRODUCT banner_image_file_name exists, skip; else check modified time.
|
||||
#File.exist?(media_dir + banner_image_file_name + banner_image_file_ext).to_s.yellow.bold
|
||||
File.exist?(media_dir + banner_image_file_name + banner_image_file_ext)
|
||||
if File.exist?(media_dir + banner_image_file_name + banner_image_file_ext) == false
|
||||
|
||||
# where the magic happens; we finally download a new image
|
||||
download_image = api_builder.get(banner_image_uri_path)
|
||||
Jekyll.logger.debug "DOWNLOADING... THE PRODUCT IMAGE URI IS: " "#{banner_image_uri_path}".to_s.cyan.bold # basic debug test
|
||||
Jekyll.logger.debug "HTTP DEBUG: A NEW PRODUCT IMAGE HTTP(S) RESPONSE: " "#{download_image.status}\n" "#{download_image.headers}\n".to_s.yellow # debug http response status
|
||||
|
||||
# only save file if data exists
|
||||
file_exist_debug = File.exist?(media_dir + banner_image_file_name + banner_image_file_ext) # file already exists? then, TODO: skip
|
||||
Jekyll.logger.debug "FILE DEBUG: DOES PRODUCT IMAGE ALREADY EXIST? " "#{file_exist_debug}".to_s.yellow # basic debug test
|
||||
|
||||
# TODO: enable to work with Windows NTFS File Systems
|
||||
#file_ctime = File.ctime(media_dir + file_name + file_ext) # in NTFS (Windows) returns creation time (birthtime)
|
||||
#Jekyll.logger.debug "DEBUG: WHEN WAS FILE LAST MODIFIED? " "#{file_ctime}".to_s.yellow # basic debug test
|
||||
|
||||
c = File.open(banner_image_file_name + banner_image_file_ext, 'w') # w - Create an empty file for writing.
|
||||
c.write(download_image.body) # write the download to local media_dir
|
||||
c.close # close the file
|
||||
FileUtils.mv "#{c.path}", "#{media_dir}" # move the file to custom path
|
||||
Jekyll.logger.debug "FILE DEBUG: THE WHOLE PRODUCT BANNER IMAGE FILE NAME " "#{banner_image_file_name}" "#{banner_image_file_ext}".to_s.yellow.bold # basic debug test
|
||||
else
|
||||
Jekyll.logger.debug "PRODUCT BANNER IMAGE ALREADY EXISTS - SKIPPING".to_s.magenta
|
||||
end
|
||||
end # end banner_image data
|
||||
end # end cached if file exists
|
||||
|
||||
end # ends product gallery images each loop
|
||||
puts "" # pretty debug spacing
|
||||
end # ends product gallery image data loop
|
||||
|
||||
end # end product_collection_ids
|
||||
puts "" # pretty debug spacing
|
||||
end # end product formatting check
|
||||
|
||||
|
||||
# begin parsing through POST json data.
|
||||
# prepare post images from sorting the json data.
|
||||
if f['api']['collections']['posts']['type'] != 'posts' # case sensitive
|
||||
Jekyll.logger.debug "CONFIG DEBUG: POSTS FILEPATH IS MISSING IN JEKYLL _CONFIG.YML ".to_s.red
|
||||
else
|
||||
# load filepath, then parse through json file in _data/posts/index.json
|
||||
json_post_path = f['api']['collections']['posts']['filepath']
|
||||
Jekyll.logger.debug "CONFIG DEBUG: POSTS PATH: " "#{json_post_path}".to_s.yellow.bold
|
||||
|
||||
read_post_json = File.read(json_post_path) # read json for all posts
|
||||
#Jekyll.logger.debug "DEBUG: READ JSON FILE: " "#{read_post_json}".to_s.yellow.bold # basic debug test
|
||||
|
||||
parsed_post_json_file = JSON.parse(read_post_json.to_s) # returns json hash
|
||||
Jekyll.logger.debug "JSON DEBUG: IS PARSED_JSON_FILE MISSING? " "#{parsed_post_json_file.blank?}".to_s.yellow # basic debug test
|
||||
|
||||
# cache / check and download all POSTS image data
|
||||
post_collection_ids = parsed_post_json_file["data"]
|
||||
# loop through each post collection id
|
||||
post_collection_ids.each do |id|
|
||||
|
||||
# loop through post gallery image data if exists
|
||||
if "#{id["attributes"]["gallery"]["data"]}".blank? || "#{id["attributes"]["gallery"]["data"]}".empty?
|
||||
Jekyll.logger.debug "GALLERY DEBUG: THE POST ID: " "#{id["id"]} " "GALLERY DATA DOESN'T EXIST".to_s.magenta
|
||||
else
|
||||
# we only need the urls for each image to prep for download
|
||||
post_gallery_images = id["attributes"]["gallery"]["data"]
|
||||
# loop through each post image.
|
||||
post_gallery_images.each do |post_image|
|
||||
|
||||
# prepare gallery_image_uri_path and store in a variable https://www.example.com/uploads/example.webp
|
||||
post_gallery_image_uri_path = "#{api_endpoint}""#{post_image["attributes"]["url"]}"
|
||||
Jekyll.logger.debug "POST FILE DEBUG: POST gallery_image_uri_path: " "#{post_gallery_image_uri_path}".to_s.yellow
|
||||
|
||||
# prepare gallery_image_file_name and store in a variable
|
||||
post_gallery_image_file_name = "#{post_image["attributes"]["hash"]}"
|
||||
Jekyll.logger.debug "POST FILE DEBUG: POST gallery_image_file_name: " "#{post_gallery_image_file_name}".to_s.yellow.bold
|
||||
|
||||
# prepare gallery_image_file_ext and store in a variable
|
||||
post_gallery_image_file_ext = "#{post_image["attributes"]["ext"]}" # get file extension from API
|
||||
Jekyll.logger.debug "POST FILE DEBUG: THE POST gallery_image_file_ext: " "#{post_gallery_image_file_ext}".to_s.yellow # basic debug test
|
||||
puts ""
|
||||
|
||||
# if cached POST post_banner_image_file_name exists, skip; else check modified time.
|
||||
if File.exist?(media_dir + post_gallery_image_file_name + post_gallery_image_file_ext) === false
|
||||
|
||||
# where the magic happens; we finally download a new image
|
||||
post_gallery_download_image = api_builder.get(post_gallery_image_uri_path)
|
||||
Jekyll.logger.debug "DOWNLOADING... THE GALLERY POST IMAGE URI IS: " "#{post_gallery_image_uri_path}".to_s.cyan.bold # basic debug test
|
||||
Jekyll.logger.debug "HTTP DEBUG: A NEW GALLERY POST IMAGE HTTP(S) RESPONSE: " "#{post_gallery_download_image.status}\n" "#{post_gallery_download_image.headers}\n".to_s.yellow # debug http response status
|
||||
|
||||
# only save file if data exists
|
||||
post_gallery_file_exist_debug = File.exist?(media_dir + post_gallery_image_file_name + post_gallery_image_file_ext) # file already exists? then, TODO: skip
|
||||
Jekyll.logger.debug "FILE DEBUG: DOES GALLERY POST IMAGE ALREADY EXIST? " "#{post_gallery_file_exist_debug}".to_s.yellow # basic debug test
|
||||
|
||||
# TODO: enable to work with Windows NTFS File Systems
|
||||
#file_ctime = File.ctime(media_dir + file_name + file_ext) # in NTFS (Windows) returns creation time (birthtime)
|
||||
#Jekyll.logger.debug "DEBUG: WHEN WAS FILE LAST MODIFIED? " "#{file_ctime}".to_s.yellow # basic debug test
|
||||
|
||||
c = File.open(post_gallery_image_file_name + post_gallery_image_file_ext, 'w') # w - Create an empty file for writing.
|
||||
c.write(post_gallery_download_image.body) # write the download to local media_dir
|
||||
c.close # close the file
|
||||
FileUtils.mv "#{c.path}", "#{media_dir}" # move the file to custom path
|
||||
Jekyll.logger.debug "FILE DEBUG: THE WHOLE GALLERY POST IMAGE FILE NAME " "#{post_gallery_image_file_name}" "#{post_gallery_image_file_ext}".to_s.yellow.bold # basic debug test
|
||||
else
|
||||
Jekyll.logger.debug "POST GALLERY IMAGE ALREADY EXISTS - SKIPPING".to_s.magenta
|
||||
end # ends does post gallery image exist?
|
||||
|
||||
end # end post_gallery_images each loop
|
||||
puts "" # pretty debug spacing
|
||||
|
||||
end # ends post gallery image data loop
|
||||
|
||||
# we only need the urls for each image to prep for download
|
||||
#pp id
|
||||
post_banner_images = id["attributes"]["banner_image"]["data"]
|
||||
# loop through each post image.
|
||||
post_banner_images.each do |banner_image|
|
||||
# get post_banner_image_uri_path from each POST
|
||||
if banner_image.blank? || banner_image.empty?
|
||||
Jekyll.logger.debug "ERROR: IMAGE DATA EMPTY for POST: " "#{banner_image["attributes"]["name"]}".to_s.red # basic debug test
|
||||
else
|
||||
# set uri_path https://www.example.com/uploads/example.webp
|
||||
post_banner_image_uri_path = "#{api_endpoint}#{id["attributes"]["banner_image"]["data"]["attributes"]["url"]}"
|
||||
Jekyll.logger.debug "POST FILE DEBUG: POST BANNER_IMAGE URI_PATH: " "#{post_banner_image_uri_path}".to_s.yellow.bold
|
||||
|
||||
# get image_file_name
|
||||
post_banner_image_file_name = "#{id["attributes"]["banner_image"]["data"]["attributes"]["hash"]}"
|
||||
Jekyll.logger.debug "POST FILE DEBUG: POST BANNER_IMAGE URI_PATH: " "#{post_banner_image_file_name}".to_s.yellow.bold
|
||||
|
||||
# prepare filename
|
||||
post_banner_image_file_ext = "#{id["attributes"]["banner_image"]["data"]["attributes"]["ext"]}"
|
||||
Jekyll.logger.debug "POST FILE DEBUG: THE FILE EXTENSION NAME: " "#{post_banner_image_file_ext}".to_s.yellow.bold # basic debug test
|
||||
|
||||
# if cached POST post_banner_image_file_name exists, skip; else check modified time.
|
||||
if File.exist?(media_dir + post_banner_image_file_name + post_banner_image_file_ext) === false
|
||||
|
||||
# where the magic happens; we finally download a new image
|
||||
post_banner_download_image = api_builder.get(post_banner_image_uri_path)
|
||||
Jekyll.logger.debug "DOWNLOADING... THE POST BANNER IMAGE URI IS: " "#{post_banner_image_uri_path}".to_s.cyan.bold # basic debug test
|
||||
Jekyll.logger.debug "HTTP DEBUG: A NEW POST BANNER IMAGE HTTP(S) RESPONSE: " "#{post_banner_download_image.status}\n" "#{post_banner_download_image.headers}\n".to_s.yellow # debug http response status
|
||||
|
||||
# only save file if data exists
|
||||
post_banner_file_exist_debug = File.exist?(media_dir + post_banner_image_file_name + post_banner_image_file_ext) # file already exists?
|
||||
Jekyll.logger.debug "FILE DEBUG: DOES POST BANNER IMAGE ALREADY EXIST? " "#{post_banner_file_exist_debug}".to_s.yellow # basic debug test
|
||||
|
||||
# TODO: enable to work with Windows NTFS File Systems
|
||||
#file_ctime = File.ctime(media_dir + file_name + file_ext) # in NTFS (Windows) returns creation time (birthtime)
|
||||
#Jekyll.logger.debug "DEBUG: WHEN WAS FILE LAST MODIFIED? " "#{file_ctime}".to_s.yellow # basic debug test
|
||||
|
||||
c = File.open(post_banner_image_file_name + post_banner_image_file_ext, 'w') # w - Create an empty file for writing.
|
||||
c.write(post_banner_download_image.body) # write the download to local media_dir
|
||||
c.close # close the file
|
||||
FileUtils.mv "#{c.path}", "#{media_dir}" # move the file to custom path
|
||||
Jekyll.logger.debug "FILE DEBUG: THE WHOLE POST BANNER IMAGE FILE NAME " "#{post_banner_image_file_name}" "#{post_banner_image_file_ext}".to_s.yellow.bold # basic debug test
|
||||
else
|
||||
Jekyll.logger.debug "POST BANNER IMAGE ALREADY EXISTS - SKIPPING".to_s.magenta
|
||||
end # end cached if file exists
|
||||
end # post banner data exist?
|
||||
end # post_banner_images.each do
|
||||
|
||||
|
||||
end # ends post collection id exist?
|
||||
puts "" # pretty debug spacing
|
||||
end # end post formatting check
|
||||
|
||||
end # end is cache_images enabled?
|
||||
|
373
_plugins/jekyll-api/lib/d-stripe-create-products.rb
Normal file
@ -0,0 +1,373 @@
|
||||
# This software creates product data from the Stripe API and populates it on Strapi frontend dashboard.
|
||||
# Copyright (C) SharpeTronics, Inc. 2013-2023
|
||||
|
||||
# Author(s): Charles Sharpe(@odinzu_me) aka SharpeTronics, Inc.
|
||||
# License: GPLv3
|
||||
# Version: 1.3
|
||||
|
||||
# This is Free Software released under GPLv3. Any misuse of this software
|
||||
# will be followed up with GPL enforcement via Software Freedom Law Center:
|
||||
# https://www.softwarefreedom.org/
|
||||
|
||||
# If you incorporate or include any code from SharpeTronics, Inc., your
|
||||
# code must be licensed as GPLv3 (not GPLv2 or MIT)
|
||||
|
||||
# The GPLv3 software license applies to the code directly included in this source distribution.
|
||||
# See the LICENSE & COPYING file for full information.
|
||||
|
||||
# Dependencies downloaded as part of the build process may be covered by other open-source licenses.
|
||||
|
||||
# We are open to granting a more permissive (such as MIT or Apache 2.0) license to SharpeTronics, Inc.
|
||||
# software on a *case-by-case* basis, for an agreed upon price. Please email
|
||||
# info@sharpetronics.com.
|
||||
|
||||
# If you would like to contribute to this code, please follow GPLv3 guidelines.
|
||||
# as an example, after making changes to the software (Called a Fork) and credit the original copyright holder as the creator with your credit added to theirs.
|
||||
|
||||
require 'fileutils' # https://ruby-doc.org/stdlib-2.4.1/libdoc/fileutils/rdoc/FileUtils.html
|
||||
require 'yaml' # https://github.com/ruby/yaml
|
||||
require 'faraday' # https://lostisland.github.io/faraday/usage/
|
||||
require 'faraday/multipart' # https://github.com/lostisland/faraday-multipart
|
||||
require 'httpx/adapters/faraday' # https://honeyryderchuck.gitlab.io/httpx/
|
||||
require 'stripe' # https://github.com/stripe/stripe-ruby
|
||||
require 'active_support/core_ext/object/blank' # load only the specific extension for .blank? support; normally used with Rails; see Jekyll gemfile
|
||||
require 'date' # https://github.com/ruby/date
|
||||
require 'json' # https://ruby-doc.org/stdlib-3.0.2/libdoc/json/rdoc/JSON.html
|
||||
|
||||
# read local Jekyll _config.yml data into memory
|
||||
config_yml = "_config.yml"
|
||||
f = YAML.load(File.read(config_yml.to_s)) # r - read file
|
||||
|
||||
# is Stripe turned on in site _config.yml file?
|
||||
stripe_enabled = f['api']['stripe']['enabled']
|
||||
|
||||
# is Stripe turned on in site _config.yml file?
|
||||
site_endpoint = f['api']['endpoint']
|
||||
|
||||
# reset the Stripe products db
|
||||
stripe_db_reset = f['api']['stripe']['reset_stripe_db']
|
||||
Jekyll.logger.debug "ENV DEBUG: Is Stripe enabled? " "#{stripe_enabled}".to_s.yellow.bold
|
||||
|
||||
# if Stripe is enabled in _config.yml, get tokens from local environment for accessing Stripe API [see documentation]
|
||||
if "#{stripe_enabled}" === "true"
|
||||
|
||||
remote_stripe_name = nil # initialize the variable outside the loop
|
||||
local_stripe_name = nil # initialize the variable outside the loop
|
||||
|
||||
# set api key globally with Stripe gem
|
||||
Stripe.api_key = ENV['STRIPE_LIVE_KEY'] # retrieved from docker-compose machine
|
||||
Stripe.max_network_retries = 3
|
||||
Stripe.open_timeout = 30 # in seconds
|
||||
|
||||
# store remote stripe json data from Stripe products
|
||||
remote_stripe_json_products = Stripe::Product.list # user must create product on Stripe (Live Key)
|
||||
|
||||
# retrieve remote Stripe product name if exists
|
||||
# parse through json file
|
||||
remote_parse_products = JSON.parse(remote_stripe_json_products.to_s) # returns a hash
|
||||
Jekyll.logger.debug "STRIPE HTTPS DEBUG: Download all remote products: \n\n" "#{remote_parse_products} \n".to_s.cyan.bold
|
||||
|
||||
# cache, verify and download each product data from product_name
|
||||
remote_stripe_product_data = remote_parse_products["data"].sort_by { |v| -v['id'] } # need ids in ascending order
|
||||
|
||||
# remove all default Stripe data ids that begin with prod_ (ids created with Stripe dashboard))
|
||||
filtered_cached_remote_data = remote_stripe_product_data.delete_if{|v| v['id'] =~ /^prod_/} # deletes id hash if exists
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Filtered Cached Remote Product IDs: \n\n" "#{filtered_cached_remote_data}\n".to_s.yellow.bold
|
||||
|
||||
# retrieve LOCAL Stripe product name
|
||||
# set filepath, load the json, then parse through json file
|
||||
json_product_path = f['api']['collections']['products']['filepath']
|
||||
|
||||
# must read data into memory before parsing file
|
||||
read_products_json = File.read(json_product_path)
|
||||
|
||||
# parse through json files
|
||||
local_parsed_products_file = JSON.parse(read_products_json) # returns a hash
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Developer debug: #{local_parsed_products_file}".to_s.yellow
|
||||
local_product_data = local_parsed_products_file["data"].sort_by { |v| v['id'] } # need ids in ascending order
|
||||
|
||||
# must have an array of ids to match against locally; checking against a remote API locally, rather than pinging another server with duplicate data on each build.
|
||||
cached_local_ids = local_product_data.map { |i| i["id"] }
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Cached Local Product ID: " "#{cached_local_ids}".to_s.yellow.bold
|
||||
|
||||
cached_remote_ids = remote_stripe_product_data.map { |x| x["id"]} # cache all remote Stripe data.
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Cached Remote Product IDs: " "#{cached_remote_ids}".to_s.yellow.bold
|
||||
|
||||
cached_remote_updated_product_time = remote_stripe_product_data.map { |x| x["updated"]}
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Cached Remote Product Modify Times: " "#{cached_remote_updated_product_time}".to_s.yellow.bold
|
||||
|
||||
# begin psueodo code here, b3ep b(oo)p b0p!
|
||||
if filtered_cached_remote_data.present?
|
||||
|
||||
# the following loop only 'counts' each remote product ID from Stripe API
|
||||
filtered_cached_remote_data.each do |update_product|
|
||||
# conv remote Stripe product unix epoch time into proper format before local_product loop
|
||||
remote_conv_modify_time = update_product['metadata'].dig('build_time')
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Remote Product ID: " "#{update_product['id']}" " updated at: " "#{remote_conv_modify_time} \n".to_s.yellow.bold
|
||||
|
||||
# next, we loop through all local product data
|
||||
# Go through each local product , then MEASURE against REMOTE TIME product after converted to same format
|
||||
local_product_data.each do |local_product|
|
||||
|
||||
# store local modify time; all time from Strapi API should be the same
|
||||
# this field is currently able to change in Strapi CMS dashboard
|
||||
local_conv_modify_time = DateTime.strptime(local_product['attributes']['updatedAt'], '%Y-%m-%dT%H:%M:%S')
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Product ID: " "#{local_product['id']}" " updated at: " "#{local_conv_modify_time} \n".to_s.yellow.bold
|
||||
|
||||
# if ids equal, deteremine if modify time is different
|
||||
if local_product['id'].to_s == update_product['id'].to_s # going through all local product data and rejecting all product IDs that are EQUAL to update_product; if no matched ids exist, then this loop ends
|
||||
|
||||
Jekyll.logger.debug "Product ID MATCH FOUND, comparing modify times... \n".to_s.magenta.bold
|
||||
|
||||
# do comparison operation of remote and local modify times.
|
||||
|
||||
if local_conv_modify_time.to_s != remote_conv_modify_time.to_s
|
||||
|
||||
begin
|
||||
puts "After checking if remote json data exists, update the product ".to_s.yellow
|
||||
local_product_name = local_product["attributes"]["heading"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Name: " "#{local_product_name}"
|
||||
local_product_id = local_product["id"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product ID: " "#{local_product_id}"
|
||||
|
||||
# TODO: Quantity needs to be split into a min, max and starting unit amount; also need to custom_unit_amount
|
||||
#local_product_quantity = local_product["attributes"]["quantity"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Quantity: " "#{local_product_quantity}"
|
||||
|
||||
local_product_description = local_product["attributes"]["description"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Description: " "#{local_product_description}"
|
||||
local_product_weight = local_product["attributes"]["weight"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Weight: " "#{local_product_weight}"
|
||||
local_product_webpage_url = local_product["attributes"]["webpage_url"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product WebPage: " "#{local_product_webpage_url}"
|
||||
local_product_tax_code = local_product["attributes"]["tax_code"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Tax Code: " "#{local_product_tax_code}"
|
||||
local_product_is_shippable = local_product["attributes"]["is_shippable"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Is Shippable?: " "#{local_product_is_shippable}"
|
||||
local_product_shipping_rates = local_product["attributes"]["shipping_rates"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Shipping Rates: " "#{local_product_shipping_rates}"
|
||||
|
||||
# TODO: On CMS API, we need to split into 4 seperate values; height, length, weight, width with 2 decimal places
|
||||
#local_product_package_dimensions = local_product["attributes"]["package_dimensions"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Pk Dimensions: " "#{local_product_package_dimensions}"
|
||||
|
||||
local_product_shipping_companies = local_product["attributes"]["shipping_companies"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Shipping Company: " "#{local_product_shipping_companies}"
|
||||
# Prices defined in each available currency option. Each key must be a three-letter ISO currency code and a supported currency. For example, to define your price in eur, pass the fields below in the eur key of currency_options.
|
||||
local_product_currency_type = local_product["attributes"]["currency_type"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Currency Type: " "#{local_product_currency_type}"
|
||||
local_product_shipping_price = local_product["attributes"]["shipping_price"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Shipping Price: " "#{local_product_shipping_price}"
|
||||
# Same as unit_amount, but accepts a decimal value in cents with at most 12 decimal places. Only one of unit_amount and unit_amount_decimal can be set.
|
||||
local_product_unit_price = local_product["attributes"]["unit_price"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Unit Price: " "#{local_product_unit_price}"
|
||||
|
||||
# TODO
|
||||
# A label that represents units of this product in Stripe and on customers’ receipts and invoices. When set, this will be included in associated invoice line item descriptions.
|
||||
#local_product_unit_label = local_product["attributes"]["unit_label"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Currency Type: " "#{local_product_unit_label}"
|
||||
|
||||
# TODO
|
||||
# An arbitrary string to be displayed on your customer’s credit card or bank statement. While most banks display this information consistently, some may display it incorrectly or not at all.
|
||||
# This may be up to 22 characters. The statement description may not include <, >, \, ", ’ characters, and will appear on your customer’s statement in capital letters. Non-ASCII characters are automatically stripped. It must contain at least one letter.
|
||||
#local_product_statement_descriptor = local_product["attributes"]["statement_descriptor"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Statement Descriptor: " "#{local_product_statement_descriptor}"
|
||||
|
||||
# TODO
|
||||
# Only 8 image URLs per product; loop through each image to get the url
|
||||
#local_product_images = local_product["attributes"]["gallery"]["data"]["attributes"]["url"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Gallery Images: " "#{local_product_images}"
|
||||
|
||||
local_product_banner_image = local_product["attributes"]["banner_image"]["data"]["attributes"]["url"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Image: " "#{site_endpoint}#{local_product_banner_image}"
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Product Beginning Update " "#{local_product_name}".to_s.yellow.bold
|
||||
# updates the specific product by setting the values of the parameters passed. Any parameters not provided will be left unchanged.
|
||||
Stripe::Product.update(
|
||||
"#{local_product_id}", # prod_id that is being updated
|
||||
|
||||
name: "#{local_product_name}",
|
||||
description: "#{local_product_description}",
|
||||
metadata: {build_time: "#{local_conv_modify_time}"},
|
||||
|
||||
#unit_amount_decimal: "#{local_product_unit_price * 100 }", # format must be in cents e.g. 2000 cents = $20
|
||||
|
||||
url: "#{site_endpoint + local_product_webpage_url}",
|
||||
tax_code: "#{local_product_tax_code}", # must match these codes https://stripe.com/docs/tax/tax-categories
|
||||
shippable: "#{local_product_is_shippable}",
|
||||
images: ["#{site_endpoint + local_product_banner_image}"],
|
||||
|
||||
# package_dimensions {
|
||||
# weight: "#{local_product_weight}",
|
||||
# height: "#{local_product_height}",
|
||||
# length: "#{local_product_length}",
|
||||
# width: "#{local_product_width}",
|
||||
# }
|
||||
|
||||
#name: "#{local_product_shipping_rates}",
|
||||
#name: "#{local_product_shipping_companies}",
|
||||
#name: "#{local_product_shipping_price}"},
|
||||
#unit_amount_decimal: "#{local_product_unit_price}",
|
||||
)
|
||||
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Product UPDATED! " "#{local_product_name} \n".to_s.cyan.bold
|
||||
# check relative stripe product id from each new local_product if error arises
|
||||
Stripe::Product.retrieve(local_product_id.to_s)
|
||||
rescue Stripe::InvalidRequestError => e
|
||||
# Invalid parameters were supplied to Stripe's API
|
||||
Jekyll.logger.debug "Stripe Error: Invalid API Request - SKIPPING PRODUCT: " "#{local_product_name}".to_s.red
|
||||
end # begin
|
||||
|
||||
else
|
||||
|
||||
# Skip
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: MODIFY TIMES MATCH, SKIPPING: ".to_s.magenta.bold
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
# Skip
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: IDS DON'T MATCH, SKIPPING: ".to_s.magenta.bold
|
||||
end # remote_product['id'] conditional
|
||||
end # local product data loop
|
||||
|
||||
end # filtered_cached_remote_data
|
||||
|
||||
else
|
||||
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Remote Stripe Data is EMPTY, SKIPPING PRODUCT UPDATES! ".to_s.red.bold
|
||||
end # filtered_cached_remote_data.present?
|
||||
|
||||
if local_product_data.present?
|
||||
|
||||
# the following loop only 'counts' each remote product ID from Stripe API
|
||||
filtered_cached_remote_data.each do |update_product|
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Remote Product ID: " "#{update_product['id']}".to_s.yellow.bold
|
||||
|
||||
if filtered_cached_remote_data.present?
|
||||
|
||||
local_product_data.each do |local_product|
|
||||
|
||||
# if ids are on stripe remote, SKIP
|
||||
if local_product_data.reject { |i| i["id"] == update_product['id'] } # going through all local product data and rejecting all product IDs that are NOT EQUAL to update_product; if no matched ids exist, then this loop ends
|
||||
Jekyll.logger.debug "Product ID MATCH FOUND!, SKIPPING \n".to_s.magenta.bold
|
||||
|
||||
else
|
||||
# only execute this after all data is sorted through and compared
|
||||
# get all product data from each id
|
||||
begin
|
||||
puts "Creating products after checking if remote json data exists".to_s.yellow
|
||||
local_product_name = local_product["attributes"]["heading"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Name: " "#{local_product_name}"
|
||||
local_product_id = local_product["id"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product ID: " "#{local_product_id}"
|
||||
|
||||
# TODO: Quantity needs to be split into a min, max and starting unit amount; also need to custom_unit_amount
|
||||
#local_product_quantity = local_product["attributes"]["quantity"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Quantity: " "#{local_product_quantity}"
|
||||
|
||||
# store local modify time; all time from Strapi API should be the same
|
||||
# this field is currently able to change in Strapi CMS dashboard
|
||||
local_conv_modify_time = DateTime.strptime(local_product['attributes']['updatedAt'], '%Y-%m-%dT%H:%M:%S')
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Product ID: " "#{local_product['id']}" " updated at: " "#{local_conv_modify_time} \n".to_s.yellow.bold
|
||||
|
||||
local_product_description = local_product["attributes"]["description"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Description: " "#{local_product_description}"
|
||||
local_product_weight = local_product["attributes"]["weight"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Weight: " "#{local_product_weight}"
|
||||
local_product_webpage_url = local_product["attributes"]["webpage_url"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product WebPage: " "#{local_product_webpage_url}"
|
||||
local_product_tax_code = local_product["attributes"]["tax_code"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Tax Code: " "#{local_product_tax_code}"
|
||||
local_product_is_shippable = local_product["attributes"]["is_shippable"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Is Shippable?: " "#{local_product_is_shippable}"
|
||||
local_product_shipping_rates = local_product["attributes"]["shipping_rates"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Shipping Rates: " "#{local_product_shipping_rates}"
|
||||
|
||||
# TODO: On CMS API, we need to split into 4 seperate values; height, length, weight, width with 2 decimal places
|
||||
#local_product_package_dimensions = local_product["attributes"]["package_dimensions"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Pk Dimensions: " "#{local_product_package_dimensions}"
|
||||
|
||||
local_product_shipping_companies = local_product["attributes"]["shipping_companies"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Shipping Company: " "#{local_product_shipping_companies}"
|
||||
# Prices defined in each available currency option. Each key must be a three-letter ISO currency code and a supported currency. For example, to define your price in eur, pass the fields below in the eur key of currency_options.
|
||||
local_product_currency_type = local_product["attributes"]["currency_type"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Currency Type: " "#{local_product_currency_type}"
|
||||
local_product_shipping_price = local_product["attributes"]["shipping_price"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Shipping Price: " "#{local_product_shipping_price}"
|
||||
# Same as unit_amount, but accepts a decimal value in cents with at most 12 decimal places. Only one of unit_amount and unit_amount_decimal can be set.
|
||||
local_product_unit_price = local_product["attributes"]["unit_price"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Unit Price: " "#{local_product_unit_price}"
|
||||
|
||||
# TODO
|
||||
# A label that represents units of this product in Stripe and on customers’ receipts and invoices. When set, this will be included in associated invoice line item descriptions.
|
||||
#local_product_unit_label = local_product["attributes"]["unit_label"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Currency Type: " "#{local_product_unit_label}"
|
||||
|
||||
# TODO
|
||||
# An arbitrary string to be displayed on your customer’s credit card or bank statement. While most banks display this information consistently, some may display it incorrectly or not at all.
|
||||
# This may be up to 22 characters. The statement description may not include <, >, \, ", ’ characters, and will appear on your customer’s statement in capital letters. Non-ASCII characters are automatically stripped. It must contain at least one letter.
|
||||
#local_product_statement_descriptor = local_product["attributes"]["statement_descriptor"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Statement Descriptor: " "#{local_product_statement_descriptor}"
|
||||
|
||||
# TODO
|
||||
# Only 8 image URLs per product; loop through each image to get the url
|
||||
#local_product_images = local_product["attributes"]["gallery"]["data"]["attributes"]["url"]
|
||||
#Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Gallery Images: " "#{local_product_images}"
|
||||
|
||||
local_product_banner_image = local_product["attributes"]["banner_image"]["data"]["attributes"]["url"]
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Product Image: " "#{local_product_banner_image}"
|
||||
|
||||
# create data on Stripe API
|
||||
Stripe::Product.create({
|
||||
name: "#{local_product_name}",
|
||||
id: "#{local_product_id}",
|
||||
description: "#{local_product_description}",
|
||||
|
||||
default_price_data: {
|
||||
currency: "#{local_product_currency_type}",
|
||||
unit_amount_decimal: "#{local_product_unit_price * 100 }", # format must be in cents e.g. 2000 cents = $20
|
||||
},
|
||||
|
||||
metadata: {build_time: "#{local_conv_modify_time}"},
|
||||
url: "#{site_endpoint + local_product_webpage_url}",
|
||||
tax_code: "#{local_product_tax_code}", # must match these codes https://stripe.com/docs/tax/tax-categories
|
||||
shippable: "#{local_product_is_shippable}",
|
||||
images: ["#{site_endpoint + local_product_banner_image}"],
|
||||
|
||||
# package_dimensions {
|
||||
# weight: "#{local_product_weight}",
|
||||
# height: "#{local_product_height}",
|
||||
# length: "#{local_product_length}",
|
||||
# width: "#{local_product_width}",
|
||||
# }
|
||||
|
||||
#name: "#{local_product_shipping_rates}",
|
||||
#name: "#{local_product_shipping_companies}",
|
||||
#name: "#{local_product_shipping_price}"},
|
||||
#unit_amount_decimal: "#{local_product_unit_price}",
|
||||
|
||||
})
|
||||
Jekyll.logger.debug "PRODUCT CREATED & POSTED! " "#{local_product_name} \n".to_s.cyan.bold
|
||||
# check relative stripe product id from each new local_product if error arises
|
||||
Stripe::Product.retrieve(local_product_id.to_s)
|
||||
rescue Stripe::InvalidRequestError => e
|
||||
# Invalid parameters were supplied to Stripe's API
|
||||
Jekyll.logger.debug "Stripe Error: Invalid API Request - SKIPPING PRODUCT: " "#{local_product_name}".to_s.red
|
||||
end # begin loop
|
||||
end # local_product_data
|
||||
end # if local_product_data.reject...
|
||||
|
||||
else
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Remote Product Data is MISSING: ".to_s.yellow.bold
|
||||
end # filtered_cached_remote_data.present?
|
||||
end # filter_remote_product_data
|
||||
|
||||
else
|
||||
|
||||
Jekyll.logger.debug "::DOCUMENT PRODUCT DEBUG:: Local Stripe Data is EMPTY, SKIPPING PRODUCT CREATION! ".to_s.red.bold
|
||||
end # local_product_data.present?
|
||||
|
||||
else
|
||||
|
||||
Jekyll.logger.debug "ENV STRIPE DEBUG: Stripe is disabled, enable it in the _config.yml; see docs for more details. " "#{stripe_enabled}".to_s.red.bold
|
||||
end
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
layout: journal_single
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: Welcome Home You
|
||||
sub_heading: Maecenas faucibus mollis interdum. Vivamus sagittis lacus
|
||||
|
||||
banner_image: "/assets/images/pic01.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Partnerships
|
||||
tag: Partnerships
|
||||
|
||||
---
|
||||
Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
layout: journal_single
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: Welcome Home YOU
|
||||
sub_heading: A sub_heading for your viewing pleasure
|
||||
|
||||
banner_image: "/assets/images/pic02.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Partnerships
|
||||
tag: Partnerships
|
||||
|
||||
---
|
||||
Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
layout: journal_single
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: Modern Engineering 2nd Edition
|
||||
sub_heading: Nullam quis risus eget urna mollis ornare vel eu leo.
|
||||
|
||||
banner_image: "/assets/images/pic01.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Engineering
|
||||
tag: Engineering
|
||||
|
||||
---
|
||||
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
layout: journal_single
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: New Industry Partner
|
||||
sub_heading: Maecenas faucibus mollis interdum. Vivamus sagittis lacus
|
||||
|
||||
banner_image: "/assets/images/pic01.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Engineering
|
||||
tag: Partnerships
|
||||
|
||||
---
|
||||
Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
layout: journal_single
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: New Research Center
|
||||
sub_heading: Integer posuere urna mollis ornare vel eu leo.
|
||||
|
||||
banner_image: "/assets/images/pic02.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Engineering
|
||||
tag: Research
|
||||
|
||||
|
||||
---
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
layout: journal_single
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: New Research Center
|
||||
sub_heading: Integer posuere urna mollis ornare vel eu leo.
|
||||
|
||||
banner_image: "/assets/images/pic01.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Engineering
|
||||
tag: Research
|
||||
|
||||
|
||||
---
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
title: Welcome to the SharpeTronics Demo Site!s
|
||||
date: 2017-09-25T09:09:13.000+00:00
|
||||
related_posts:
|
||||
- _posts/2017-02-12-modern.md
|
||||
- _posts/2017-08-01-welcome.md
|
||||
sub_heading: An introduction to SharpeTronics
|
||||
tags:
|
||||
- Demo
|
||||
- Forestry
|
||||
layout: journal_single
|
||||
banner_image: ''
|
||||
|
||||
---
|
||||
Welcome to the Belkirk College of Engineering Demo Site!
|
||||
|
||||
This site allows you to explore SharpeTronics's features and functionality, and is **not** meant to be used as a production website. To get started building your own site, please see our [documentation](https://sharpetronics.com/help).
|
||||
|
||||
Thank you for choosing to demo SharpeTronics!
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
layout: journal_single
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: Geometry in Fundamental Singularities
|
||||
sub_heading: Nullam quis risus eget urna mollis ornare vel eu leo.
|
||||
|
||||
banner_image: "/assets/images/pic03.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Engineering
|
||||
tag: Engineering
|
||||
|
||||
---
|
||||
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
@ -1,18 +0,0 @@
|
||||
---
|
||||
layout: journal_single
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: Meditation in the Modern Age
|
||||
sub_heading: A post sub_heading for viewing pleasure
|
||||
|
||||
banner_image: "/assets/images/pic02.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Research
|
||||
tag: Demo
|
||||
|
||||
---
|
||||
Mauris neque quam, fermentum ut nisl vitae, convallis maximus nisl. Sed mattis nunc id lorem euismod placerat. Vivamus porttitor magna enim, ac accumsan tortor cursus at. Phasellus sed ultricies mi non congue ullam corper. Praesent tincidunt sed tellus ut rutrum. Sed vitae justo condimentum, porta lectus vitae, ultricies congue gravida diam non fringilla.
|
||||
|
||||
Nunc quis dui scelerisque, scelerisque urna ut, dapibus orci. Sed vitae condimentum lectus, ut imperdiet quam. Maecenas in justo ut nulla aliquam sodales vel at ligula. Sed blandit diam odio, sed fringilla lectus molestie sit amet. Praesent eu tortor viverra lorem mattis pulvinar feugiat in turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce ullamcorper tellus sit amet mattis dignissim. Phasellus ut metus ligula. Curabitur nec leo
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:20:40.674Z
|
||||
layout: post
|
||||
title: Our Privacy Policy
|
||||
subheading: Your data is always yours.
|
||||
slug: our-privacy-policy
|
||||
date: 2020-02-03
|
||||
author: Charles
|
||||
banner_image: /uploads/terms_48bec2a697.webp
|
||||
banner_image_alt: An image of a gradient of colours.
|
||||
title: Our Privacy Policy
|
||||
sub_heading: Your data is always yours.
|
||||
tags: Celebration, Privacy, Terms & Conditions,
|
||||
banner_image_description: an image gradient of blue and white.
|
||||
category: Legal
|
||||
tags: Privacy,
|
||||
---
|
||||
<h2>Privacy Policy for SharpeTronics.com, Inc.</h2>
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:20:58.472Z
|
||||
layout: post
|
||||
title: Our Terms & Conditions
|
||||
subheading: Our rules and regulations.
|
||||
slug: our-terms-and-conditions
|
||||
date: 2020-02-03
|
||||
author: Charles
|
||||
banner_image: /uploads/terms_48bec2a697.webp
|
||||
banner_image_alt: An image with a gradient of colours.
|
||||
title: Our Terms & Conditions
|
||||
sub_heading: Our rules and regulations.
|
||||
tags: Celebration, Privacy, Terms & Conditions,
|
||||
banner_image_description: an image gradient of blue and white.
|
||||
category: Legal
|
||||
tags: Terms & Conditions,
|
||||
---
|
||||
<h2><strong>Terms and Conditions</strong></h2>
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:16:18.403Z
|
||||
layout: post
|
||||
title: Welcome To An Appalachian Technology Company
|
||||
subheading: Where light travels at high altitudes.
|
||||
slug: welcome-to-an-appalachian-technology-company
|
||||
date: 2021-01-03
|
||||
author: Charles
|
||||
banner_image: /uploads/wv_seneca_rocks_sky_0d5928baa9.webp
|
||||
banner_image_alt: WV Sky Seneca Rocks
|
||||
title: Welcome To An Appalachian Technology Company
|
||||
sub_heading: Where light travels at high altitudes.
|
||||
tags: Celebration,
|
||||
banner_image_description: An image of the night sky in West Virginia.
|
||||
category: Company
|
||||
tags: Celebration, Linux, Open Source, Technology,
|
||||
---
|
||||
Welcome to SharpeTronics, where light travels at high altitudes. We are a mountain made company in the Appalachians of West Virginia that strives with software and hardware technologies. We are statewide leaders in our area of expertise and invite you to support local business.
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:27:25.997Z
|
||||
layout: post
|
||||
title: Sharpetronics Inc. Becomes Official
|
||||
subheading: Winding Roads
|
||||
slug: sharpetronics-inc-becomes-official
|
||||
date: 2021-03-17
|
||||
author: Charles
|
||||
banner_image: /uploads/pillars_face_art_973bf824dd.webp
|
||||
banner_image_alt: An image of a pillar holding up a building.
|
||||
title: SharpeTronics Inc. Becomes Official
|
||||
sub_heading: Winding Roads
|
||||
tags: Celebration,
|
||||
banner_image_description: A pillar with a head holding up the ceiling.
|
||||
category: Company
|
||||
tags: Contribute, Technology,
|
||||
---
|
||||
We as in SharpeTronics Inc. are proud to announce our business is official with the mountain state of West Virginia on March 17, 2021.
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:12:00.118Z
|
||||
layout: post
|
||||
title: Big Startups Without Big Tech
|
||||
subheading: Liquid Democracy Empowering Network Users
|
||||
slug: big-startups-without-big-tech
|
||||
date: 2021-06-29
|
||||
author: Charles
|
||||
banner_image: /uploads/decentralized_385bd5a376.webp
|
||||
banner_image_alt: An image of interconnecting objects
|
||||
title: Big Startups Without Big Tech
|
||||
sub_heading: Liquid Democracy Empowering Network Users
|
||||
tags: Blockchain, Linux,
|
||||
banner_image_description: Transparent cubes and a high tech lighting backdrop
|
||||
category: How-to
|
||||
tags: Blockchain,
|
||||
---
|
||||
Welcome to the Blockchain Internet called DFINITY. In my spare time, I have been tinkering and learning **Motoko**. It is a language built for the Internet Computer (IC) that can be used to interface applications, websites and other various software.
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:10:34.668Z
|
||||
layout: post
|
||||
title: Linux VPS Hardening
|
||||
subheading: Initializing a secure environment
|
||||
slug: linux-vps-hardening
|
||||
date: 2021-07-26
|
||||
author: Charles
|
||||
banner_image: /uploads/linux_admin_0def8999f2.webp
|
||||
banner_image_alt: an image of a hooded individual typing on a keyboard
|
||||
title: Linux VPS Hardening
|
||||
sub_heading: Initializing a secure environment
|
||||
tags: Linux, Privacy, Security,
|
||||
category: How-to
|
||||
banner_image_description: The back of a black hoodie hacking at software
|
||||
category: Devops
|
||||
tags: Linux, VPS, SSL, Security,
|
||||
---
|
||||
### Planting Seeds
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:35:18.838Z
|
||||
layout: post
|
||||
title: Configure a Static Qt5 from Source on Ubuntu 18.04 with X11 Support
|
||||
subheading: Compiling & Configuring Qt from Source
|
||||
slug: configure-a-static-qt5-from-source-on-ubuntu-18-04-with-x11-support
|
||||
date: 2021-11-11
|
||||
author: Charles
|
||||
banner_image: /uploads/quantum_qt5_95dcd080f1.webp
|
||||
banner_image_alt: An image of a gold computer circuit.
|
||||
title: Configure a Static Qt5 from Source on Ubuntu 18.04 with X11 Support
|
||||
sub_heading: Compiling & Configuring Qt from Source
|
||||
tags: Linux, VPS, ARM64, AArch64, X11,
|
||||
category: How-to
|
||||
banner_image: /uploads/quantum_qt5_41fa19c935.webp
|
||||
banner_image_description: A golden circuit board.
|
||||
category: Devops
|
||||
tags: Linux, Qt5, ARM64, Raspberry Pi 400, X11,
|
||||
---
|
||||
### Configure, Build, Install & Setup Qt 5.15.2 Source on Ubuntu 18.04 with X11 Support
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:07:37.794Z
|
||||
layout: post
|
||||
title: Setup a Secure NGINX HTTPS Web Server with Let's Encrypt + Strapi 4.0 Headless CMS
|
||||
subheading: Static Websites with CMS
|
||||
slug: setup-a-secure-nginx-https-web-server-with-let-s-encrypt-strapi-4-0-headless-cms
|
||||
date: 2021-12-27
|
||||
author: Charles
|
||||
banner_image: /uploads/santa_rudolph_unsplash_0ae8e3d5a7.webp
|
||||
banner_image_alt: An image of two pair of holiday cheer feet.
|
||||
title: Setup a Secure NGINX HTTPS Web Server with Let's Encrypt + Strapi 4.0 Headless CMS
|
||||
sub_heading: Static Websites with CMS
|
||||
tags: Nginx, Strapi, Headless CMS, JAMstack,
|
||||
banner_image_description: Two feet wearing socks beside each other with faces of Santa Clause and another of Rudolph
|
||||
category: How-to
|
||||
tags: Nginx, Strapi, SSL, Headless CMS, JAMstack,
|
||||
---
|
||||
## General
|
||||
For this tutorial, we will launch a secure SSL NGINX web server for your website domain example.org and enable an API to be consumed from the subdomain i.e. api.example.org with Strapi 4.0.
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:35:01.620Z
|
||||
layout: post
|
||||
title: Compiling Fresh XMPP Ejabberd Server Binaries 22.05 on Ubuntu 20.04 with Erlang OTP 24
|
||||
subheading: Creating and host your own end-to-end encryption Instant Messenger app
|
||||
slug: compiling-fresh-xmpp-ejabberd-server-binaries-22-05-on-ubuntu-20-04-with-erlang-otp-24
|
||||
date: 2022-06-21
|
||||
author: Charles
|
||||
banner_image: /uploads/ejabberd_in_the_jungle_8a9f00e089.webp
|
||||
banner_image_alt: Compiling Fresh XMPP Ejabberd Server Binaries 22.05 on Ubuntu 20.04 with Erlang OTP 24
|
||||
title: Compiling Fresh XMPP Ejabberd Server Binaries 22.05 on Ubuntu 20.04 with Erlang OTP 24
|
||||
sub_heading: Creating and host your own end-to-end encryption Instant Messenger app
|
||||
tags: Linux, XMPP, Ejabberd,
|
||||
banner_image_description: A human male swinging above the trees in a jungle.
|
||||
category: Devops
|
||||
tags: Privacy, XMPP, Ejabberd,
|
||||
---
|
||||
# Compiling ejabberd v22.05
|
||||
### A XMPP server based on Erlang/OTP 24
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-11T22:04:01.861Z
|
||||
layout: post
|
||||
title: How to Setup a Docker Drone CI with HTTPS
|
||||
subheading: Obiwon Can Oh Be! A digital C3-PO working beside you!
|
||||
slug: how-to-setup-a-docker-drone-ci-with-https
|
||||
date: 2022-06-23
|
||||
author: Charles
|
||||
banner_image: /uploads/r2d2_skywalker_c84e2364fe.webp
|
||||
banner_image_alt: Skywalker with R2D2
|
||||
title: How to Setup a Docker Drone CI with HTTPS
|
||||
sub_heading: Obiwon Can Oh Be! A digital C3-PO working beside you!
|
||||
tags: Nginx, Linux, VPS, Drone CI, Docker,
|
||||
banner_image_description: r2d2 and Luke lego people standing on a laptop
|
||||
category: How-to
|
||||
tags: VPS, SSL, Drone CI, Docker,
|
||||
---
|
||||
> R2D2, you know better than to trust a strange computer! [beeps]
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-15T21:46:42.406Z
|
||||
layout: post
|
||||
title: How to Setup a Secure Docker Drone Runne with Drone CI
|
||||
subheading: BeeYoop BeeDeepBoom Weeop DEEpaEEya
|
||||
slug: how-to-setup-a-secure-docker-drone-runne-with-drone-ci
|
||||
date: 2022-06-23
|
||||
author: Charles
|
||||
banner_image: /uploads/c3po_a_friend_in_need_74a237a413.webp
|
||||
banner_image_alt: Black and white still image of C3PO
|
||||
title: How to Setup a Secure Docker Drone Runner with Drone CI
|
||||
sub_heading: BeeYoop BeeDeepBoom Weeop DEEpaEEya
|
||||
tags: Linux, Drone CI, Docker,
|
||||
banner_image_description: a picture of c3po from Star Wars
|
||||
category: How-to
|
||||
tags: Linux, Drone CI, Docker,
|
||||
---
|
||||
> BeeYoop BeeDeepBoom Weeop DEEpaEEya
|
||||
|
@ -1,13 +1,15 @@
|
||||
---
|
||||
updatedAt: 2022-10-15T18:40:33.689Z
|
||||
layout: post
|
||||
title: Update your Strapi CMS with your own Favicon
|
||||
subheading: How-to replace the favicon
|
||||
slug: update-your-strapi-cms-with-your-own-favicon
|
||||
date: 2022-07-12
|
||||
author: Charles
|
||||
banner_image: /uploads/code_eff0ff4f77.webp
|
||||
banner_image_alt: Macguyvering Strapi
|
||||
title: Update your Strapi CMS with your own Favicon
|
||||
sub_heading: How-to replace the favicon
|
||||
tags: Strapi, Configure, Contribute,
|
||||
banner_image: /uploads/code_2b5ed5fa9c.webp
|
||||
banner_image_description: computer code matrix
|
||||
category: How-to
|
||||
tags: Jekyll, Strapi, Headless CMS,
|
||||
---
|
||||
In this article, we will be replacing the Strapi favicon with your own favicon. This same process is similar to how we replace the login logo `AuthLogo` and menu logo with `MenuLogo`. For more details, please visit Strapi documentations example configuration. [Strapi Documents]
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
updatedAt: 2022-10-12T23:07:49.156Z
|
||||
updatedAt: 2022-10-15T21:18:32.132Z
|
||||
layout: post
|
||||
title: Upgrade your Crosshair VI Hero Motherboard Firmware with System76's PopOS!
|
||||
subheading: I was doing a bit of yak shaving this morning, and it looks like it might have paid off.
|
||||
|
@ -1,22 +0,0 @@
|
||||
---
|
||||
layout: shop_single
|
||||
|
||||
featured: 0 #starred, featured or simple for product pages display sections.
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: Our Most Recent Rest Product Title
|
||||
sub_heading: Maecenas faucibus mollis interdum. Vivamus sagittis lacus
|
||||
|
||||
banner_image: "/assets/images/pic02.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Product
|
||||
tag: Electronics
|
||||
|
||||
---
|
||||
Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
@ -1,23 +0,0 @@
|
||||
---
|
||||
layout: shop_single
|
||||
|
||||
featured: true #starred, featured or simple for product pages display sections.
|
||||
record: product-one
|
||||
|
||||
author: Charles #case sensitive, please use capitalization for names.
|
||||
|
||||
title: Our Most Recent Rest Product Title
|
||||
sub_heading: Maecenas faucibus mollis interdum. Vivamus sagittis lacus
|
||||
|
||||
banner_image: "/assets/images/pic01.jpg" #Size of banner_image 840x341
|
||||
banner_image_alt: "image alt"
|
||||
|
||||
category: Product
|
||||
tag: Electronics
|
||||
|
||||
---
|
||||
Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
||||
|
||||
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Maecenas faucibus mollis interdum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
|
36
collections/_products/2022-09-01-chicken-platter.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
stripe_id: 8
|
||||
metadata: 2022-10-05T23:44:48+00:00
|
||||
layout: product
|
||||
heading: chicken platter
|
||||
subheading: sadfasdf
|
||||
slug: chicken-platter
|
||||
date: 2022-09-01
|
||||
author: Charles
|
||||
banner_image: /uploads/terms_48bec2a697.webp
|
||||
banner_image_description: a short desc. about the banner image
|
||||
category: How-to
|
||||
gallery:
|
||||
- image_path: /uploads/code_2b5ed5fa9c.webp
|
||||
title: code_2b5ed5fa9c
|
||||
- image_path: /uploads/r2d2_skywalker_c84e2364fe.webp
|
||||
title: r2d2_skywalker_c84e2364fe
|
||||
|
||||
tags: Jekyll,
|
||||
webpage_url: https://www.sharpetronics.com/products/2017-02-03-drrragon/
|
||||
is_featured: false
|
||||
is_software: true
|
||||
is_shippable: false
|
||||
currency_type: USD
|
||||
country_origin: USA
|
||||
unit_price: 2
|
||||
quantity: 2
|
||||
package_dimensions: 1x1x1mm
|
||||
material_type: e.g. gold and silver
|
||||
weight: 1oz
|
||||
tax_code: txcd_00000000
|
||||
shipping_price: 2
|
||||
shipping_rates: Standard
|
||||
shipping_company: UPS
|
||||
---
|
||||
A place to describe the product to your readers. af asd
|
36
collections/_products/2022-09-13-new-product-nameeee.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
stripe_id: 2
|
||||
metadata: 2022-10-10T23:34:32+00:00
|
||||
layout: product
|
||||
heading: new_product_nameeee
|
||||
subheading: test again yupy an update
|
||||
slug: new-product-nameeee
|
||||
date: 2022-09-13
|
||||
author: Charles
|
||||
banner_image: /uploads/optimus_primed_886bcb1942.jpeg
|
||||
banner_image_description: this is a description
|
||||
category: Legal
|
||||
gallery:
|
||||
- image_path: /uploads/c3po_a_friend_in_need_74a237a413.webp
|
||||
title: c3po_a_friend_in_need_74a237a413
|
||||
- image_path: /uploads/r2d2_skywalker_c84e2364fe.webp
|
||||
title: r2d2_skywalker_c84e2364fe
|
||||
|
||||
tags: Strapi, Celebration,
|
||||
webpage_url: https://www.sharpetronics.com/products/example
|
||||
is_featured: true
|
||||
is_software: true
|
||||
is_shippable: false
|
||||
currency_type: USD
|
||||
country_origin: USA
|
||||
unit_price: 2.5
|
||||
quantity: 1
|
||||
package_dimensions: N/a
|
||||
material_type: e.g. gold and silver
|
||||
weight: 1.0lb
|
||||
tax_code: txcd_20030000
|
||||
shipping_price: 5
|
||||
shipping_rates: Standard
|
||||
shipping_company: UPS
|
||||
---
|
||||
A place to describe the product to your readers. yay changing the data. changing the data yay more data that isn't saving
|
34
collections/_products/2022-10-04-i-am-a-bananna-product.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
stripe_id: 7
|
||||
metadata: 2022-10-02T20:36:28+00:00
|
||||
layout: product
|
||||
heading: I am a bananna product
|
||||
subheading: my sppooon is too beiigg
|
||||
slug: i-am-a-bananna-product
|
||||
date: 2022-10-04
|
||||
author: Charles
|
||||
banner_image: /uploads/santa_rudolph_unsplash_0ae8e3d5a7.webp
|
||||
banner_image_description: a short desc. about the banner image
|
||||
category: Company
|
||||
gallery:
|
||||
- image_path: /uploads/c3po_a_friend_in_need_74a237a413.webp
|
||||
title: c3po_a_friend_in_need_74a237a413
|
||||
|
||||
tags: Nginx,
|
||||
webpage_url: www.dash.sharpetronics.com
|
||||
is_featured: true
|
||||
is_software: false
|
||||
is_shippable: true
|
||||
currency_type: USD
|
||||
country_origin: USA
|
||||
unit_price: 1
|
||||
quantity: 1
|
||||
package_dimensions: 1x1x1mm
|
||||
material_type: gold
|
||||
weight: 1lb
|
||||
tax_code: txcd_00000000
|
||||
shipping_price: 1
|
||||
shipping_rates: Standard
|
||||
shipping_company: UPS
|
||||
---
|
||||
A place to describe the product to your readers.
|
36
collections/_products/2022-10-21-another-productt.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
stripe_id: 5
|
||||
metadata: 2022-10-11T22:37:24+00:00
|
||||
layout: product
|
||||
heading: another productt
|
||||
subheading: another producttatastasatdfg s
|
||||
slug: another-productt
|
||||
date: 2022-10-21
|
||||
author: Charles
|
||||
banner_image: /uploads/code_2b5ed5fa9c.webp
|
||||
banner_image_description: a short desc. about the banner image
|
||||
category: Legal
|
||||
gallery:
|
||||
- image_path: /uploads/code_2b5ed5fa9c.webp
|
||||
title: code_2b5ed5fa9c
|
||||
- image_path: /uploads/r2d2_skywalker_c84e2364fe.webp
|
||||
title: r2d2_skywalker_c84e2364fe
|
||||
|
||||
tags:
|
||||
webpage_url: https://www.sharpetronics.com/products/2017-02-03-dragon
|
||||
is_featured: true
|
||||
is_software: true
|
||||
is_shippable: false
|
||||
currency_type: USD
|
||||
country_origin: USA
|
||||
unit_price: 4
|
||||
quantity: 3
|
||||
package_dimensions: 1x1x1mm
|
||||
material_type: e.g. gold and silver
|
||||
weight: 3
|
||||
tax_code: txcd_20030000
|
||||
shipping_price: 4
|
||||
shipping_rates: Standard
|
||||
shipping_company: UPS
|
||||
---
|
||||
A place to describe the product to your readers.
|
@ -73,5 +73,6 @@ services:
|
||||
ports:
|
||||
- 4000:4000
|
||||
environment:
|
||||
- API_TOKEN=$API_TOKEN
|
||||
- API_TOKEN=$API_TOKEN,
|
||||
- STRIPE_LIVE_KEY=$STRIPE_LIVE_KEY
|
||||
command: jekyll serve --lsi --watch --verbose --trace
|
||||
|
@ -30,7 +30,7 @@ SPECIAL THANKS
|
||||
@YOU
|
||||
|
||||
@ajlkn
|
||||
aj.lkn.io
|
||||
aj.lkn.io/
|
||||
|
||||
@strapijs
|
||||
strapi.io/
|
||||
@ -120,9 +120,6 @@ gpl-3.0.en.html
|
||||
Web Browser Debugging - Testing UI/UX of the website
|
||||
google.com/chrome/, mozilla.org/en-US/firefox
|
||||
|
||||
Stack overflow - Best answers
|
||||
stackoverflow.com
|
||||
|
||||
Startpage - Search engine privacy
|
||||
startpage.com
|
||||
|
||||
|
43
project.geany
Normal file
@ -0,0 +1,43 @@
|
||||
[editor]
|
||||
line_wrapping=false
|
||||
line_break_column=72
|
||||
auto_continue_multiline=true
|
||||
|
||||
[file_prefs]
|
||||
final_new_line=true
|
||||
ensure_convert_new_lines=false
|
||||
strip_trailing_spaces=false
|
||||
replace_tabs=false
|
||||
|
||||
[indentation]
|
||||
indent_width=4
|
||||
indent_type=0
|
||||
indent_hard_tab_width=8
|
||||
detect_indent=false
|
||||
detect_indent_width=true
|
||||
indent_mode=2
|
||||
|
||||
[project]
|
||||
name=SharpeTronics
|
||||
base_path=/home/csharpe/Desktop/Local-Development/Jekyll/sharpetronics.com/sharpetronics.com
|
||||
description=
|
||||
|
||||
[long line marker]
|
||||
long_line_behaviour=1
|
||||
long_line_column=144
|
||||
|
||||
[files]
|
||||
current_page=7
|
||||
FILE_NAME_0=1664;Ruby;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2FGemfile;0;2
|
||||
FILE_NAME_1=3444;YAML;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2F_config.yml;0;2
|
||||
FILE_NAME_2=0;Ruby;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2F_plugins%2Fjekyll-api%2Flib%2Fa-get-collections.rb;0;2
|
||||
FILE_NAME_3=1641;Ruby;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2F_plugins%2Fjekyll-api%2Flib%2Fb-generate-posts.rb;0;2
|
||||
FILE_NAME_4=6421;Ruby;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2F_plugins%2Fjekyll-api%2Flib%2Fb-generate-products.rb;0;2
|
||||
FILE_NAME_5=17518;Ruby;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2F_plugins%2Fjekyll-api%2Flib%2Fc-download-images.rb;0;2
|
||||
FILE_NAME_6=13355;Ruby;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2F_plugins%2Fjekyll-api%2Flib%2Fd-stripe-create-products.rb;0;2
|
||||
FILE_NAME_7=1593;Markdown;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2FREADME.md;0;4
|
||||
FILE_NAME_8=300;None;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2F.env;0;4
|
||||
FILE_NAME_9=356;YAML;0;EUTF-8;0;1;0;%2Fhome%2Fcsharpe%2FDesktop%2FLocal-Development%2FJekyll%2Fsharpetronics.com%2Fsharpetronics.com%2F.drone.yml;0;4
|
||||
|
||||
[VTE]
|
||||
last_dir=/home/csharpe
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
BIN
uploads/optimus_primed_886bcb1942.jpeg
Normal file
After Width: | Height: | Size: 593 KiB |
BIN
uploads/optimus_primed_886bcb1942_2f94743eba.jpeg
Normal file
After Width: | Height: | Size: 593 KiB |
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 213 KiB |