mirror of https://github.com/jpanther/congo.git
Compare commits
1 Commits
40640f2f34
...
c84bbe4ce2
Author | SHA1 | Date |
---|---|---|
Wen Junhua | c84bbe4ce2 |
File diff suppressed because it is too large
Load Diff
|
@ -9,8 +9,7 @@
|
||||||
"dev": "NODE_ENV=development ./node_modules/tailwindcss/lib/cli.js -i ./assets/css/main.css -o ./assets/css/compiled/main.css --jit -w",
|
"dev": "NODE_ENV=development ./node_modules/tailwindcss/lib/cli.js -i ./assets/css/main.css -o ./assets/css/compiled/main.css --jit -w",
|
||||||
"build": "NODE_ENV=production ./node_modules/tailwindcss/lib/cli.js -i ./assets/css/main.css -o ./assets/css/compiled/main.css --jit",
|
"build": "NODE_ENV=production ./node_modules/tailwindcss/lib/cli.js -i ./assets/css/main.css -o ./assets/css/compiled/main.css --jit",
|
||||||
"example": "hugo server --bind 0.0.0.0 -p 8008 --source exampleSite --themesDir ../.. --buildDrafts -b http://localhost/congo/ ",
|
"example": "hugo server --bind 0.0.0.0 -p 8008 --source exampleSite --themesDir ../.. --buildDrafts -b http://localhost/congo/ ",
|
||||||
"lighthouse": "lhci autorun",
|
"lighthouse": "lhci autorun"
|
||||||
"add-icon": "node scripts/index.js add-icon"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -33,12 +32,11 @@
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
"chart.js": "^4.4.1",
|
"chart.js": "^4.4.1",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"jsdom": "^23.0.1",
|
|
||||||
"katex": "^0.16.9",
|
"katex": "^0.16.9",
|
||||||
"mermaid": "^10.6.1",
|
"mermaid": "^10.6.1",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
"prettier-plugin-go-template": "^0.0.15",
|
"prettier-plugin-go-template": "^0.0.15",
|
||||||
"prettier-plugin-tailwindcss": "^0.5.10",
|
"prettier-plugin-tailwindcss": "^0.5.9",
|
||||||
"quicklink": "^2.3.0",
|
"quicklink": "^2.3.0",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"tailwindcss": "^3.4.0",
|
"tailwindcss": "^3.4.0",
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
const { program } = require("commander");
|
|
||||||
const { add_icon_to_congo } = require("./update_icon");
|
|
||||||
|
|
||||||
// Adds an icon to the project.
|
|
||||||
program
|
|
||||||
.command("add-icon <icon_name>")
|
|
||||||
.description("Add icon to the project")
|
|
||||||
.action(add_icon_to_congo);
|
|
||||||
|
|
||||||
program.parse(process.argv);
|
|
|
@ -1,97 +0,0 @@
|
||||||
const jsdom = require("jsdom");
|
|
||||||
const fs = require("fs");
|
|
||||||
|
|
||||||
const DOC_DIR = "./exampleSite/content/samples/icons";
|
|
||||||
const FONTAWESOME_VERSION = "v6.5.1";
|
|
||||||
const DEFAULT_TABLE_DELIMITER = "| -------------------- | --------------------------------- |";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves an icon to the congo project and update documentation.
|
|
||||||
* @param {string} icon_name Icon name from Font Awesome to download
|
|
||||||
* @returns null
|
|
||||||
*/
|
|
||||||
const add_icon_to_congo = async (icon_name) => {
|
|
||||||
try {
|
|
||||||
const icon_url = create_icon_url(icon_name, FONTAWESOME_VERSION);
|
|
||||||
const file = await get_file(icon_url);
|
|
||||||
const final_svg = modify_svg_string(file);
|
|
||||||
const icon_download_path = create_icon_download_path(icon_name);
|
|
||||||
save_file(icon_download_path, final_svg);
|
|
||||||
add_documentation(icon_name);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const modify_svg_string = (svg_string) => {
|
|
||||||
try {
|
|
||||||
dom = new jsdom.JSDOM(svg_string);
|
|
||||||
svg = dom.window.document.documentElement.querySelector("svg");
|
|
||||||
svg.querySelector("path").setAttribute("fill", "currentColor");
|
|
||||||
return svg.outerHTML;
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error("Invalid SVG file");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const create_icon_url = (icon_name, fontawesome_version) => {
|
|
||||||
return `https://site-assets.fontawesome.com/releases/${fontawesome_version}/svgs/brands/${icon_name}.svg`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const create_icon_download_path = (icon_name) => {
|
|
||||||
return `./assets/icons/${icon_name}.svg`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const get_file = async (url) => {
|
|
||||||
console.log("Getting file at " + url + "...");
|
|
||||||
const response = await fetch(url);
|
|
||||||
if (response.status >= 400) {
|
|
||||||
throw new Error("Could not download icon / icon not found");
|
|
||||||
}
|
|
||||||
console.log("File retrieved!");
|
|
||||||
return response.text();
|
|
||||||
};
|
|
||||||
|
|
||||||
const save_file = (file_path, file) => {
|
|
||||||
console.log("Saving file at " + file_path + "...");
|
|
||||||
fs.writeFile(file_path, file, function (err) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.log("File saved!");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const add_documentation = async (icon_name) => {
|
|
||||||
files = get_md_docs();
|
|
||||||
|
|
||||||
for (const file of files) {
|
|
||||||
const file_path = `${DOC_DIR}/${file}`;
|
|
||||||
const file_contents = fs.readFileSync(file_path, "utf8");
|
|
||||||
const file_result = process_file(file_contents, icon_name);
|
|
||||||
// Save file_result to file_path
|
|
||||||
fs.writeFile(file_path, file_result, function (err) {
|
|
||||||
if (err) throw err;
|
|
||||||
});
|
|
||||||
console.log(`Updated ${file_path}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the file contents to include the icon name.
|
|
||||||
* @param {string} file_contents contents of the documentation files.
|
|
||||||
* @returns {string} processed file contents.
|
|
||||||
*/
|
|
||||||
const process_file = (file_contents, icon_name) => {
|
|
||||||
const [headers, table] = file_contents.split(DEFAULT_TABLE_DELIMITER);
|
|
||||||
const table_rows = table.split("\n").map((x) => x.trim()).filter((row) => row !== "");
|
|
||||||
table_rows.push(table_rows[0].replace("amazon", icon_name));
|
|
||||||
table_rows.sort();
|
|
||||||
const new_table = table_rows.join("\n");
|
|
||||||
return `${headers.trimEnd()}\n${DEFAULT_TABLE_DELIMITER}\n${new_table}\n`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const get_md_docs = () => {
|
|
||||||
return fs.readdirSync(DOC_DIR).filter((file) => file.endsWith(".md"));
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = { add_icon_to_congo };
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
import argparse
|
||||||
|
import bs4
|
||||||
|
import re
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
import os
|
||||||
|
|
||||||
|
from typing import Tuple, List
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_FONTAWESOME_VERSION = "v6.5.1"
|
||||||
|
DEFAULT_BASE_URL = (
|
||||||
|
"https://site-assets.fontawesome.com/releases/%s/svgs/brands/"
|
||||||
|
% DEFAULT_FONTAWESOME_VERSION
|
||||||
|
+ "%s.svg"
|
||||||
|
)
|
||||||
|
DEFAULT_BASE_PATH = os.path.join(os.getcwd(), "..")
|
||||||
|
DEFAULT_ICON_DIR_PATH = os.path.join(
|
||||||
|
DEFAULT_BASE_PATH,
|
||||||
|
"assets",
|
||||||
|
"icons",
|
||||||
|
)
|
||||||
|
DEFAULT_SVG_ATTR = {"fill": "currentColor"}
|
||||||
|
DEFAULT_ICON_DOCS_DIR = os.path.join(
|
||||||
|
DEFAULT_BASE_PATH, "exampleSite", "content", "samples", "icons"
|
||||||
|
)
|
||||||
|
DEFAULT_TABLE_DELIMITER = "| -------------------- | --------------------------------- |"
|
||||||
|
|
||||||
|
|
||||||
|
def download_icon(download_url: str) -> None:
|
||||||
|
"""Downloads the icon based on the URL"""
|
||||||
|
with requests.Session() as s:
|
||||||
|
return s.get(download_url).content
|
||||||
|
|
||||||
|
|
||||||
|
def update_svg_to_theme(svg: bytes) -> bytes:
|
||||||
|
"""Update the current color of SVG to match theme"""
|
||||||
|
soup = bs4.BeautifulSoup(svg, features="html.parser")
|
||||||
|
|
||||||
|
# Update attrs
|
||||||
|
svg_elem = soup.find("svg").find("path")
|
||||||
|
for k, v in DEFAULT_SVG_ATTR.items():
|
||||||
|
svg_elem[k] = v
|
||||||
|
|
||||||
|
# Remove comments
|
||||||
|
return re.sub(r"<!.*?->", "", str(soup))
|
||||||
|
|
||||||
|
|
||||||
|
def update_docs(icon_name: str) -> None:
|
||||||
|
"""Update icon to docs"""
|
||||||
|
files = get_folder_md(DEFAULT_ICON_DOCS_DIR)
|
||||||
|
for file in files:
|
||||||
|
# Parse Table
|
||||||
|
logging.debug(f"reading {file}")
|
||||||
|
with open(file) as f:
|
||||||
|
file_data = f.read()
|
||||||
|
table_fmt, table = parse_table(file_data)
|
||||||
|
table.append(str(table[0]).replace("amazon", icon_name))
|
||||||
|
|
||||||
|
# Write Doc
|
||||||
|
with open(file, "w") as f:
|
||||||
|
f.write(
|
||||||
|
"\n".join(
|
||||||
|
(
|
||||||
|
table_fmt,
|
||||||
|
DEFAULT_TABLE_DELIMITER,
|
||||||
|
"\n".join(sorted(table)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_folder_md(dir_path: str) -> List[str]:
|
||||||
|
return list(
|
||||||
|
map(
|
||||||
|
lambda path: os.path.join(dir_path, path),
|
||||||
|
filter(lambda x: x.endswith(".md"), os.listdir(dir_path)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_table(table_str: str) -> Tuple[str, List[str]]:
|
||||||
|
"""Parse the table to a list of (article_fmt, (icon_name, icon_shortcode))"""
|
||||||
|
headers, table = table_str.split(DEFAULT_TABLE_DELIMITER)
|
||||||
|
return headers.strip(), list(
|
||||||
|
filter(
|
||||||
|
lambda x: len(x.strip()) > 0,
|
||||||
|
map(
|
||||||
|
lambda x: x.strip(),
|
||||||
|
table.split("\n"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def save_file(name: str, svg: str) -> None:
|
||||||
|
file_name = f"{name}.svg"
|
||||||
|
logging.debug(f"saving icon to {file_name}")
|
||||||
|
with open(
|
||||||
|
os.path.join(
|
||||||
|
DEFAULT_ICON_DIR_PATH,
|
||||||
|
file_name,
|
||||||
|
),
|
||||||
|
"w",
|
||||||
|
) as file:
|
||||||
|
file.write(svg)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> Tuple[str, str, int]:
|
||||||
|
"""
|
||||||
|
Parse arguments.
|
||||||
|
Returns the following:
|
||||||
|
1. Icon URL: str
|
||||||
|
2. Icon Representation :str
|
||||||
|
3. Log Level: int
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser(description="This script adds an icon to this congo theme and updates the relevant documentation.")
|
||||||
|
parser.add_argument(
|
||||||
|
"-v",
|
||||||
|
"--verbose",
|
||||||
|
help="show debug messages during script execution",
|
||||||
|
required=False,
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-u",
|
||||||
|
"--url",
|
||||||
|
help="full url of the icon svg, defaults to fortawesome url",
|
||||||
|
required=False,
|
||||||
|
nargs=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"name",
|
||||||
|
help="name of the icon to be added. EG: `github`",
|
||||||
|
)
|
||||||
|
|
||||||
|
parse_res = parser.parse_args()
|
||||||
|
url = DEFAULT_BASE_URL % parse_res.name
|
||||||
|
if parse_res.url is not None:
|
||||||
|
url = parse_res.url[0]
|
||||||
|
|
||||||
|
log_level = logging.DEBUG if parse_res.verbose else logging.INFO
|
||||||
|
return url, parse_res.name, log_level
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
icon_url, icon_name, log_level = parse_args()
|
||||||
|
|
||||||
|
# Setup logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=log_level,
|
||||||
|
format="%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s",
|
||||||
|
datefmt="%Y-%m-%d %H:%M:%S",
|
||||||
|
)
|
||||||
|
logging.debug(f"Using default base URL: {DEFAULT_BASE_URL}")
|
||||||
|
logging.info(f"Using Log Level: {logging.getLevelName(log_level)}")
|
||||||
|
logging.info(f"Using URL: {icon_url}")
|
||||||
|
logging.info(f"Using Icon Name: {icon_name}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Download Icon
|
||||||
|
logging.debug(f"fetching icon at {icon_url}")
|
||||||
|
svg_content = download_icon(icon_url)
|
||||||
|
|
||||||
|
# Patch svg attrs
|
||||||
|
logging.debug(
|
||||||
|
f"remove svg comments and update svg attrs with {DEFAULT_SVG_ATTR}"
|
||||||
|
)
|
||||||
|
final_svg = update_svg_to_theme(svg_content)
|
||||||
|
|
||||||
|
# Save file
|
||||||
|
logging.debug(f"saving icon to {DEFAULT_ICON_DIR_PATH}")
|
||||||
|
save_file(icon_name, final_svg)
|
||||||
|
|
||||||
|
# Write to docs
|
||||||
|
logging.debug(f"updating docs from {DEFAULT_ICON_DOCS_DIR} dir")
|
||||||
|
update_docs(icon_name)
|
||||||
|
except Exception as e:
|
||||||
|
logging.critical(f"error adding icon {str(e)}")
|
||||||
|
else:
|
||||||
|
logging.info(f"{icon_name} added successfully")
|
Loading…
Reference in New Issue