✨ feat: add support for giscus & utterances comments
parent
93c8b577b8
commit
19d120019b
@ -0,0 +1,81 @@
|
||||
function setGiscusTheme(newTheme) {
|
||||
// Get the giscus iframe.
|
||||
const frame = document.querySelector('iframe.giscus-frame');
|
||||
|
||||
if (frame) {
|
||||
// If the iframe exists, send a message to set the theme.
|
||||
frame.contentWindow.postMessage(
|
||||
{ giscus: { setConfig: { theme: newTheme } } },
|
||||
'https://giscus.app'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to initialize Giscus. This function is run when the window loads.
|
||||
function initGiscus() {
|
||||
// Get the div that will contain the comments.
|
||||
const commentsDiv = document.querySelector('.comments');
|
||||
if (commentsDiv) {
|
||||
// Get the various settings from data attributes on the div.
|
||||
const repo = commentsDiv.getAttribute('data-repo');
|
||||
const repoId = commentsDiv.getAttribute('data-repo-id');
|
||||
const category = commentsDiv.getAttribute('data-category');
|
||||
const categoryId = commentsDiv.getAttribute('data-category-id');
|
||||
const strictTitleMatching = commentsDiv.getAttribute('data-strict');
|
||||
const term = commentsDiv.getAttribute('data-term');
|
||||
const reactionsEnabled = commentsDiv.getAttribute('data-reactions-enabled');
|
||||
const inputPosition = commentsDiv.getAttribute('data-input-position');
|
||||
const lightTheme = commentsDiv.getAttribute('data-light-theme');
|
||||
const darkTheme = commentsDiv.getAttribute('data-dark-theme');
|
||||
const lang = commentsDiv.getAttribute('data-lang');
|
||||
const lazyLoading = commentsDiv.getAttribute('data-lazy-loading');
|
||||
|
||||
// Create a new script tag that will load the Giscus script.
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://giscus.app/client.js';
|
||||
script.async = true;
|
||||
|
||||
// Set the various settings as data attributes on the script tag.
|
||||
script.setAttribute('data-repo', repo);
|
||||
script.setAttribute('data-repo-id', repoId);
|
||||
script.setAttribute('data-category', category);
|
||||
script.setAttribute('data-category-id', categoryId);
|
||||
script.setAttribute('data-term', term);
|
||||
script.setAttribute('data-strict', strictTitleMatching);
|
||||
script.setAttribute('data-reactions-enabled', reactionsEnabled);
|
||||
script.setAttribute('data-emit-metadata', '0');
|
||||
script.setAttribute('data-input-position', inputPosition);
|
||||
script.setAttribute('data-lang', lang);
|
||||
script.setAttribute('crossorigin', 'anonymous');
|
||||
|
||||
// Set the mapping if it is provided.
|
||||
const mapping = commentsDiv.getAttribute('data-mapping');
|
||||
if (mapping) {
|
||||
script.setAttribute('data-mapping', mapping);
|
||||
}
|
||||
|
||||
// Choose the correct theme based on the current theme of the document.
|
||||
const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
|
||||
const selectedTheme = currentTheme === 'dark' ? darkTheme : lightTheme;
|
||||
script.setAttribute('data-theme', selectedTheme);
|
||||
|
||||
// Set the loading attribute if lazy loading is enabled.
|
||||
if (lazyLoading === 'true') {
|
||||
script.setAttribute('data-loading', 'lazy');
|
||||
}
|
||||
|
||||
// Add the script tag to the div.
|
||||
commentsDiv.appendChild(script);
|
||||
|
||||
// Listen for theme changes and update the Giscus theme when they occur.
|
||||
window.addEventListener('themeChanged', (event) => {
|
||||
const selectedTheme = event.detail.theme === 'dark' ? darkTheme : lightTheme;
|
||||
setGiscusTheme(selectedTheme);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize Giscus when the window loads.
|
||||
window.addEventListener('load', () => {
|
||||
initGiscus();
|
||||
});
|
@ -0,0 +1 @@
|
||||
function setGiscusTheme(t){var e=document.querySelector("iframe.giscus-frame");e&&e.contentWindow.postMessage({giscus:{setConfig:{theme:t}}},"https://giscus.app")}function initGiscus(){var t=document.querySelector(".comments");if(t){var e=t.getAttribute("data-repo"),a=t.getAttribute("data-repo-id"),i=t.getAttribute("data-category"),r=t.getAttribute("data-category-id"),d=t.getAttribute("data-strict"),s=t.getAttribute("data-term"),u=t.getAttribute("data-reactions-enabled"),n=t.getAttribute("data-input-position");const b=t.getAttribute("data-light-theme"),A=t.getAttribute("data-dark-theme");var o=t.getAttribute("data-lang"),c=t.getAttribute("data-lazy-loading"),g=document.createElement("script"),e=(g.src="https://giscus.app/client.js",g.async=!0,g.setAttribute("data-repo",e),g.setAttribute("data-repo-id",a),g.setAttribute("data-category",i),g.setAttribute("data-category-id",r),g.setAttribute("data-term",s),g.setAttribute("data-strict",d),g.setAttribute("data-reactions-enabled",u),g.setAttribute("data-emit-metadata","0"),g.setAttribute("data-input-position",n),g.setAttribute("data-lang",o),g.setAttribute("crossorigin","anonymous"),t.getAttribute("data-mapping")),a=(e&&g.setAttribute("data-mapping",e),document.documentElement.getAttribute("data-theme")||"light"),i="dark"===a?A:b;g.setAttribute("data-theme",i),"true"===c&&g.setAttribute("data-loading","lazy"),t.appendChild(g),window.addEventListener("themeChanged",t=>{setGiscusTheme("dark"===t.detail.theme?A:b)})}}window.addEventListener("load",()=>{initGiscus()});
|
@ -1,37 +0,0 @@
|
||||
// Get the theme switcher button element.
|
||||
const themeSwitcher = document.querySelector(".theme-switcher");
|
||||
|
||||
// Retrieve theme from localStorage.
|
||||
let currentTheme = localStorage.getItem("theme");
|
||||
|
||||
// Function to switch between dark and light themes.
|
||||
function switchTheme() {
|
||||
// Set the new theme based on the current theme.
|
||||
currentTheme = currentTheme === "dark" ? "light" : "dark";
|
||||
document.documentElement.setAttribute("data-theme", currentTheme);
|
||||
localStorage.setItem("theme", currentTheme);
|
||||
|
||||
// Send a message to the Utterances iframe to change its theme.
|
||||
document.querySelectorAll(".utterances-frame").forEach((frame) => {
|
||||
frame.contentWindow.postMessage(
|
||||
{ type: 'set-theme', theme: `github-${currentTheme}` },
|
||||
'*'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize the theme switcher button.
|
||||
themeSwitcher.addEventListener("click", switchTheme, false);
|
||||
|
||||
// Update the theme based on system preference if the user hasn't manually changed the theme.
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", e => {
|
||||
if (!localStorage.getItem("theme")) {
|
||||
currentTheme = e.matches ? "dark" : "light";
|
||||
document.documentElement.setAttribute("data-theme", currentTheme);
|
||||
}
|
||||
});
|
||||
|
||||
// Fix the theme switcher button not working on the first click by updating currentTheme.
|
||||
if (!currentTheme) {
|
||||
currentTheme = document.documentElement.getAttribute("data-theme");
|
||||
}
|
@ -1 +0,0 @@
|
||||
const themeSwitcher=document.querySelector(".theme-switcher");let currentTheme=localStorage.getItem("theme");function switchTheme(){currentTheme="dark"===currentTheme?"light":"dark",document.documentElement.setAttribute("data-theme",currentTheme),localStorage.setItem("theme",currentTheme),document.querySelectorAll(".utterances-frame").forEach(e=>{e.contentWindow.postMessage({type:"set-theme",theme:`github-${currentTheme}`},"*")})}themeSwitcher.addEventListener("click",switchTheme,!1),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{localStorage.getItem("theme")||(currentTheme=e.matches?"dark":"light",document.documentElement.setAttribute("data-theme",currentTheme))}),currentTheme||(currentTheme=document.documentElement.getAttribute("data-theme"));
|
@ -0,0 +1,33 @@
|
||||
// Get the theme switcher button element.
|
||||
const themeSwitcher = document.querySelector(".theme-switcher");
|
||||
|
||||
// Retrieve theme from localStorage.
|
||||
let currentTheme = localStorage.getItem("theme");
|
||||
|
||||
// Function to switch between dark and light themes.
|
||||
function setTheme(theme) {
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
localStorage.setItem("theme", theme);
|
||||
|
||||
// Dispatch a custom event for utterances and giscus.
|
||||
const event = new CustomEvent("themeChanged", {
|
||||
detail: { theme: theme }
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function switchTheme() {
|
||||
// Set the new theme based on the current theme.
|
||||
const newTheme = currentTheme === "dark" ? "light" : "dark";
|
||||
setTheme(newTheme);
|
||||
}
|
||||
|
||||
themeSwitcher.addEventListener("click", switchTheme, false);
|
||||
|
||||
// Update the theme based on system preference if the user hasn't manually changed the theme.
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", e => {
|
||||
if (!localStorage.getItem("theme")) {
|
||||
const newTheme = e.matches ? "dark" : "light";
|
||||
setTheme(newTheme);
|
||||
}
|
||||
});
|
@ -0,0 +1,37 @@
|
||||
// Get the theme switcher button element.
|
||||
const themeSwitcher = document.querySelector(".theme-switcher");
|
||||
|
||||
// Retrieve theme from localStorage.
|
||||
let currentTheme = localStorage.getItem("theme");
|
||||
|
||||
// Function to set theme
|
||||
function setTheme(theme, saveToLocalStorage = false) {
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
currentTheme = theme;
|
||||
|
||||
if (saveToLocalStorage) {
|
||||
localStorage.setItem("theme", theme);
|
||||
}
|
||||
|
||||
// Dispatch a custom event for utterances and giscus.
|
||||
const event = new CustomEvent("themeChanged", {
|
||||
detail: { theme: theme }
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
// Function to switch between dark and light themes.
|
||||
function switchTheme() {
|
||||
// Set the new theme based on the current theme.
|
||||
const newTheme = currentTheme === "dark" ? "light" : "dark";
|
||||
setTheme(newTheme, true); // Save the theme to localStorage when the user changes it.
|
||||
}
|
||||
|
||||
// Initialize the theme switcher button.
|
||||
themeSwitcher.addEventListener("click", switchTheme, false);
|
||||
|
||||
// Update the theme based on system preference if the user hasn't manually changed the theme.
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", e => {
|
||||
const newTheme = e.matches ? "dark" : "light";
|
||||
setTheme(newTheme);
|
||||
});
|
@ -0,0 +1,64 @@
|
||||
function setUtterancesTheme(newTheme) {
|
||||
// Get the frame with class "utterances-frame".
|
||||
const frame = document.querySelector(".utterances-frame");
|
||||
|
||||
if (frame) {
|
||||
// If the iframe exists, send a message to set the theme.
|
||||
frame.contentWindow.postMessage(
|
||||
{ type: 'set-theme', theme: newTheme },
|
||||
'https://utteranc.es'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function initUtterances() {
|
||||
// Get the comments div.
|
||||
const commentsDiv = document.querySelector('.comments');
|
||||
|
||||
// Check if the comments div exists.
|
||||
if (commentsDiv) {
|
||||
// Get all necessary attributes for initializing Utterances.
|
||||
const repo = commentsDiv.getAttribute('data-repo');
|
||||
const issueTerm = commentsDiv.getAttribute('data-issue-term');
|
||||
const label = commentsDiv.getAttribute('data-label');
|
||||
const lightTheme = commentsDiv.getAttribute('data-light-theme');
|
||||
const darkTheme = commentsDiv.getAttribute('data-dark-theme');
|
||||
const lazyLoading = commentsDiv.getAttribute('data-lazy-loading');
|
||||
|
||||
// Create a new script element.
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://utteranc.es/client.js';
|
||||
script.async = true;
|
||||
script.setAttribute('repo', repo);
|
||||
script.setAttribute('issue-term', issueTerm);
|
||||
script.setAttribute('label', label);
|
||||
|
||||
// Set the initial theme.
|
||||
const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
|
||||
const selectedTheme = currentTheme === 'dark' ? darkTheme : lightTheme;
|
||||
script.setAttribute('theme', selectedTheme);
|
||||
|
||||
script.setAttribute('crossorigin', 'anonymous');
|
||||
|
||||
// Enable lazy loading if specified.
|
||||
if (lazyLoading === 'true') {
|
||||
script.setAttribute('data-loading', 'lazy');
|
||||
}
|
||||
|
||||
// Append the script to the comments div.
|
||||
commentsDiv.appendChild(script);
|
||||
|
||||
// Listen for themeChanged event to update the theme.
|
||||
window.addEventListener('themeChanged', (event) => {
|
||||
// Determine the new theme based on the event detail.
|
||||
const selectedTheme = event.detail.theme === 'dark' ? darkTheme : lightTheme;
|
||||
// Set the new theme.
|
||||
setUtterancesTheme(selectedTheme);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize Utterances once the window has loaded.
|
||||
window.addEventListener('load', () => {
|
||||
initUtterances();
|
||||
});
|
@ -0,0 +1 @@
|
||||
function setUtterancesTheme(t){const e=document.querySelector(".utterances-frame");e&&e.contentWindow.postMessage({type:"set-theme",theme:t},"https://utteranc.es")}function initUtterances(){const t=document.querySelector(".comments");if(t){var e=t.getAttribute("data-repo"),a=t.getAttribute("data-issue-term"),r=t.getAttribute("data-label");const s=t.getAttribute("data-light-theme"),d=t.getAttribute("data-dark-theme");var n=t.getAttribute("data-lazy-loading"),i=document.createElement("script"),e=(i.src="https://utteranc.es/client.js",i.async=!0,i.setAttribute("repo",e),i.setAttribute("issue-term",a),i.setAttribute("label",r),document.documentElement.getAttribute("data-theme")||"light"),a="dark"===e?d:s;i.setAttribute("theme",a),i.setAttribute("crossorigin","anonymous"),"true"===n&&i.setAttribute("data-loading","lazy"),t.appendChild(i),window.addEventListener("themeChanged",t=>{setUtterancesTheme("dark"===t.detail.theme?d:s)})}}window.addEventListener("load",()=>{initUtterances()});
|
@ -0,0 +1,64 @@
|
||||
{%- macro add_comments() -%}
|
||||
|
||||
{% set giscus_enabled = config.extra.giscus.enabled_for_all_posts or page.extra.giscus %}
|
||||
{% set utterances_enabled = config.extra.utterances.enabled_for_all_posts or page.extra.utterances %}
|
||||
|
||||
{# Ensure only one comment system is enabled #}
|
||||
{% if giscus_enabled and utterances_enabled %}
|
||||
{{ throw(message="ERROR: Multiple comment systems have been enabled for the same page. Check your config.toml and individual page settings to ensure only one comment system is activated at a time.") }}
|
||||
|
||||
{% elif giscus_enabled %}
|
||||
{# Create a div to host giscus comments #}
|
||||
<div class="comments"
|
||||
{# Store required giscus data attributes in the div #}
|
||||
data-repo="{{ config.extra.giscus.repo }}"
|
||||
data-repo-id="{{ config.extra.giscus.repo_id }}"
|
||||
data-category="{{ config.extra.giscus.category }}"
|
||||
data-category-id="{{ config.extra.giscus.category_id }}"
|
||||
{% if config.extra.giscus.mapping == "slug" %}
|
||||
data-mapping="specific"
|
||||
data-term="{{ page.slug }}"
|
||||
{% else %}
|
||||
data-mapping="{{ config.extra.giscus.mapping }}"
|
||||
{% endif %}
|
||||
data-strict="{{ config.extra.giscus.strict_title_matching }}"
|
||||
data-reactions-enabled="{{ config.extra.giscus.enable_reactions }}"
|
||||
{% if config.extra.giscus.comment_box_above_comments %}
|
||||
data-input-position="top"
|
||||
{% else %}
|
||||
data-input-position="bottom"
|
||||
{% endif %}
|
||||
data-light-theme="{{ config.extra.giscus.light_theme }}"
|
||||
data-dark-theme="{{ config.extra.giscus.dark_theme }}"
|
||||
{% if config.extra.giscus.lang %}
|
||||
data-lang="{{ config.extra.giscus.lang }}"
|
||||
{% else %}
|
||||
data-lang="{{ lang }}"
|
||||
{% endif %}
|
||||
data-lazy-loading="{{ config.extra.giscus.lazy_loading | default(value=true) }}">
|
||||
</div>
|
||||
|
||||
{# giscus script to load the widget #}
|
||||
<script src="{{ get_url(path='js/giscus_min.js', trailing_slash=false) | safe }}"/></script>
|
||||
|
||||
{% elif utterances_enabled %}
|
||||
{# Create a div to host utterances comments #}
|
||||
<div class="comments"
|
||||
{# Store required utterances data attributes in the div #}
|
||||
data-repo="{{ config.extra.utterances.repo }}"
|
||||
{% if config.extra.utterances.issue_term == "slug" %}
|
||||
data-issue-term="{{ page.slug }}"
|
||||
{% else %}
|
||||
data-issue-term="{{ config.extra.utterances.issue_term }}"
|
||||
{% endif %}
|
||||
data-label="{{ config.extra.utterances.label }}"
|
||||
data-light-theme="{{ config.extra.utterances.light_theme }}"
|
||||
data-dark-theme="{{ config.extra.utterances.dark_theme }}"
|
||||
data-lazy-loading="{{ config.extra.utterances.lazy_loading | default(value=true) }}">
|
||||
</div>
|
||||
|
||||
{# utterances script to load the widget #}
|
||||
<script src="{{ get_url(path='js/utterances_min.js', trailing_slash=false) | safe }}"/></script>
|
||||
{% endif %}
|
||||
|
||||
{%- endmacro add_comments -%}
|
Loading…
Reference in New Issue