1/* global CONFIG */ 2/* eslint-disable no-console */ 3 4(function() { 5 const leancloudSelector = url => { 6 url = encodeURI(url); 7 return document.getElementById(url).querySelector('.leancloud-visitors-count'); 8 }; 9 10 const addCount = Counter => { 11 const visitors = document.querySelector('.leancloud_visitors'); 12 const url = decodeURI(visitors.id); 13 const title = visitors.dataset.flagTitle; 14 15 Counter('get', `/classes/Counter?where=${encodeURIComponent(JSON.stringify({ url }))}`) 16 .then(response => response.json()) 17 .then(({ results }) => { 18 if (results.length > 0) { 19 const counter = results[0]; 20 leancloudSelector(url).innerText = counter.time + 1; 21 Counter('put', '/classes/Counter/' + counter.objectId, { 22 time: { 23 '__op' : 'Increment', 24 'amount': 1 25 } 26 }) 27 .catch(error => { 28 console.error('Failed to save visitor count', error); 29 }); 30 } else if (CONFIG.leancloud_visitors.security) { 31 leancloudSelector(url).innerText = 'Counter not initialized! More info at console err msg.'; 32 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`.'); 33 } else { 34 Counter('post', '/classes/Counter', { title, url, time: 1 }) 35 .then(response => response.json()) 36 .then(() => { 37 leancloudSelector(url).innerText = 1; 38 }) 39 .catch(error => { 40 console.error('Failed to create', error); 41 }); 42 } 43 }) 44 .catch(error => { 45 console.error('LeanCloud Counter Error', error); 46 }); 47 }; 48 49 const showTime = Counter => { 50 const visitors = document.querySelectorAll('.leancloud_visitors'); 51 const entries = [...visitors].map(element => { 52 return decodeURI(element.id); 53 }); 54 55 Counter('get', `/classes/Counter?where=${encodeURIComponent(JSON.stringify({ url: { '$in': entries } }))}`) 56 .then(response => response.json()) 57 .then(({ results }) => { 58 for (const url of entries) { 59 const target = results.find(item => item.url === url); 60 leancloudSelector(url).innerText = target ? target.time : 0; 61 } 62 }) 63 .catch(error => { 64 console.error('LeanCloud Counter Error', error); 65 }); 66 }; 67 68 const { app_id, app_key, server_url } = CONFIG.leancloud_visitors; 69 const fetchData = api_server => { 70 const Counter = (method, url, data) => { 71 return fetch(`${api_server}/1.1${url}`, { 72 method, 73 headers: { 74 'X-LC-Id' : app_id, 75 'X-LC-Key' : app_key, 76 'Content-Type': 'application/json' 77 }, 78 body: JSON.stringify(data) 79 }); 80 }; 81 if (CONFIG.page.isPost) { 82 if (CONFIG.hostname !== location.hostname) return; 83 addCount(Counter); 84 } else if (document.querySelectorAll('.post-title-link').length >= 1) { 85 showTime(Counter); 86 } 87 }; 88 89 let api_server; 90 if (server_url) { 91 api_server = server_url; 92 } else if (app_id.slice(-9) === '-MdYXbMMI') { 93 api_server = `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com`; 94 } 95 96 document.addEventListener('page:loaded', () => { 97 if (api_server) { 98 fetchData(api_server); 99 } else { 100 fetch(`https://app-router.leancloud.cn/2/route?appId=${app_id}`) 101 .then(response => response.json()) 102 .then(({ api_server }) => { 103 fetchData(`https://${api_server}`); 104 }); 105 } 106 }); 107})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.