jekyll-ham 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2035183c2d81e23112bbabb5936425cad0a9b5dcc08dc82c2f22840f6af05881
4
+ data.tar.gz: bed0c2ac6c4a3b8372e4b804b64757bb8678b534f698e59c5153007c2fa1269c
5
+ SHA512:
6
+ metadata.gz: c35f90a52794c653e06d3f0bad9b03449765d8696cfbd4f64f5c1cd66030f0acffe14804c7aabdaf387c1c504ae65dfbd468c97c198e490557d5bfa4fff4e666
7
+ data.tar.gz: 4125c51568a0fbc99500ca57862b27d532d3581dcfdab3059c3d64d868db3b670d5ade5b973420c35eb3c229fff1f64ea175a0730af9f9fd020f11c8deb1a05b
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Reinhart Previano Koentjoro
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ ---
2
+ layout: page
3
+ title: Main Page
4
+ further_reading:
5
+ - title: Official Documentation
6
+ url: https://reinhart1010.github.io/ham-docs/
7
+ target: _blank
8
+ external_links:
9
+ - title: GitHub Repository
10
+ url: https://github.com/reinhart1010/ham/
11
+ icon: bi bi-github
12
+ target: _blank
13
+ - title: Issues List
14
+ url: https://github.com/reinhart1010/ham/issues/
15
+ icon: bi bi-bug
16
+ target: _blank
17
+ - title: Discussions
18
+ url: https://github.com/reinhart1010/ham/discussions/
19
+ icon: bi bi-chat-dots
20
+ target: _blank
21
+ ---
22
+
23
+ # HAM 🥩
24
+ HAM is a Jekyll-based boilerplate template for generating better, static wiki-style websites. HAM can be instantly used to build static wiki pages. But the best of all, the default theme of HAM can be easily customized to create more personalized wiki pages, unlike those from MediaWiki, for example.
25
+
26
+ This project is built to replace the current, MediaWiki installation at hackapedia.reinhart1010.id after I found out difficult to create custom styles for it, while other, Git-based alternatives such as GitHub Wiki sucks (no, really) and may not support self-hosting on shared hosting providers.
27
+
28
+ ## What does HAM stand for?
29
+ HAM is short for:
30
+
31
+ + Hackapedia's Abstraction Machine
32
+ + HAM Ain't MediaWiki
33
+ + [Halfmoon] and Markdown
34
+ + && i++ (can we get more pull requests to add more stuff into this list?)
35
+
36
+ ## Features
37
+ ### What HAM is
38
+ - [x] A static-site wiki generator
39
+ - [x] A better alternative than GitHub pages
40
+ - [x] Highly customizable through [Halfmoon] and [Jekyll]
41
+ - [x] Uses GitHub-Flavored Markdown (GFM)
42
+ - [x] Optimized for GitHub Pages and Gitlab Pages
43
+
44
+ ### What HAM isn't
45
+ - [ ] Optimized for large wiki content (this is where advanced alternatives such as [MediaWiki] excels at)
46
+ - [ ] Built-in support for hosting content written in MediaWiki markup syntax (however there are converters to Markdown)
47
+ - [ ] Supported in legacy web browsers (see [Compatibility](#browser-compatibility))
48
+
49
+ ### What HAM would be
50
+ - [ ] Supporting Forem (DEV.to) liquid tags (YouTube embeds, Twitter posts, etc.)
51
+
52
+ ## Browser Compatibility
53
+ HAM heavily uses [Halfmoon] CSS framework on the generated page due to its theming flexibility based on CSS variables. However, that comes with a cost: **CSS variables are not supported in old browsers**. If you're thinking of Internet Explorer 11, well, don't think too far, because this exact feature may not be supported on some smart TV models, too! There are plans to either include a JavaScript-based polyfill or fallback CSS for this, but I might want to do that later.
54
+
55
+ [Halfmoon]: https://gethalfmoon.com
56
+ [Jekyll]: https://jekyllrb.com
57
+ [MediaWiki]: https://mediawiki.org
data/_config.yml ADDED
@@ -0,0 +1,20 @@
1
+ ham:
2
+ site_name: HAM
3
+ site_tagline: The truly static, Git-based wiki project
4
+ site_icon: https://raw.githubusercontent.com/googlefonts/noto-emoji/main/svg/emoji_u1f969.svg
5
+ contributing:
6
+ discuss:
7
+ type: url
8
+ url: https://github.com/reinhart1010/HAM/discussions/
9
+ view_source_base_url: https://github.com/reinhart1010/HAM/blob/main/
10
+ issue_url: https://github.com/reinhart1010/HAM/issues/
11
+ kramdown:
12
+ input: GFM
13
+ plugins:
14
+ - jekyll-readme-index
15
+ - jekyll-seo-tag
16
+ - jekyll-sitemap
17
+ - jekyll-titles-from-headings
18
+ theme: jekyll-ham
19
+ readme_index:
20
+ with_frontmatter: true
@@ -0,0 +1,7 @@
1
+ <a href="{{ link.url }}" class="sidebar-link sidebar-link-with-icon" target="{{ link.target }}">
2
+ <span class="sidebar-icon">
3
+ <i class="{{ link.icon | default: 'bi bi-file-text' }}" aria-hidden="true"></i>
4
+ </span>
5
+ {{ link.title }}
6
+ {% if link.target == '_blank' %}<i class="bi bi-arrow-up-right-circle ml-5" aria-hidden="true"></i>{% endif %}
7
+ </a>
File without changes
@@ -0,0 +1,26 @@
1
+ <nav class="navbar">
2
+ <div class="navbar-content">
3
+ <button class="btn btn-action" type="button" onclick="halfmoon.toggleSidebar()">
4
+ <i class="bi bi-list" aria-hidden="true"></i>
5
+ <span class="sr-only">Toggle sidebar</span>
6
+ </button>
7
+ </div>
8
+ <a href="/" class="navbar-brand">
9
+ {% if site.ham.site_icon != null %}
10
+ <img src="{{ site.ham.site_icon }}" alt="{{ site.ham.site_name }}">
11
+ {% endif %}{{ site.ham.site_name }}
12
+ </a>
13
+ {% if site.ham.site_tagline != null %}
14
+ <span class="navbar-text d-none d-sm-block">{{ site.ham.site_tagline }}</span> <!-- text-monospace = font-family shifted to monospace -->
15
+ {% endif %}
16
+ <div class="ml-auto">
17
+ <button onClick="halfmoon.toggleDarkMode()" class="btn btn-action bg-dark-lm bg-white-dm text-white-lm text-dark-dm">
18
+ <i class="bi bi-moon-stars" aria-hidden="true"></i>
19
+ <span class="sr-only">Toggle Dark Mode</span>
20
+ </button>
21
+ <a href="#search" class="btn btn-action btn-primary">
22
+ <i class="bi bi-search" aria-hidden="true"></i>
23
+ <span class="sr-only">Search</span>
24
+ </a>
25
+ </div>
26
+ </nav>
@@ -0,0 +1,12 @@
1
+ <div id="search" class="modal" tabindex="-1" role="dialog">
2
+ <div class="modal-dialog" role="document">
3
+ <div class="modal-content">
4
+ <a href="#" class="close" role="button" aria-label="Close">
5
+ <span aria-hidden="true">&times;</span>
6
+ </a>
7
+ <input id="search-input" type="text" class="form-control" placeholder="Keyword">
8
+ <ul id="results-container" class="my-10"></ul>
9
+ <span>Tip: Use <kbd>Ctrl+K</kbd> to search</span>
10
+ </div>
11
+ </div>
12
+ </div>
@@ -0,0 +1,36 @@
1
+ <div class="sidebar">
2
+ <div class="sidebar-menu">
3
+ <h5 id="on-this-page" class="sidebar-title">On This Page</h5>
4
+ <div class="sidebar-divider"></div>
5
+ <div id="_ham_on_this_page_ul"></div>
6
+ <br>
7
+ {% if site.ham.contributing != null %}
8
+ <h5 id="contribute" class="sidebar-title">Contribute to This Page</h5>
9
+ <div class="sidebar-divider"></div>
10
+ {% if site.ham.contributing.discuss.type != null %}
11
+ <a href="{% if site.ham.contributing.discuss.type == 'url' %}{{ site.ham.contributing.discuss.url }}{% else %}#discuss{% endif %}" class="sidebar-link sidebar-link-with-icon">
12
+ <span class="sidebar-icon">
13
+ <i class="bi bi-chat-dots" aria-hidden="true"></i>
14
+ </span>
15
+ Discuss
16
+ </a>
17
+ {% endif %}
18
+ {% if site.ham.contributing.issue_url != null %}
19
+ <a href="{{ site.ham.contributing.issue_url }}" class="sidebar-link sidebar-link-with-icon">
20
+ <span class="sidebar-icon">
21
+ <i class="bi bi-bug" aria-hidden="true"></i>
22
+ </span>
23
+ Report New Issue
24
+ </a>
25
+ {% endif %}
26
+ {% if site.ham.contributing.view_source_base_url != null %}
27
+ <a href="{{ site.ham.contributing.view_source_base_url }}{{ page.path }}" class="sidebar-link sidebar-link-with-icon">
28
+ <span class="sidebar-icon">
29
+ <i class="bi bi-code-slash" aria-hidden="true"></i>
30
+ </span>
31
+ View Source
32
+ </a>
33
+ {% endif %}
34
+ {% endif %}
35
+ </div>
36
+ </div>
@@ -0,0 +1,51 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <!-- Meta tags -->
5
+ <meta charset="utf-8" />
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
7
+ <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
8
+ <meta name="viewport" content="width=device-width" />
9
+
10
+ <!-- Favicon and title -->
11
+ <link rel="icon" href="{{ site.ham.site_favicon | default: site.ham.site_icon }}">
12
+ <title>{{ page.title }} - {{ site.ham.site_title }}</title>
13
+
14
+ <!-- Halfmoon CSS -->
15
+ <link href="https://cdn.jsdelivr.net/npm/halfmoon@1.1.1/css/halfmoon-variables.min.css" rel="stylesheet" />
16
+
17
+ <!-- Bootstrap Icons CSS -->
18
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" rel="stylesheet" />
19
+
20
+ <!-- Additional CSS -->
21
+ <link href="/assets/default.css" rel="stylesheet" />
22
+ <link href="/assets/main.css" rel="stylesheet" />
23
+
24
+ </head>
25
+ <body class="with-custom-webkit-scrollbars with-custom-css-scrollbars" data-dm-shortcut-enabled="true" data-sidebar-shortcut-enabled="true" data-set-preferred-mode-onload="true">
26
+ {% include search-modal.html %}
27
+ <div class="page-wrapper with-navbar with-sidebar">
28
+ <div class="sticky-alerts"></div>
29
+ {% include navbar.html %}
30
+ {% include sidebar.html %}
31
+ <div class="content-wrapper">
32
+ <div class="container-fluid">
33
+ {{ content }}
34
+ </div>
35
+ </div>
36
+ {% include footer.html %}
37
+ </div>
38
+
39
+ <!-- Simple Jekyll Search JS -->
40
+ <script src="https://unpkg.com/simple-jekyll-search@latest/dest/simple-jekyll-search.min.js"></script>
41
+ <script>
42
+ var sjs = SimpleJekyllSearch({
43
+ searchInput: document.getElementById('search-input'),
44
+ resultsContainer: document.getElementById('results-container'),
45
+ json: '/search.json'
46
+ })
47
+ </script>
48
+ <!-- Halfmoon JS -->
49
+ <script src="https://cdn.jsdelivr.net/npm/halfmoon@1.1.1/js/halfmoon.min.js"></script>
50
+ </body>
51
+ </html>
@@ -0,0 +1,41 @@
1
+ ---
2
+ layout: default
3
+ ---
4
+ <div class="row">
5
+ <div class="col-xl-8 p-20 collapse-group article-wrapper" id="_ham_content">
6
+ {{ content }}
7
+ </div>
8
+ <div class="col-xl-4 pt-xl-20 pb-20">
9
+ {% if page.related_topics != null %}
10
+ <h5 id="related-topics" class="sidebar-title">Related Topics</h5>
11
+ <div class="sidebar-divider"></div>
12
+ {% for link in page.related_topics %}
13
+ {% include external-link.html %}
14
+ {% endfor %}
15
+ {% endif %}
16
+ {% if page.further_reading != null %}
17
+ <h5 id="further-reading" class="sidebar-title">Further Reading</h5>
18
+ <div class="sidebar-divider"></div>
19
+ {% for link in page.further_reading %}
20
+ {% include external-link.html %}
21
+ {% endfor %}
22
+ {% endif %}
23
+ {% if page.external_links != null %}
24
+ <h5 id="external-links" class="sidebar-title">External Links</h5>
25
+ <div class="sidebar-divider"></div>
26
+ {% for link in page.external_links %}
27
+ {% include external-link.html %}
28
+ {% endfor %}
29
+ {% endif %}
30
+ </div>
31
+ </div>
32
+
33
+ <script src="https://unpkg.com/to-uri@1.0.4/lib/toURI.js"></script>
34
+ <script src="/assets/entry-parser.js"></script>
35
+ <script>
36
+ var siteName = '{{ site.ham.site_name }}';
37
+ var siteTagline = '{{ site.ham.site_tagline }}';
38
+ var disableTagline = '{{ page.ham.disable_tagline }}';
39
+ if (disableTagline.length > 0 && disableTagline == true) siteName = null;
40
+ parseRawEntry(document.getElementById('_ham_content'), document.getElementById('_ham_on_this_page_ul'), siteName, siteTagline);
41
+ </script>
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: page
3
+ ---
4
+
5
+ {{ content }}
@@ -0,0 +1,36 @@
1
+ :root {
2
+ --font-family-serif: 'Linux Libertine', 'Linux Libertine Display O', Georgia, 'Noto Serif', 'Times New Roman', Times, serif;
3
+ --heading-font-weight: 700;
4
+ }
5
+
6
+ /* Use serif font for headings (a-la MediaWiki) */
7
+ .article-wrapper h1, .article-wrapper h2, .content-wrapper .h1, .content-wrapper .h2 {
8
+ font-family: var(--font-family-serif);
9
+ font-weight: 400;
10
+ }
11
+ .article-sitesub {
12
+ font-family: var(--font-family-serif);
13
+ font-style: italic;
14
+ }
15
+
16
+ /* Lowers the font size for H3, H4, H5, H6 */
17
+ .article-wrapper h3, .content-wrapper .h3 {
18
+ font-size: 1.75rem;
19
+ }
20
+ .article-wrapper h4, .content-wrapper .h4 {
21
+ font-size: 1.5rem;
22
+ }
23
+ .article-wrapper h5, .content-wrapper .h5 {
24
+ font-size: 1.25rem;
25
+ }
26
+ .article-wrapper h6, .content-wrapper .h6 {
27
+ font-size: 1rem;
28
+ }
29
+
30
+ /* Removes list styling for .task-list */
31
+ .task-list {
32
+ list-style-type: none;
33
+ }
34
+ .task-list-item-checkbox {
35
+ margin-right: 0.5rem;
36
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Automatically generate ID names based on the heading name
3
+ * @param {String} name The heading name
4
+ */
5
+ function createSectionHeadingId(name){
6
+ var i = 0;
7
+ var finalName = '';
8
+ do {
9
+ finalName = toURI(name);
10
+ if (i > 0) finalName += '-' + i;
11
+ i++;
12
+ } while (document.getElementById(finalName));
13
+ return finalName;
14
+ }
15
+
16
+ /**
17
+ * Scans the first-level attributes of HTML to be included on "On This Page" list
18
+ * @param {Node} originalContent The HTML element containing the original rendered article
19
+ * @param {String} tagline The site tagline
20
+ * @param {Node} onThisPageEntry The HTML element pointing the "On This Page" entry
21
+ */
22
+ function parseRawEntry(originalContent, onThisPageEntry, siteTitle, siteTagline){
23
+ var headingTags = ['H2', 'H3', 'H4', 'H5', 'H6'];
24
+ var i, j;
25
+ var taglinePlaced = false;
26
+ var children = originalContent.childNodes;
27
+ var currentAccordionId = '';
28
+ for (i = 0; i < children.length; i++){
29
+ var node = children[i];
30
+ if (node.nodeName == 'H1' && !taglinePlaced && typeof siteTitle === 'string' && siteTitle.length > 0){
31
+ var newTagline = document.createElement('span');
32
+ newTagline.textContent = 'from ' + siteTitle;
33
+ newTagline.className = 'font-size-18 article-sitesub';
34
+ if (typeof siteTagline === 'string' && siteTagline.length > 0){
35
+ newTagline.textContent += ', ' + siteTagline;
36
+ }
37
+ originalContent.insertBefore(newTagline, children[i + 1]);
38
+ taglinePlaced = true;
39
+ }
40
+ if (headingTags.indexOf(node.nodeName) >= 0){
41
+ var currentHeadingLevel = node.nodeName.substring(1,2);
42
+ isInsideAccordion = true;
43
+ if (!node.id) node.id = createSectionHeadingId(node.textContent);
44
+
45
+ if (node.nodeName === 'H2'){
46
+ currentAccordionId = node.id;
47
+ }
48
+
49
+ // Create "On This Page entry"
50
+ var newA = document.createElement('a');
51
+ newA.href = '#' + node.id;
52
+ newA.className = 'sidebar-link text-truncate';
53
+ newA.setAttribute('onclick', 'expandAccordion(\'' + currentAccordionId + '\')');
54
+ for (j = 2; j < currentHeadingLevel; j++){
55
+ var newSpan = document.createElement('span');
56
+ newSpan.className = 'ml-10 d-inline-block';
57
+ newSpan.setAttribute('aria-hidden', true);
58
+ newA.appendChild(newSpan);
59
+ }
60
+ newA.appendChild(document.createTextNode(node.textContent));
61
+ onThisPageEntry.appendChild(newA);
62
+ }
63
+ }
64
+ for (i = 0; i < children.length; i++){
65
+ var node = children[i];
66
+ if (node.nodeName === 'H2'){
67
+ var start = i; end = i;
68
+ var collapseChildren = [];
69
+ while (end + 1 < children.length && children[end + 1].nodeName !== 'H2') end++;
70
+
71
+ // Mark children
72
+ if (start === end) continue;
73
+ for (j = start + 1; j <= end; end--){
74
+ collapseChildren.push(children[j].cloneNode(true));
75
+ // Mark for deletion
76
+ children[j].remove();
77
+ }
78
+
79
+ // Create actual collapse
80
+ var newDetails = document.createElement('details');
81
+ newDetails.className = 'collapse-panel w-full _ham_accordion_autoexpand';
82
+ var newSummary = document.createElement('summary');
83
+ newSummary.className = 'collapse-header font-size-20 h2';
84
+ newSummary.innerHTML = node.innerHTML;
85
+ var newDiv = document.createElement('div');
86
+ newDiv.className = 'collapse-content';
87
+ for (j = 0; j < collapseChildren.length; j++) newDiv.appendChild(collapseChildren[j]);
88
+ newDetails.appendChild(newSummary);
89
+ newDetails.appendChild(newDiv);
90
+
91
+ newDetails.id = children[i].id;
92
+ children[i].outerHTML = newDetails.outerHTML;
93
+ }
94
+ }
95
+ }
96
+
97
+ var _ham_state_is_all_accordion_collapsed = true;
98
+
99
+ function autoexpandAccordion(){
100
+ if (window.innerWidth > 768 && _ham_state_is_all_accordion_collapsed === true){
101
+ document.querySelectorAll('._ham_accordion_autoexpand').forEach(function (el){
102
+ el.setAttribute('open', 'true');
103
+ });
104
+ _ham_state_is_all_accordion_collapsed = false;
105
+ } else if (_ham_state_is_all_accordion_collapsed === false){
106
+ document.querySelectorAll('._ham_accordion_autoexpand').forEach(function (el){
107
+ el.removeAttribute('open');
108
+ });
109
+ _ham_state_is_all_accordion_collapsed = true;
110
+ }
111
+ }
112
+
113
+ function expandAccordion(id){
114
+ var el = document.getElementById(id);
115
+ el.setAttribute('open', 'true');
116
+ }
117
+
118
+ window.addEventListener("load", autoexpandAccordion);
data/assets/main.css ADDED
@@ -0,0 +1 @@
1
+ /* TODO: Add your CSS here (Jekyll will override it) */
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-ham
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Reinhart Previano Koentjoro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-11-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ description:
28
+ email:
29
+ - reinhart@reinhart1010.id
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE.txt
35
+ - README.md
36
+ - _config.yml
37
+ - _includes/external-link.html
38
+ - _includes/footer.html
39
+ - _includes/navbar.html
40
+ - _includes/search-modal.html
41
+ - _includes/sidebar.html
42
+ - _layouts/default.html
43
+ - _layouts/page.html
44
+ - _layouts/post.html
45
+ - assets/default.css
46
+ - assets/entry-parser.js
47
+ - assets/main.css
48
+ homepage: https://github.com/reinhart1010/ham
49
+ licenses:
50
+ - MIT
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubygems_version: 3.2.22
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Hackapedia's Abstraction Machine.
71
+ test_files: []