Restructure how icon themes are generated
This commit is contained in:
+12
-4
@@ -35,7 +35,7 @@ import zipfile
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from utils.material_icons import processMaterialIcons
|
from utils.icon_themes import processFontAwesome, processMaterialIcons
|
||||||
|
|
||||||
CURR_DIR = Path(__file__).parent
|
CURR_DIR = Path(__file__).parent
|
||||||
SETUP_DIR = CURR_DIR / "setup"
|
SETUP_DIR = CURR_DIR / "setup"
|
||||||
@@ -330,10 +330,10 @@ def buildSampleZip(args: argparse.Namespace | None = None) -> None:
|
|||||||
##
|
##
|
||||||
|
|
||||||
def buildIconTheme(args: argparse.Namespace) -> None:
|
def buildIconTheme(args: argparse.Namespace) -> None:
|
||||||
"""Build an icon theme."""
|
"""Build icon themes."""
|
||||||
print("")
|
print("")
|
||||||
print("Build Icon Theme")
|
print("Build Icon Themes")
|
||||||
print("================")
|
print("=================")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
workDir = Path(args.sources).absolute()
|
workDir = Path(args.sources).absolute()
|
||||||
@@ -384,6 +384,14 @@ def buildIconTheme(args: argparse.Namespace) -> None:
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if style in ("all", "fa"):
|
||||||
|
processFontAwesome(workDir, iconsDir, {
|
||||||
|
"font_awesome": {
|
||||||
|
"name": "Font Awesome 6",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
print("Done")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -0,0 +1,270 @@
|
|||||||
|
"""
|
||||||
|
novelWriter – Icon Theme Utils
|
||||||
|
==============================
|
||||||
|
|
||||||
|
This file is a part of novelWriter
|
||||||
|
Copyright (C) 2025 Veronica Berglyd Olsen and novelWriter contributors
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from xml.etree import ElementTree as ET
|
||||||
|
|
||||||
|
UTILS = Path(__file__).parent
|
||||||
|
|
||||||
|
ET.register_namespace("", "http://www.w3.org/2000/svg")
|
||||||
|
MATERIAL_REPO = "https://github.com/google/material-design-icons.git"
|
||||||
|
FONT_AWESOME_REPO = "https://github.com/FortAwesome/Font-Awesome.git"
|
||||||
|
ICONS = [
|
||||||
|
"alert_error",
|
||||||
|
"alert_info",
|
||||||
|
"alert_question",
|
||||||
|
"alert_warn",
|
||||||
|
|
||||||
|
"cls_archive",
|
||||||
|
"cls_character",
|
||||||
|
"cls_custom",
|
||||||
|
"cls_entity",
|
||||||
|
"cls_none",
|
||||||
|
"cls_novel",
|
||||||
|
"cls_object",
|
||||||
|
"cls_plot",
|
||||||
|
"cls_template",
|
||||||
|
"cls_timeline",
|
||||||
|
"cls_trash",
|
||||||
|
"cls_world",
|
||||||
|
|
||||||
|
"prj_folder",
|
||||||
|
"prj_document",
|
||||||
|
"prj_title",
|
||||||
|
"prj_chapter",
|
||||||
|
"prj_scene",
|
||||||
|
"prj_note",
|
||||||
|
|
||||||
|
"fmt_bold",
|
||||||
|
"fmt_italic",
|
||||||
|
"fmt_mark",
|
||||||
|
"fmt_strike",
|
||||||
|
"fmt_subscript",
|
||||||
|
"fmt_superscript",
|
||||||
|
"fmt_underline",
|
||||||
|
"fmt_toolbar",
|
||||||
|
|
||||||
|
"search",
|
||||||
|
"search_cancel",
|
||||||
|
"search_case",
|
||||||
|
"search_loop",
|
||||||
|
"search_preserve",
|
||||||
|
"search_project",
|
||||||
|
"search_regex",
|
||||||
|
"search_replace",
|
||||||
|
"search_word",
|
||||||
|
|
||||||
|
"bullet-off",
|
||||||
|
"bullet-on",
|
||||||
|
"unfold-hide",
|
||||||
|
"unfold-show",
|
||||||
|
|
||||||
|
"add",
|
||||||
|
"bookmarks",
|
||||||
|
"browse",
|
||||||
|
"cancel",
|
||||||
|
"checked",
|
||||||
|
"chevron_down",
|
||||||
|
"chevron_left",
|
||||||
|
"chevron_right",
|
||||||
|
"chevron_up",
|
||||||
|
"close",
|
||||||
|
"copy",
|
||||||
|
"document_add",
|
||||||
|
"document",
|
||||||
|
"edit",
|
||||||
|
"exclude",
|
||||||
|
"export",
|
||||||
|
"filter",
|
||||||
|
"fit_height",
|
||||||
|
"fit_width",
|
||||||
|
"folder",
|
||||||
|
"font",
|
||||||
|
"import",
|
||||||
|
"language",
|
||||||
|
"lines",
|
||||||
|
"list",
|
||||||
|
"manuscript",
|
||||||
|
"margin_bottom",
|
||||||
|
"margin_left",
|
||||||
|
"margin_right",
|
||||||
|
"margin_top",
|
||||||
|
"maximise",
|
||||||
|
"minimise",
|
||||||
|
"more_arrow",
|
||||||
|
"more_vertical",
|
||||||
|
"noncheckable",
|
||||||
|
"novel_view",
|
||||||
|
"open",
|
||||||
|
"outline",
|
||||||
|
"panel",
|
||||||
|
"pin",
|
||||||
|
"project_copy",
|
||||||
|
"project_view",
|
||||||
|
"quote",
|
||||||
|
"refresh",
|
||||||
|
"remove",
|
||||||
|
"revert",
|
||||||
|
"settings",
|
||||||
|
"star",
|
||||||
|
"stats",
|
||||||
|
"text",
|
||||||
|
"timer_off",
|
||||||
|
"timer",
|
||||||
|
"unchecked",
|
||||||
|
"view",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _loadMap(name: str) -> dict[str, str]:
|
||||||
|
"""Load a theme map file."""
|
||||||
|
data = json.loads((UTILS / f"{name}.json").read_text(encoding="utf-8"))
|
||||||
|
icons = {}
|
||||||
|
for key in ICONS:
|
||||||
|
if icon := data.get(key, ""):
|
||||||
|
icons[key] = icon
|
||||||
|
else:
|
||||||
|
print(f"- Missing: {key}")
|
||||||
|
return icons
|
||||||
|
|
||||||
|
|
||||||
|
def _fixXml(svg: ET.Element) -> str:
|
||||||
|
"""Clean up the SVG XML and add needed fields."""
|
||||||
|
svg.set("fill", "#000000")
|
||||||
|
svg.set("height", "128")
|
||||||
|
svg.set("width", "128")
|
||||||
|
return ET.tostring(svg).decode()
|
||||||
|
|
||||||
|
|
||||||
|
def _writeThemeFile(
|
||||||
|
path: Path, name: str, author: str, license: str, icons: dict[str, ET.Element]
|
||||||
|
) -> None:
|
||||||
|
"""Write an icon theme file."""
|
||||||
|
with open(path.with_suffix(".icons"), mode="w", encoding="utf-8") as out:
|
||||||
|
out.write("# This file is automatically generated. Do not edit.\n\n")
|
||||||
|
out.write("# Meta\n")
|
||||||
|
out.write(f"meta:name = {name}\n")
|
||||||
|
out.write(f"meta:author = {author}\n")
|
||||||
|
out.write(f"meta:license = {license}\n")
|
||||||
|
out.write("\n")
|
||||||
|
out.write("# Icons\n")
|
||||||
|
for key, svg in icons.items():
|
||||||
|
out.write(f"icon:{key:<15s} = {_fixXml(svg)}\n")
|
||||||
|
print(f"- Wrote: {len(icons)} icons")
|
||||||
|
print(f"- Target: {path.relative_to(UTILS.parent)}")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _cloneRepo(repoPath: Path, repoUrl: str) -> None:
|
||||||
|
"""Clone or update a local repo of icons."""
|
||||||
|
print(f"Updating: {repoUrl}")
|
||||||
|
if not repoPath.is_dir():
|
||||||
|
subprocess.call(["git", "clone", repoUrl, "--depth", "50"], cwd=repoPath.parent)
|
||||||
|
else:
|
||||||
|
subprocess.call(["git", "pull"], cwd=repoPath)
|
||||||
|
print("")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def processMaterialIcons(workDir: Path, iconsDir: Path, jobs: dict) -> None:
|
||||||
|
"""Process material icons of a given spec and write output file."""
|
||||||
|
srcRepo = workDir / "material-design-icons"
|
||||||
|
_cloneRepo(srcRepo, MATERIAL_REPO)
|
||||||
|
|
||||||
|
for file, job in jobs.items():
|
||||||
|
name: str = job["name"]
|
||||||
|
style: str = job["style"]
|
||||||
|
filled: bool = job["filled"]
|
||||||
|
weight: int = job["weight"]
|
||||||
|
|
||||||
|
kind = f"wght{weight}" if weight != 400 else ""
|
||||||
|
kind += "fill1" if filled else ""
|
||||||
|
|
||||||
|
print(f"Processing: {name}")
|
||||||
|
|
||||||
|
icons: dict[str, ET.Element] = {}
|
||||||
|
iconSrc = srcRepo / "symbols" / "web"
|
||||||
|
for key, icon in _loadMap("material_symbols").items():
|
||||||
|
if kind:
|
||||||
|
fileNmae = f"{icon}_{kind}_24px.svg"
|
||||||
|
else:
|
||||||
|
fileNmae = f"{icon}_24px.svg"
|
||||||
|
iconFile = iconSrc / icon / f"materialsymbols{style}" / fileNmae
|
||||||
|
if iconFile.is_file():
|
||||||
|
icons[key] = ET.fromstring(iconFile.read_text(encoding="utf-8"))
|
||||||
|
else:
|
||||||
|
print(f"Not Found: {iconFile}")
|
||||||
|
|
||||||
|
target = iconsDir / f"{file}.icons"
|
||||||
|
_writeThemeFile(target, name, "Google Inc", "Apache 2.0", icons)
|
||||||
|
|
||||||
|
print("")
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def processFontAwesome(workDir: Path, iconsDir: Path, jobs: dict) -> None:
|
||||||
|
"""Process Font Awesome icons of a given spec and write output file."""
|
||||||
|
srcRepo = workDir / "Font-Awesome"
|
||||||
|
_cloneRepo(srcRepo, FONT_AWESOME_REPO)
|
||||||
|
|
||||||
|
for file, job in jobs.items():
|
||||||
|
name: str = job["name"]
|
||||||
|
print(f"Processing: {name}")
|
||||||
|
|
||||||
|
icons: dict[str, ET.Element] = {}
|
||||||
|
iconSrc = srcRepo / "svgs"
|
||||||
|
for key, value in _loadMap("font_awesome").items():
|
||||||
|
icon, _, forced = value.partition(":")
|
||||||
|
iconSolid = iconSrc / "solid" / f"{icon}.svg"
|
||||||
|
iconRegular = iconSrc / "regular" / f"{icon}.svg"
|
||||||
|
if forced == "regular":
|
||||||
|
iconFile = iconRegular
|
||||||
|
elif forced == "solid":
|
||||||
|
iconFile = iconSolid
|
||||||
|
elif iconSolid.is_file():
|
||||||
|
iconFile = iconSolid
|
||||||
|
elif iconRegular.is_file():
|
||||||
|
iconFile = iconRegular
|
||||||
|
else:
|
||||||
|
print(f"Not Found: {icon}.svg")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if iconFile.is_file():
|
||||||
|
svg = ET.fromstring(iconFile.read_text(encoding="utf-8"))
|
||||||
|
viewbox = [int(x) for x in svg.get("viewBox", "").split()]
|
||||||
|
viewbox = [viewbox[2]//2 - 256, 0, 512, 512]
|
||||||
|
svg.set("viewBox", " ".join(str(x) for x in viewbox))
|
||||||
|
icons[key] = svg
|
||||||
|
else:
|
||||||
|
print(f"Not Found: {icon}.svg")
|
||||||
|
continue
|
||||||
|
|
||||||
|
target = iconsDir / f"{file}.icons"
|
||||||
|
_writeThemeFile(target, name, "Fonticons Inc", "Font Awesome Free License", icons)
|
||||||
|
|
||||||
|
print("")
|
||||||
|
|
||||||
|
return
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
"""
|
|
||||||
novelWriter – Material Icon Theme
|
|
||||||
=================================
|
|
||||||
|
|
||||||
This file is a part of novelWriter
|
|
||||||
Copyright (C) 2025 Veronica Berglyd Olsen and novelWriter contributors
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
from xml.etree import ElementTree as ET
|
|
||||||
|
|
||||||
ET.register_namespace("", "http://www.w3.org/2000/svg")
|
|
||||||
MATERIAL_REPO = "https://github.com/google/material-design-icons.git"
|
|
||||||
ICON_MAP = {
|
|
||||||
"alert_error": "error",
|
|
||||||
"alert_info": "info",
|
|
||||||
"alert_question": "help",
|
|
||||||
"alert_warn": "warning",
|
|
||||||
|
|
||||||
"cls_archive": "archive",
|
|
||||||
"cls_character": "group",
|
|
||||||
"cls_custom": "label",
|
|
||||||
"cls_entity": "apartment",
|
|
||||||
"cls_none": "close",
|
|
||||||
"cls_novel": "book_2",
|
|
||||||
"cls_object": "key",
|
|
||||||
"cls_plot": "extension",
|
|
||||||
"cls_template": "topic",
|
|
||||||
"cls_timeline": "hourglass_empty",
|
|
||||||
"cls_trash": "delete",
|
|
||||||
"cls_world": "globe",
|
|
||||||
|
|
||||||
"prj_folder": "folder",
|
|
||||||
"prj_document": "news",
|
|
||||||
"prj_title": "news",
|
|
||||||
"prj_chapter": "news",
|
|
||||||
"prj_scene": "news",
|
|
||||||
"prj_note": "sticky_note_2",
|
|
||||||
|
|
||||||
"fmt_bold": "format_bold",
|
|
||||||
"fmt_italic": "format_italic",
|
|
||||||
"fmt_mark": "format_ink_highlighter",
|
|
||||||
"fmt_strike": "strikethrough_s",
|
|
||||||
"fmt_subscript": "subscript",
|
|
||||||
"fmt_superscript": "superscript",
|
|
||||||
"fmt_underline": "format_underlined",
|
|
||||||
"fmt_toolbar": "text_format",
|
|
||||||
|
|
||||||
"search": "search",
|
|
||||||
"search_cancel": "close",
|
|
||||||
"search_case": "match_case",
|
|
||||||
"search_loop": "laps",
|
|
||||||
"search_preserve": "text_fields",
|
|
||||||
"search_project": "document_search",
|
|
||||||
"search_regex": "regular_expression",
|
|
||||||
"search_replace": "find_replace",
|
|
||||||
"search_word": "match_word",
|
|
||||||
|
|
||||||
"bullet-off": "radio_button_unchecked",
|
|
||||||
"bullet-on": "radio_button_checked",
|
|
||||||
"unfold-hide": "arrow_right",
|
|
||||||
"unfold-show": "arrow_drop_down",
|
|
||||||
|
|
||||||
"add": "add",
|
|
||||||
"bookmarks": "bookmarks",
|
|
||||||
"browse": "folder_open",
|
|
||||||
"cancel": "cancel",
|
|
||||||
"checked": "check_box",
|
|
||||||
"chevron_down": "keyboard_arrow_down",
|
|
||||||
"chevron_left": "arrow_back_ios",
|
|
||||||
"chevron_right": "arrow_forward_ios",
|
|
||||||
"chevron_up": "keyboard_arrow_up",
|
|
||||||
"close": "close",
|
|
||||||
"copy": "content_copy",
|
|
||||||
"document_add": "note_add",
|
|
||||||
"document": "docs",
|
|
||||||
"edit": "edit",
|
|
||||||
"exclude": "do_not_disturb_on",
|
|
||||||
"export": "file_export",
|
|
||||||
"filter": "filter_alt",
|
|
||||||
"fit_height": "fit_page_height",
|
|
||||||
"fit_width": "fit_page_width",
|
|
||||||
"folder": "folder",
|
|
||||||
"font": "font_download",
|
|
||||||
"import": "tab_move",
|
|
||||||
"language": "translate",
|
|
||||||
"lines": "reorder",
|
|
||||||
"list": "format_list_bulleted",
|
|
||||||
"manuscript": "export_notes",
|
|
||||||
"margin_bottom": "vertical_align_bottom",
|
|
||||||
"margin_left": "keyboard_tab_rtl",
|
|
||||||
"margin_right": "keyboard_tab",
|
|
||||||
"margin_top": "vertical_align_top",
|
|
||||||
"maximise": "fullscreen",
|
|
||||||
"minimise": "fullscreen_exit",
|
|
||||||
"more_arrow": "arrow_right",
|
|
||||||
"more_vertical": "more_vert",
|
|
||||||
"noncheckable": "indeterminate_check_box",
|
|
||||||
"novel_view": "book_4_spark",
|
|
||||||
"open": "open_in_new",
|
|
||||||
"outline": "summarize",
|
|
||||||
"panel": "dock_to_bottom",
|
|
||||||
"pin": "keep",
|
|
||||||
"project_copy": "folder_copy",
|
|
||||||
"project_view": "bookmark_manager",
|
|
||||||
"quote": "format_quote",
|
|
||||||
"refresh": "refresh",
|
|
||||||
"remove": "remove",
|
|
||||||
"revert": "settings_backup_restore",
|
|
||||||
"settings": "settings",
|
|
||||||
"star": "star",
|
|
||||||
"stats": "bar_chart",
|
|
||||||
"text": "subject",
|
|
||||||
"timer_off": "timer_off",
|
|
||||||
"timer": "timer",
|
|
||||||
"unchecked": "disabled_by_default",
|
|
||||||
"view": "visibility",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _fixXml(svg: str) -> str:
|
|
||||||
"""Clean up the SVG XML and add needed fields."""
|
|
||||||
xSvg = ET.fromstring(svg)
|
|
||||||
xSvg.set("fill", "#000000")
|
|
||||||
xSvg.set("height", "128")
|
|
||||||
xSvg.set("width", "128")
|
|
||||||
return ET.tostring(xSvg).decode()
|
|
||||||
|
|
||||||
|
|
||||||
def processMaterialIcons(workDir: Path, iconsDir: Path, jobs: dict) -> None:
|
|
||||||
"""Process material icons of a given spec and write output file."""
|
|
||||||
srcRepo = workDir / "material-design-icons"
|
|
||||||
if not srcRepo.is_dir():
|
|
||||||
subprocess.call(["git", "clone", MATERIAL_REPO, "--depth", "50"], cwd=workDir)
|
|
||||||
else:
|
|
||||||
subprocess.call(["git", "pull"], cwd=srcRepo)
|
|
||||||
|
|
||||||
for file, job in jobs.items():
|
|
||||||
name: str = job["name"]
|
|
||||||
style: str = job["style"]
|
|
||||||
filled: bool = job["filled"]
|
|
||||||
weight: int = job["weight"]
|
|
||||||
|
|
||||||
kind = f"wght{weight}" if weight != 400 else ""
|
|
||||||
kind += "fill1" if filled else ""
|
|
||||||
|
|
||||||
print("")
|
|
||||||
print(f"Processing: {name}")
|
|
||||||
print("")
|
|
||||||
with open(iconsDir / f"{file}.icons", mode="w", encoding="utf-8") as icons:
|
|
||||||
icons.write("# This file is automatically generated. Do not edit.\n\n")
|
|
||||||
icons.write("# Meta\n")
|
|
||||||
icons.write(f"meta:name = {name}\n")
|
|
||||||
icons.write("meta:author = Google Inc\n")
|
|
||||||
icons.write("meta:license = Apache 2.0\n")
|
|
||||||
icons.write("\n")
|
|
||||||
icons.write("# Icons\n")
|
|
||||||
iconSrc = srcRepo / "symbols" / "web"
|
|
||||||
for key, icon in ICON_MAP.items():
|
|
||||||
if kind:
|
|
||||||
fileNmae = f"{icon}_{kind}_24px.svg"
|
|
||||||
else:
|
|
||||||
fileNmae = f"{icon}_24px.svg"
|
|
||||||
iconFile = iconSrc / icon / f"materialsymbols{style}" / fileNmae
|
|
||||||
if iconFile.is_file():
|
|
||||||
svg = iconFile.read_text(encoding="utf-8")
|
|
||||||
icons.write(f"icon:{key:<15s} = {_fixXml(svg)}\n")
|
|
||||||
print(f"Wrote: {iconFile.stem}")
|
|
||||||
else:
|
|
||||||
print(f"Not Found: {iconFile}")
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
"alert_error": "error",
|
||||||
|
"alert_info": "info",
|
||||||
|
"alert_question": "help",
|
||||||
|
"alert_warn": "warning",
|
||||||
|
|
||||||
|
"cls_archive": "archive",
|
||||||
|
"cls_character": "group",
|
||||||
|
"cls_custom": "label",
|
||||||
|
"cls_entity": "apartment",
|
||||||
|
"cls_none": "close",
|
||||||
|
"cls_novel": "book_2",
|
||||||
|
"cls_object": "key",
|
||||||
|
"cls_plot": "extension",
|
||||||
|
"cls_template": "topic",
|
||||||
|
"cls_timeline": "hourglass_empty",
|
||||||
|
"cls_trash": "delete",
|
||||||
|
"cls_world": "globe",
|
||||||
|
|
||||||
|
"prj_folder": "folder",
|
||||||
|
"prj_document": "news",
|
||||||
|
"prj_title": "news",
|
||||||
|
"prj_chapter": "news",
|
||||||
|
"prj_scene": "news",
|
||||||
|
"prj_note": "sticky_note_2",
|
||||||
|
|
||||||
|
"fmt_bold": "format_bold",
|
||||||
|
"fmt_italic": "format_italic",
|
||||||
|
"fmt_mark": "format_ink_highlighter",
|
||||||
|
"fmt_strike": "strikethrough_s",
|
||||||
|
"fmt_subscript": "subscript",
|
||||||
|
"fmt_superscript": "superscript",
|
||||||
|
"fmt_underline": "format_underlined",
|
||||||
|
"fmt_toolbar": "text_format",
|
||||||
|
|
||||||
|
"search": "search",
|
||||||
|
"search_cancel": "close",
|
||||||
|
"search_case": "match_case",
|
||||||
|
"search_loop": "laps",
|
||||||
|
"search_preserve": "text_fields",
|
||||||
|
"search_project": "document_search",
|
||||||
|
"search_regex": "regular_expression",
|
||||||
|
"search_replace": "find_replace",
|
||||||
|
"search_word": "match_word",
|
||||||
|
|
||||||
|
"bullet-off": "radio_button_unchecked",
|
||||||
|
"bullet-on": "radio_button_checked",
|
||||||
|
"unfold-hide": "arrow_right",
|
||||||
|
"unfold-show": "arrow_drop_down",
|
||||||
|
|
||||||
|
"add": "add",
|
||||||
|
"bookmarks": "bookmarks",
|
||||||
|
"browse": "folder_open",
|
||||||
|
"cancel": "cancel",
|
||||||
|
"checked": "check_box",
|
||||||
|
"chevron_down": "keyboard_arrow_down",
|
||||||
|
"chevron_left": "arrow_back_ios",
|
||||||
|
"chevron_right": "arrow_forward_ios",
|
||||||
|
"chevron_up": "keyboard_arrow_up",
|
||||||
|
"close": "close",
|
||||||
|
"copy": "content_copy",
|
||||||
|
"document_add": "note_add",
|
||||||
|
"document": "docs",
|
||||||
|
"edit": "edit",
|
||||||
|
"exclude": "do_not_disturb_on",
|
||||||
|
"export": "file_export",
|
||||||
|
"filter": "filter_alt",
|
||||||
|
"fit_height": "fit_page_height",
|
||||||
|
"fit_width": "fit_page_width",
|
||||||
|
"folder": "folder",
|
||||||
|
"font": "font_download",
|
||||||
|
"import": "tab_move",
|
||||||
|
"language": "translate",
|
||||||
|
"lines": "reorder",
|
||||||
|
"list": "format_list_bulleted",
|
||||||
|
"manuscript": "export_notes",
|
||||||
|
"margin_bottom": "vertical_align_bottom",
|
||||||
|
"margin_left": "keyboard_tab_rtl",
|
||||||
|
"margin_right": "keyboard_tab",
|
||||||
|
"margin_top": "vertical_align_top",
|
||||||
|
"maximise": "fullscreen",
|
||||||
|
"minimise": "fullscreen_exit",
|
||||||
|
"more_arrow": "arrow_right",
|
||||||
|
"more_vertical": "more_vert",
|
||||||
|
"noncheckable": "indeterminate_check_box",
|
||||||
|
"novel_view": "book_4_spark",
|
||||||
|
"open": "open_in_new",
|
||||||
|
"outline": "summarize",
|
||||||
|
"panel": "dock_to_bottom",
|
||||||
|
"pin": "keep",
|
||||||
|
"project_copy": "folder_copy",
|
||||||
|
"project_view": "bookmark_manager",
|
||||||
|
"quote": "format_quote",
|
||||||
|
"refresh": "refresh",
|
||||||
|
"remove": "remove",
|
||||||
|
"revert": "settings_backup_restore",
|
||||||
|
"settings": "settings",
|
||||||
|
"star": "star",
|
||||||
|
"stats": "bar_chart",
|
||||||
|
"text": "subject",
|
||||||
|
"timer_off": "timer_off",
|
||||||
|
"timer": "timer",
|
||||||
|
"unchecked": "disabled_by_default",
|
||||||
|
"view": "visibility"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user