Separate third party inline scripts (#241)

This commit is contained in:
2021-04-11 00:46:18 +08:00 committed by GitHub
parent 5c32efa7d3
commit a66b93036c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 873 additions and 548 deletions

View File

@ -553,6 +553,7 @@ quicklink:
# For more flexibility you can add some patterns (RegExp, Function, or Array) to ignores.
# See: https://github.com/GoogleChromeLabs/quicklink#custom-ignore-patterns
# This option is deprecated. Use `CONFIG.quicklink.ignores` in your custom scripts instead.
ignores:

View File

@ -4,7 +4,7 @@
{{ partial('_partials/head/head.njk', {}, {cache: theme.cache.enable}) }}
{%- include '_partials/head/head-unique.njk' -%}
<title>{% block title %}{% endblock %}</title>
{{- next_js('load-config.js', true) }}
{{- next_js('config.js') }}
{{- next_inject('head') }}
{{ partial('_third-party/analytics/index.njk', {}, {cache: theme.cache.enable}) }}
<noscript>
@ -45,15 +45,9 @@
{{ partial('_third-party/index.njk', {}, {cache: theme.cache.enable}) }}
{{ partial('_third-party/statistics/index.njk', {}, {cache: theme.cache.enable}) }}
{%- if theme.pjax %}
<div class="pjax">
{%- endif %}
{%- include '_third-party/math/index.njk' -%}
{%- include '_third-party/quicklink.njk' -%}
{{- next_inject('bodyEnd') }}
{%- if theme.pjax %}
</div>
{%- endif %}
</body>
</html>

View File

@ -9,15 +9,8 @@
{# Exports some front-matter variables to Front-End #}
{# https://hexo.io/docs/variables.html #}
<meta name="hexo-config-page" content="{{
{
sidebar: page.sidebar or '',
isHome : is_home(),
isPost : is_post(),
lang : page.lang
} | safedump | escape
}}">
<meta name="hexo-config-calendar" content="{{
theme.calendar | safedump | escape
if page.type === 'schedule' and not page.title
}}">
{{ next_data('page', next_config_unique()) }}
{{ next_data('calendar',
theme.calendar if page.type === 'schedule' and not page.title else '')
}}

View File

@ -53,4 +53,4 @@
<script src="{{ theme.vendors.nprogress_js }}"></script>
{%- endif %}
<meta name="hexo-config" content="{{ next_config() | safedump | escape }}">
{{ next_data('main', next_config()) }}

View File

@ -1,11 +1,4 @@
{%- if theme.baidu_analytics %}
<script{{ pjax }}>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?{{ theme.baidu_analytics }}";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
{{ next_js('third-party/analytics/baidu-analytics.js') }}
<script async src="https://hm.baidu.com/hm.js?{{ theme.baidu_analytics }}"></script>
{%- endif %}

View File

@ -1,30 +1,7 @@
{%- if theme.google_analytics.tracking_id %}
{%- if not theme.google_analytics.only_pageview %}
<script async src="https://www.googletagmanager.com/gtag/js?id={{ theme.google_analytics.tracking_id }}"></script>
<script{{ pjax }}>
if (CONFIG.hostname === location.hostname) {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ theme.google_analytics.tracking_id }}');
}
</script>
{%- else %}
<script>
function sendPageView() {
if (CONFIG.hostname !== location.hostname) return;
var uid = localStorage.getItem('uid') || (Math.random() + '.' + Math.random());
localStorage.setItem('uid', uid);
navigator.sendBeacon('https://www.google-analytics.com/collect', new URLSearchParams({
v : 1,
tid: '{{ theme.google_analytics.tracking_id }}',
cid: uid,
t : 'pageview',
dp : encodeURIComponent(location.pathname)
}));
}
document.addEventListener('pjax:complete', sendPageView);
sendPageView();
</script>
{%- endif %}
{{ next_data('google_analytics', theme.google_analytics) }}
{{ next_js('third-party/analytics/google-analytics.js') }}
{%- endif %}

View File

@ -1,7 +1,5 @@
{%- if theme.growingio_analytics %}
<script{{ pjax }}>
!function(e,t,n,g,i){e[i]=e[i]||function(){(e[i].q=e[i].q||[]).push(arguments)},n=t.createElement("script"),tag=t.getElementsByTagName("script")[0],n.async=1,n.src=('https:'==document.location.protocol?'https://':'http://')+g,tag.parentNode.insertBefore(n,tag)}(window,document,"script","assets.growingio.com/2.1/gio.js","gio");
gio('init', '{{ theme.growingio_analytics }}', {});
gio('send');
</script>
<script async src="//assets.growingio.com/2.1/gio.js"></script>
{{ next_data('growingio_analytics', theme.growingio_analytics) }}
{{ next_js('third-party/analytics/growingio.js') }}
{%- endif %}

View File

@ -1,22 +1,5 @@
{%- if theme.chatra.enable %}
{%- if theme.chatra.embed %}
<script>
window.ChatraSetup = {
mode : 'frame',
injectTo: '{{ theme.chatra.embed }}'
};
</script>
{%- endif %}
<script>
(function(d, w, c) {
w.ChatraID = '{{ theme.chatra.id }}';
var s = d.createElement('script');
w[c] = w[c] || function() {
(w[c].q = w[c].q || []).push(arguments);
};
s.async = {{ theme.chatra.async }};
s.src = 'https://call.chatra.io/chatra.js';
if (d.head) d.head.appendChild(s);
})(document, window, 'Chatra');
</script>
{{ next_data('chatra', theme.chatra) }}
{{ next_js('third-party/chat/chatra.js') }}
<script{{ ' async' if theme.chatra.async }} src="https://call.chatra.io/chatra.js"></script>
{%- endif %}

View File

@ -1,15 +1,2 @@
{%- if is_home() %}
<script id="cy_cmt_num" src="https://changyan.sohu.com/upload/plugins/plugins.list.count.js?clientId={{ theme.changyan.appid }}"></script>
{% elif page.comments %}
<script>
NexT.utils.loadComments('#SOHUCS', () => {
NexT.utils.getScript('https://changyan.sohu.com/upload/changyan.js', () => {
window.changyan.api.config({
appid: '{{ theme.changyan.appid }}',
conf : '{{ theme.changyan.appkey }}'
});
});
});
</script>
<script src="https://assets.changyan.sohu.com/upload/plugins/plugins.count.js"></script>
{%- endif %}
{{ next_data('changyan', theme.changyan) }}
{{ next_js('third-party/comments/changyan.js') }}

View File

@ -1,37 +1,6 @@
{%- if theme.disqus.count %}
<script>
function loadCount() {
var d = document, s = d.createElement('script');
s.src = 'https://{{ theme.disqus.shortname }}.disqus.com/count.js';
s.id = 'dsq-count-scr';
(d.head || d.body).appendChild(s);
{{ next_data('disqus', theme.disqus, {
i18n: {
disqus: __('disqus')
}
// defer loading until the whole page loading is completed
window.addEventListener('load', loadCount, false);
</script>
{%- endif %}
{%- if page.comments %}
<script>
var disqus_config = function() {
this.page.url = {{ page.permalink | safedump }};
this.page.identifier = {{ page.path | safedump }};
this.page.title = {{ page.title | safedump }};
{% if __('disqus') !== 'disqus' -%}
this.language = '{{ __('disqus') }}';
{% endif -%}
};
NexT.utils.loadComments('#disqus_thread', () => {
if (window.DISQUS) {
DISQUS.reset({
reload: true,
config: disqus_config
});
} else {
var d = document, s = d.createElement('script');
s.src = 'https://{{ theme.disqus.shortname }}.disqus.com/embed.js';
s.setAttribute('data-timestamp', '' + +new Date());
(d.head || d.body).appendChild(s);
}
});
</script>
{%- endif %}
}) }}
{{ next_js('third-party/comments/disqus.js') }}

View File

@ -1,18 +1,6 @@
{%- if page.comments %}
<link rel="stylesheet" href="{{ theme.vendors.disqusjs_css }}">
<script>
NexT.utils.loadComments('#disqus_thread', () => {
NexT.utils.getScript('{{ theme.vendors.disqusjs_js }}', () => {
window.dsqjs = new DisqusJS({
api : '{{ theme.disqusjs.api }}' || 'https://disqus.com/api/',
apikey : '{{ theme.disqusjs.apikey }}',
shortname : '{{ theme.disqusjs.shortname }}',
url : {{ page.permalink | safedump }},
identifier: {{ page.path | safedump }},
title : {{ page.title | safedump }},
});
}, window.DisqusJS);
});
</script>
{%- endif %}
{{ next_data('disqusjs', theme.disqusjs, {
js: theme.vendors.disqusjs_js
}) }}
{{ next_js('third-party/comments/disqusjs.js') }}

View File

@ -1,26 +1,7 @@
{%- if page.comments %}
<link rel="stylesheet" href="{{ theme.vendors.gitalk_css }}">
<script>
NexT.utils.loadComments('.gitalk-container', () => {
NexT.utils.getScript('{{ theme.vendors.gitalk_js }}', () => {
var gitalk = new Gitalk({
clientID : '{{ theme.gitalk.client_id }}',
clientSecret: '{{ theme.gitalk.client_secret }}',
repo : '{{ theme.gitalk.repo }}',
owner : '{{ theme.gitalk.github_id }}',
admin : ['{{ theme.gitalk.admin_user }}'],
id : '{{ gitalk_md5(page.path) }}',
proxy : '{{ theme.gitalk.proxy }}',
{%- if theme.gitalk.language == '' %}
language: window.navigator.language,
{% else %}
language: '{{ theme.gitalk.language }}',
{%- endif %}
distractionFreeMode: {{ theme.gitalk.distraction_free_mode }}
});
gitalk.render(document.querySelector('.gitalk-container'));
}, window.Gitalk);
});
</script>
{%- endif %}
{{ next_data('gitalk', theme.gitalk, {
js: theme.vendors.gitalk_js,
path_md5: gitalk_md5(page.path)
}) }}
{{ next_js('third-party/comments/gitalk.js') }}

View File

@ -1,10 +1,2 @@
{%- if page.comments %}
<script>
NexT.utils.loadComments('#isso-thread', () => {
const script = document.createElement('script');
script.src = '{{ theme.isso }}js/embed.min.js';
script.dataset.isso = '{{ theme.isso }}';
document.querySelector('#isso-thread').appendChild(script);
});
</script>
{%- endif %}
{{ next_data('isso', theme.isso) }}
{{ next_js('third-party/comments/isso.js') }}

View File

@ -1,17 +1 @@
{%- if page.comments %}
<script>
NexT.utils.loadComments('#lv-container', () => {
window.livereOptions = {
refer: {{ page.path | replace(r/index\.html$/, '') | safedump }}
};
(function(d, s) {
var j, e = d.getElementsByTagName(s)[0];
if (typeof LivereTower === 'function') { return; }
j = d.createElement(s);
j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
j.async = true;
e.parentNode.insertBefore(j, e);
})(document, 'script');
});
</script>
{%- endif %}
{{ next_js('third-party/comments/livere.js') }}

View File

@ -1,14 +1,2 @@
{%- if page.comments %}
<script>
NexT.utils.loadComments('.utterances-container', () => {
const script = document.createElement('script');
script.src = 'https://utteranc.es/client.js';
script.setAttribute('repo', {{ theme.utterances.repo | safedump }});
script.setAttribute('issue-term', {{ theme.utterances.issue_term | safedump }});
script.setAttribute('theme', {{ theme.utterances.theme | safedump }});
script.crossOrigin = 'anonymous';
script.async = true;
document.querySelector('.utterances-container').appendChild(script);
});
</script>
{%- endif %}
{{ next_data('utterances', theme.utterances) }}
{{ next_js('third-party/comments/utterances.js') }}

View File

@ -1,4 +1,6 @@
{%- if theme.math.mathjax.enable or theme.math.katex.enable %}
{%- set enable_math = false %}
{%- set is_index_has_math = false %}
{# At home, check if there has `mathjax: true` post #}
@ -11,10 +13,14 @@
{%- endif %}
{%- if theme.math.every_page or is_index_has_math or page.mathjax %}
{%- if theme.math.mathjax.enable %}
{%- include '_third-party/math/mathjax.njk' -%}
{% elif theme.math.katex.enable %}
{%- include '_third-party/math/katex.njk' -%}
{%- endif %}
{%- set enable_math = true %}
{%- endif %}
{{ next_data('enableMath', enable_math) }}
{%- if theme.math.mathjax.enable %}
{%- include '_third-party/math/mathjax.njk' -%}
{% elif theme.math.katex.enable %}
{%- include '_third-party/math/katex.njk' -%}
{%- endif %}
{%- endif %}

View File

@ -1,5 +1,8 @@
<link rel="stylesheet" href="{{ theme.vendors.katex }}">
{%- if theme.math.katex.copy_tex %}
<script src="{{ theme.vendors.copy_tex_js }}"></script>
<link rel="stylesheet" href="{{ theme.vendors.copy_tex_css }}">
{{ next_data('katex', {
copy_tex_js: theme.vendors.copy_tex_js
}) }}
{{ next_js('third-party/math/katex.js') }}
{%- endif %}

View File

@ -1,31 +1,4 @@
<script>
if (typeof MathJax === 'undefined') {
window.MathJax = {
tex: {
inlineMath: {'[+]': [['$', '$']]},
tags: '{{ theme.math.mathjax.tags }}'
},
options: {
renderActions: {
insertedScript: [200, () => {
document.querySelectorAll('mjx-container').forEach(node => {
const target = node.parentNode;
if (target.nodeName.toLowerCase() === 'li') {
target.parentNode.classList.add('has-jax');
}
});
}, '', false]
}
}
};
const script = document.createElement('script');
script.src = '{{ theme.vendors.mathjax }}';
script.defer = true;
document.head.appendChild(script);
} else {
MathJax.startup.document.state(0);
MathJax.typesetClear();
MathJax.texReset();
MathJax.typeset();
}
</script>
{{ next_data('mathjax', theme.math.mathjax, {
js: theme.vendors.mathjax
}) }}
{{ next_js('third-party/math/mathjax.js') }}

View File

@ -1,22 +1,4 @@
{%- if theme.nprogress.enable %}
<script>
NProgress.configure({
showSpinner: {{ theme.nprogress.spinner | safedump }}
});
NProgress.start();
document.addEventListener('readystatechange', () => {
if (document.readyState === 'interactive') {
NProgress.inc(0.8);
}
if (document.readyState === 'complete') {
NProgress.done();
}
});
document.addEventListener('pjax:send', () => {
NProgress.start();
});
document.addEventListener('pjax:success', () => {
NProgress.done();
});
</script>
{{ next_data('nprogress', theme.nprogress) }}
{{ next_js('third-party/nprogress.js') }}
{%- endif %}

View File

@ -1,16 +1,7 @@
{%- if page.quicklink.enable %}
{%- if theme.quicklink.enable %}
<script src="{{ theme.vendors.quicklink }}"></script>
<script>
{%- if page.quicklink.delay %}
window.addEventListener('load', () => {
{%- endif %}
quicklink.listen({
timeout : {{ page.quicklink.timeout }},
priority: {{ page.quicklink.priority }},
ignores : [uri => uri.includes('#'),uri => uri === '{{ url | replace(r/index\.html$/, '') }}',{{ page.quicklink.ignores }}]
});
{%- if page.quicklink.delay %}
});
{%- endif %}
</script>
{{ next_data('quicklink', page.quicklink, {
url: url | replace(r/index\.html$/, '')
}) }}
{{ next_js('third-party/quicklink.js') }}
{%- endif %}

View File

@ -1,22 +1,5 @@
{%- if theme.rating.enable %}
<script{{ pjax }}>
if (CONFIG.page.isPost) {
wpac_init = window.wpac_init || [];
wpac_init.push({
widget: 'Rating',
id : {{ theme.rating.id }},
el : 'wpac-rating',
color : '{{ theme.rating.color }}'
});
(function() {
if ('WIDGETPACK_LOADED' in window) return;
WIDGETPACK_LOADED = true;
var mc = document.createElement('script');
mc.type = 'text/javascript';
mc.async = true;
mc.src = '//embed.widgetpack.com/widget.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(mc, s.nextSibling);
})();
}
</script>
<script src="https://embed.widgetpack.com/widget.js" async></script>
{{ next_data('rating', theme.rating) }}
{{ next_js('third-party/rating.js') }}
{%- endif %}

View File

@ -1,4 +1,4 @@
<script src="{{ theme.vendors.algolia_search }}"></script>
<script src="{{ theme.vendors.instant_search }}"></script>
{{- next_js('algolia-search.js') }}
{{- next_js('third-party/search/algolia-search.js') }}

View File

@ -1 +1 @@
{{- next_js('local-search.js') }}
{{- next_js('third-party/search/local-search.js') }}

View File

@ -1,66 +1,6 @@
{%- if theme.firestore.enable %}
<script src="{{ theme.vendors.firebase_app }}"></script>
<script src="{{ theme.vendors.firebase_firestore }}"></script>
<script>
firebase.initializeApp({
apiKey : '{{ theme.firestore.apiKey }}',
projectId: '{{ theme.firestore.projectId }}'
});
function getCount(doc, increaseCount) {
// IncreaseCount will be false when not in article page
return doc.get().then(d => {
// Has no data, initialize count
let count = d.exists ? d.data().count : 0;
// If first view this article
if (increaseCount) {
// Increase count
count++;
doc.set({
count
});
}
return count;
});
}
function appendCountTo(el) {
return count => {
el.innerText = count;
};
}
</script>
<script{{ pjax }}>
(function() {
const db = firebase.firestore();
const articles = db.collection('{{ theme.firestore.collection }}');
if (CONFIG.page.isPost) {
// Fix issue #118
// https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
const title = document.querySelector('.post-title').textContent.trim();
const doc = articles.doc(title);
let increaseCount = CONFIG.hostname === location.hostname;
if (localStorage.getItem(title)) {
increaseCount = false;
} else {
// Mark as visited
localStorage.setItem(title, true);
}
getCount(doc, increaseCount).then(appendCountTo(document.querySelector('.firestore-visitors-count')));
} else if (CONFIG.page.isHome) {
const promises = [...document.querySelectorAll('.post-title')].map(element => {
const title = element.textContent.trim();
const doc = articles.doc(title);
return getCount(doc);
});
Promise.all(promises).then(counts => {
const metas = document.querySelectorAll('.firestore-visitors-count');
counts.forEach((val, idx) => {
appendCountTo(metas[idx])(val);
});
});
}
})();
</script>
{{ next_data('firestore', theme.firestore) }}
{{ next_js('third-party/statistics/firestore.js') }}
{%- endif %}

View File

@ -1,99 +1,4 @@
{%- if theme.leancloud_visitors.enable %}
<script{{ pjax }}>
(function() {
function leancloudSelector(url) {
url = encodeURI(url);
return document.getElementById(url).querySelector('.leancloud-visitors-count');
}
function addCount(Counter) {
const visitors = document.querySelector('.leancloud_visitors');
const url = decodeURI(visitors.id);
const title = visitors.dataset.flagTitle;
Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({ url })))
.then(response => response.json())
.then(({ results }) => {
if (results.length > 0) {
const counter = results[0];
leancloudSelector(url).innerText = counter.time + 1;
Counter('put', '/classes/Counter/' + counter.objectId, { time: { '__op': 'Increment', 'amount': 1 } })
.catch(error => {
console.error('Failed to save visitor count', error);
});
} else {
{%- if theme.leancloud_visitors.security %}
leancloudSelector(url).innerText = 'Counter not initialized! More info at console err msg.';
console.error('ATTENTION! LeanCloud counter has security bug, see how to solve it here: https://github.com/theme-next/hexo-leancloud-counter-security. \n However, you can still use LeanCloud without security, by setting `security` option to `false`.');
{% else %}
Counter('post', '/classes/Counter', { title, url, time: 1 })
.then(response => response.json())
.then(() => {
leancloudSelector(url).innerText = 1;
})
.catch(error => {
console.error('Failed to create', error);
});
{%- endif %}
}
})
.catch(error => {
console.error('LeanCloud Counter Error', error);
});
}
function showTime(Counter) {
const visitors = document.querySelectorAll('.leancloud_visitors');
const entries = [...visitors].map(element => {
return decodeURI(element.id);
});
Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({ url: { '$in': entries } })))
.then(response => response.json())
.then(({ results }) => {
for (let url of entries) {
const target = results.find(item => item.url === url);
leancloudSelector(url).innerText = target ? target.time : 0;
}
})
.catch(error => {
console.error('LeanCloud Counter Error', error);
});
}
const { app_id, app_key, server_url } = {{ theme.leancloud_visitors | safedump }};
function fetchData(api_server) {
const Counter = (method, url, data) => {
return fetch(`${api_server}/1.1${url}`, {
method,
headers: {
'X-LC-Id' : app_id,
'X-LC-Key' : app_key,
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
};
if (CONFIG.page.isPost) {
if (CONFIG.hostname !== location.hostname) return;
addCount(Counter);
} else if (document.querySelectorAll('.post-title-link').length >= 1) {
showTime(Counter);
}
}
const api_server = app_id.slice(-9) === '-MdYXbMMI' ? `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com` : server_url;
if (api_server) {
fetchData(api_server);
} else {
fetch('https://app-router.leancloud.cn/2/route?appId=' + app_id)
.then(response => response.json())
.then(({ api_server }) => {
fetchData('https://' + api_server);
});
}
})();
</script>
{{ next_data('leancloud_visitors', theme.leancloud_visitors) }}
{{ next_js('third-party/statistics/lean-analytics.js') }}
{%- endif %}

View File

@ -1,23 +1,6 @@
{%- if theme.mermaid.enable %}
<script{{ pjax }}>
var mermaidElements = document.querySelectorAll('.mermaid');
if (mermaidElements.length) {
NexT.utils.getScript('{{ theme.vendors.mermaid }}', () => {
mermaidElements.forEach(element => {
const newElement = document.createElement('div');
newElement.innerHTML = element.innerHTML;
newElement.className = element.className;
element.parentNode.replaceChild(newElement, element);
});
mermaid.init({
theme : '{{ theme.mermaid.theme }}',
logLevel : 3,
flowchart: { curve : 'linear' },
gantt : { axisFormat: '%m/%d/%Y' },
sequence : { actorMargin: 50 }
}, '.mermaid');
}, window.mermaid);
}
</script>
{{ next_data('mermaid', theme.mermaid, {
js: theme.vendors.mermaid
}) }}
{{ next_js('third-party/tags/mermaid.js') }}
{%- endif %}

View File

@ -1,23 +1,7 @@
{%- if theme.pdf.enable %}
{%- set pdfobject_uri = theme.vendors.pdfobject %}
{%- set pdf_uri = url_for('lib/pdf/web/viewer.html') %}
<script{{ pjax }}>
if (document.querySelectorAll('.pdf-container').length) {
NexT.utils.getScript('{{ pdfobject_uri }}', () => {
document.querySelectorAll('.pdf-container').forEach(element => {
PDFObject.embed(element.dataset.target, element, {
pdfOpenParams: {
navpanes : 0,
toolbar : 0,
statusbar: 0,
pagemode : 'thumbs',
view : 'FitH'
},
PDFJS_URL: '{{ pdf_uri }}',
height : element.dataset.height
});
});
}, window.PDFObject);
}
</script>
{{ next_data('pdf', {
object_url: theme.vendors.pdfobject,
url: url_for('lib/pdf/web/viewer.html')
}) }}
{{ next_js('third-party/tags/pdf.js') }}
{%- endif %}

View File

@ -18,14 +18,6 @@ hexo.extend.filter.register('after_generate', () => {
hexo.route.remove('js/motion.js');
}
if (!theme.algolia_search.enable) {
hexo.route.remove('js/algolia-search.js');
}
if (!theme.local_search.enable) {
hexo.route.remove('js/local-search.js');
}
if (!theme.pjax) {
hexo.route.remove('js/pjax.js');
}
@ -37,4 +29,101 @@ hexo.extend.filter.register('after_generate', () => {
if (theme.scheme === 'Pisces' || theme.scheme === 'Gemini') {
hexo.route.remove('js/schemes/muse.js');
}
// Third Party Scripts
// Analytics
if (!theme.baidu_analytics) {
hexo.route.remove('js/third-party/analytics/baidu-analytics.js');
}
if (!theme.google_analytics.tracking_id) {
hexo.route.remove('js/third-party/analytics/google-analytics.js');
}
if (!theme.growingio_analytics) {
hexo.route.remove('js/third-party/analytics/growingio.js');
}
// Chat
if (!theme.chatra.enable) {
hexo.route.remove('js/third-party/chat/chatra.js');
}
// Comments
if (!theme.changyan.enable || !theme.changyan.appid || !theme.changyan.appkey) {
hexo.route.remove('js/third-party/comments/changyan.js');
}
if (!theme.disqus.enable || !theme.disqus.shortname) {
hexo.route.remove('js/third-party/comments/disqus.js');
}
if (!theme.disqusjs.enable || !theme.disqusjs.shortname || !theme.disqusjs.apikey) {
hexo.route.remove('js/third-party/comments/disqusjs.js');
}
if (!theme.gitalk.enable) {
hexo.route.remove('js/third-party/comments/gitalk.js');
}
if (!theme.isso) {
hexo.route.remove('js/third-party/comments/isso.js');
}
if (!theme.livere_uid) {
hexo.route.remove('js/third-party/comments/livere.js');
}
if (!theme.utterances.enable || !theme.utterances.repo) {
hexo.route.remove('js/third-party/comments/utterances.js');
}
// Math
if (!theme.math.katex.enable || !theme.math.katex.copy_tex) {
hexo.route.remove('js/third-party/math/katex.js');
}
if (!theme.math.mathjax.enable) {
hexo.route.remove('js/third-party/math/mathjax.js');
}
// Search
if (!theme.algolia_search.enable) {
hexo.route.remove('js/third-party/search/algolia-search.js');
}
if (!theme.local_search.enable) {
hexo.route.remove('js/third-party/search/local-search.js');
}
// Statistics
if (!theme.firestore.enable) {
hexo.route.remove('js/third-party/statistics/firestore.js');
}
if (!theme.leancloud_visitors.enable) {
hexo.route.remove('js/third-party/statistics/lean-analytics.js');
}
// Tags
if (!theme.mermaid.enable) {
hexo.route.remove('js/third-party/tags/mermaid.js');
}
if (!theme.pdf.enable) {
hexo.route.remove('js/third-party/tags/pdf.js');
}
// Others
if (!theme.nprogress.enable) {
hexo.route.remove('js/third-party/nprogress.js');
}
if (!theme.quicklink.enable) {
hexo.route.remove('js/third-party/quicklink.js');
}
if (!theme.rating.enable) {
hexo.route.remove('js/third-party/rating.js');
}
});

View File

@ -29,6 +29,14 @@ hexo.extend.helper.register('next_js', function(file, pjax = false) {
return `<script ${pjax ? 'data-pjax ' : ''}src="${src}"></script>`;
});
hexo.extend.helper.register('next_data', function(name, ...data) {
const { escape_html } = this;
const json = data.length === 1 ? data[0] : Object.assign({}, ...data);
return `<script class="next-config" data-name="${name}" type="application/json">${
escape_html(JSON.stringify(json))
}</script>`;
});
hexo.extend.helper.register('next_pre', function() {
const { preconnect } = this.theme;
if (!preconnect) return '';

View File

@ -47,3 +47,17 @@ hexo.extend.helper.register('next_config', function() {
}
return exportConfig;
});
hexo.extend.helper.register('next_config_unique', function() {
const { page, is_home, is_post } = this;
return {
sidebar : page.sidebar || '',
isHome : is_home(),
isPost : is_post(),
lang : page.lang,
comments : page.comments || '',
permalink: page.permalink || '',
path : page.path || '',
title : page.title || ''
};
});

60
source/js/config.js Normal file
View File

@ -0,0 +1,60 @@
if (!window.NexT) window.NexT = {};
(function() {
const className = 'next-config';
const staticConfig = {};
let variableConfig = {};
const parse = (text) => {
const jsonString = new DOMParser()
.parseFromString(text, 'text/html').documentElement
.textContent;
return JSON.parse(jsonString || '{}');
};
const update = (name) => {
const targetEle = document.querySelector(`.${className}[data-name="${name}"]`);
if (!targetEle) return;
const parsedConfig = parse(targetEle.text);
if (name === 'main') {
Object.assign(staticConfig, parsedConfig);
} else {
variableConfig[name] = parsedConfig;
}
};
update('main');
window.CONFIG = new Proxy({}, {
get(overrideConfig, name) {
let existing;
if (name in staticConfig) {
existing = staticConfig[name];
} else {
if (!(name in variableConfig)) update(name);
existing = variableConfig[name];
}
let override = overrideConfig[name];
if (override === undefined && typeof existing === 'object') {
override = {};
overrideConfig[name] = override;
}
if (typeof override === 'object') {
return new Proxy({...existing, ...override}, {
set(target, prop, value) {
override[prop] = value;
return true;
}
});
}
return existing;
}
});
document.addEventListener('pjax:success', () => {
variableConfig = {};
});
})();

View File

@ -1,15 +0,0 @@
if (!window.NexT) window.NexT = {};
if (!window.CONFIG) {
window.CONFIG = JSON.parse(
document.querySelector('meta[name="hexo-config"]').content || '{}'
);
}
(() => {
document.querySelectorAll('meta[name^="hexo-config-"]')
.forEach(configMeta => {
const key = configMeta.name.slice('hexo-config-'.length);
window.CONFIG[key] = JSON.parse(configMeta.content || '{}');
});
})();

View File

@ -3,7 +3,7 @@
const pjax = new Pjax({
selectors: [
'head title',
'head meta[name^="hexo-config-"]',
'script[type="application/json"]',
'.main-inner',
'.post-toc-wrap',
'.languages',
@ -16,7 +16,7 @@ const pjax = new Pjax({
});
document.addEventListener('pjax:success', () => {
pjax.executeScripts(document.querySelectorAll('script[data-pjax], .pjax script'));
pjax.executeScripts(document.querySelectorAll('script[data-pjax]'));
NexT.boot.refresh();
// Define Motion Sequence & Bootstrap Motion.
if (CONFIG.motion.enable) {

View File

@ -0,0 +1,7 @@
/* global _hmt */
if (!window._hmt) window._hmt = [];
document.addEventListener('pjax:success', () => {
_hmt.push(['_trackPageview', location.pathname]);
});

View File

@ -0,0 +1,35 @@
/* global CONFIG, dataLayer, gtag */
if (!CONFIG.google_analytics.only_pageview) {
if (CONFIG.hostname === location.hostname) {
window.dataLayer = window.dataLayer || [];
window.gtag = function() {
dataLayer.push(arguments);
};
gtag('js', new Date());
gtag('config', CONFIG.google_analytics.tracking_id);
document.addEventListener('pjax:success', () => {
gtag('event', 'page_view', {
page_location: location.href,
page_path : location.pathname,
page_title : document.title
});
});
}
} else {
const sendPageView = () => {
if (CONFIG.hostname !== location.hostname) return;
const uid = localStorage.getItem('uid') || (Math.random() + '.' + Math.random());
localStorage.setItem('uid', uid);
navigator.sendBeacon('https://www.google-analytics.com/collect', new URLSearchParams({
v : 1,
tid: CONFIG.google_analytics.tracking_id,
cid: uid,
t : 'pageview',
dp : encodeURIComponent(location.pathname)
}));
};
document.addEventListener('pjax:complete', sendPageView);
sendPageView();
}

View File

@ -0,0 +1,10 @@
/* global CONFIG, gio */
if (!window.gio) {
window.gio = function() {
(window.gio.q = window.gio.q || []).push(arguments);
};
}
gio('init', `${CONFIG.growingio_analytics}`, {});
gio('send');

10
source/js/third-party/chat/chatra.js vendored Normal file
View File

@ -0,0 +1,10 @@
/* global CONFIG */
if (CONFIG.chatra.embed) {
window.ChatraSetup = {
mode : 'frame',
injectTo: CONFIG.chatra.embed
};
}
window.ChatraID = CONFIG.chatra.id;

View File

@ -0,0 +1,20 @@
/* global NexT, CONFIG */
document.addEventListener('page:loaded', () => {
if (CONFIG.page.isHome) {
NexT.utils.getScript(
`https://changyan.sohu.com/upload/plugins/plugins.list.count.js?clientId=${CONFIG.changyan.appid}`,
{ attributes: {id: 'cy_cmt_num' } }
);
} else if (CONFIG.page.comments) {
NexT.utils.loadComments('#SOHUCS')
.then(() => NexT.utils.getScript('https://changyan.sohu.com/upload/changyan.js'))
.then(() => {
window.changyan.api.config({
appid: CONFIG.changyan.appid,
conf : CONFIG.changyan.appkey
});
});
NexT.utils.getScript('https://assets.changyan.sohu.com/upload/plugins/plugins.count.js');
}
});

View File

@ -0,0 +1,39 @@
/* global NexT, CONFIG, DISQUS */
document.addEventListener('page:loaded', () => {
if (CONFIG.disqus.count) {
const loadCount = () => {
NexT.utils.getScript(`https://${CONFIG.disqus.shortname}.disqus.com/count.js`, {
attributes: { id: 'dsq-count-scr' }
});
};
// defer loading until the whole page loading is completed
window.addEventListener('load', loadCount, false);
}
if (CONFIG.page.comments) {
const disqus_config = function() {
this.page.url = CONFIG.page.permalink;
this.page.identifier = CONFIG.page.path;
this.page.title = CONFIG.page.title;
if (CONFIG.disqus.i18n.disqus !== 'disqus') {
this.language = CONFIG.disqus.i18n.disqus;
}
};
NexT.utils.loadComments('#disqus_thread').then(() => {
if (window.DISQUS) {
DISQUS.reset({
reload: true,
config: disqus_config
});
} else {
NexT.utils.getScript(`https://${CONFIG.disqus.shortname}.disqus.com/embed.js`, {
attributes: { dataset: { timestamp: '' + +new Date() } }
});
}
});
}
});

View File

@ -0,0 +1,18 @@
/* global NexT, CONFIG, DisqusJS */
document.addEventListener('page:loaded', () => {
if (!CONFIG.page.comments) return;
NexT.utils.loadComments('#disqus_thread')
.then(() => NexT.utils.getScript(CONFIG.disqusjs.js, { condition: window.DisqusJS }))
.then(() => {
window.dsqjs = new DisqusJS({
api : CONFIG.disqusjs.api || 'https://disqus.com/api/',
apikey : CONFIG.disqusjs.apikey,
shortname : CONFIG.disqusjs.shortname,
url : CONFIG.page.permalink,
identifier: CONFIG.page.path,
title : CONFIG.page.title
});
});
});

View File

@ -0,0 +1,24 @@
/* global NexT, CONFIG, Gitalk */
document.addEventListener('page:loaded', () => {
if (!CONFIG.page.comments) return;
NexT.utils.loadComments('.gitalk-container')
.then(() => NexT.utils.getScript(CONFIG.gitalk.js, {
condition: window.Gitalk
}))
.then(() => {
const gitalk = new Gitalk({
clientID : CONFIG.gitalk.client_id,
clientSecret : CONFIG.gitalk.client_secret,
repo : CONFIG.gitalk.repo,
owner : CONFIG.gitalk.github_id,
admin : [CONFIG.gitalk.admin_user],
id : CONFIG.gitalk.path_md5,
proxy : CONFIG.gitalk.proxy,
language : CONFIG.gitalk.language || window.navigator.language,
distractionFreeMode: CONFIG.gitalk.distraction_free_mode
});
gitalk.render(document.querySelector('.gitalk-container'));
});
});

15
source/js/third-party/comments/isso.js vendored Normal file
View File

@ -0,0 +1,15 @@
/* global NexT, CONFIG */
document.addEventListener('page:loaded', () => {
if (!CONFIG.page.comments) return;
NexT.utils.loadComments('#isso-thread')
.then(() => NexT.utils.getScript(`${CONFIG.isso}js/embed.min.js`, {
attributes: {
dataset: {
isso: `${CONFIG.isso}`
}
},
parentNode: document.querySelector('#isso-thread')
}));
});

View File

@ -0,0 +1,19 @@
/* global NexT, CONFIG, LivereTower */
document.addEventListener('page:loaded', () => {
if (!CONFIG.page.comments) return;
NexT.utils.loadComments('#lv-container').then(() => {
window.livereOptions = {
refer: CONFIG.page.path.replace(/index\.html$/, '')
};
if (typeof LivereTower === 'function') return;
NexT.utils.getScript('https://cdn-city.livere.com/js/embed.dist.js', {
attributes: {
async: true
}
});
});
});

View File

@ -0,0 +1,17 @@
/* global NexT, CONFIG */
document.addEventListener('page:loaded', () => {
if (!CONFIG.page.comments) return;
NexT.utils.loadComments('.utterances-container')
.then(() => NexT.utils.getScript('https://utteranc.es/client.js', {
attributes: {
async : true,
crossOrigin : 'anonymous',
'repo' : CONFIG.utterances.repo,
'issue-term': CONFIG.utterances.issue_term,
'theme' : CONFIG.utterances.theme
},
parentNode: document.querySelector('.utterances-container')
}));
});

7
source/js/third-party/math/katex.js vendored Normal file
View File

@ -0,0 +1,7 @@
/* global NexT, CONFIG */
document.addEventListener('page:loaded', () => {
if (!CONFIG.enableMath) return;
NexT.utils.getScript(CONFIG.katex.copy_tex_js).catch(() => {});
});

36
source/js/third-party/math/mathjax.js vendored Normal file
View File

@ -0,0 +1,36 @@
/* global NexT, CONFIG, MathJax */
document.addEventListener('page:loaded', () => {
if (!CONFIG.enableMath) return;
if (typeof MathJax === 'undefined') {
window.MathJax = {
tex: {
inlineMath: {'[+]': [['$', '$']]},
tags : CONFIG.mathjax.tags
},
options: {
renderActions: {
insertedScript: [200, () => {
document.querySelectorAll('mjx-container').forEach(node => {
const target = node.parentNode;
if (target.nodeName.toLowerCase() === 'li') {
target.parentNode.classList.add('has-jax');
}
});
}, '', false]
}
}
};
NexT.utils.getScript(CONFIG.mathjax.js, {
attributes: {
defer: true
}
});
} else {
MathJax.startup.document.state(0);
MathJax.typesetClear();
MathJax.texReset();
MathJax.typeset();
}
});

20
source/js/third-party/nprogress.js vendored Normal file
View File

@ -0,0 +1,20 @@
/* global CONFIG, NProgress */
NProgress.configure({
showSpinner: CONFIG.nprogress.spinner
});
NProgress.start();
document.addEventListener('readystatechange', () => {
if (document.readyState === 'interactive') {
NProgress.inc(0.8);
}
if (document.readyState === 'complete') {
NProgress.done();
}
});
document.addEventListener('pjax:send', () => {
NProgress.start();
});
document.addEventListener('pjax:success', () => {
NProgress.done();
});

44
source/js/third-party/quicklink.js vendored Normal file
View File

@ -0,0 +1,44 @@
/* global CONFIG, quicklink */
(function() {
if (typeof CONFIG.quicklink.ignores === 'string') {
const ignoresStr = `[${CONFIG.quicklink.ignores}]`;
try {
CONFIG.quicklink.ignores = JSON.parse(ignoresStr);
} catch {
// eslint-disable-next-line no-console
console.error('Setting regex and function in config file is deprecated. Try setting `CONFIG.quicklink.ignores` in any script code.');
// eslint-disable-next-line no-eval
CONFIG.quicklink.ignores = eval(ignoresStr);
}
}
let resetFn = null;
const onRefresh = () => {
if (resetFn) resetFn();
if (!CONFIG.quicklink.enable) return;
let ignoresArr = CONFIG.quicklink.ignores || [];
if (!Array.isArray(ignoresArr)) {
ignoresArr = [ignoresArr];
}
resetFn = quicklink.listen({
timeout : CONFIG.quicklink.timeout,
priority: CONFIG.quicklink.priority,
ignores : [
uri => uri.includes('#'),
uri => uri === CONFIG.quicklink.url,
...ignoresArr
]
});
};
if (CONFIG.quicklink.delay) {
window.addEventListener('load', onRefresh);
document.addEventListener('pjax:success', onRefresh);
} else {
document.addEventListener('page:loaded', onRefresh);
}
})();

22
source/js/third-party/rating.js vendored Normal file
View File

@ -0,0 +1,22 @@
/* global CONFIG, WPac */
(function() {
const widgets = [{
widget: 'Rating',
id : CONFIG.rating.id,
el : 'wpac-rating',
color : CONFIG.rating.color
}];
document.addEventListener('page:loaded', () => {
if (!CONFIG.page.isPost) return;
const newWidgets = widgets.map(widget => ({...widget}));
if (window.WPac) {
WPac.init(newWidgets);
} else {
window.wpac_init = newWidgets;
}
});
})();

View File

@ -0,0 +1,63 @@
/* global CONFIG, firebase */
firebase.initializeApp({
apiKey : CONFIG.firestore.apiKey,
projectId: CONFIG.firestore.projectId
});
(function() {
const getCount = (doc, increaseCount) => {
// IncreaseCount will be false when not in article page
return doc.get().then(d => {
// Has no data, initialize count
let count = d.exists ? d.data().count : 0;
// If first view this article
if (increaseCount) {
// Increase count
count++;
doc.set({
count
});
}
return count;
});
};
const appendCountTo = (el) => {
return count => {
el.innerText = count;
};
};
document.addEventListener('page:loaded', () => {
const db = firebase.firestore();
const articles = db.collection(CONFIG.firestore.collection);
if (CONFIG.page.isPost) {
// Fix issue #118
// https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
const title = document.querySelector('.post-title').textContent.trim();
const doc = articles.doc(title);
let increaseCount = CONFIG.hostname === location.hostname;
if (localStorage.getItem(title)) {
increaseCount = false;
} else {
// Mark as visited
localStorage.setItem(title, true);
}
getCount(doc, increaseCount).then(appendCountTo(document.querySelector('.firestore-visitors-count')));
} else if (CONFIG.page.isHome) {
const promises = [...document.querySelectorAll('.post-title')].map(element => {
const title = element.textContent.trim();
const doc = articles.doc(title);
return getCount(doc);
});
Promise.all(promises).then(counts => {
const metas = document.querySelectorAll('.firestore-visitors-count');
counts.forEach((val, idx) => {
appendCountTo(metas[idx])(val);
});
});
}
});
})();

View File

@ -0,0 +1,102 @@
/* global CONFIG */
/* eslint-disable no-console */
(function() {
const leancloudSelector = (url) => {
url = encodeURI(url);
return document.getElementById(url).querySelector('.leancloud-visitors-count');
};
const addCount = (Counter) => {
const visitors = document.querySelector('.leancloud_visitors');
const url = decodeURI(visitors.id);
const title = visitors.dataset.flagTitle;
Counter('get', `/classes/Counter?where=${encodeURIComponent(JSON.stringify({url}))}`)
.then(response => response.json())
.then(({results}) => {
if (results.length > 0) {
const counter = results[0];
leancloudSelector(url).innerText = counter.time + 1;
Counter('put', '/classes/Counter/' + counter.objectId, {
time: {
'__op' : 'Increment',
'amount': 1
}
})
.catch(error => {
console.error('Failed to save visitor count', error);
});
} else if (CONFIG.leancloud_visitors.security) {
leancloudSelector(url).innerText = 'Counter not initialized! More info at console err msg.';
console.error('ATTENTION! LeanCloud counter has security bug, see how to solve it here: https://github.com/theme-next/hexo-leancloud-counter-security. \n However, you can still use LeanCloud without security, by setting `security` option to `false`.');
} else {
Counter('post', '/classes/Counter', {title, url, time: 1})
.then(response => response.json())
.then(() => {
leancloudSelector(url).innerText = 1;
})
.catch(error => {
console.error('Failed to create', error);
});
}
})
.catch(error => {
console.error('LeanCloud Counter Error', error);
});
};
const showTime = (Counter) => {
const visitors = document.querySelectorAll('.leancloud_visitors');
const entries = [...visitors].map(element => {
return decodeURI(element.id);
});
Counter('get', `/classes/Counter?where=${encodeURIComponent(JSON.stringify({url: {'$in': entries}}))}`)
.then(response => response.json())
.then(({results}) => {
for (const url of entries) {
const target = results.find(item => item.url === url);
leancloudSelector(url).innerText = target ? target.time : 0;
}
})
.catch(error => {
console.error('LeanCloud Counter Error', error);
});
};
const {app_id, app_key, server_url} = CONFIG.leancloud_visitors;
const fetchData = (api_server) => {
const Counter = (method, url, data) => {
return fetch(`${api_server}/1.1${url}`, {
method,
headers: {
'X-LC-Id' : app_id,
'X-LC-Key' : app_key,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
};
if (CONFIG.page.isPost) {
if (CONFIG.hostname !== location.hostname) return;
addCount(Counter);
} else if (document.querySelectorAll('.post-title-link').length >= 1) {
showTime(Counter);
}
};
const api_server = app_id.slice(-9) === '-MdYXbMMI' ? `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com` : server_url;
document.addEventListener('page:loaded', () => {
if (api_server) {
fetchData(api_server);
} else {
fetch(`https://app-router.leancloud.cn/2/route?appId=${app_id}`)
.then(response => response.json())
.then(({api_server}) => {
fetchData(`https://${api_server}`);
});
}
});
})();

25
source/js/third-party/tags/mermaid.js vendored Normal file
View File

@ -0,0 +1,25 @@
/* global NexT, CONFIG, mermaid */
document.addEventListener('page:loaded', () => {
const mermaidElements = document.querySelectorAll('.mermaid');
if (mermaidElements.length) {
NexT.utils.getScript(CONFIG.mermaid.js, {
condition: window.mermaid
}).then(() => {
mermaidElements.forEach(element => {
const newElement = document.createElement('div');
newElement.innerHTML = element.innerHTML;
newElement.className = element.className;
element.parentNode.replaceChild(newElement, element);
});
mermaid.init({
theme : CONFIG.mermaid.theme,
logLevel : 3,
flowchart: {curve: 'linear'},
gantt : {axisFormat: '%m/%d/%Y'},
sequence : {actorMargin: 50}
}, '.mermaid');
});
}
});

23
source/js/third-party/tags/pdf.js vendored Normal file
View File

@ -0,0 +1,23 @@
/* global NexT, CONFIG, PDFObject */
document.addEventListener('page:loaded', () => {
if (document.querySelectorAll('.pdf-container').length) {
NexT.utils.getScript(CONFIG.pdf.object_url, {
condition: window.PDFObject
}).then(() => {
document.querySelectorAll('.pdf-container').forEach(element => {
PDFObject.embed(element.dataset.target, element, {
pdfOpenParams: {
navpanes : 0,
toolbar : 0,
statusbar: 0,
pagemode : 'thumbs',
view : 'FitH'
},
PDFJS_URL: CONFIG.pdf.url,
height : element.dataset.height
});
});
});
}
});

View File

@ -14,6 +14,21 @@ if (typeof DOMTokenList.prototype.replace !== 'function') {
};
}
(function() {
const onPageLoaded = () => document.dispatchEvent(
new Event('page:loaded', {
bubbles: true
})
);
if (document.readyState === 'loading') {
document.addEventListener('readystatechange', onPageLoaded, {once: true});
} else {
onPageLoaded();
}
document.addEventListener('pjax:success', onPageLoaded);
})();
NexT.utils = {
/**
@ -72,7 +87,7 @@ NexT.utils = {
*/
registerCopyCode: function() {
let figure = document.querySelectorAll('figure.highlight');
if (figure.length === 0) figure = document.querySelectorAll('pre');
if (figure.length === 0) figure = document.querySelectorAll('pre:not(.mermaid)');
figure.forEach(element => {
element.querySelectorAll('.code .line span').forEach(span => {
span.classList.forEach(name => {
@ -322,33 +337,53 @@ NexT.utils = {
}
},
getScript: function(url, callback, condition) {
getScript: (url, {
condition = false,
attributes: {
id = '',
async = false,
defer = false,
crossOrigin = '',
dataset = {},
...otherAttributes
} = {},
parentNode = null
} = {}) => new Promise((resolve, reject) => {
if (condition) {
callback();
resolve();
} else {
const script = document.createElement('script');
script.onload = () => {
setTimeout(callback);
};
script.src = url;
document.head.appendChild(script);
}
},
loadComments: function(selector, callback) {
if (id) script.id = id;
if (crossOrigin) script.crossOrigin = crossOrigin;
script.async = async;
script.defer = defer;
Object.assign(script.dataset, dataset);
Object.entries(otherAttributes).forEach(([name, value]) => {
script.setAttribute(name, String(value));
});
script.onload = resolve;
script.onerror = reject;
script.src = url;
(parentNode || document.head).appendChild(script);
}
}),
loadComments: (selector) => new Promise((resolve) => {
const element = document.querySelector(selector);
if (!CONFIG.comments.lazyload || !element) {
callback();
resolve();
return;
}
const intersectionObserver = new IntersectionObserver((entries, observer) => {
const entry = entries[0];
if (entry.isIntersecting) {
callback();
observer.disconnect();
}
if (!entry.isIntersecting) return;
resolve();
observer.disconnect();
});
intersectionObserver.observe(element);
return intersectionObserver;
}
})
};