PageSourceSearch

https://www.kusunoki-pub.jp/_partials.js?v=202610021838

js kusunoki-pub.jp collected 2026-10-08 09:22:21 UTC 11,277 bytes, 242 lines download raw bytes

1 
2(function () {
3  const HEADER_HTML = `
4  <header class="site-header">
5    <div class="container header-inner">
6      <a href="/" class="brand" aria-label="クスノキ出版 トップへ">
7        <img class="brand-logo" src="/assets/logo-green-132.png" alt="クスノキ出版ロゴ" width="44" height="44">
8        <span class="brand-text">
9          <span class="brand-name">クスノキ出版</span>
10          <span class="brand-sub">Kusunoki Publishing</span>
11        </span>
12      </a>
13      <button class="nav-toggle" aria-label="メニューを開く" aria-expanded="false" aria-controls="primary-nav">
14        <span class="nav-toggle-bar"></span>
15        <span class="nav-toggle-bar"></span>
16        <span class="nav-toggle-bar"></span>
17      </button>
18      <nav class="nav" id="primary-nav" aria-label="サイトメニュー">
19        <a href="/" data-nav="home">ホーム</a>
20        <a href="/shonen-tantei/" data-nav="series">シリーズ</a>
21        <a href="/books/" data-nav="books">書店|図書館の方へ</a>
22        <a href="/author/" data-nav="author">著者</a>
23        <a href="/about/" data-nav="about">出版社</a>
24        <a href="/contact/" data-nav="contact">お問い合わせ</a>
25        <a href="https://kusunokipub.official.ec/" target="_blank" rel="noopener" class="nav-shop" data-nav="shop">ショップ →</a>
26      </nav>
27      <div class="nav-backdrop" aria-hidden="true"></div>
28    </div>
29  </header>`;
30
31  const FOOTER_HTML = `
32  <footer class="site-footer">
33    <div class="container footer-grid">
34      <div class="footer-brand">
35        <div class="brand">
36          <img class="brand-logo" src="/assets/logo-green-132.png" alt="クスノキ出版ロゴ" width="44" height="44">
37          <span class="brand-text">
38            <span class="brand-name">クスノキ出版</span>
39            <span class="brand-sub">Kusunoki Publishing</span>
40          </span>
41        </div>
42        <p class="footer-tagline">物語を、加須から世界へ。</p>
43      </div>
44      <div class="footer-info">
45        <h4>発行元</h4>
46        <p>
47          発行:クスノキ出版<br>
48          発売元:紡出版(つむぎしゅっぱん)<br>
49          〒347-0055 埼玉県加須市中央1-6-8<br>
50          寿々木別館ビル
51        </p>
52      </div>
53      <div class="footer-links">
54        <h4>メニュー</h4>
55        <ul>
56          <li><a href="/">ホーム</a></li>
57          <li><a href="/shonen-tantei/">シリーズ</a></li>
58          <li><a href="/books/">書店|図書館の方へ</a></li>
59          <li><a href="/stores/">取扱店のご案内</a></li>
60          <li><a href="/author/">著者</a></li>
61          <li><a href="/about/">出版社について</a></li>
62          <li><a href="/contact/">お問い合わせ</a></li>
63          <li><a href="https://kusunokipub.official.ec/" target="_blank" rel="noopener">ショップ →</a></li>
64          <li><a href="/privacy/">プライバシーポリシー</a></li>
65        </ul>
66      </div>
67      <div class="footer-social">
68        <h4>フォロー</h4>
69        <ul class="social-list">
70          <li><a href="https://www.instagram.com/kusunoki_masaki/?hl=ja" target="_blank" rel="noopener" aria-label="Instagram公式">
71            <svg viewBox="0 0 24 24" aria-hidden="true" width="22" height="22"><path fill="currentColor" d="M12 2.2c3.2 0 3.6 0 4.85.07 1.17.05 1.8.25 2.23.42.56.22.96.48 1.38.9.42.42.68.82.9 1.38.17.42.37 1.06.42 2.23.06 1.26.07 1.64.07 4.85s0 3.6-.07 4.85c-.05 1.17-.25 1.8-.42 2.23-.22.56-.48.96-.9 1.38-.42.42-.82.68-1.38.9-.42.17-1.06.37-2.23.42-1.26.06-1.64.07-4.85.07s-3.6 0-4.85-.07c-1.17-.05-1.8-.25-2.23-.42-.56-.22-.96-.48-1.38-.9-.42-.42-.68-.82-.9-1.38-.17-.42-.37-1.06-.42-2.23C2.2 15.6 2.2 15.2 2.2 12s0-3.6.07-4.85c.05-1.17.25-1.8.42-2.23.22-.56.48-.96.9-1.38.42-.42.82-.68 1.38-.9.42-.17 1.06-.37 2.23-.42C8.4 2.2 8.8 2.2 12 2.2M12 0C8.74 0 8.33 0 7.05.07 5.78.13 4.9.33 4.14.63c-.8.32-1.48.73-2.15 1.4C1.32 2.7.92 3.38.6 4.18c-.3.76-.5 1.64-.56 2.91C-.03 8.37 0 8.78 0 12s0 3.63.07 4.91c.06 1.27.26 2.15.56 2.91.32.8.73 1.48 1.4 2.15.67.67 1.35 1.08 2.15 1.4.76.3 1.64.5 2.91.56C8.37 23.97 8.78 24 12 24s3.63-.03 4.91-.07c1.27-.06 2.15-.26 2.91-.56.8-.32 1.48-.73 2.15-1.4.67-.67 1.08-1.35 1.4-2.15.3-.76.5-1.64.56-2.91.04-1.28.07-1.69.07-4.91s-.03-3.63-.07-4.91c-.06-1.27-.26-2.15-.56-2.91-.32-.8-.73-1.48-1.4-2.15C21.3 1.32 20.62.92 19.82.6c-.76-.3-1.64-.5-2.91-.56C15.63.03 15.22 0 12 0zm0 5.84A6.16 6.16 0 0 0 5.84 12 6.16 6.16 0 0 0 12 18.16 6.16 6.16 0 0 0 18.16 12 6.16 6.16 0 0 0 12 5.84zm0 10.16A4 4 0 1 1 12 8a4 4 0 0 1 0 8zm6.4-10.4a1.44 1.44 0 1 0 0-2.88 1.44 1.44 0 0 0 0 2.88z"/></svg>
72            <span>Instagram</span>
73          </a></li>
74          <li><a href="https://note.com/kusunoki_pub" target="_blank" rel="noopener" aria-label="Note公式">
75            <svg viewBox="0 0 24 24" aria-hidden="true" width="22" height="22"><path fill="currentColor" d="M4 3h13.5L22 7.5V21H4V3zm2 2v14h14V8.5L16.5 5H6zm3 4h8v2H9V9zm0 4h8v2H9v-2zm0 4h5v2H9v-2z"/></svg>
76            <span>note</span>
77          </a></li>
78          <li><a href="https://www.youtube.com/@%E3%82%AF%E3%82%B9%E3%83%8E%E3%82%AD%E5%87%BA%E7%89%88" target="_blank" rel="noopener" aria-label="YouTube公式">
79            <svg viewBox="0 0 24 24" aria-hidden="true" width="22" height="22"><path fill="currentColor" d="M23.5 6.2a3 3 0 0 0-2.1-2.1C19.5 3.5 12 3.5 12 3.5s-7.5 0-9.4.6A3 3 0 0 0 .5 6.2C0 8.1 0 12 0 12s0 3.9.5 5.8a3 3 0 0 0 2.1 2.1c1.9.6 9.4.6 9.4.6s7.5 0 9.4-.6a3 3 0 0 0 2.1-2.1c.5-1.9.5-5.8.5-5.8s0-3.9-.5-5.8zM9.6 15.6V8.4L15.8 12l-6.2 3.6z"/></svg>
80            <span>YouTube</span>
81          </a></li>
82        </ul>
83        <h4 class="footer-extlinks-title">リンク</h4>
84        <ul class="footer-extlinks">
85          <li><a href="https://neil.chips.jp/chihosho/linkpage.html" target="_blank" rel="noopener">地方・小出版流通センター</a></li>
86        </ul>
87      </div>
88    </div>
89    <div class="footer-bottom">
90      <div class="container">
91        <small>© <span id="year"></span> Kusunoki Publishing / Tsumugi Publishing. All Rights Reserved.</small>
92      </div>
93    </div>
94  </footer>`;
95
96  function getBasePath() {
97    const scripts = document.querySelectorAll('script[src]');
98    for (const s of scripts) {
99      const src = s.getAttribute('src') || '';
100      const m = src.match(/^(.*\/)?_partials\.js(\?.*)?$/);
101      if (m) {
102        return m[1] ? m[1] : './';
103      }
104    }
105    
106    let path = location.pathname.replace(/\/+$/, '');
107    const parts = path.split('/').filter(Boolean);
108    const last = parts[parts.length - 1] || '';
109    const dirDepth = parts.length - (last.endsWith('.html') ? 1 : 0);
110    return dirDepth <= 0 ? './' : '../'.repeat(dirDepth);
111  }
112
113  function rewriteAbsolutePaths(rootEl) {
114    const bp = getBasePath();
115    rootEl.querySelectorAll('[href^="/"],[src^="/"]').forEach(el => {
116      ['href', 'src'].forEach(attr => {
117        const v = el.getAttribute(attr);
118        if (v && v.startsWith('/') && !v.startsWith('//')) {
119          el.setAttribute(attr, bp + v.slice(1));
120        }
121      });
122    });
123  }
124
125  function buildHTML(tpl) {
126    const bp = getBasePath();
127    return tpl.replace(/href="\//g, `href="${bp}`).replace(/src="\//g, `src="${bp}`);
128  }
129
130  function appendIndexHtmlForFileProtocol(rootEl) {
131    if (location.protocol !== 'file:') return;
132    rootEl.querySelectorAll('a[href]').forEach(a => {
133      const href = a.getAttribute('href');
134      if (!href) return;
135      if (/^(https?:|mailto:|tel:|#|javascript:)/i.test(href)) return;
136      
137      const [pathPart, rest] = [href.split(/[?#]/)[0], href.substring(href.split(/[?#]/)[0].length)];
138      if (!pathPart) return;
139      
140      if (pathPart.endsWith('/')) {
141        a.setAttribute('href', pathPart + 'index.html' + rest);
142      } else if (pathPart === '.' || pathPart === '..') {
143        a.setAttribute('href', pathPart + '/index.html' + rest);
144      }
145    });
146  }
147
148  function injectPartials() {
149    const headerSlot = document.querySelector('[data-partial="header"]');
150    const footerSlot = document.querySelector('[data-partial="footer"]');
151    if (headerSlot) headerSlot.outerHTML = buildHTML(HEADER_HTML);
152    if (footerSlot) footerSlot.outerHTML = buildHTML(FOOTER_HTML);
153
154    rewriteAbsolutePaths(document.body);
155
156    appendIndexHtmlForFileProtocol(document.body);
157
158    const y = document.getElementById('year');
159    if (y) y.textContent = new Date().getFullYear();
160
161    const path = location.pathname.toLowerCase();
162    
163    const navKey =
164      /\/books\//.test(path) ? 'books' :
165      /\/shonen-tantei\//.test(path) ? 'series' :
166      /\/author\//.test(path) ? 'author' :
167      /\/about\//.test(path) ? 'about' :
168      /\/contact\//.test(path) ? 'contact' :
169      'home';
170    if (navKey) {
171      const link = document.querySelector(`[data-nav="${navKey}"]`);
172      if (link) link.classList.add('active');
173    }
174
175    bindNavToggle();
176    bindInteractions();
177  }
178
179  function bindNavToggle() {
180    const toggle = document.querySelector('.nav-toggle');
181    const nav = document.querySelector('.nav');
182    const backdrop = document.querySelector('.nav-backdrop');
183    if (!toggle || !nav) return;
184    const closeNav = () => {
185      toggle.setAttribute('aria-expanded', 'false');
186      nav.classList.remove('is-open');
187      if (backdrop) backdrop.classList.remove('is-visible');
188      document.body.classList.remove('nav-locked');
189    };
190    const openNav = () => {
191      toggle.setAttribute('aria-expanded', 'true');
192      nav.classList.add('is-open');
193      if (backdrop) backdrop.classList.add('is-visible');
194      document.body.classList.add('nav-locked');
195    };
196    toggle.addEventListener('click', () => {
197      const expanded = toggle.getAttribute('aria-expanded') === 'true';
198      expanded ? closeNav() : openNav();
199    });
200    if (backdrop) backdrop.addEventListener('click', closeNav);
201    nav.querySelectorAll('a').forEach(a => a.addEventListener('click', closeNav));
202    window.addEventListener('resize', () => {
203      if (window.innerWidth > 720) closeNav();
204    });
205  }
206
207  function bindInteractions() {
208    document.querySelectorAll('a[href^="#"]').forEach(a => {
209      a.addEventListener('click', e => {
210        const href = a.getAttribute('href');
211        if (!href || href === '#') return;
212        const target = document.querySelector(href);
213        if (!target) return;
214        e.preventDefault();
215        const y = target.getBoundingClientRect().top + window.scrollY - 80;
216        window.scrollTo({top: y, behavior: 'smooth'});
217      });
218    });
219
220    const io = new IntersectionObserver(entries => {
221      entries.forEach(ent => {
222        if (ent.isIntersecting) {
223          ent.target.classList.add('in');
224          io.unobserve(ent.target);
225        }
226      });
227    }, {threshold: 0.12});
228    document.querySelectorAll(
229      '.section-head, .book-feature, .label-card, .book-card, .author-grid, .concept-card, .store-card, .contact-form, .content-block, .editorial-split, .video-tile, .timeline-item, .character-card, .world-tile'
230    ).forEach(el => {
231      el.classList.add('reveal');
232      io.observe(el);
233    });
234
235  }
236
237  if (document.readyState === 'loading') {
238    document.addEventListener('DOMContentLoaded', injectPartials);
239  } else {
240    injectPartials();
241  }
242})();

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.