mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Added emoji index to icon search
This commit is contained in:
parent
a776d0018f
commit
356cde2ad8
@ -14,7 +14,7 @@ and used in `mkdocs.yml`, documents and templates.
|
||||
<div class="mdx-icon-search" data-mdx-component="icon-search">
|
||||
<input
|
||||
class="md-input md-input--stretch mdx-icon-search__input"
|
||||
placeholder="Search the icon database"
|
||||
placeholder="Search the icon and emoji database"
|
||||
data-mdx-component="icon-search-query"
|
||||
/>
|
||||
<div class="mdx-icon-search-result" data-mdx-component="icon-search-result">
|
||||
@ -24,8 +24,8 @@ and used in `mkdocs.yml`, documents and templates.
|
||||
</div>
|
||||
<small>
|
||||
:octicons-light-bulb-16:
|
||||
**Tip:** Enter some keywords to find the perfect icon and click on the
|
||||
shortcode to copy it to your clipboard.
|
||||
**Tip:** Enter some keywords to find the perfect icon or emoji and click on
|
||||
the shortcode to copy it to your clipboard.
|
||||
</small>
|
||||
|
||||
## Configuration
|
||||
|
File diff suppressed because one or more lines are too long
1
material/assets/javascripts/bundle.21e94a31.min.js.map
Normal file
1
material/assets/javascripts/bundle.21e94a31.min.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.fbcb1fc3.min.js",
|
||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.fbcb1fc3.min.js.map",
|
||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.21e94a31.min.js",
|
||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.21e94a31.min.js.map",
|
||||
"assets/javascripts/vendor.js": "assets/javascripts/vendor.00ecb175.min.js",
|
||||
"assets/javascripts/vendor.js.map": "assets/javascripts/vendor.00ecb175.min.js.map",
|
||||
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.3f4c5856.min.js",
|
||||
@ -9,8 +9,8 @@
|
||||
"assets/stylesheets/main.css.map": "assets/stylesheets/main.45122f27.min.css.map",
|
||||
"assets/stylesheets/palette.css": "assets/stylesheets/palette.e03a20ad.min.css",
|
||||
"assets/stylesheets/palette.css.map": "assets/stylesheets/palette.e03a20ad.min.css.map",
|
||||
"overrides/assets/javascripts/bundle.js": "overrides/assets/javascripts/bundle.759c98a8.min.js",
|
||||
"overrides/assets/javascripts/bundle.js.map": "overrides/assets/javascripts/bundle.759c98a8.min.js.map",
|
||||
"overrides/assets/javascripts/bundle.js": "overrides/assets/javascripts/bundle.f4aeaef7.min.js",
|
||||
"overrides/assets/javascripts/bundle.js.map": "overrides/assets/javascripts/bundle.f4aeaef7.min.js.map",
|
||||
"overrides/assets/stylesheets/main.css": "overrides/assets/stylesheets/main.c2cc92d1.min.css",
|
||||
"overrides/assets/stylesheets/main.css.map": "overrides/assets/stylesheets/main.c2cc92d1.min.css.map"
|
||||
}
|
@ -217,7 +217,7 @@
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script src="{{ 'assets/javascripts/vendor.00ecb175.min.js' | url }}"></script>
|
||||
<script src="{{ 'assets/javascripts/bundle.fbcb1fc3.min.js' | url }}"></script>
|
||||
<script src="{{ 'assets/javascripts/bundle.21e94a31.min.js' | url }}"></script>
|
||||
{% for path in config["extra_javascript"] %}
|
||||
<script src="{{ path | url }}"></script>
|
||||
{% endfor %}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -53,5 +53,5 @@
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
<script src="{{ 'overrides/assets/javascripts/bundle.759c98a8.min.js' | url }}"></script>
|
||||
<script src="{{ 'overrides/assets/javascripts/bundle.f4aeaef7.min.js' | url }}"></script>
|
||||
{% endblock %}
|
||||
|
@ -20,7 +20,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Observable, ObservableInput, merge } from "rxjs"
|
||||
import { NEVER, Observable, ObservableInput, merge } from "rxjs"
|
||||
import { filter, sample, take } from "rxjs/operators"
|
||||
|
||||
import { configuration } from "~/_"
|
||||
@ -99,6 +99,10 @@ function fetchSearchIndex(url: string): ObservableInput<SearchIndex> {
|
||||
export function mountSearch(
|
||||
el: HTMLElement, { keyboard$ }: MountOptions
|
||||
): Observable<Component<Search>> {
|
||||
if (location.protocol === "file:")
|
||||
return NEVER
|
||||
|
||||
/* Set up search worker */
|
||||
const config = configuration()
|
||||
const worker = setupSearchWorker(config.search, fetchSearchIndex(
|
||||
`${config.base}/search/search_index.json`
|
||||
|
@ -184,7 +184,7 @@ export function setupInstantLoading(
|
||||
const el = ev.target.closest("a")
|
||||
if (el && !el.target && urls.includes(el.href)) {
|
||||
ev.preventDefault()
|
||||
return of<HistoryState>({
|
||||
return of({
|
||||
url: new URL(el.href)
|
||||
})
|
||||
}
|
||||
@ -193,7 +193,7 @@ export function setupInstantLoading(
|
||||
})
|
||||
)
|
||||
),
|
||||
share()
|
||||
share<HistoryState>()
|
||||
)
|
||||
|
||||
/* Intercept history back and forward */
|
||||
@ -203,8 +203,8 @@ export function setupInstantLoading(
|
||||
map(ev => ({
|
||||
url: new URL(location.href),
|
||||
offset: ev.state
|
||||
} as HistoryState)),
|
||||
share()
|
||||
})),
|
||||
share<HistoryState>()
|
||||
)
|
||||
|
||||
/* Emit location change */
|
||||
|
@ -39,10 +39,33 @@ import {
|
||||
* Types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Icon
|
||||
*/
|
||||
export interface Icon {
|
||||
shortcode: string /* Icon shortcode */
|
||||
url: string /* Icon URL */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Icon search database
|
||||
*/
|
||||
export interface IconSearchDatabase {
|
||||
base: string /* Category base URL */
|
||||
data: Record<string, string> /* Category data */
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon search index
|
||||
*/
|
||||
export type IconSearchIndex = string[]
|
||||
export interface IconSearchIndex {
|
||||
icons: IconSearchDatabase /* Icon database */
|
||||
emojis: IconSearchDatabase /* Emoji database */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Icon search
|
||||
@ -67,7 +90,7 @@ export function mountIconSearch(
|
||||
): Observable<Component<IconSearch>> {
|
||||
const config = configuration()
|
||||
const index$ = requestJSON<IconSearchIndex>(
|
||||
`${config.base}/overrides/assets/javascripts/icons.json`
|
||||
`${config.base}/overrides/assets/javascripts/icon_search_index.json`
|
||||
)
|
||||
|
||||
/* Retrieve nested components */
|
||||
|
@ -55,7 +55,7 @@ import {
|
||||
|
||||
import { renderIconSearchResult } from "../../../templates"
|
||||
import { Component } from "../../_"
|
||||
import { IconSearchIndex } from "../_"
|
||||
import { Icon, IconSearchIndex } from "../_"
|
||||
import { IconSearchQuery } from "../query"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -66,7 +66,7 @@ import { IconSearchQuery } from "../query"
|
||||
* Icon search result
|
||||
*/
|
||||
export interface IconSearchResult {
|
||||
data: string[] /* Search result data */
|
||||
data: Icon[] /* Search result data */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -139,11 +139,35 @@ export function mountIconSearchResult(
|
||||
|
||||
/* Create and return component */
|
||||
return combineLatest([
|
||||
index$,
|
||||
query$.pipe(distinctUntilKeyChanged("value"))
|
||||
query$.pipe(distinctUntilKeyChanged("value")),
|
||||
index$
|
||||
.pipe(
|
||||
map(({ icons, emojis }) => [
|
||||
...Object.keys(icons.data),
|
||||
...Object.keys(emojis.data)
|
||||
])
|
||||
)
|
||||
])
|
||||
.pipe(
|
||||
map(([index, { value }]) => ({ data: search(index, value) })),
|
||||
withLatestFrom(index$),
|
||||
map(([[{ value }, data], index]) => {
|
||||
const results = search(data, value)
|
||||
return {
|
||||
data: results.map(name => {
|
||||
if (name in index.icons.data) {
|
||||
return {
|
||||
shortcode: name,
|
||||
url: `${index.icons.base}${index.icons.data[name]}`
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
shortcode: name,
|
||||
url: `${index.emojis.base}${index.emojis.data[name]}`
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}),
|
||||
tap(internal$),
|
||||
finalize(() => internal$.complete()),
|
||||
map(state => ({ ref: el, ...state }))
|
||||
|
@ -25,33 +25,12 @@ import { wrap } from "fuzzaldrin-plus"
|
||||
import { translation } from "~/_"
|
||||
import { h } from "~/utilities"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Data
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Icon CDN URL
|
||||
*/
|
||||
const base =
|
||||
"https://raw.githubusercontent.com/" +
|
||||
"squidfunk/mkdocs-material/" +
|
||||
"master/material/.icons/"
|
||||
import { Icon } from "../../components"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Helper functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Convert icon search result to shortcode
|
||||
*
|
||||
* @param value - Icon search result
|
||||
*
|
||||
* @returns Shortcode
|
||||
*/
|
||||
function shortcode(value: string): string {
|
||||
return `:${value.replace(/\.svg$/, "").replace(/\//g, "-")}:`
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight an icon search result
|
||||
*
|
||||
@ -61,7 +40,7 @@ function shortcode(value: string): string {
|
||||
* @returns Highlighted result
|
||||
*/
|
||||
function highlight(value: string, query: string) {
|
||||
return wrap(shortcode(value), query, {
|
||||
return wrap(value, query, {
|
||||
wrap: {
|
||||
tagOpen: "<b>",
|
||||
tagClose: "</b>"
|
||||
@ -76,25 +55,25 @@ function highlight(value: string, query: string) {
|
||||
/**
|
||||
* Render an icon search result
|
||||
*
|
||||
* @param value - Icon search result
|
||||
* @param icon - Icon search result
|
||||
* @param query - Icon search query
|
||||
*
|
||||
* @returns Element
|
||||
*/
|
||||
export function renderIconSearchResult(
|
||||
value: string, query: string
|
||||
icon: Icon, query: string
|
||||
): HTMLElement {
|
||||
return (
|
||||
<li class="mdx-icon-search-result__item">
|
||||
<span class="twemoji">
|
||||
<img src={base + value} />
|
||||
<img src={icon.url} />
|
||||
</span>
|
||||
<button
|
||||
class="md-clipboard--inline"
|
||||
title={translation("clipboard.copy")}
|
||||
data-clipboard-text={shortcode(value)}
|
||||
data-clipboard-text={`:${icon.shortcode}:`}
|
||||
>
|
||||
<code>{highlight(value, query)}</code>
|
||||
<code>{`:${highlight(icon.shortcode, query)}:`}</code>
|
||||
</button>
|
||||
</li>
|
||||
)
|
||||
|
@ -345,14 +345,40 @@ export default (_env: never, args: Configuration): Configuration[] => {
|
||||
/* Save template with replaced assets */
|
||||
fs.writeFileSync(file, template, "utf8")
|
||||
}
|
||||
}
|
||||
|
||||
/* Build search index for bundled icons */
|
||||
const index = await glob("**/*.svg", { cwd: "material/.icons" })
|
||||
fs.writeFileSync(
|
||||
"material/overrides/assets/javascripts/icons.json",
|
||||
JSON.stringify(index)
|
||||
)
|
||||
/* Build search index for bundled icons */
|
||||
const icons: Record<string, string> = {}
|
||||
for (const file of await glob("**/*.svg", {
|
||||
cwd: "material/.icons"
|
||||
})) {
|
||||
const name = file.replace(/\.svg$/, "").replace(/\//g, "-")
|
||||
icons[name] = file
|
||||
}
|
||||
|
||||
/* Build search index for emojis (based on Twemoji) */
|
||||
const emojis: Record<string, string> = {}
|
||||
const [database] = await glob("venv/**/twemoji_db.py")
|
||||
if (typeof database !== "undefined") {
|
||||
const contents = fs.readFileSync(database, "utf8")
|
||||
const [, content] = contents.match(/^emoji = ({.*})$.alias/ms)!
|
||||
for (const [name, data] of toPairs(JSON.parse(content))) {
|
||||
emojis[name.replace(/(^:|:$)/g, "")] = `${data.unicode}.svg`
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(
|
||||
"material/overrides/assets/javascripts/icon_search_index.json",
|
||||
JSON.stringify({
|
||||
icons: {
|
||||
base: "https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/material/.icons/",
|
||||
data: icons
|
||||
},
|
||||
emojis: {
|
||||
base: "https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/",
|
||||
data: emojis
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user