@microlink/google 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/js/main.js DELETED
@@ -1,397 +0,0 @@
1
- const createHeroStats = () => {
2
- const stats = document.createElement('div')
3
- stats.className = 'hero-stats reveal-on-load'
4
- stats.innerHTML = `
5
- <div class="hero-stat"><strong>10</strong><span>Google verticals</span></div>
6
- <div class="hero-stat"><strong>~1s</strong><span>Typical latency</span></div>
7
- <div class="hero-stat hero-stat--serialization"><strong>HTML/MARKDOWN</strong><span>Output serialization</span></div>
8
- `
9
- return stats
10
- }
11
-
12
- const createVisualBadges = () => {
13
- const badges = document.createElement('div')
14
- badges.className = 'hero-badges'
15
- badges.innerHTML = `
16
- <div class="hero-badge top">10 products</div>
17
- <div class="hero-badge bottom">&lt;1s response</div>
18
- `
19
- return badges
20
- }
21
-
22
- const decorateHero = section => {
23
- const hero = section.querySelector('div[align="center"]')
24
- if (!hero || hero.dataset.enhanced === 'true') return
25
-
26
- hero.dataset.enhanced = 'true'
27
- hero.className = 'hero-block'
28
-
29
- const image = hero.querySelector('img')
30
- const summary = hero.querySelector('p')
31
-
32
- const copy = document.createElement('div')
33
- copy.className = 'hero-copy'
34
-
35
- const eyebrow = document.createElement('div')
36
- eyebrow.className = 'hero-eyebrow reveal-on-load'
37
- eyebrow.textContent = 'npm i @microlink/google'
38
-
39
- const title = document.createElement('h1')
40
- title.innerHTML = 'Structured <span>Google</span><br>API for LLMs.'
41
- title.className = 'reveal-on-load'
42
-
43
- copy.append(eyebrow, title)
44
-
45
- if (summary) {
46
- summary.classList.add('reveal-on-load')
47
- copy.append(summary)
48
- }
49
-
50
- const visual = document.createElement('div')
51
- visual.className = 'hero-visual reveal-on-load'
52
- visual.innerHTML = `
53
- <div class="browser-frame">
54
- <div class="browser-bar">
55
- <span class="browser-dots"><i></i><i></i><i></i></span>
56
- <span class="browser-url">https://search.microlink.io</span>
57
- </div>
58
- <div class="browser-screen"></div>
59
- </div>
60
- `
61
-
62
- if (image) {
63
- image.className = 'hero-banner'
64
- visual.querySelector('.browser-screen').append(image)
65
- }
66
-
67
- visual.append(createVisualBadges())
68
-
69
- hero.replaceChildren(copy, visual)
70
- hero.after(createHeroStats())
71
- }
72
-
73
- const decorateUseCases = section => {
74
- const useCasesHeading = [...section.querySelectorAll('h2')].find(
75
- node => node.textContent.trim().toLowerCase() === 'common llm use cases'
76
- )
77
-
78
- if (!useCasesHeading) return
79
-
80
- const intro = useCasesHeading.nextElementSibling
81
- const list = intro?.nextElementSibling
82
- if (!list || list.tagName !== 'UL' || list.dataset.enhanced === 'true') return
83
-
84
- list.dataset.enhanced = 'true'
85
- list.classList.add('use-case-grid')
86
-
87
- const variants = [
88
- 'use-case-card--agentic',
89
- 'use-case-card--rag',
90
- 'use-case-card--news',
91
- 'use-case-card--local'
92
- ]
93
-
94
- ;[...list.children].forEach((item, index) => {
95
- item.classList.add('use-case-card', 'reveal-on-load')
96
- if (variants[index]) item.classList.add(variants[index])
97
-
98
- const link = item.querySelector('a')
99
- if (link) {
100
- const title = link.textContent.trim()
101
- const description = item.textContent.replace(title, '').trim()
102
- const heading = document.createElement('strong')
103
-
104
- heading.textContent = title
105
- link.replaceChildren(heading)
106
-
107
- if (description) {
108
- const body = document.createElement('p')
109
- body.textContent = description
110
- link.append(body)
111
- }
112
-
113
- link.classList.add('use-case-link')
114
- item.replaceChildren(link)
115
- }
116
- })
117
-
118
- const heroStats = section.querySelector('.hero-stats')
119
- if (heroStats && !section.querySelector('.hero-use-cases')) {
120
- const heroUseCases = document.createElement('div')
121
- const heroIntro = document.createElement('p')
122
-
123
- heroUseCases.className = 'hero-use-cases reveal-on-load'
124
- heroIntro.className = 'hero-use-cases__intro'
125
- heroIntro.textContent =
126
- 'Explore the most common LLM workflows and jump straight to the tutorial that matches your use case.'
127
-
128
- list.classList.add('hero-use-cases__grid')
129
-
130
- heroUseCases.append(heroIntro, list)
131
- heroStats.after(heroUseCases)
132
- }
133
- }
134
-
135
- const decorateCodeBlocks = section => {
136
- section.querySelectorAll('pre').forEach(pre => {
137
- if (pre.parentElement?.classList.contains('code-shell')) return
138
- const shell = document.createElement('div')
139
- const header = document.createElement('div')
140
- const code = pre.querySelector('code')
141
- const languageClass = [...(code?.classList || [])].find(value =>
142
- value.startsWith('language-')
143
- )
144
- shell.className = 'code-shell'
145
- header.className = 'code-shell__header'
146
- header.innerHTML = `
147
- <span class="code-shell__dots" aria-hidden="true"><i></i><i></i><i></i></span>
148
- <span class="code-shell__label">${
149
- languageClass ? languageClass.replace('language-', '') : 'code'
150
- }</span>
151
- `
152
- pre.parentNode.insertBefore(shell, pre)
153
- shell.append(header, pre)
154
- })
155
- }
156
-
157
- const decorateTables = section => {
158
- section.querySelectorAll('table').forEach(table => {
159
- if (table.parentElement?.classList.contains('table-shell')) return
160
- const shell = document.createElement('div')
161
- shell.className = 'table-shell'
162
- table.parentNode.insertBefore(shell, table)
163
- shell.append(table)
164
- })
165
- }
166
-
167
- const revealContent = section => {
168
- ;[...section.querySelectorAll('h2, h3')].forEach(node =>
169
- node.classList.add('reveal-on-load')
170
- )
171
- }
172
-
173
- const disableDocsifyDefaultScrollSpy = section => {
174
- section
175
- .querySelectorAll(':is(h1, h2, h3, h4, h5) > a.anchor[data-id]')
176
- .forEach(anchor => {
177
- anchor.classList.remove('anchor')
178
- })
179
- }
180
-
181
- let teardownNavigationTracking = () => {}
182
-
183
- const decodeValue = value => {
184
- try {
185
- return decodeURIComponent(value)
186
- } catch {
187
- return value
188
- }
189
- }
190
-
191
- const extractSectionIdFromHref = href => {
192
- if (!href) return null
193
-
194
- const value = href.trim()
195
- const hashIndex = value.indexOf('#')
196
- const hash = hashIndex >= 0 ? value.slice(hashIndex + 1) : value
197
-
198
- if (!hash) return null
199
-
200
- const isRouteHash = hash.startsWith('/')
201
- const normalizedHash = isRouteHash ? hash.slice(1) : hash
202
- const [, query = ''] = normalizedHash.split('?')
203
- const idFromQuery = query ? new URLSearchParams(query).get('id') : null
204
-
205
- if (idFromQuery) return decodeValue(idFromQuery)
206
- if (isRouteHash) return null
207
-
208
- const [idCandidate = ''] = normalizedHash.split('?')
209
- return idCandidate ? decodeValue(idCandidate) : null
210
- }
211
-
212
- const setupNavigationTracking = section => {
213
- const sidebarNav = document.querySelector('.sidebar .sidebar-nav')
214
- if (!sidebarNav) return () => {}
215
-
216
- const navLinks = [...sidebarNav.querySelectorAll('a[href]')]
217
- const trackedLinks = navLinks
218
- .map(link => ({
219
- id: extractSectionIdFromHref(link.getAttribute('href')),
220
- link
221
- }))
222
- .filter(entry => entry.id)
223
-
224
- const trackedIds = new Set(trackedLinks.map(entry => entry.id))
225
- const headings = [...section.querySelectorAll('h2[id], h3[id]')]
226
- const headingsToTrack = headings.filter(heading => trackedIds.has(heading.id))
227
- const scopedHeadings = headingsToTrack.length > 0 ? headingsToTrack : headings
228
- const firstHeadingId = scopedHeadings[0]?.id || trackedLinks[0]?.id || null
229
-
230
- let activeId = null
231
-
232
- const setActiveLink = id => {
233
- navLinks.forEach(link => {
234
- link.classList.remove('active')
235
- link.classList.remove('is-active')
236
- link.removeAttribute('aria-current')
237
- link.closest('li')?.classList.remove('active')
238
- link.closest('li')?.classList.remove('is-active')
239
- })
240
-
241
- const targetId = id || firstHeadingId
242
- const activeLink =
243
- trackedLinks.find(entry => entry.id === targetId)?.link ||
244
- navLinks.find(link => link.closest('li')?.classList.contains('active')) ||
245
- navLinks[0]
246
-
247
- if (!activeLink) return
248
-
249
- activeLink.classList.add('active', 'is-active')
250
- activeLink.setAttribute('aria-current', 'location')
251
- const activeItem = activeLink.closest('li')
252
-
253
- activeItem?.classList.add('active', 'is-active')
254
-
255
- let parentItem = activeItem?.parentElement?.closest('li')
256
- while (parentItem) {
257
- parentItem.classList.add('active')
258
- parentItem = parentItem.parentElement?.closest('li')
259
- }
260
-
261
- activeId = extractSectionIdFromHref(activeLink.getAttribute('href'))
262
- }
263
-
264
- const getCurrentSectionId = () => {
265
- const triggerOffset = Math.max(8, window.innerHeight * 0.03)
266
- const threshold = window.scrollY + triggerOffset
267
- let currentSectionId = null
268
-
269
- for (const heading of scopedHeadings) {
270
- if (heading.offsetTop <= threshold) {
271
- currentSectionId = heading.id
272
- continue
273
- }
274
- break
275
- }
276
-
277
- return currentSectionId
278
- }
279
-
280
- let frameId = null
281
-
282
- const syncActiveLink = () => {
283
- frameId = null
284
-
285
- if (scopedHeadings.length === 0) {
286
- setActiveLink(null)
287
- return
288
- }
289
-
290
- const sectionId = getCurrentSectionId()
291
- const firstHeadingTop = scopedHeadings[0].offsetTop
292
- const nearTopThreshold = Math.max(8, window.innerHeight * 0.03)
293
- const isBeforeFirstHeading =
294
- window.scrollY + nearTopThreshold < firstHeadingTop
295
-
296
- if (isBeforeFirstHeading) {
297
- setActiveLink(firstHeadingId)
298
- return
299
- }
300
-
301
- if (sectionId) {
302
- setActiveLink(sectionId)
303
- return
304
- }
305
-
306
- if (!activeId) {
307
- setActiveLink(firstHeadingId)
308
- }
309
- }
310
-
311
- const requestSync = () => {
312
- if (frameId !== null) return
313
- frameId = window.requestAnimationFrame(syncActiveLink)
314
- }
315
-
316
- const handleNavClick = event => {
317
- const link = event.target.closest('a[href]')
318
- if (!link || !sidebarNav.contains(link)) return
319
-
320
- const sectionId = extractSectionIdFromHref(link.getAttribute('href'))
321
- if (sectionId) setActiveLink(sectionId)
322
- }
323
-
324
- sidebarNav.addEventListener('click', handleNavClick)
325
- window.addEventListener('scroll', requestSync, { passive: true })
326
- window.addEventListener('resize', requestSync)
327
-
328
- requestSync()
329
- window.setTimeout(requestSync, 140)
330
-
331
- return () => {
332
- sidebarNav.removeEventListener('click', handleNavClick)
333
- window.removeEventListener('scroll', requestSync)
334
- window.removeEventListener('resize', requestSync)
335
- if (frameId !== null) window.cancelAnimationFrame(frameId)
336
- }
337
- }
338
-
339
- const enhancePage = () => {
340
- teardownNavigationTracking()
341
- teardownNavigationTracking = () => {}
342
-
343
- const section = document.querySelector('.markdown-section')
344
- const content = document.querySelector('.content')
345
- const sidebar = document.querySelector('.sidebar')
346
- if (!section) return
347
-
348
- if (content) {
349
- content.id = 'main-content'
350
- content.setAttribute('role', 'main')
351
- content.setAttribute('tabindex', '-1')
352
- }
353
-
354
- if (sidebar) {
355
- sidebar.setAttribute('role', 'navigation')
356
- sidebar.setAttribute('aria-label', 'Primary navigation')
357
- }
358
-
359
- decorateHero(section)
360
- decorateUseCases(section)
361
- decorateCodeBlocks(section)
362
- decorateTables(section)
363
- revealContent(section)
364
- disableDocsifyDefaultScrollSpy(section)
365
- teardownNavigationTracking = setupNavigationTracking(section)
366
- }
367
-
368
- window.$docsify = {
369
- name: '@microlink/google',
370
- repo: 'microlinkhq/google',
371
- logo: '/static/banner.png',
372
- externalLinkRel: 'noopener noreferrer',
373
- subMaxLevel: 2,
374
- auto2top: true,
375
- maxLevel: 3,
376
- plugins: [
377
- hook => {
378
- hook.doneEach(() => {
379
- enhancePage()
380
- const appLink = document.querySelector('.app-name-link')
381
- if (appLink && !appLink.dataset.bound) {
382
- appLink.dataset.bound = 'true'
383
- appLink.onclick = event => {
384
- event.preventDefault()
385
- const shouldReduceMotion = window.matchMedia(
386
- '(prefers-reduced-motion: reduce)'
387
- ).matches
388
- window.scrollTo({
389
- top: 0,
390
- behavior: shouldReduceMotion ? 'auto' : 'smooth'
391
- })
392
- }
393
- }
394
- })
395
- }
396
- ]
397
- }