PageSourceSearch

https://sm5mg.github.io/js/main.js?v=1.29.1

js sm5mg.github.io collected 2026-10-03 09:57:53 UTC 6,051 bytes, 210 lines download raw bytes

1// utils
2const util = {
3
4  // https://github.com/jerryc127/hexo-theme-butterfly
5  diffDate: (d, more = false) => {
6    const dateNow = new Date()
7    const datePost = new Date(d)
8    const dateDiff = dateNow.getTime() - datePost.getTime()
9    const minute = 1000 * 60
10    const hour = minute * 60
11    const day = hour * 24
12
13    let result
14    if (more) {
15      const dayCount = dateDiff / day
16      const hourCount = dateDiff / hour
17      const minuteCount = dateDiff / minute
18
19      if (dayCount > 14) {
20        result = null
21      } else if (dayCount >= 1) {
22        result = parseInt(dayCount) + ' ' + ctx.date_suffix.day
23      } else if (hourCount >= 1) {
24        result = parseInt(hourCount) + ' ' + ctx.date_suffix.hour
25      } else if (minuteCount >= 1) {
26        result = parseInt(minuteCount) + ' ' + ctx.date_suffix.min
27      } else {
28        result = ctx.date_suffix.just
29      }
30    } else {
31      result = parseInt(dateDiff / day)
32    }
33    return result
34  },
35
36  copy: (id, msg) => {
37    const el = document.getElementById(id);
38    if (el) {
39      el.select();
40      document.execCommand("Copy");
41      if (msg && msg.length > 0) {
42        hud.toast(msg, 2500);
43      }
44    }
45  },
46
47  toggle: (id) => {
48    const el = document.getElementById(id);
49    if (el) {
50      el.classList.toggle("display");
51    }
52  },
53
54  scrollTop: () => {
55    window.scrollTo({top: 0, behavior: "smooth"});
56  },
57
58  scrollComment: () => {
59    document.getElementById('comments').scrollIntoView({behavior: "smooth"});
60  },
61
62  viewportLazyload: (target, func, enabled = true) => {
63    if (!enabled || !("IntersectionObserver" in window)) {
64      func();
65      return;
66    }
67    const observer = new IntersectionObserver((entries) => {
68      if (entries[0].intersectionRatio > 0) {
69        func();
70        observer.disconnect();
71      }
72    });
73    observer.observe(target);
74  }
75}
76
77const hud = {
78  toast: (msg, duration) => {
79    const d = Number(isNaN(duration) ? 2000 : duration);
80    var el = document.createElement('div');
81    el.classList.add('toast');
82    el.classList.add('show');
83    el.innerHTML = msg;
84    document.body.appendChild(el);
85
86    setTimeout(function(){ document.body.removeChild(el) }, d);
87    
88  },
89
90}
91
92// defines
93
94const l_body = document.querySelector('.l_body');
95
96
97const init = {
98  toc: () => {
99    utils.jq(() => {
100      const scrollOffset = 32;
101      var segs = [];
102      $("article.md-text :header").each(function (idx, node) {
103        segs.push(node);
104      });
105      function activeTOC() {
106        var scrollTop = $(this).scrollTop();
107        var topSeg = null;
108        for (var idx in segs) {
109          var seg = $(segs[idx]);
110          if (seg.offset().top > scrollTop + scrollOffset) {
111            continue;
112          }
113          if (!topSeg) {
114            topSeg = seg;
115          } else if (seg.offset().top >= topSeg.offset().top) {
116            topSeg = seg;
117          }
118        }
119        if (topSeg) {
120          $("#data-toc a.toc-link").removeClass("active");
121          var link = "#" + topSeg.attr("id");
122          if (link != '#undefined') {
123            const highlightItem = $('#data-toc a.toc-link[href="' + encodeURI(link) + '"]');
124            if (highlightItem.length > 0) {
125              highlightItem.addClass("active");
126            }
127          } else {
128            $('#data-toc a.toc-link:first').addClass("active");
129          }
130        }
131      }
132      function scrollTOC() {
133        const e0 = document.querySelector('#data-toc .toc');
134        const e1 = document.querySelector('#data-toc .toc a.toc-link.active');
135        if (e0 == null || e1 == null) {
136          return;
137        }
138        const offsetBottom = e1.getBoundingClientRect().bottom - e0.getBoundingClientRect().bottom + 100;
139        const offsetTop = e1.getBoundingClientRect().top - e0.getBoundingClientRect().top - 64;
140        if (offsetTop < 0) {
141          e0.scrollBy({top: offsetTop, behavior: "smooth"});
142        } else if (offsetBottom > 0) {
143          e0.scrollBy({top: offsetBottom, behavior: "smooth"});
144        }
145      }
146      
147      var timeout = null;
148      window.addEventListener('scroll', function() {
149        activeTOC();
150        if(timeout !== null) clearTimeout(timeout);
151        timeout = setTimeout(function() {
152          scrollTOC();
153        }.bind(this), 50);
154      });      
155    })
156  },
157  sidebar: () => {
158    utils.jq(() => {
159      $("#data-toc a.toc-link").click(function (e) {
160        sidebar.dismiss();
161      });
162    })
163  },
164  relativeDate: (selector) => {
165    selector.forEach(item => {
166      const $this = item
167      const timeVal = $this.getAttribute('datetime')
168      let relativeValue = util.diffDate(timeVal, true)
169      if (relativeValue) {
170        $this.innerText = relativeValue
171      }
172    })
173  },
174  /**
175   * Tabs tag listener (without twitter bootstrap).
176   */
177  registerTabsTag: function () {
178    // Binding `nav-tabs` & `tab-content` by real time permalink changing.
179    document.querySelectorAll('.tabs .nav-tabs .tab').forEach(element => {
180      element.addEventListener('click', event => {
181        event.preventDefault();
182        // Prevent selected tab to select again.
183        if (element.classList.contains('active')) return;
184        // Add & Remove active class on `nav-tabs` & `tab-content`.
185        [...element.parentNode.children].forEach(target => {
186          target.classList.toggle('active', target === element);
187        });
188        // https://stackoverflow.com/questions/20306204/using-queryselector-with-ids-that-are-numbers
189        const tActive = document.getElementById(element.querySelector('a').getAttribute('href').replace('#', ''));
190        [...tActive.parentNode.children].forEach(target => {
191          target.classList.toggle('active', target === tActive);
192        });
193        // Trigger event
194        tActive.dispatchEvent(new Event('tabs:click', {
195          bubbles: true
196        }));
197      });
198    });
199
200    window.dispatchEvent(new Event('tabs:register'));
201  },
202
203}
204
205
206// init
207init.toc()
208init.sidebar()
209init.relativeDate(document.querySelectorAll('#post-meta time'))
210init.registerTabsTag()

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.