extends "res://addons/icon_explorer/internal/scripts/collection.gd" const IconBootstrap := preload("res://addons/icon_explorer/internal/ext/bootstrap/icon.gd") const ZipExtractorThreaded := preload("res://addons/icon_explorer/internal/scripts/tools/zip_extractor_threaded.gd") const _DOWNLOAD_FILE: String = "https://github.com/twbs/icons/archive/main.zip" func _init() -> void: self.name = "Bootstrap Icons" self.version = "" self.author = "The Bootstrap Authors" self.license = "MIT" self.web = "https://github.com/twbs/icons" # OVERRIDE func color_icon(buffer: String, color: String) -> String: return buffer.replace("currentColor", "#" + color) # OVERRIDE func load() -> Array: var dir: DirAccess = DirAccess.open(self._meta_directory()) if !dir: return [[], PackedStringArray()] var icons: Array[Icon] = [] var buffers: PackedStringArray = PackedStringArray() var err: Error = dir.list_dir_begin() if err != OK: push_error("[Icon Explorer] Failed to list directory: " + error_string(err)) return [[], PackedStringArray()] var file_name: String = dir.get_next() while file_name != "": if dir.current_is_dir(): file_name = dir.get_next() continue var res: Array = self._load_item(file_name) if res.size() == 2: icons.append(res[0]) buffers.append(res[1]) file_name = dir.get_next() dir.list_dir_end() dir = null var parser_version: JSON = JSON.new() var res_version: int = parser_version.parse(FileAccess.get_file_as_string(self.directory().path_join("icons-main/package.json"))) if res_version != OK: push_warning("could not parse bootstrap package.json: '%s'", [parser_version.get_error_message()]) return [[], PackedStringArray()] self.version = parser_version.data["version"] return [icons, buffers] func _load_item(file_name: String) -> Array: var icon: IconBootstrap = IconBootstrap.new() icon.collection = self icon.svg_size = Vector2i(16, 16) icon.colorable = true var meta: String = FileAccess.get_file_as_string(self._meta_directory().path_join(file_name)) if meta == "": push_warning("could not read bootstrap meta file '", file_name, "'") return [] var cur_token: int = 0 for line: String in meta.split("\n"): if line.begins_with("title: "): icon.name = line.lstrip("title: ") cur_token = 0 continue if line == "categories:": cur_token = 1 continue if line == "tags:": cur_token = 2 continue if line.begins_with(" - "): match cur_token: 1: icon.categories.append(line.lstrip(" - ")) 2: icon.tags.append(line.lstrip(" - ")) continue if line.begins_with("added:"): icon.version_added = line.lstrip("added: ") if icon.name == "": push_warning("bootstrap '", file_name, "' has no name") return [] icon.icon_path = self.icon_directory().path_join(file_name.get_basename() + ".svg") var buffer: String = FileAccess.get_file_as_string(icon.icon_path) if buffer == "": push_warning("could not load '" + icon.icon_path + "'") return [] return [icon, self.color_icon(buffer, "FFFFFF")] # OVERRIDE func install(http: HTTPRequest, _version: String) -> Error: DirAccess.make_dir_recursive_absolute(self.directory()) var zip_path: String = OS.get_temp_dir().path_join(self.name.validate_filename() + ".zip") http.download_file = zip_path var downloader: Io.Downloader = Io.Downloader.new(http) downloader.await_request(_DOWNLOAD_FILE) if downloader.result != HTTPRequest.RESULT_SUCCESS: return Error.FAILED var extractor: ZipExtractorThreaded = ZipExtractorThreaded.new(_create_extract_path.bind([ "icons-main/package.json", "icons-main/icons/", "icons-main/docs/content/icons/", "icons-main/LICENSE", ])) extractor.thread_count = maxi(OS.get_processor_count() / 2, 1) extractor.extract(zip_path, self.directory()) extractor.wait() if extractor.error() != Error.OK: return Error.FAILED DirAccess.remove_absolute(zip_path) return Error.OK # OVERRIDE func remove() -> Error: self.version = "" return super.remove() # OVERRIDE func update_latest_version(http: HTTPRequest) -> void: var downloader: Io.Downloader = Io.Downloader.new(http) downloader.await_request("https://raw.githubusercontent.com/twbs/icons/main/package.json") if downloader.result != HTTPRequest.RESULT_SUCCESS: return var parser_version: JSON = JSON.new() var res_version: int = parser_version.parse(downloader.body.get_string_from_utf8()) if res_version != OK: push_warning("could get latest bootstrap version: '%s'", [parser_version.get_error_message()]) return self.latest_version = parser_version.data["version"] # OVERRIDE func icon_directory() -> String: return self.directory().path_join("icons-main/icons/") func _meta_directory() -> String: return self.directory().path_join("icons-main/docs/content/icons/")