Skip to content

Commit 0e60957

Browse files
committed
Add Repository last updated tags
Note: This is supposed to be an extension for the last PR q2a#91 This PR introduces a new feature that enhances plugin visibility and compatibility display: - Fetches all plugin repository links and retrieves their metadata. - Stores metadata locally using localStorage for performance, and also not bombard fetches to `raw.githubusercontent.com` on every page request. - Dynamically generates a footer section for each plugin with: - Repository update date - "Q2A Tested With" tag based on the plugin’s `max_q2a` metadata.json key, if available. This helps users quickly assess which plugins are compatible with their Q2A version and when they were last updated. I also added a message to the Plugins & Themes pages, explaining that "outdated" plugins doesn't necessarily mean that they don't work. Some of them just don't require to be updated as frequently. Also, everybody can create PRs to update the `max_q2a` version of a plugin they know it works, because they're using it.
1 parent 2826801 commit 0e60957

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2463
-245
lines changed

_includes/breadcrumbs.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<nav class="breadcrumbs-container">
2+
<ul class="breadcrumbs">
3+
{% assign crumbs = page.url | remove:'/index.html' | split: '/' %}
4+
<li class="breadcrumb-item">
5+
<a href="{% if site.baseurl == '/' %}{{ site.baseurl }}{% else %}{{ site.baseurl }}/{% endif %}">Home</a>
6+
</li>
7+
{% for crumb in crumbs offset: 1 %}
8+
{% if forloop.last %}
9+
<li class="breadcrumb-item">{{ page.title }}</li>
10+
{% else %}
11+
<li class="breadcrumb-item">
12+
<a href="{{ site.baseurl }}{% assign crumb_limit = forloop.index | plus: 1 %}{% for crumb in crumbs limit: crumb_limit %}{{ crumb | append: '/' | replace:'without-plugin/','without-plugins/' }}{% endfor %}">{{ crumb | replace:'-',' ' | remove:'.html' | capitalize }}</a>
13+
</li>
14+
{% endif %}
15+
{% endfor %}
16+
</ul>
17+
</nav>

_includes/footer.html

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
1+
<div class="jump-top-container">
2+
<div id="jump-top" class="jump-top noSelect desktop-only"><span class="material-icons">arrow_upward</span></div>
3+
</div>
4+
5+
<div class="page-status-container"></div>
6+
17
<footer class="footer">
2-
<nav class="footer-nav">
3-
{% for navpage in site.nav.footer %}
4-
<a class="footer-nav-link" href="{{ navpage.url }}">{{ navpage.name }}</a>
5-
{% endfor %}
6-
</nav>
7-
<div class="credit">
8-
Created by <a href="http://www.gidgreen.com/">Gideon Greenspan</a>, <a href="https://github.com/svivian">Scott Vivian</a>,
9-
and <a href="https://github.com/q2a/question2answer/graphs/contributors">contributors</a>
8+
<div class="footer-container">
9+
<nav class="footer-nav">
10+
<ul>
11+
{% for navpage in site.nav.footer %}
12+
<li>
13+
<a class="footer-nav-link" href="{% if navpage.url contains 'http' %}{{ navpage.url }}{% else %}{{ site.baseurl }}{{ navpage.url }}{% endif %}">{{ navpage.name }}</a>
14+
</li>
15+
{% endfor %}
16+
</ul>
17+
</nav>
18+
<div class="credit">
19+
Created by <a href="http://www.gidgreen.com/">Gideon Greenspan</a>, <a href="https://github.com/svivian">Scott Vivian</a>,
20+
and <a href="https://github.com/q2a/question2answer/graphs/contributors">contributors</a>
21+
</div>
1022
</div>
1123
</footer>

_includes/header.html

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,84 @@
1+
{% if page.slug == 'homepage' %}
12
<div class="wave-container"></div>
3+
{% endif %}
24

35
<header class="header">
4-
<div class="header-logo">
5-
<a href="/"><img class="logo-img normal-logo" src="/images/question2answer-logo-white-350x40.png" alt="Question2Answer logo"></a>
6+
<div class="header-container flex-row">
7+
<div class="flex-item logo-container">
8+
<div id="main-nav-trigger" class="material-icons noSelect mobile-only">menu</div>
9+
<a href="{% if site.baseurl == '/' %}{{ site.baseurl }}{% else %}{{ site.baseurl }}/{% endif %}" class="header-logo">
10+
<img class="logo-img normal-logo" src="{{ site.baseurl }}/images/question2answer-logo-350x40.webp" alt="Question2Answer logo">
11+
{% if page.slug == 'homepage' %}
12+
<img class="logo-img white-logo" src="{{ site.baseurl }}/images/question2answer-logo-white-350x40.webp" alt="Question2Answer logo">
13+
{% endif %}
14+
</a>
15+
</div>
16+
17+
<nav class="nav-container flex-item flex-middle no-select">
18+
<a href="{% if site.baseurl == '/' %}{{ site.baseurl }}{% else %}{{ site.baseurl }}/{% endif %}" class="header-logo mobile-only">
19+
<img class="logo-img normal-logo" src="{{ site.baseurl }}/images/question2answer-logo-350x40.webp" alt="Question2Answer logo">
20+
</a>
21+
<ul class="nav mega-menu flex-item">
22+
<span class="mega-menu-trigger">
23+
<span class="nav-item" tabindex="0">
24+
Documentation
25+
<span class="docs-caret"></span>
26+
</span>
27+
</span>
28+
29+
<ul class="nav nav-main flex-item display-none">
30+
{% for navpage in site.nav.main %}{% capture parent_url %}{{ navpage.path }}{% endcapture %}
31+
<li>
32+
<span class="nav-item toggleChildren{% if page.url == parent_url %} selected-nav{% endif %}" tabindex="0">
33+
{{ navpage.name }}
34+
<span class="docs-caret"></span>
35+
</span>
36+
{% if navpage.sub %}
37+
<ul class="sub-nav display-none">
38+
{% for subnavpage in site.nav[navpage.sub] %}{% capture child_url %}{{ subnavpage.path }}{% endcapture %}
39+
<li><a href="{{ site.baseurl }}{{ subnavpage.path }}"
40+
class="sub-nav-item{% if page.url == child_url %} selected-nav{% endif %}">{{ subnavpage.name }}</a></li>
41+
{% endfor %}
42+
</ul>
43+
{% endif %}
44+
</li>
45+
{% endfor %}
46+
</ul>
47+
<ul class="nav nav-main-second flex-item">
48+
{% for navpage in site.nav.second %}{% capture parent_url %}{{ navpage.path }}{% endcapture %}
49+
<li>
50+
<span class="nav-item toggleChildren{% if page.url == parent_url %} selected-nav{% endif %}" tabindex="0">
51+
{{ navpage.name }}
52+
<span class="docs-caret"></span>
53+
</span>
54+
{% if navpage.sub %}
55+
<ul class="sub-nav display-none">
56+
{% for subnavpage in site.nav[navpage.sub] %}{% capture child_url %}{{ subnavpage.path }}{% endcapture %}
57+
<li><a href="{{ site.baseurl }}{{ subnavpage.path }}"
58+
class="sub-nav-item{% if page.url == child_url %} selected-nav{% endif %}">{{ subnavpage.name }}</a></li>
59+
{% endfor %}
60+
</ul>
61+
{% endif %}
62+
</li>
63+
{% endfor %}
64+
</ul>
65+
</ul>
66+
<ul class="nav nav-main-third flex-item">
67+
{% for navpage in site.nav.third %}{% capture parent_url %}{{ navpage.path }}{% endcapture %}
68+
<li>
69+
<a class="nav-item
70+
{% if page.url == parent_url %} selected-nav {% endif %}
71+
{{ navpage.class | default: '' }}"
72+
href="{% if navpage.url contains 'http' %}{{ navpage.url }}{% else %}{{ site.baseurl }}{{ navpage.url }}{% endif %}">{{ navpage.name }}</a>
73+
</li>
74+
{% endfor %}
75+
</ul>
76+
</nav>
77+
78+
<div class="darkPane"></div>
679
</div>
7-
<nav class="top-nav main-nav">
8-
{% for navpage in site.nav.main %}
9-
<a class="main-nav-link" href="{{ navpage.path }}">{{ navpage.name }}</a>
10-
{% endfor %}
11-
{% for navpage in site.nav.second %}
12-
<a class="main-nav-link {{ navpage.class | default: '' }}" href="{{ navpage.url }}">{{ navpage.name }}</a>
13-
{% endfor %}
14-
</nav>
1580
</header>
81+
82+
{% if page.slug != 'homepage' %}
83+
{% include breadcrumbs.html %}
84+
{% endif %}

_includes/sidebar.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<section>
2+
<nav class="page-sidebar-content">
3+
<ul class="docs-nav">
4+
<!-- will populate -->
5+
</ul>
6+
</nav>
7+
</section>

_layouts/default.html

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,39 @@
11
<!doctype html>
22
<html lang="en">
3-
<head>
4-
<meta charset="utf-8">
5-
<meta name="viewport" content="width=device-width initial-scale=1" />
6-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7-
8-
<link rel="preconnect" href="https://fonts.gstatic.com">
9-
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700">
10-
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
11-
<link rel="stylesheet" href="/css/styles2020.css">
12-
13-
<title>{% if page.title %}{{ page.title | escape }}{% else %}{{ site.title }}{% endif %}</title>
14-
<meta name="description" content="{{ site.description }}">
15-
16-
<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.url }}">
17-
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
18-
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
19-
{% include analytics.html %}
20-
</head>
21-
22-
<body class="page">
23-
24-
{% include header.html %}
25-
26-
<main class="page-container">
27-
{{ content }}
28-
</main>
29-
30-
{% include footer.html %}
31-
32-
<script>
33-
window.addEventListener('load', stickyHeader);
34-
window.addEventListener('scroll', stickyHeader, {passive: true});
35-
36-
// Get the offset position of the navbar
37-
var header = document.querySelector('header.header');
38-
var stickyPos = header ? header.offsetTop : 0;
39-
40-
function stickyHeader() {
41-
if (window.scrollY > stickyPos) {
42-
header.classList.add('sticky');
43-
} else {
44-
header.classList.remove('sticky');
45-
}
46-
}
47-
</script>
48-
</body>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width initial-scale=1" />
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
8+
<link rel="preconnect" href="https://fonts.gstatic.com">
9+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&amp;display=swap">
10+
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
11+
<link rel="stylesheet" href="{{ site.baseurl }}/css/styles.css">
12+
13+
<title>{% if page.title %}{{ page.title | escape }}{% else %}{{ site.title }}{% endif %}</title>
14+
<meta name="description" content="{{ site.description }}">
15+
16+
<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.url }}">
17+
<link rel="shortcut icon" type="image/x-icon" href="{{ site.baseurl }}/favicon.ico">
18+
<link rel="apple-touch-icon" sizes="180x180" href="{{ site.baseurl }}/apple-touch-icon.png">
19+
{% include analytics.html %}
20+
</head>
21+
22+
<body class="page{% if page.slug %} template-{{ page.slug }}{% endif %}">
23+
24+
{% include header.html %}
25+
26+
<main class="page-container">
27+
{{ content }}
28+
</main>
29+
30+
{% include footer.html %}
31+
32+
<script src="{{ site.baseurl }}/js/scripts.js"></script>
33+
34+
{% if page.slug == 'addons-plugins' or page.slug == 'addons-themes' %}
35+
<script src="{{ site.baseurl }}/js/GithubLinks.js"></script>
36+
{% endif %}
37+
38+
</body>
4939
</html>

_layouts/home.html

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@
22
layout: default
33
---
44

5-
<h1 class="home-intro"><strong>Question2Answer</strong> (Q2A) is a popular open source Q&A platform for PHP/MySQL, currently running on <a href="https://www.question2answer.org/sites.php">24,500+ sites in 40 languages</a>.</h1>
5+
<div class="home-intro-container">
6+
<h1 class="home-intro"><strong>Question2Answer</strong> (Q2A) is a popular open source Q&A platform for PHP/MySQL, currently running on <a href="https://www.question2answer.org/sites.php">24,500+ sites in 40 languages</a>.</h1>
7+
</div>
68

7-
{{ content }}
9+
<div class="notice-container display-none">
10+
<div class="notice">
11+
<div class="close-notice material-icons">close</div>
12+
<div class="notice-image"></div>
13+
<div class="notice-text home-intro-card">
14+
{{ content }}
15+
</div>
16+
<div class="clear"></div>
17+
</div>
18+
<div class="close-sheet"></div>
19+
</div>
820

9-
<div class="showcase-cols">
21+
<article class="showcase-cols">
1022

1123
{% capture answerText %}
1224
<p>A Q&amp;A site helps your online community to share knowledge.
@@ -23,8 +35,8 @@ <h1 class="home-intro"><strong>Question2Answer</strong> (Q2A) is a popular open
2335
{% include card-showcase.html icon="people" title="Why offer Q&amp;A on my site?" answer=answerText %}
2436

2537
{% capture answerText %}
26-
<p><a href="https://www.question2answer.org/question2answer-latest.zip"><b>Download Question2Answer</b></a>, then read <a href="/install/">how to install</a>.
27-
Version 1.8.8 was <a href="/install/versions/">released</a> on July 25th, 2023.
38+
<p><a href="https://www.question2answer.org/question2answer-latest.zip"><b>Download Question2Answer</b></a>, then read <a href="{{ site.baseurl }}/install/">how to install</a>.
39+
Version 1.8.8 was <a href="{{ site.baseurl }}/install/versions/">released</a> on July 25th, 2023.
2840
Also <a href="https://github.com/q2a/question2answer">on GitHub</a>.</p>
2941
<p>Question2Answer is open source, <a href="https://www.question2answer.org/license.php">licensed under GPL v2+</a>.</p>
3042
{% endcapture %}
@@ -43,9 +55,9 @@ <h1 class="home-intro"><strong>Question2Answer</strong> (Q2A) is a popular open
4355

4456
{% capture answerText %}
4557
<ul>
46-
<li>Q2A takes 5 minutes (or less!) to <a href="/install/">install</a>.</li>
47-
<li>Easy styling with <a href="/themes/">CSS themes</a>.</li>
48-
<li>Supports <a href="/translate/">translation</a> into any language.</li>
58+
<li>Q2A takes 5 minutes (or less!) to <a href="{{ site.baseurl }}/install/">install</a>.</li>
59+
<li>Easy styling with <a href="{{ site.baseurl }}/themes/">CSS themes</a>.</li>
60+
<li>Supports <a href="{{ site.baseurl }}/translate/">translation</a> into any language.</li>
4961
<li>Custom sidebar, widgets, pages and links.</li>
5062
<li>SEO features such as <a href="https://www.sitemaps.org/">XML Sitemap</a> and neat URLs.</li>
5163
</ul>
@@ -68,35 +80,35 @@ <h1 class="home-intro"><strong>Question2Answer</strong> (Q2A) is a popular open
6880
<li>Create experts, editors, moderators and admins.</li>
6981
<li>User avatars (or <a href="https://en.gravatar.com/">Gravatar</a>) and custom fields.</li>
7082
<li>Private messages and public wall posts.</li>
71-
<li>Log in via Facebook or others (using <a href="/addons/plugins/">plugins</a>).</li>
83+
<li>Log in via Facebook or others (using <a href="{{ site.baseurl }}/addons/plugins/">plugins</a>).</li>
7284
</ul>
7385
{% endcapture %}
7486
{% include card-showcase.html icon="face" title="Built-in user account management ..." answer=answerText %}
7587

7688
{% capture answerText %}
7789
<ul>
78-
<li>Out-of-the-box <a href="/install/wordpress/">WordPress</a> and Joomla integration.</li>
79-
<li>Custom <a href="/install/single-sign-on/">single sign-on</a> support for other sites.</li>
80-
<li>Deep integration and customization via <a href="/plugins/">plugins</a>.</li>
90+
<li>Out-of-the-box <a href="{{ site.baseurl }}/install/wordpress/">WordPress</a> and Joomla integration.</li>
91+
<li>Custom <a href="{{ site.baseurl }}/install/single-sign-on/">single sign-on</a> support for other sites.</li>
92+
<li>Deep integration and customization via <a href="{{ site.baseurl }}/plugins/">plugins</a>.</li>
8193
</ul>
8294
{% endcapture %}
8395
{% include card-showcase.html icon="assignment_ind" title="... or integrate with existing sites" answer=answerText %}
8496

8597
{% capture answerText %}
8698
<ul>
87-
<li>PHP/MySQL <a href="/install/optimize/">scalable</a> to millions of users and posts.</li>
88-
<li><a href="/install/security/">Safe from</a> XSS, CSRF and SQL injection attacks.</li>
99+
<li>PHP/MySQL <a href="{{ site.baseurl }}/install/optimize/">scalable</a> to millions of users and posts.</li>
100+
<li><a href="{{ site.baseurl }}/install/security/">Safe from</a> XSS, CSRF and SQL injection attacks.</li>
89101
<li>Beat spam with captchas, moderation and/or flagging.</li>
90102
</ul>
91103
{% endcapture %}
92104
{% include card-showcase.html icon="policy" title="Fast and secure" answer=answerText %}
93105

94106
{% capture answerText %}
95107
<p>Contribute <a href="https://github.com/q2a/question2answer">via Github</a>,
96-
create a <a href="/themes/">theme</a>,
97-
<a href="/plugins/">plugin</a> or
98-
<a href="/translate/">translation</a>.</p>
108+
create a <a href="{{ site.baseurl }}/themes/">theme</a>,
109+
<a href="{{ site.baseurl }}/plugins/">plugin</a> or
110+
<a href="{{ site.baseurl }}/translate/">translation</a>.</p>
99111
{% endcapture %}
100112
{% include card-showcase.html icon="translate" title="How can I help?" answer=answerText %}
101113

102-
</div>
114+
</article>

_layouts/page.html

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,10 @@
33
---
44

55
<div class="docs-container">
6-
<div class="page-sidebar">
7-
{% include nav-sub.html %}
8-
</div>
9-
10-
<div class="page-content">
6+
<article class="page-content">
117
{{ content }}
12-
</div>
8+
</article>
9+
<aside class="page-sidebar desktop-only">
10+
{% include sidebar.html %}
11+
</aside>
1312
</div>
14-
15-
<script>
16-
// toggle sub-menu
17-
var menuToggle = document.querySelector('.page-sidebar-toggle');
18-
menuToggle.addEventListener('click', function(ev) {
19-
var nav = this.nextElementSibling;
20-
if (nav.classList.contains('expanded'))
21-
nav.classList.remove('expanded');
22-
else
23-
nav.classList.add('expanded');
24-
});
25-
</script>

addons/clients.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
layout: page
33
menu: addons
44
title: "Question2Answer - Add-ons - Clients"
5+
slug: addons-clients
56
---
67

78
# Question2Answer Clients

addons/index.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22
layout: page
33
menu: addons
44
title: "Question2Answer - Add-ons"
5+
slug: addons
56
---
67

78
# Question2Answer is being extended by the community.
89

910
This page links to add-ons created by Question2Answer users. These are not endorsed for quality or suitability, but we hope they are useful. If you have something to contribute, please submit a pull request to [the docs](https://github.com/q2a/q2a.github.io/) or [get in touch](https://www.question2answer.org/feedback.php) - your help is much appreciated!
1011

11-
## [Translations](/addons/translations/)
12+
## [Translations]({{ site.baseurl }}/addons/translations/)
1213

13-
## [Themes](/addons/themes/)
14+
## [Themes]({{ site.baseurl }}/addons/themes/)
1415

15-
## [Plugins](/addons/plugins/)
16+
## [Plugins]({{ site.baseurl }}/addons/plugins/)
1617

17-
## [Clients](/addons/clients/)
18+
## [Clients]({{ site.baseurl }}/addons/clients/)
1819

0 commit comments

Comments
 (0)