diff --git a/igniter/bootstrap_repos.py b/igniter/bootstrap_repos.py index b44689ba89..7c4f8b4b69 100644 --- a/igniter/bootstrap_repos.py +++ b/igniter/bootstrap_repos.py @@ -203,6 +203,12 @@ class OpenPypeVersion(semver.VersionInfo): openpype_version.staging = True return openpype_version + def __hash__(self): + if self.path: + return hash(self.path) + else: + return hash(str(self)) + class BootstrapRepos: """Class for bootstrapping local OpenPype installation. @@ -650,6 +656,9 @@ class BootstrapRepos: v for v in openpype_versions if v.path.suffix != ".zip" ] + # remove duplicates + openpype_versions = list(set(openpype_versions)) + return openpype_versions def process_entered_location(self, location: str) -> Union[Path, None]: diff --git a/openpype/cli.py b/openpype/cli.py index df38c74a21..12997cc7f4 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -60,13 +60,6 @@ def tray(debug=False): help="Ftrack api user") @click.option("--ftrack-api-key", envvar="FTRACK_API_KEY", help="Ftrack api key") -@click.option("--ftrack-events-path", - envvar="FTRACK_EVENTS_PATH", - help=("path to ftrack event handlers")) -@click.option("--no-stored-credentials", is_flag=True, - help="don't use stored credentials") -@click.option("--store-credentials", is_flag=True, - help="store provided credentials") @click.option("--legacy", is_flag=True, help="run event server without mongo storing") @click.option("--clockify-api-key", envvar="CLOCKIFY_API_KEY", @@ -77,9 +70,6 @@ def eventserver(debug, ftrack_url, ftrack_user, ftrack_api_key, - ftrack_events_path, - no_stored_credentials, - store_credentials, legacy, clockify_api_key, clockify_workspace): @@ -87,10 +77,6 @@ def eventserver(debug, This should be ideally used by system service (such us systemd or upstart on linux and window service). - - You have to set either proper environment variables to provide URL and - credentials or use option to specify them. If you use --store_credentials - provided credentials will be stored for later use. """ if debug: os.environ['OPENPYPE_DEBUG'] = "3" @@ -99,9 +85,6 @@ def eventserver(debug, ftrack_url, ftrack_user, ftrack_api_key, - ftrack_events_path, - no_stored_credentials, - store_credentials, legacy, clockify_api_key, clockify_workspace diff --git a/openpype/hooks/pre_mac_launch.py b/openpype/hooks/pre_mac_launch.py new file mode 100644 index 0000000000..3f07ae07db --- /dev/null +++ b/openpype/hooks/pre_mac_launch.py @@ -0,0 +1,34 @@ +import os +from openpype.lib import PreLaunchHook + + +class LaunchWithTerminal(PreLaunchHook): + """Mac specific pre arguments for application. + + Mac applications should be launched using "open" argument which is internal + callbacks to open executable. We also add argument "-a" to tell it's + application open. This is used only for executables ending with ".app". It + is expected that these executables lead to app packages. + """ + order = 1000 + + platforms = ["darwin"] + + def execute(self): + executable = str(self.launch_context.executable) + # Skip executables not ending with ".app" or that are not folder + if not executable.endswith(".app") or not os.path.isdir(executable): + return + + # Check if first argument match executable path + # - Few applications are not executed directly but through OpenPype + # process (Photoshop, AfterEffects, Harmony, ...). These should not + # use `open`. + if self.launch_context.launch_args[0] != executable: + return + + # Tell `open` to pass arguments if there are any + if len(self.launch_context.launch_args) > 1: + self.launch_context.launch_args.insert(1, "--args") + # Prepend open arguments + self.launch_context.launch_args.insert(0, ["open", "-a"]) diff --git a/openpype/hosts/blender/plugins/create/create_setdress.py b/openpype/hosts/blender/plugins/create/create_setdress.py deleted file mode 100644 index 97c737c235..0000000000 --- a/openpype/hosts/blender/plugins/create/create_setdress.py +++ /dev/null @@ -1,25 +0,0 @@ -import bpy - -from avalon import api, blender -import openpype.hosts.blender.api.plugin - - -class CreateSetDress(openpype.hosts.blender.api.plugin.Creator): - """A grouped package of loaded content""" - - name = "setdressMain" - label = "Set Dress" - family = "setdress" - icon = "cubes" - defaults = ["Main", "Anim"] - - def process(self): - asset = self.data["asset"] - subset = self.data["subset"] - name = openpype.hosts.blender.api.plugin.asset_name(asset, subset) - collection = bpy.data.collections.new(name=name) - bpy.context.scene.collection.children.link(collection) - self.data['task'] = api.Session.get('AVALON_TASK') - blender.lib.imprint(collection, self.data) - - return collection diff --git a/openpype/hosts/blender/plugins/load/load_layout.py b/openpype/hosts/blender/plugins/load/load_layout.py index 87ef9670a6..2092be9139 100644 --- a/openpype/hosts/blender/plugins/load/load_layout.py +++ b/openpype/hosts/blender/plugins/load/load_layout.py @@ -25,9 +25,6 @@ class BlendLayoutLoader(plugin.AssetLoader): icon = "code-fork" color = "orange" - animation_creator_name = "CreateAnimation" - setdress_creator_name = "CreateSetDress" - def _remove(self, objects, obj_container): for obj in list(objects): if obj.type == 'ARMATURE': @@ -293,7 +290,6 @@ class UnrealLayoutLoader(plugin.AssetLoader): color = "orange" animation_creator_name = "CreateAnimation" - setdress_creator_name = "CreateSetDress" def _remove_objects(self, objects): for obj in list(objects): @@ -383,7 +379,7 @@ class UnrealLayoutLoader(plugin.AssetLoader): def _process( self, libpath, layout_container, container_name, representation, - actions, parent + actions, parent_collection ): with open(libpath, "r") as fp: data = json.load(fp) @@ -392,6 +388,11 @@ class UnrealLayoutLoader(plugin.AssetLoader): layout_collection = bpy.data.collections.new(container_name) scene.collection.children.link(layout_collection) + parent = parent_collection + + if parent is None: + parent = scene.collection + all_loaders = api.discover(api.Loader) avalon_container = bpy.data.collections.get( @@ -516,23 +517,9 @@ class UnrealLayoutLoader(plugin.AssetLoader): container_metadata["libpath"] = libpath container_metadata["lib_container"] = lib_container - # Create a setdress subset to contain all the animation for all - # the rigs in the layout - creator_plugin = get_creator_by_name(self.setdress_creator_name) - if not creator_plugin: - raise ValueError("Creator plugin \"{}\" was not found.".format( - self.setdress_creator_name - )) - parent = api.create( - creator_plugin, - name="animation", - asset=api.Session["AVALON_ASSET"], - options={"useSelection": True}, - data={"dependencies": str(context["representation"]["_id"])}) - layout_collection = self._process( libpath, layout_container, container_name, - str(context["representation"]["_id"]), None, parent) + str(context["representation"]["_id"]), None, None) container_metadata["obj_container"] = layout_collection diff --git a/openpype/hosts/blender/plugins/load/load_look.py b/openpype/hosts/blender/plugins/load/load_look.py new file mode 100644 index 0000000000..279af2b626 --- /dev/null +++ b/openpype/hosts/blender/plugins/load/load_look.py @@ -0,0 +1,218 @@ +"""Load a model asset in Blender.""" + +from pathlib import Path +from pprint import pformat +from typing import Dict, List, Optional + +import os +import json +import bpy + +from avalon import api, blender +import openpype.hosts.blender.api.plugin as plugin + + +class BlendLookLoader(plugin.AssetLoader): + """Load models from a .blend file. + + Because they come from a .blend file we can simply link the collection that + contains the model. There is no further need to 'containerise' it. + """ + + families = ["look"] + representations = ["json"] + + label = "Load Look" + icon = "code-fork" + color = "orange" + + def get_all_children(self, obj): + children = list(obj.children) + + for child in children: + children.extend(child.children) + + return children + + def _process(self, libpath, container_name, objects): + with open(libpath, "r") as fp: + data = json.load(fp) + + path = os.path.dirname(libpath) + materials_path = f"{path}/resources" + + materials = [] + + for entry in data: + file = entry.get('fbx_filename') + if file is None: + continue + + bpy.ops.import_scene.fbx(filepath=f"{materials_path}/{file}") + + mesh = [o for o in bpy.context.scene.objects if o.select_get()][0] + material = mesh.data.materials[0] + material.name = f"{material.name}:{container_name}" + + texture_file = entry.get('tga_filename') + if texture_file: + node_tree = material.node_tree + pbsdf = node_tree.nodes['Principled BSDF'] + base_color = pbsdf.inputs[0] + tex_node = base_color.links[0].from_node + tex_node.image.filepath = f"{materials_path}/{texture_file}" + + materials.append(material) + + for obj in objects: + for child in self.get_all_children(obj): + mesh_name = child.name.split(':')[0] + if mesh_name == material.name.split(':')[0]: + child.data.materials.clear() + child.data.materials.append(material) + break + + bpy.data.objects.remove(mesh) + + return materials, objects + + def process_asset( + self, context: dict, name: str, namespace: Optional[str] = None, + options: Optional[Dict] = None + ) -> Optional[List]: + """ + Arguments: + name: Use pre-defined name + namespace: Use pre-defined namespace + context: Full parenthood of representation to load + options: Additional settings dictionary + """ + + libpath = self.fname + asset = context["asset"]["name"] + subset = context["subset"]["name"] + + lib_container = plugin.asset_name( + asset, subset + ) + unique_number = plugin.get_unique_number( + asset, subset + ) + namespace = namespace or f"{asset}_{unique_number}" + container_name = plugin.asset_name( + asset, subset, unique_number + ) + + container = bpy.data.collections.new(lib_container) + container.name = container_name + blender.pipeline.containerise_existing( + container, + name, + namespace, + context, + self.__class__.__name__, + ) + + metadata = container.get(blender.pipeline.AVALON_PROPERTY) + + metadata["libpath"] = libpath + metadata["lib_container"] = lib_container + + selected = [o for o in bpy.context.scene.objects if o.select_get()] + + materials, objects = self._process(libpath, container_name, selected) + + # Save the list of imported materials in the metadata container + metadata["objects"] = objects + metadata["materials"] = materials + + metadata["parent"] = str(context["representation"]["parent"]) + metadata["family"] = context["representation"]["context"]["family"] + + nodes = list(container.objects) + nodes.append(container) + self[:] = nodes + return nodes + + def update(self, container: Dict, representation: Dict): + collection = bpy.data.collections.get(container["objectName"]) + libpath = Path(api.get_representation_path(representation)) + extension = libpath.suffix.lower() + + self.log.info( + "Container: %s\nRepresentation: %s", + pformat(container, indent=2), + pformat(representation, indent=2), + ) + + assert collection, ( + f"The asset is not loaded: {container['objectName']}" + ) + assert not (collection.children), ( + "Nested collections are not supported." + ) + assert libpath, ( + "No existing library file found for {container['objectName']}" + ) + assert libpath.is_file(), ( + f"The file doesn't exist: {libpath}" + ) + assert extension in plugin.VALID_EXTENSIONS, ( + f"Unsupported file: {libpath}" + ) + + collection_metadata = collection.get(blender.pipeline.AVALON_PROPERTY) + collection_libpath = collection_metadata["libpath"] + + normalized_collection_libpath = ( + str(Path(bpy.path.abspath(collection_libpath)).resolve()) + ) + normalized_libpath = ( + str(Path(bpy.path.abspath(str(libpath))).resolve()) + ) + self.log.debug( + "normalized_collection_libpath:\n %s\nnormalized_libpath:\n %s", + normalized_collection_libpath, + normalized_libpath, + ) + if normalized_collection_libpath == normalized_libpath: + self.log.info("Library already loaded, not updating...") + return + + for obj in collection_metadata['objects']: + for child in self.get_all_children(obj): + child.data.materials.clear() + + for material in collection_metadata['materials']: + bpy.data.materials.remove(material) + + namespace = collection_metadata['namespace'] + name = collection_metadata['name'] + + container_name = f"{namespace}_{name}" + + materials, objects = self._process( + libpath, container_name, collection_metadata['objects']) + + collection_metadata["objects"] = objects + collection_metadata["materials"] = materials + collection_metadata["libpath"] = str(libpath) + collection_metadata["representation"] = str(representation["_id"]) + + def remove(self, container: Dict) -> bool: + collection = bpy.data.collections.get(container["objectName"]) + if not collection: + return False + + collection_metadata = collection.get(blender.pipeline.AVALON_PROPERTY) + + for obj in collection_metadata['objects']: + for child in self.get_all_children(obj): + child.data.materials.clear() + + for material in collection_metadata['materials']: + bpy.data.materials.remove(material) + + bpy.data.collections.remove(collection) + + return True diff --git a/openpype/hosts/blender/plugins/load/load_rig.py b/openpype/hosts/blender/plugins/load/load_rig.py index 9035458c12..b6be8f4cf6 100644 --- a/openpype/hosts/blender/plugins/load/load_rig.py +++ b/openpype/hosts/blender/plugins/load/load_rig.py @@ -107,6 +107,9 @@ class BlendRigLoader(plugin.AssetLoader): if action is not None: local_obj.animation_data.action = action + elif local_obj.animation_data.action is not None: + plugin.prepare_data( + local_obj.animation_data.action, collection_name) # Set link the drivers to the local object if local_obj.data.animation_data: diff --git a/openpype/hosts/blender/plugins/publish/extract_animation_collection.py b/openpype/hosts/blender/plugins/publish/extract_animation_collection.py deleted file mode 100644 index 19dc59c5cd..0000000000 --- a/openpype/hosts/blender/plugins/publish/extract_animation_collection.py +++ /dev/null @@ -1,61 +0,0 @@ -import os -import json - -import openpype.api -import pyblish.api - -import bpy - - -class ExtractSetDress(openpype.api.Extractor): - """Extract setdress.""" - - label = "Extract SetDress" - hosts = ["blender"] - families = ["setdress"] - optional = True - order = pyblish.api.ExtractorOrder + 0.1 - - def process(self, instance): - stagingdir = self.staging_dir(instance) - - json_data = [] - - for i in instance.context: - collection = i.data.get("name") - container = None - for obj in bpy.data.collections[collection].objects: - if obj.type == "ARMATURE": - container_name = obj.get("avalon").get("container_name") - container = bpy.data.collections[container_name] - if container: - json_dict = { - "subset": i.data.get("subset"), - "container": container.name, - } - json_dict["instance_name"] = container.get("avalon").get( - "instance_name" - ) - json_data.append(json_dict) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - json_filename = f"{instance.name}.json" - json_path = os.path.join(stagingdir, json_filename) - - with open(json_path, "w+") as file: - json.dump(json_data, fp=file, indent=2) - - json_representation = { - "name": "json", - "ext": "json", - "files": json_filename, - "stagingDir": stagingdir, - } - instance.data["representations"].append(json_representation) - - self.log.info( - "Extracted instance '{}' to: {}".format(instance.name, - json_representation) - ) diff --git a/openpype/hosts/blender/plugins/publish/extract_fbx.py b/openpype/hosts/blender/plugins/publish/extract_fbx.py index dc74348949..05149eacc1 100644 --- a/openpype/hosts/blender/plugins/publish/extract_fbx.py +++ b/openpype/hosts/blender/plugins/publish/extract_fbx.py @@ -54,6 +54,14 @@ class ExtractFBX(openpype.api.Extractor): # We set the scale of the scene for the export scene.unit_settings.scale_length = 0.01 + new_materials = [] + + for obj in collections[0].all_objects: + if obj.type == 'MESH': + mat = bpy.data.materials.new(obj.name) + obj.data.materials.append(mat) + new_materials.append(mat) + # We export the fbx bpy.ops.export_scene.fbx( filepath=filepath, @@ -66,6 +74,13 @@ class ExtractFBX(openpype.api.Extractor): scene.unit_settings.scale_length = old_scale + for mat in new_materials: + bpy.data.materials.remove(mat) + + for obj in collections[0].all_objects: + if obj.type == 'MESH': + obj.data.materials.pop() + if "representations" not in instance.data: instance.data["representations"] = [] diff --git a/openpype/hosts/blender/plugins/publish/extract_fbx_animation.py b/openpype/hosts/blender/plugins/publish/extract_fbx_animation.py index 1036800705..8312114c7b 100644 --- a/openpype/hosts/blender/plugins/publish/extract_fbx_animation.py +++ b/openpype/hosts/blender/plugins/publish/extract_fbx_animation.py @@ -1,4 +1,5 @@ import os +import json import openpype.api @@ -121,6 +122,25 @@ class ExtractAnimationFBX(openpype.api.Extractor): pair[1].user_clear() bpy.data.actions.remove(pair[1]) + json_filename = f"{instance.name}.json" + json_path = os.path.join(stagingdir, json_filename) + + json_dict = {} + + collection = instance.data.get("name") + container = None + for obj in bpy.data.collections[collection].objects: + if obj.type == "ARMATURE": + container_name = obj.get("avalon").get("container_name") + container = bpy.data.collections[container_name] + if container: + json_dict = { + "instance_name": container.get("avalon").get("instance_name") + } + + with open(json_path, "w+") as file: + json.dump(json_dict, fp=file, indent=2) + if "representations" not in instance.data: instance.data["representations"] = [] @@ -130,7 +150,15 @@ class ExtractAnimationFBX(openpype.api.Extractor): 'files': fbx_filename, "stagingDir": stagingdir, } + json_representation = { + 'name': 'json', + 'ext': 'json', + 'files': json_filename, + "stagingDir": stagingdir, + } instance.data["representations"].append(fbx_representation) + instance.data["representations"].append(json_representation) + self.log.info("Extracted instance '{}' to: {}".format( instance.name, fbx_representation)) diff --git a/openpype/hosts/hiero/api/lib.py b/openpype/hosts/hiero/api/lib.py index a9982d96c4..d8a235be77 100644 --- a/openpype/hosts/hiero/api/lib.py +++ b/openpype/hosts/hiero/api/lib.py @@ -214,7 +214,9 @@ def get_track_items( # add all if no track_type is defined return_list.append(track_item) - return return_list + # return output list but make sure all items are TrackItems + return [_i for _i in return_list + if type(_i) == hiero.core.TrackItem] def get_track_item_pype_tag(track_item): diff --git a/openpype/hosts/hiero/plugins/publish_old_workflow/extract_clip_effects.py b/openpype/hosts/hiero/plugins/publish/extract_clip_effects.py similarity index 92% rename from openpype/hosts/hiero/plugins/publish_old_workflow/extract_clip_effects.py rename to openpype/hosts/hiero/plugins/publish/extract_clip_effects.py index d2ac7f4786..5b0aa270a7 100644 --- a/openpype/hosts/hiero/plugins/publish_old_workflow/extract_clip_effects.py +++ b/openpype/hosts/hiero/plugins/publish/extract_clip_effects.py @@ -52,10 +52,11 @@ class ExtractClipEffects(openpype.api.Extractor): instance.data["representations"] = list() transfer_data = [ - "handleStart", "handleEnd", "sourceIn", "sourceOut", - "frameStart", "frameEnd", "sourceInH", "sourceOutH", - "clipIn", "clipOut", "clipInH", "clipOutH", "asset", "track", - "version" + "handleStart", "handleEnd", + "sourceStart", "sourceStartH", "sourceEnd", "sourceEndH", + "frameStart", "frameEnd", + "clipIn", "clipOut", "clipInH", "clipOutH", + "asset", "version" ] # pass data to version diff --git a/openpype/hosts/hiero/plugins/publish_old_workflow/precollect_clip_effects.py b/openpype/hosts/hiero/plugins/publish/precollect_clip_effects.py similarity index 93% rename from openpype/hosts/hiero/plugins/publish_old_workflow/precollect_clip_effects.py rename to openpype/hosts/hiero/plugins/publish/precollect_clip_effects.py index f9bde24255..5a9f89651c 100644 --- a/openpype/hosts/hiero/plugins/publish_old_workflow/precollect_clip_effects.py +++ b/openpype/hosts/hiero/plugins/publish/precollect_clip_effects.py @@ -5,7 +5,7 @@ import pyblish.api class PreCollectClipEffects(pyblish.api.InstancePlugin): """Collect soft effects instances.""" - order = pyblish.api.CollectorOrder - 0.508 + order = pyblish.api.CollectorOrder - 0.579 label = "Pre-collect Clip Effects Instances" families = ["clip"] @@ -24,7 +24,8 @@ class PreCollectClipEffects(pyblish.api.InstancePlugin): self.clip_in_h = self.clip_in - self.handle_start self.clip_out_h = self.clip_out + self.handle_end - track = instance.data["trackItem"] + track_item = instance.data["item"] + track = track_item.parent() track_index = track.trackIndex() tracks_effect_items = instance.context.data.get("tracksEffectItems") clip_effect_items = instance.data.get("clipEffectItems") @@ -112,7 +113,12 @@ class PreCollectClipEffects(pyblish.api.InstancePlugin): node = sitem.node() node_serialized = self.node_serialisation(node) node_name = sitem.name() - node_class = re.sub(r"\d+", "", node_name) + + if "_" in node_name: + node_class = re.sub(r"(?:_)[_0-9]+", "", node_name) # more numbers + else: + node_class = re.sub(r"\d+", "", node_name) # one number + # collect timelineIn/Out effect_t_in = int(sitem.timelineIn()) effect_t_out = int(sitem.timelineOut()) @@ -121,6 +127,7 @@ class PreCollectClipEffects(pyblish.api.InstancePlugin): return self.log.debug("node_name: `{}`".format(node_name)) + self.log.debug("node_class: `{}`".format(node_class)) return {node_name: { "class": node_class, diff --git a/openpype/hosts/hiero/plugins/publish/precollect_instances.py b/openpype/hosts/hiero/plugins/publish/precollect_instances.py index 8cccdec99a..f7449561ef 100644 --- a/openpype/hosts/hiero/plugins/publish/precollect_instances.py +++ b/openpype/hosts/hiero/plugins/publish/precollect_instances.py @@ -2,6 +2,9 @@ import pyblish import openpype from openpype.hosts.hiero import api as phiero from openpype.hosts.hiero.otio import hiero_export +import hiero + +from compiler.ast import flatten # # developer reload modules from pprint import pformat @@ -14,18 +17,40 @@ class PrecollectInstances(pyblish.api.ContextPlugin): label = "Precollect Instances" hosts = ["hiero"] + audio_track_items = [] + def process(self, context): - otio_timeline = context.data["otioTimeline"] + self.otio_timeline = context.data["otioTimeline"] + selected_timeline_items = phiero.get_track_items( - selected=True, check_enabled=True, check_tagged=True) + selected=True, check_tagged=True, check_enabled=True) + + # only return enabled track items + if not selected_timeline_items: + selected_timeline_items = phiero.get_track_items( + check_enabled=True, check_tagged=True) + self.log.info( "Processing enabled track items: {}".format( selected_timeline_items)) + # add all tracks subtreck effect items to context + all_tracks = hiero.ui.activeSequence().videoTracks() + tracks_effect_items = self.collect_sub_track_items(all_tracks) + context.data["tracksEffectItems"] = tracks_effect_items + + # process all sellected timeline track items for track_item in selected_timeline_items: data = {} clip_name = track_item.name() + source_clip = track_item.source() + + # get clips subtracks and anotations + annotations = self.clip_annotations(source_clip) + subtracks = self.clip_subtrack(track_item) + self.log.debug("Annotations: {}".format(annotations)) + self.log.debug(">> Subtracks: {}".format(subtracks)) # get openpype tag data tag_data = phiero.get_track_item_pype_data(track_item) @@ -76,12 +101,15 @@ class PrecollectInstances(pyblish.api.ContextPlugin): "item": track_item, "families": families, "publish": tag_data["publish"], - "fps": context.data["fps"] + "fps": context.data["fps"], + + # clip's effect + "clipEffectItems": subtracks, + "clipAnnotations": annotations }) # otio clip data - otio_data = self.get_otio_clip_instance_data( - otio_timeline, track_item) or {} + otio_data = self.get_otio_clip_instance_data(track_item) or {} self.log.debug("__ otio_data: {}".format(pformat(otio_data))) data.update(otio_data) self.log.debug("__ data: {}".format(pformat(data))) @@ -185,6 +213,10 @@ class PrecollectInstances(pyblish.api.ContextPlugin): item = data.get("item") clip_name = item.name() + # test if any audio clips + if not self.test_any_audio(item): + return + asset = data["asset"] subset = "audioMain" @@ -215,7 +247,28 @@ class PrecollectInstances(pyblish.api.ContextPlugin): self.log.debug( "_ instance.data: {}".format(pformat(instance.data))) - def get_otio_clip_instance_data(self, otio_timeline, track_item): + def test_any_audio(self, track_item): + # collect all audio tracks to class variable + if not self.audio_track_items: + for otio_clip in self.otio_timeline.each_clip(): + if otio_clip.parent().kind != "Audio": + continue + self.audio_track_items.append(otio_clip) + + # get track item timeline range + timeline_range = self.create_otio_time_range_from_timeline_item_data( + track_item) + + # loop trough audio track items and search for overlaping clip + for otio_audio in self.audio_track_items: + parent_range = otio_audio.range_in_parent() + + # if any overaling clip found then return True + if openpype.lib.is_overlapping_otio_ranges( + parent_range, timeline_range, strict=False): + return True + + def get_otio_clip_instance_data(self, track_item): """ Return otio objects for timeline, track and clip @@ -231,7 +284,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): ti_track_name = track_item.parent().name() timeline_range = self.create_otio_time_range_from_timeline_item_data( track_item) - for otio_clip in otio_timeline.each_clip(): + for otio_clip in self.otio_timeline.each_clip(): track_name = otio_clip.parent().name parent_range = otio_clip.range_in_parent() if ti_track_name not in track_name: @@ -258,3 +311,76 @@ class PrecollectInstances(pyblish.api.ContextPlugin): return hiero_export.create_otio_time_range( frame_start, frame_duration, fps) + + @staticmethod + def collect_sub_track_items(tracks): + """ + Returns dictionary with track index as key and list of subtracks + """ + # collect all subtrack items + sub_track_items = {} + for track in tracks: + items = track.items() + + # skip if no clips on track > need track with effect only + if items: + continue + + # skip all disabled tracks + if not track.isEnabled(): + continue + + track_index = track.trackIndex() + _sub_track_items = flatten(track.subTrackItems()) + + # continue only if any subtrack items are collected + if len(_sub_track_items) < 1: + continue + + enabled_sti = [] + # loop all found subtrack items and check if they are enabled + for _sti in _sub_track_items: + # checking if not enabled + if not _sti.isEnabled(): + continue + if isinstance(_sti, hiero.core.Annotation): + continue + # collect the subtrack item + enabled_sti.append(_sti) + + # continue only if any subtrack items are collected + if len(enabled_sti) < 1: + continue + + # add collection of subtrackitems to dict + sub_track_items[track_index] = enabled_sti + + return sub_track_items + + @staticmethod + def clip_annotations(clip): + """ + Returns list of Clip's hiero.core.Annotation + """ + annotations = [] + subTrackItems = flatten(clip.subTrackItems()) + annotations += [item for item in subTrackItems if isinstance( + item, hiero.core.Annotation)] + return annotations + + @staticmethod + def clip_subtrack(clip): + """ + Returns list of Clip's hiero.core.SubTrackItem + """ + subtracks = [] + subTrackItems = flatten(clip.parent().subTrackItems()) + for item in subTrackItems: + # avoid all anotation + if isinstance(item, hiero.core.Annotation): + continue + # # avoid all not anaibled + if not item.isEnabled(): + continue + subtracks.append(item) + return subtracks diff --git a/openpype/hosts/hiero/plugins/publish/precollect_workfile.py b/openpype/hosts/hiero/plugins/publish/precollect_workfile.py index bc4ef7e150..530a433423 100644 --- a/openpype/hosts/hiero/plugins/publish/precollect_workfile.py +++ b/openpype/hosts/hiero/plugins/publish/precollect_workfile.py @@ -75,10 +75,26 @@ class PrecollectWorkfile(pyblish.api.ContextPlugin): "activeProject": project, "otioTimeline": otio_timeline, "currentFile": curent_file, - "fps": fps, + "colorspace": self.get_colorspace(project), + "fps": fps } context.data.update(context_data) self.log.info("Creating instance: {}".format(instance)) self.log.debug("__ instance.data: {}".format(pformat(instance.data))) self.log.debug("__ context_data: {}".format(pformat(context_data))) + + def get_colorspace(self, project): + # get workfile's colorspace properties + return { + "useOCIOEnvironmentOverride": project.useOCIOEnvironmentOverride(), + "lutSetting16Bit": project.lutSetting16Bit(), + "lutSetting8Bit": project.lutSetting8Bit(), + "lutSettingFloat": project.lutSettingFloat(), + "lutSettingLog": project.lutSettingLog(), + "lutSettingViewer": project.lutSettingViewer(), + "lutSettingWorkingSpace": project.lutSettingWorkingSpace(), + "lutUseOCIOForExport": project.lutUseOCIOForExport(), + "ocioConfigName": project.ocioConfigName(), + "ocioConfigPath": project.ocioConfigPath() + } diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 909993a173..edf68ad6fc 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -2156,6 +2156,10 @@ def load_capture_preset(path=None, data=None): for key in preset['Display Options']: if key.startswith('background'): disp_options[key] = preset['Display Options'][key] + disp_options[key][0] = (float(disp_options[key][0])/255) + disp_options[key][1] = (float(disp_options[key][1])/255) + disp_options[key][2] = (float(disp_options[key][2])/255) + disp_options[key].pop() else: disp_options['displayGradient'] = True diff --git a/openpype/hosts/maya/plugins/load/load_ass.py b/openpype/hosts/maya/plugins/load/load_ass.py index b4bbd93f99..b7d44dd431 100644 --- a/openpype/hosts/maya/plugins/load/load_ass.py +++ b/openpype/hosts/maya/plugins/load/load_ass.py @@ -81,7 +81,10 @@ class AssProxyLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): if c is not None: cmds.setAttr(groupName + ".useOutlinerColor", 1) cmds.setAttr(groupName + ".outlinerColor", - c[0], c[1], c[2]) + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) self[:] = nodes diff --git a/openpype/hosts/maya/plugins/load/load_gpucache.py b/openpype/hosts/maya/plugins/load/load_gpucache.py index 5b1b29e184..d0a83b8177 100644 --- a/openpype/hosts/maya/plugins/load/load_gpucache.py +++ b/openpype/hosts/maya/plugins/load/load_gpucache.py @@ -38,7 +38,10 @@ class GpuCacheLoader(api.Loader): if c is not None: cmds.setAttr(root + ".useOutlinerColor", 1) cmds.setAttr(root + ".outlinerColor", - c[0], c[1], c[2]) + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) # Create transform with shape transform_name = label + "_GPU" diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index 37a2b145d4..96269f2771 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -85,7 +85,11 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): c = colors.get(family) if c is not None: groupNode.useOutlinerColor.set(1) - groupNode.outlinerColor.set(c[0], c[1], c[2]) + groupNode.outlinerColor.set( + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) self[:] = newNodes diff --git a/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py b/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py index b705b55f4d..f5662ba462 100644 --- a/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py +++ b/openpype/hosts/maya/plugins/load/load_vdb_to_redshift.py @@ -62,7 +62,10 @@ class LoadVDBtoRedShift(api.Loader): if c is not None: cmds.setAttr(root + ".useOutlinerColor", 1) cmds.setAttr(root + ".outlinerColor", - c[0], c[1], c[2]) + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) # Create VR volume_node = cmds.createNode("RedshiftVolumeShape", diff --git a/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py b/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py index 82ccdb481b..80b453bd13 100644 --- a/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py +++ b/openpype/hosts/maya/plugins/load/load_vdb_to_vray.py @@ -55,7 +55,10 @@ class LoadVDBtoVRay(api.Loader): if c is not None: cmds.setAttr(root + ".useOutlinerColor", 1) cmds.setAttr(root + ".outlinerColor", - c[0], c[1], c[2]) + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) # Create VR grid_node = cmds.createNode("VRayVolumeGrid", diff --git a/openpype/hosts/maya/plugins/load/load_vrayproxy.py b/openpype/hosts/maya/plugins/load/load_vrayproxy.py index d5d4a941e3..e70f40bf5a 100644 --- a/openpype/hosts/maya/plugins/load/load_vrayproxy.py +++ b/openpype/hosts/maya/plugins/load/load_vrayproxy.py @@ -74,7 +74,10 @@ class VRayProxyLoader(api.Loader): if c is not None: cmds.setAttr("{0}.useOutlinerColor".format(group_node), 1) cmds.setAttr("{0}.outlinerColor".format(group_node), - c[0], c[1], c[2]) + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) return containerise( name=name, diff --git a/openpype/hosts/maya/plugins/load/load_vrayscene.py b/openpype/hosts/maya/plugins/load/load_vrayscene.py index b0f0c2a54b..465dab2a76 100644 --- a/openpype/hosts/maya/plugins/load/load_vrayscene.py +++ b/openpype/hosts/maya/plugins/load/load_vrayscene.py @@ -53,7 +53,10 @@ class VRaySceneLoader(api.Loader): if c is not None: cmds.setAttr("{0}.useOutlinerColor".format(group_node), 1) cmds.setAttr("{0}.outlinerColor".format(group_node), - c[0], c[1], c[2]) + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) return containerise( name=name, diff --git a/openpype/hosts/maya/plugins/load/load_yeti_cache.py b/openpype/hosts/maya/plugins/load/load_yeti_cache.py index 43c8aa16a0..de0ea6823c 100644 --- a/openpype/hosts/maya/plugins/load/load_yeti_cache.py +++ b/openpype/hosts/maya/plugins/load/load_yeti_cache.py @@ -66,7 +66,10 @@ class YetiCacheLoader(api.Loader): if c is not None: cmds.setAttr(group_name + ".useOutlinerColor", 1) cmds.setAttr(group_name + ".outlinerColor", - c[0], c[1], c[2]) + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) nodes.append(group_node) diff --git a/openpype/hosts/maya/plugins/load/load_yeti_rig.py b/openpype/hosts/maya/plugins/load/load_yeti_rig.py index a329be4cf5..3f67f98f51 100644 --- a/openpype/hosts/maya/plugins/load/load_yeti_rig.py +++ b/openpype/hosts/maya/plugins/load/load_yeti_rig.py @@ -84,7 +84,10 @@ class YetiRigLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): if c is not None: cmds.setAttr(groupName + ".useOutlinerColor", 1) cmds.setAttr(groupName + ".outlinerColor", - c[0], c[1], c[2]) + (float(c[0])/255), + (float(c[1])/255), + (float(c[2])/255) + ) self[:] = nodes return nodes diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 0dc91d67a9..4b777cdfe2 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -49,9 +49,6 @@ class ExtractPlayblast(openpype.api.Extractor): preset['camera'] = camera - preset['format'] = "image" - preset['quality'] = 95 - preset['compression'] = "png" preset['start_frame'] = start preset['end_frame'] = end camera_option = preset.get("camera_option", {}) diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index 016efa6499..c888f03518 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -42,10 +42,6 @@ class ExtractThumbnail(openpype.api.Extractor): # preset["off_screen"] = False preset['camera'] = camera - preset['format'] = "image" - # preset['compression'] = "qt" - preset['quality'] = 50 - preset['compression'] = "jpg" preset['start_frame'] = instance.data["frameStart"] preset['end_frame'] = instance.data["frameStart"] preset['camera_options'] = { diff --git a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py index 9aeaad7ff1..8d2c7d8f63 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rendersettings.py +++ b/openpype/hosts/maya/plugins/publish/validate_rendersettings.py @@ -243,7 +243,10 @@ class ValidateRenderSettings(pyblish.api.InstancePlugin): "Cannot get value of {}.{}".format( node, attribute_name)) else: - if value != render_value: + # compare values as strings to get around various + # datatypes possible in Settings and Render + # Settings + if str(value) != str(render_value): invalid = True cls.log.error( ("Invalid value {} set on {}.{}. " diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index e6dde813a7..63cac0fd8b 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -1059,7 +1059,7 @@ class WorkfileSettings(object): # replace reset resolution from avalon core to pype's self.reset_frame_range_handles() # add colorspace menu item - # self.set_colorspace() + self.set_colorspace() def set_favorites(self): work_dir = os.getenv("AVALON_WORKDIR") diff --git a/openpype/hosts/nuke/plugins/load/load_luts.py b/openpype/hosts/nuke/plugins/load/load_effects.py similarity index 94% rename from openpype/hosts/nuke/plugins/load/load_luts.py rename to openpype/hosts/nuke/plugins/load/load_effects.py index 85ec3e2060..6306767f37 100644 --- a/openpype/hosts/nuke/plugins/load/load_luts.py +++ b/openpype/hosts/nuke/plugins/load/load_effects.py @@ -4,18 +4,19 @@ import json from collections import OrderedDict -class LoadLuts(api.Loader): +class LoadEffects(api.Loader): """Loading colorspace soft effect exported from nukestudio""" - representations = ["lutJson"] - families = ["lut"] + representations = ["effectJson"] + families = ["effect"] - label = "Load Luts - nodes" + label = "Load Effects - nodes" order = 0 icon = "cc" color = style.colors.light ignore_attr = ["useLifetime"] + def load(self, context, name, namespace, data): """ Loading function to get the soft effects to particular read node @@ -66,15 +67,15 @@ class LoadLuts(api.Loader): for key, value in json.load(f).iteritems()} # get correct order of nodes by positions on track and subtrack - nodes_order = self.reorder_nodes(json_f["effects"]) + nodes_order = self.reorder_nodes(json_f) # adding nodes to node graph # just in case we are in group lets jump out of it nuke.endGroup() - GN = nuke.createNode("Group") - - GN["name"].setValue(object_name) + GN = nuke.createNode( + "Group", + "name {}_1".format(object_name)) # adding content to the group node with GN: @@ -186,7 +187,7 @@ class LoadLuts(api.Loader): for key, value in json.load(f).iteritems()} # get correct order of nodes by positions on track and subtrack - nodes_order = self.reorder_nodes(json_f["effects"]) + nodes_order = self.reorder_nodes(json_f) # adding nodes to node graph # just in case we are in group lets jump out of it @@ -266,7 +267,11 @@ class LoadLuts(api.Loader): None: if nothing found """ search_name = "{0}_{1}".format(asset, subset) - node = [n for n in nuke.allNodes() if search_name in n["name"].value()] + + node = [ + n for n in nuke.allNodes(filter="Read") + if search_name in n["file"].value() + ] if len(node) > 0: rn = node[0] else: @@ -286,8 +291,10 @@ class LoadLuts(api.Loader): def reorder_nodes(self, data): new_order = OrderedDict() - trackNums = [v["trackIndex"] for k, v in data.items()] - subTrackNums = [v["subTrackIndex"] for k, v in data.items()] + trackNums = [v["trackIndex"] for k, v in data.items() + if isinstance(v, dict)] + subTrackNums = [v["subTrackIndex"] for k, v in data.items() + if isinstance(v, dict)] for trackIndex in range( min(trackNums), max(trackNums) + 1): @@ -300,6 +307,7 @@ class LoadLuts(api.Loader): def get_item(self, data, trackIndex, subTrackIndex): return {key: val for key, val in data.items() + if isinstance(val, dict) if subTrackIndex == val["subTrackIndex"] if trackIndex == val["trackIndex"]} diff --git a/openpype/hosts/nuke/plugins/load/load_luts_ip.py b/openpype/hosts/nuke/plugins/load/load_effects_ip.py similarity index 95% rename from openpype/hosts/nuke/plugins/load/load_luts_ip.py rename to openpype/hosts/nuke/plugins/load/load_effects_ip.py index a0af29c7f4..6c71f2ae16 100644 --- a/openpype/hosts/nuke/plugins/load/load_luts_ip.py +++ b/openpype/hosts/nuke/plugins/load/load_effects_ip.py @@ -5,13 +5,13 @@ from collections import OrderedDict from openpype.hosts.nuke.api import lib -class LoadLutsInputProcess(api.Loader): +class LoadEffectsInputProcess(api.Loader): """Loading colorspace soft effect exported from nukestudio""" - representations = ["lutJson"] - families = ["lut"] + representations = ["effectJson"] + families = ["effect"] - label = "Load Luts - Input Process" + label = "Load Effects - Input Process" order = 0 icon = "eye" color = style.colors.alert @@ -67,15 +67,15 @@ class LoadLutsInputProcess(api.Loader): for key, value in json.load(f).iteritems()} # get correct order of nodes by positions on track and subtrack - nodes_order = self.reorder_nodes(json_f["effects"]) + nodes_order = self.reorder_nodes(json_f) # adding nodes to node graph # just in case we are in group lets jump out of it nuke.endGroup() - GN = nuke.createNode("Group") - - GN["name"].setValue(object_name) + GN = nuke.createNode( + "Group", + "name {}_1".format(object_name)) # adding content to the group node with GN: @@ -190,7 +190,7 @@ class LoadLutsInputProcess(api.Loader): for key, value in json.load(f).iteritems()} # get correct order of nodes by positions on track and subtrack - nodes_order = self.reorder_nodes(json_f["effects"]) + nodes_order = self.reorder_nodes(json_f) # adding nodes to node graph # just in case we are in group lets jump out of it @@ -304,8 +304,10 @@ class LoadLutsInputProcess(api.Loader): def reorder_nodes(self, data): new_order = OrderedDict() - trackNums = [v["trackIndex"] for k, v in data.items()] - subTrackNums = [v["subTrackIndex"] for k, v in data.items()] + trackNums = [v["trackIndex"] for k, v in data.items() + if isinstance(v, dict)] + subTrackNums = [v["subTrackIndex"] for k, v in data.items() + if isinstance(v, dict)] for trackIndex in range( min(trackNums), max(trackNums) + 1): @@ -318,6 +320,7 @@ class LoadLutsInputProcess(api.Loader): def get_item(self, data, trackIndex, subTrackIndex): return {key: val for key, val in data.items() + if isinstance(val, dict) if subTrackIndex == val["subTrackIndex"] if trackIndex == val["trackIndex"]} diff --git a/openpype/hosts/nuke/startup/menu.py b/openpype/hosts/nuke/startup/menu.py index 9eb656afa9..c452acb709 100644 --- a/openpype/hosts/nuke/startup/menu.py +++ b/openpype/hosts/nuke/startup/menu.py @@ -1,6 +1,7 @@ from openpype.hosts.nuke.api.lib import ( on_script_load, - check_inventory_versions + check_inventory_versions, + WorkfileSettings ) import nuke @@ -9,8 +10,14 @@ from openpype.api import Logger log = Logger().get_logger(__name__) -nuke.addOnScriptSave(on_script_load) +# fix ffmpeg settings on script +nuke.addOnScriptLoad(on_script_load) + +# set checker for last versions on loaded containers nuke.addOnScriptLoad(check_inventory_versions) nuke.addOnScriptSave(check_inventory_versions) +# # set apply all workfile settings on script load and save +nuke.addOnScriptLoad(WorkfileSettings().set_context_settings) + log.info('Automatic syncing of write file knob to script version') diff --git a/openpype/hosts/tvpaint/api/__init__.py b/openpype/hosts/tvpaint/api/__init__.py index bd9ef51a76..57a03d38b7 100644 --- a/openpype/hosts/tvpaint/api/__init__.py +++ b/openpype/hosts/tvpaint/api/__init__.py @@ -19,6 +19,10 @@ CREATE_PATH = os.path.join(PLUGINS_DIR, "create") def on_instance_toggle(instance, old_value, new_value): + # Review may not have real instance in wokrfile metadata + if not instance.data.get("uuid"): + return + instance_id = instance.data["uuid"] found_idx = None current_instances = pipeline.list_instances() diff --git a/openpype/hosts/tvpaint/plugins/create/create_review.py b/openpype/hosts/tvpaint/plugins/create/create_review.py deleted file mode 100644 index 88b039c8e4..0000000000 --- a/openpype/hosts/tvpaint/plugins/create/create_review.py +++ /dev/null @@ -1,19 +0,0 @@ -from avalon.tvpaint import pipeline -from openpype.hosts.tvpaint.api import plugin - - -class CreateReview(plugin.Creator): - """Review for global review of all layers.""" - name = "review" - label = "Review" - family = "review" - icon = "cube" - defaults = ["Main"] - - def process(self): - instances = pipeline.list_instances() - for instance in instances: - if instance["family"] == self.family: - self.log.info("Review family is already Created.") - return - super(CreateReview, self).process() diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_instances.py b/openpype/hosts/tvpaint/plugins/publish/collect_instances.py index 27bd8e9ede..9b11f9fe80 100644 --- a/openpype/hosts/tvpaint/plugins/publish/collect_instances.py +++ b/openpype/hosts/tvpaint/plugins/publish/collect_instances.py @@ -1,3 +1,4 @@ +import os import json import copy import pyblish.api @@ -17,6 +18,20 @@ class CollectInstances(pyblish.api.ContextPlugin): json.dumps(workfile_instances, indent=4) )) + # Backwards compatibility for workfiles that already have review + # instance in metadata. + review_instance_exist = False + for instance_data in workfile_instances: + if instance_data["family"] == "review": + review_instance_exist = True + break + + # Fake review instance if review was not found in metadata families + if not review_instance_exist: + workfile_instances.append( + self._create_review_instance_data(context) + ) + for instance_data in workfile_instances: instance_data["fps"] = context.data["sceneFps"] @@ -90,6 +105,16 @@ class CollectInstances(pyblish.api.ContextPlugin): instance, json.dumps(instance.data, indent=4) )) + def _create_review_instance_data(self, context): + """Fake review instance data.""" + + return { + "family": "review", + "asset": context.data["asset"], + # Dummy subset name + "subset": "reviewMain" + } + def create_render_layer_instance(self, context, instance_data): name = instance_data["name"] # Change label diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_workfile.py b/openpype/hosts/tvpaint/plugins/publish/collect_workfile.py new file mode 100644 index 0000000000..b059be90bf --- /dev/null +++ b/openpype/hosts/tvpaint/plugins/publish/collect_workfile.py @@ -0,0 +1,43 @@ +import os +import json +import pyblish.api +from avalon import io + + +class CollectWorkfile(pyblish.api.ContextPlugin): + label = "Collect Workfile" + order = pyblish.api.CollectorOrder - 1 + hosts = ["tvpaint"] + + def process(self, context): + current_file = context.data["currentFile"] + + self.log.info( + "Workfile path used for workfile family: {}".format(current_file) + ) + + dirpath, filename = os.path.split(current_file) + basename, ext = os.path.splitext(filename) + instance = context.create_instance(name=basename) + + task_name = io.Session["AVALON_TASK"] + subset_name = "workfile" + task_name.capitalize() + + # Create Workfile instance + instance.data.update({ + "subset": subset_name, + "asset": context.data["asset"], + "label": subset_name, + "publish": True, + "family": "workfile", + "families": ["workfile"], + "representations": [{ + "name": ext.lstrip("."), + "ext": ext.lstrip("."), + "files": filename, + "stagingDir": dirpath + }] + }) + self.log.info("Collected workfile instance: {}".format( + json.dumps(instance.data, indent=4) + )) diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_workfile_metadata.py b/openpype/hosts/tvpaint/plugins/publish/validate_workfile_metadata.py new file mode 100644 index 0000000000..757da3294a --- /dev/null +++ b/openpype/hosts/tvpaint/plugins/publish/validate_workfile_metadata.py @@ -0,0 +1,49 @@ +import pyblish.api +from avalon.tvpaint import save_file + + +class ValidateWorkfileMetadataRepair(pyblish.api.Action): + """Store current context into workfile metadata.""" + + label = "Use current context" + icon = "wrench" + on = "failed" + + def process(self, context, _plugin): + """Save current workfile which should trigger storing of metadata.""" + current_file = context.data["currentFile"] + # Save file should trigger + save_file(current_file) + + +class ValidateWorkfileMetadata(pyblish.api.ContextPlugin): + """Validate if wokrfile contain required metadata for publising.""" + + label = "Validate Workfile Metadata" + order = pyblish.api.ValidatorOrder + + families = ["workfile"] + + actions = [ValidateWorkfileMetadataRepair] + + required_keys = {"project", "asset", "task"} + + def process(self, context): + workfile_context = context.data["workfile_context"] + if not workfile_context: + raise AssertionError( + "Current workfile is missing whole metadata about context." + ) + + missing_keys = [] + for key in self.required_keys: + value = workfile_context.get(key) + if not value: + missing_keys.append(key) + + if missing_keys: + raise AssertionError( + "Current workfile is missing metadata about {}.".format( + ", ".join(missing_keys) + ) + ) diff --git a/openpype/hosts/unreal/plugins/create/create_look.py b/openpype/hosts/unreal/plugins/create/create_look.py new file mode 100644 index 0000000000..7d3913b883 --- /dev/null +++ b/openpype/hosts/unreal/plugins/create/create_look.py @@ -0,0 +1,66 @@ +import unreal +from openpype.hosts.unreal.api.plugin import Creator +from avalon.unreal import pipeline + + +class CreateLook(Creator): + """Shader connections defining shape look""" + + name = "unrealLook" + label = "Unreal - Look" + family = "look" + icon = "paint-brush" + + root = "/Game/Avalon/Assets" + suffix = "_INS" + + def __init__(self, *args, **kwargs): + super(CreateLook, self).__init__(*args, **kwargs) + + def process(self): + name = self.data["subset"] + + selection = [] + if (self.options or {}).get("useSelection"): + sel_objects = unreal.EditorUtilityLibrary.get_selected_assets() + selection = [a.get_path_name() for a in sel_objects] + + # Create the folder + path = f"{self.root}/{self.data['asset']}" + new_name = pipeline.create_folder(path, name) + full_path = f"{path}/{new_name}" + + # Create a new cube static mesh + ar = unreal.AssetRegistryHelpers.get_asset_registry() + cube = ar.get_asset_by_object_path("/Engine/BasicShapes/Cube.Cube") + + # Create the avalon publish instance object + container_name = f"{name}{self.suffix}" + pipeline.create_publish_instance( + instance=container_name, path=full_path) + + # Get the mesh of the selected object + original_mesh = ar.get_asset_by_object_path(selection[0]).get_asset() + materials = original_mesh.get_editor_property('materials') + + self.data["members"] = [] + + # Add the materials to the cube + for material in materials: + name = material.get_editor_property('material_slot_name') + object_path = f"{full_path}/{name}.{name}" + object = unreal.EditorAssetLibrary.duplicate_loaded_asset( + cube.get_asset(), object_path + ) + + # Remove the default material of the cube object + object.get_editor_property('static_materials').pop() + + object.add_material( + material.get_editor_property('material_interface')) + + self.data["members"].append(object_path) + + unreal.EditorAssetLibrary.save_asset(object_path) + + pipeline.imprint(f"{full_path}/{container_name}", self.data) diff --git a/openpype/hosts/unreal/plugins/load/load_animation.py b/openpype/hosts/unreal/plugins/load/load_animation.py index 18910983ea..481285d603 100644 --- a/openpype/hosts/unreal/plugins/load/load_animation.py +++ b/openpype/hosts/unreal/plugins/load/load_animation.py @@ -1,4 +1,5 @@ import os +import json from avalon import api, pipeline from avalon.unreal import lib @@ -61,10 +62,16 @@ class AnimationFBXLoader(api.Loader): task = unreal.AssetImportTask() task.options = unreal.FbxImportUI() - # If there are no options, the process cannot be automated - if options: + libpath = self.fname.replace("fbx", "json") + + with open(libpath, "r") as fp: + data = json.load(fp) + + instance_name = data.get("instance_name") + + if instance_name: automated = True - actor_name = 'PersistentLevel.' + options.get('instance_name') + actor_name = 'PersistentLevel.' + instance_name actor = unreal.EditorLevelLibrary.get_actor_reference(actor_name) skeleton = actor.skeletal_mesh_component.skeletal_mesh.skeleton task.options.set_editor_property('skeleton', skeleton) @@ -81,16 +88,31 @@ class AnimationFBXLoader(api.Loader): # set import options here task.options.set_editor_property( - 'automated_import_should_detect_type', True) + 'automated_import_should_detect_type', False) task.options.set_editor_property( - 'original_import_type', unreal.FBXImportType.FBXIT_ANIMATION) + 'original_import_type', unreal.FBXImportType.FBXIT_SKELETAL_MESH) + task.options.set_editor_property( + 'mesh_type_to_import', unreal.FBXImportType.FBXIT_ANIMATION) task.options.set_editor_property('import_mesh', False) task.options.set_editor_property('import_animations', True) + task.options.set_editor_property('override_full_name', True) - task.options.skeletal_mesh_import_data.set_editor_property( - 'import_content_type', - unreal.FBXImportContentType.FBXICT_SKINNING_WEIGHTS + task.options.anim_sequence_import_data.set_editor_property( + 'animation_length', + unreal.FBXAnimationLengthImportType.FBXALIT_EXPORTED_TIME ) + task.options.anim_sequence_import_data.set_editor_property( + 'import_meshes_in_bone_hierarchy', False) + task.options.anim_sequence_import_data.set_editor_property( + 'use_default_sample_rate', True) + task.options.anim_sequence_import_data.set_editor_property( + 'import_custom_attribute', True) + task.options.anim_sequence_import_data.set_editor_property( + 'import_bone_tracks', True) + task.options.anim_sequence_import_data.set_editor_property( + 'remove_redundant_keys', True) + task.options.anim_sequence_import_data.set_editor_property( + 'convert_scene', True) unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task]) diff --git a/openpype/hosts/unreal/plugins/load/load_setdress.py b/openpype/hosts/unreal/plugins/load/load_setdress.py deleted file mode 100644 index da302deb1c..0000000000 --- a/openpype/hosts/unreal/plugins/load/load_setdress.py +++ /dev/null @@ -1,127 +0,0 @@ -import json - -from avalon import api -import unreal - - -class AnimationCollectionLoader(api.Loader): - """Load Unreal SkeletalMesh from FBX""" - - families = ["setdress"] - representations = ["json"] - - label = "Load Animation Collection" - icon = "cube" - color = "orange" - - def load(self, context, name, namespace, options): - from avalon import api, pipeline - from avalon.unreal import lib - from avalon.unreal import pipeline as unreal_pipeline - import unreal - - # Create directory for asset and avalon container - root = "/Game/Avalon/Assets" - asset = context.get('asset').get('name') - suffix = "_CON" - - tools = unreal.AssetToolsHelpers().get_asset_tools() - asset_dir, container_name = tools.create_unique_asset_name( - "{}/{}".format(root, asset), suffix="") - - container_name += suffix - - unreal.EditorAssetLibrary.make_directory(asset_dir) - - libpath = self.fname - - with open(libpath, "r") as fp: - data = json.load(fp) - - all_loaders = api.discover(api.Loader) - - for element in data: - reference = element.get('_id') - - loaders = api.loaders_from_representation(all_loaders, reference) - loader = None - for l in loaders: - if l.__name__ == "AnimationFBXLoader": - loader = l - break - - if not loader: - continue - - instance_name = element.get('instance_name') - - api.load( - loader, - reference, - namespace=instance_name, - options=element - ) - - # Create Asset Container - lib.create_avalon_container( - container=container_name, path=asset_dir) - - data = { - "schema": "openpype:container-2.0", - "id": pipeline.AVALON_CONTAINER_ID, - "asset": asset, - "namespace": asset_dir, - "container_name": container_name, - "loader": str(self.__class__.__name__), - "representation": context["representation"]["_id"], - "parent": context["representation"]["parent"], - "family": context["representation"]["context"]["family"] - } - unreal_pipeline.imprint( - "{}/{}".format(asset_dir, container_name), data) - - asset_content = unreal.EditorAssetLibrary.list_assets( - asset_dir, recursive=True, include_folder=True - ) - - return asset_content - - def update(self, container, representation): - from avalon import api, io - from avalon.unreal import pipeline - - source_path = api.get_representation_path(representation) - - with open(source_path, "r") as fp: - data = json.load(fp) - - animation_containers = [ - i for i in pipeline.ls() if - i.get('asset') == container.get('asset') and - i.get('family') == 'animation'] - - for element in data: - new_version = io.find_one({"_id": io.ObjectId(element.get('_id'))}) - new_version_number = new_version.get('context').get('version') - anim_container = None - for i in animation_containers: - if i.get('container_name') == (element.get('subset') + "_CON"): - anim_container = i - break - if not anim_container: - continue - - api.update(anim_container, new_version_number) - - container_path = "{}/{}".format(container["namespace"], - container["objectName"]) - # update metadata - pipeline.imprint( - container_path, - { - "representation": str(representation["_id"]), - "parent": str(representation["parent"]) - }) - - def remove(self, container): - unreal.EditorAssetLibrary.delete_directory(container["namespace"]) diff --git a/openpype/hosts/unreal/plugins/publish/extract_look.py b/openpype/hosts/unreal/plugins/publish/extract_look.py new file mode 100644 index 0000000000..0f1539a7d5 --- /dev/null +++ b/openpype/hosts/unreal/plugins/publish/extract_look.py @@ -0,0 +1,120 @@ +import json +import os + +import unreal +from unreal import MaterialEditingLibrary as mat_lib + +import openpype.api + + +class ExtractLook(openpype.api.Extractor): + """Extract look.""" + + label = "Extract Look" + hosts = ["unreal"] + families = ["look"] + optional = True + + def process(self, instance): + # Define extract output file path + stagingdir = self.staging_dir(instance) + resources_dir = instance.data["resourcesDir"] + + ar = unreal.AssetRegistryHelpers.get_asset_registry() + + transfers = [] + + json_data = [] + + for member in instance: + asset = ar.get_asset_by_object_path(member) + object = asset.get_asset() + + name = asset.get_editor_property('asset_name') + + json_element = {'material': str(name)} + + material_obj = object.get_editor_property('static_materials')[0] + material = material_obj.material_interface + + base_color = mat_lib.get_material_property_input_node( + material, unreal.MaterialProperty.MP_BASE_COLOR) + + base_color_name = base_color.get_editor_property('parameter_name') + + texture = mat_lib.get_material_default_texture_parameter_value( + material, base_color_name) + + if texture: + # Export Texture + tga_filename = f"{instance.name}_{name}_texture.tga" + + tga_exporter = unreal.TextureExporterTGA() + + tga_export_task = unreal.AssetExportTask() + + tga_export_task.set_editor_property('exporter', tga_exporter) + tga_export_task.set_editor_property('automated', True) + tga_export_task.set_editor_property('object', texture) + tga_export_task.set_editor_property( + 'filename', f"{stagingdir}/{tga_filename}") + tga_export_task.set_editor_property('prompt', False) + tga_export_task.set_editor_property('selected', False) + + unreal.Exporter.run_asset_export_task(tga_export_task) + + json_element['tga_filename'] = tga_filename + + transfers.append(( + f"{stagingdir}/{tga_filename}", + f"{resources_dir}/{tga_filename}")) + + fbx_filename = f"{instance.name}_{name}.fbx" + + fbx_exporter = unreal.StaticMeshExporterFBX() + fbx_exporter.set_editor_property('text', False) + + options = unreal.FbxExportOption() + options.set_editor_property('ascii', False) + options.set_editor_property('collision', False) + + task = unreal.AssetExportTask() + task.set_editor_property('exporter', fbx_exporter) + task.set_editor_property('options', options) + task.set_editor_property('automated', True) + task.set_editor_property('object', object) + task.set_editor_property( + 'filename', f"{stagingdir}/{fbx_filename}") + task.set_editor_property('prompt', False) + task.set_editor_property('selected', False) + + unreal.Exporter.run_asset_export_task(task) + + json_element['fbx_filename'] = fbx_filename + + transfers.append(( + f"{stagingdir}/{fbx_filename}", + f"{resources_dir}/{fbx_filename}")) + + json_data.append(json_element) + + json_filename = f"{instance.name}.json" + json_path = os.path.join(stagingdir, json_filename) + + with open(json_path, "w+") as file: + json.dump(json_data, fp=file, indent=2) + + if "transfers" not in instance.data: + instance.data["transfers"] = [] + if "representations" not in instance.data: + instance.data["representations"] = [] + + json_representation = { + 'name': 'json', + 'ext': 'json', + 'files': json_filename, + "stagingDir": stagingdir, + } + + instance.data["representations"].append(json_representation) + instance.data["transfers"].extend(transfers) diff --git a/openpype/lib/applications.py b/openpype/lib/applications.py index a44c43102f..d82b7cd847 100644 --- a/openpype/lib/applications.py +++ b/openpype/lib/applications.py @@ -440,7 +440,20 @@ class EnvironmentTool: class ApplicationExecutable: + """Representation of executable loaded from settings.""" + def __init__(self, executable): + # On MacOS check if exists path to executable when ends with `.app` + # - it is common that path will lead to "/Applications/Blender" but + # real path is "/Applications/Blender.app" + if ( + platform.system().lower() == "darwin" + and not os.path.exists(executable) + ): + _executable = executable + ".app" + if os.path.exists(_executable): + executable = _executable + self.executable_path = executable def __str__(self): @@ -1177,17 +1190,23 @@ def prepare_context_environments(data): try: workdir = get_workdir_with_workdir_data(workdir_data, anatomy) - if not os.path.exists(workdir): - log.debug( - "Creating workdir folder: \"{}\"".format(workdir) - ) - os.makedirs(workdir) except Exception as exc: raise ApplicationLaunchFailed( "Error in anatomy.format: {}".format(str(exc)) ) + if not os.path.exists(workdir): + log.debug( + "Creating workdir folder: \"{}\"".format(workdir) + ) + try: + os.makedirs(workdir) + except Exception as exc: + raise ApplicationLaunchFailed( + "Couldn't create workdir because: {}".format(str(exc)) + ) + context_env = { "AVALON_PROJECT": project_doc["name"], "AVALON_ASSET": asset_doc["name"], diff --git a/openpype/lib/delivery.py b/openpype/lib/delivery.py new file mode 100644 index 0000000000..943cd9fcaf --- /dev/null +++ b/openpype/lib/delivery.py @@ -0,0 +1,306 @@ +"""Functions useful for delivery action or loader""" +import os +import shutil +import clique +import collections + +def collect_frames(files): + """ + Returns dict of source path and its frame, if from sequence + + Uses clique as most precise solution + + Args: + files(list): list of source paths + Returns: + (dict): {'/asset/subset_v001.0001.png': '0001', ....} + """ + collections, remainder = clique.assemble(files) + + sources_and_frames = {} + if collections: + for collection in collections: + src_head = collection.head + src_tail = collection.tail + + for index in collection.indexes: + src_frame = collection.format("{padding}") % index + src_file_name = "{}{}{}".format(src_head, src_frame, + src_tail) + sources_and_frames[src_file_name] = src_frame + else: + sources_and_frames[remainder.pop()] = None + + return sources_and_frames + + +def sizeof_fmt(num, suffix='B'): + """Returns formatted string with size in appropriate unit""" + for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']: + if abs(num) < 1024.0: + return "%3.1f%s%s" % (num, unit, suffix) + num /= 1024.0 + return "%.1f%s%s" % (num, 'Yi', suffix) + + +def path_from_representation(representation, anatomy): + from avalon import pipeline # safer importing + + try: + template = representation["data"]["template"] + + except KeyError: + return None + + try: + context = representation["context"] + context["root"] = anatomy.roots + path = pipeline.format_template_with_optional_keys( + context, template + ) + + except KeyError: + # Template references unavailable data + return None + + return os.path.normpath(path) + + +def copy_file(src_path, dst_path): + """Hardlink file if possible(to save space), copy if not""" + from avalon.vendor import filelink # safer importing + + if os.path.exists(dst_path): + return + try: + filelink.create( + src_path, + dst_path, + filelink.HARDLINK + ) + except OSError: + shutil.copyfile(src_path, dst_path) + + +def get_format_dict(anatomy, location_path): + """Returns replaced root values from user provider value. + + Args: + anatomy (Anatomy) + location_path (str): user provided value + Returns: + (dict): prepared for formatting of a template + """ + format_dict = {} + if location_path: + location_path = location_path.replace("\\", "/") + root_names = anatomy.root_names_from_templates( + anatomy.templates["delivery"] + ) + if root_names is None: + format_dict["root"] = location_path + else: + format_dict["root"] = {} + for name in root_names: + format_dict["root"][name] = location_path + return format_dict + + +def check_destination_path(repre_id, + anatomy, anatomy_data, + datetime_data, template_name): + """ Try to create destination path based on 'template_name'. + + In the case that path cannot be filled, template contains unmatched + keys, provide error message to filter out repre later. + + Args: + anatomy (Anatomy) + anatomy_data (dict): context to fill anatomy + datetime_data (dict): values with actual date + template_name (str): to pick correct delivery template + Returns: + (collections.defauldict): {"TYPE_OF_ERROR":"ERROR_DETAIL"} + """ + anatomy_data.update(datetime_data) + anatomy_filled = anatomy.format_all(anatomy_data) + dest_path = anatomy_filled["delivery"][template_name] + report_items = collections.defaultdict(list) + + if not dest_path.solved: + msg = ( + "Missing keys in Representation's context" + " for anatomy template \"{}\"." + ).format(template_name) + + sub_msg = ( + "Representation: {}
" + ).format(repre_id) + + if dest_path.missing_keys: + keys = ", ".join(dest_path.missing_keys) + sub_msg += ( + "- Missing keys: \"{}\"
" + ).format(keys) + + if dest_path.invalid_types: + items = [] + for key, value in dest_path.invalid_types.items(): + items.append("\"{}\" {}".format(key, str(value))) + + keys = ", ".join(items) + sub_msg += ( + "- Invalid value DataType: \"{}\"
" + ).format(keys) + + report_items[msg].append(sub_msg) + + return report_items + + +def process_single_file( + src_path, repre, anatomy, template_name, anatomy_data, format_dict, + report_items, log +): + """Copy single file to calculated path based on template + + Args: + src_path(str): path of source representation file + _repre (dict): full repre, used only in process_sequence, here only + as to share same signature + anatomy (Anatomy) + template_name (string): user selected delivery template name + anatomy_data (dict): data from repre to fill anatomy with + format_dict (dict): root dictionary with names and values + report_items (collections.defaultdict): to return error messages + log (Logger): for log printing + Returns: + (collections.defaultdict , int) + """ + if not os.path.exists(src_path): + msg = "{} doesn't exist for {}".format(src_path, + repre["_id"]) + report_items["Source file was not found"].append(msg) + return report_items, 0 + + anatomy_filled = anatomy.format(anatomy_data) + if format_dict: + template_result = anatomy_filled["delivery"][template_name] + delivery_path = template_result.rootless.format(**format_dict) + else: + delivery_path = anatomy_filled["delivery"][template_name] + + # context.representation could be .psd + delivery_path = delivery_path.replace("..", ".") + + delivery_folder = os.path.dirname(delivery_path) + if not os.path.exists(delivery_folder): + os.makedirs(delivery_folder) + + log.debug("Copying single: {} -> {}".format(src_path, delivery_path)) + copy_file(src_path, delivery_path) + + return report_items, 1 + + +def process_sequence( + src_path, repre, anatomy, template_name, anatomy_data, format_dict, + report_items, log +): + """ For Pype2(mainly - works in 3 too) where representation might not + contain files. + + Uses listing physical files (not 'files' on repre as a)might not be + present, b)might not be reliable for representation and copying them. + + TODO Should be refactored when files are sufficient to drive all + representations. + + Args: + src_path(str): path of source representation file + repre (dict): full representation + anatomy (Anatomy) + template_name (string): user selected delivery template name + anatomy_data (dict): data from repre to fill anatomy with + format_dict (dict): root dictionary with names and values + report_items (collections.defaultdict): to return error messages + log (Logger): for log printing + Returns: + (collections.defaultdict , int) + """ + if not os.path.exists(src_path): + msg = "{} doesn't exist for {}".format(src_path, + repre["_id"]) + report_items["Source file was not found"].append(msg) + return report_items, 0 + + dir_path, file_name = os.path.split(str(src_path)) + + context = repre["context"] + ext = context.get("ext", context.get("representation")) + + if not ext: + msg = "Source extension not found, cannot find collection" + report_items[msg].append(src_path) + log.warning("{} <{}>".format(msg, context)) + return report_items, 0 + + ext = "." + ext + # context.representation could be .psd + ext = ext.replace("..", ".") + + src_collections, remainder = clique.assemble(os.listdir(dir_path)) + src_collection = None + for col in src_collections: + if col.tail != ext: + continue + + src_collection = col + break + + if src_collection is None: + msg = "Source collection of files was not found" + report_items[msg].append(src_path) + log.warning("{} <{}>".format(msg, src_path)) + return report_items, 0 + + frame_indicator = "@####@" + + anatomy_data["frame"] = frame_indicator + anatomy_filled = anatomy.format(anatomy_data) + + if format_dict: + template_result = anatomy_filled["delivery"][template_name] + delivery_path = template_result.rootless.format(**format_dict) + else: + delivery_path = anatomy_filled["delivery"][template_name] + + delivery_folder = os.path.dirname(delivery_path) + dst_head, dst_tail = delivery_path.split(frame_indicator) + dst_padding = src_collection.padding + dst_collection = clique.Collection( + head=dst_head, + tail=dst_tail, + padding=dst_padding + ) + + if not os.path.exists(delivery_folder): + os.makedirs(delivery_folder) + + src_head = src_collection.head + src_tail = src_collection.tail + uploaded = 0 + for index in src_collection.indexes: + src_padding = src_collection.format("{padding}") % index + src_file_name = "{}{}{}".format(src_head, src_padding, src_tail) + src = os.path.normpath( + os.path.join(dir_path, src_file_name) + ) + + dst_padding = dst_collection.format("{padding}") % index + dst = "{}{}{}".format(dst_head, dst_padding, dst_tail) + log.debug("Copying single: {} -> {}".format(src, dst)) + copy_file(src, dst) + uploaded += 1 + + return report_items, uploaded diff --git a/openpype/modules/base.py b/openpype/modules/base.py index cd2ec778c5..441a9731b7 100644 --- a/openpype/modules/base.py +++ b/openpype/modules/base.py @@ -699,6 +699,10 @@ class TrayModulesManager(ModulesManager): output.append(module) return output + def restart_tray(self): + if self.tray_manager: + self.tray_manager.restart() + def tray_init(self): report = {} time_start = time.time() diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index ea953441a2..7a4481c526 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -105,7 +105,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): families = ["render.farm", "prerender.farm", "renderlayer", "imagesequence", "vrayscene"] - aov_filter = {"maya": [r".+(?:\.|_)([Bb]eauty)(?:\.|_).*"], + aov_filter = {"maya": [r".*(?:\.|_)?([Bb]eauty)(?:\.|_)?.*"], "aftereffects": [r".*"], # for everything from AE "harmony": [r".*"], # for everything from AE "celaction": [r".*"]} diff --git a/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py b/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py index 410e51e2a4..e60045bd50 100644 --- a/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py +++ b/openpype/modules/ftrack/event_handlers_server/event_sync_to_avalon.py @@ -1101,9 +1101,6 @@ class SyncToAvalonEvent(BaseEvent): # Parents, Hierarchy ent_path_items = [ent["name"] for ent in ftrack_ent["link"]] parents = ent_path_items[1:len(ent_path_items)-1:] - hierarchy = "" - if len(parents) > 0: - hierarchy = os.path.sep.join(parents) # TODO logging self.log.debug( @@ -1132,7 +1129,6 @@ class SyncToAvalonEvent(BaseEvent): "ftrackId": ftrack_ent["id"], "entityType": ftrack_ent.entity_type, "parents": parents, - "hierarchy": hierarchy, "tasks": {}, "visualParent": vis_par } @@ -1975,14 +1971,9 @@ class SyncToAvalonEvent(BaseEvent): if cur_par == parents: continue - hierarchy = "" - if len(parents) > 0: - hierarchy = os.path.sep.join(parents) - if "data" not in self.updates[mongo_id]: self.updates[mongo_id]["data"] = {} self.updates[mongo_id]["data"]["parents"] = parents - self.updates[mongo_id]["data"]["hierarchy"] = hierarchy # Skip custom attributes if didn't change if not hier_cust_attrs_ids: diff --git a/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py b/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py index ff39db4383..c20491349f 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delete_asset.py @@ -11,23 +11,28 @@ from avalon.api import AvalonMongoDB class DeleteAssetSubset(BaseAction): '''Edit meta data action.''' - #: Action identifier. + # Action identifier. identifier = "delete.asset.subset" - #: Action label. + # Action label. label = "Delete Asset/Subsets" - #: Action description. + # Action description. description = "Removes from Avalon with all childs and asset from Ftrack" icon = statics_icon("ftrack", "action_icons", "DeleteAsset.svg") settings_key = "delete_asset_subset" - #: Db connection - dbcon = AvalonMongoDB() + # Db connection + dbcon = None splitter = {"type": "label", "value": "---"} action_data_by_id = {} asset_prefix = "asset:" subset_prefix = "subset:" + def __init__(self, *args, **kwargs): + self.dbcon = AvalonMongoDB() + + super(DeleteAssetSubset, self).__init__(*args, **kwargs) + def discover(self, session, entities, event): """ Validation """ task_ids = [] @@ -446,7 +451,14 @@ class DeleteAssetSubset(BaseAction): if len(assets_to_delete) > 0: map_av_ftrack_id = spec_data["without_ftrack_id"] # Prepare data when deleting whole avalon asset - avalon_assets = self.dbcon.find({"type": "asset"}) + avalon_assets = self.dbcon.find( + {"type": "asset"}, + { + "_id": 1, + "data.visualParent": 1, + "data.ftrackId": 1 + } + ) avalon_assets_by_parent = collections.defaultdict(list) for asset in avalon_assets: asset_id = asset["_id"] @@ -537,11 +549,13 @@ class DeleteAssetSubset(BaseAction): ftrack_proc_txt, ", ".join(ftrack_ids_to_delete) )) - ftrack_ents_to_delete = ( + entities_by_link_len = ( self._filter_entities_to_delete(ftrack_ids_to_delete, session) ) - for entity in ftrack_ents_to_delete: - session.delete(entity) + for link_len in sorted(entities_by_link_len.keys(), reverse=True): + for entity in entities_by_link_len[link_len]: + session.delete(entity) + try: session.commit() except Exception: @@ -600,29 +614,11 @@ class DeleteAssetSubset(BaseAction): joined_ids_to_delete ) ).all() - filtered = to_delete_entities[:] - while True: - changed = False - _filtered = filtered[:] - for entity in filtered: - entity_id = entity["id"] + entities_by_link_len = collections.defaultdict(list) + for entity in to_delete_entities: + entities_by_link_len[len(entity["link"])].append(entity) - for _entity in tuple(_filtered): - if entity_id == _entity["id"]: - continue - - for _link in _entity["link"]: - if entity_id == _link["id"] and _entity in _filtered: - _filtered.remove(_entity) - changed = True - break - - filtered = _filtered - - if not changed: - break - - return filtered + return entities_by_link_len def report_handle(self, report_messages, project_name, event): if not report_messages: diff --git a/openpype/modules/ftrack/event_handlers_user/action_delivery.py b/openpype/modules/ftrack/event_handlers_user/action_delivery.py index 88fdbe3669..2e7599647a 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delivery.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delivery.py @@ -1,18 +1,20 @@ import os import copy import json -import shutil import collections -import clique from bson.objectid import ObjectId -from avalon import pipeline -from avalon.vendor import filelink - from openpype.api import Anatomy, config from openpype.modules.ftrack.lib import BaseAction, statics_icon from openpype.modules.ftrack.lib.avalon_sync import CUST_ATTR_ID_KEY +from openpype.lib.delivery import ( + path_from_representation, + get_format_dict, + check_destination_path, + process_single_file, + process_sequence +) from avalon.api import AvalonMongoDB @@ -72,7 +74,7 @@ class Delivery(BaseAction): "value": project_name }) - # Prpeare anatomy data + # Prepare anatomy data anatomy = Anatomy(project_name) new_anatomies = [] first = None @@ -366,12 +368,18 @@ class Delivery(BaseAction): def launch(self, session, entities, event): if "values" not in event["data"]: - return + return { + "success": True, + "message": "Nothing to do" + } values = event["data"]["values"] skipped = values.pop("__skipped__") if skipped: - return None + return { + "success": False, + "message": "Action skipped" + } user_id = event["source"]["user"]["id"] user_entity = session.query( @@ -389,27 +397,45 @@ class Delivery(BaseAction): try: self.db_con.install() - self.real_launch(session, entities, event) - job["status"] = "done" + report = self.real_launch(session, entities, event) - except Exception: + except Exception as exc: + report = { + "success": False, + "title": "Delivery failed", + "items": [{ + "type": "label", + "value": ( + "Error during delivery action process:
{}" + "

Check logs for more information." + ).format(str(exc)) + }] + } self.log.warning( "Failed during processing delivery action.", exc_info=True ) finally: - if job["status"] != "done": + if report["success"]: + job["status"] = "done" + else: job["status"] = "failed" session.commit() self.db_con.uninstall() - if job["status"] == "failed": + if not report["success"]: + self.show_interface( + items=report["items"], + title=report["title"], + event=event + ) return { "success": False, - "message": "Delivery failed. Check logs for more information." + "message": "Errors during delivery process. See report." } - return True + + return report def real_launch(self, session, entities, event): self.log.info("Delivery action just started.") @@ -429,7 +455,7 @@ class Delivery(BaseAction): if not repre_names: return { "success": True, - "message": "Not selected components to deliver." + "message": "No selected components to deliver." } location_path = location_path.strip() @@ -450,18 +476,7 @@ class Delivery(BaseAction): anatomy = Anatomy(project_name) - format_dict = {} - if location_path: - location_path = location_path.replace("\\", "/") - root_names = anatomy.root_names_from_templates( - anatomy.templates["delivery"] - ) - if root_names is None: - format_dict["root"] = location_path - else: - format_dict["root"] = {} - for name in root_names: - format_dict["root"][name] = location_path + format_dict = get_format_dict(anatomy, location_path) datetime_data = config.get_datetime_data() for repre in repres_to_deliver: @@ -471,41 +486,15 @@ class Delivery(BaseAction): debug_msg += " with published path {}.".format(source_path) self.log.debug(debug_msg) - # Get destination repre path anatomy_data = copy.deepcopy(repre["context"]) - anatomy_data.update(datetime_data) - anatomy_filled = anatomy.format_all(anatomy_data) - test_path = anatomy_filled["delivery"][anatomy_name] + repre_report_items = check_destination_path(repre["_id"], + anatomy, + anatomy_data, + datetime_data, + anatomy_name) - if not test_path.solved: - msg = ( - "Missing keys in Representation's context" - " for anatomy template \"{}\"." - ).format(anatomy_name) - - if test_path.missing_keys: - keys = ", ".join(test_path.missing_keys) - sub_msg = ( - "Representation: {}
- Missing keys: \"{}\"
" - ).format(str(repre["_id"]), keys) - - if test_path.invalid_types: - items = [] - for key, value in test_path.invalid_types.items(): - items.append("\"{}\" {}".format(key, str(value))) - - keys = ", ".join(items) - sub_msg = ( - "Representation: {}
" - "- Invalid value DataType: \"{}\"
" - ).format(str(repre["_id"]), keys) - - report_items[msg].append(sub_msg) - self.log.warning( - "{} Representation: \"{}\" Filled: <{}>".format( - msg, str(repre["_id"]), str(test_path) - ) - ) + if repre_report_items: + report_items.update(repre_report_items) continue # Get source repre path @@ -514,153 +503,30 @@ class Delivery(BaseAction): if frame: repre["context"]["frame"] = len(str(frame)) * "#" - repre_path = self.path_from_represenation(repre, anatomy) + repre_path = path_from_representation(repre, anatomy) # TODO add backup solution where root of path from component - # is repalced with root + # is replaced with root args = ( repre_path, + repre, anatomy, anatomy_name, anatomy_data, format_dict, - report_items + report_items, + self.log ) if not frame: - self.process_single_file(*args) + process_single_file(*args) else: - self.process_sequence(*args) + process_sequence(*args) return self.report(report_items) - def process_single_file( - self, repre_path, anatomy, anatomy_name, anatomy_data, format_dict, - report_items - ): - anatomy_filled = anatomy.format(anatomy_data) - if format_dict: - template_result = anatomy_filled["delivery"][anatomy_name] - delivery_path = template_result.rootless.format(**format_dict) - else: - delivery_path = anatomy_filled["delivery"][anatomy_name] - - delivery_folder = os.path.dirname(delivery_path) - if not os.path.exists(delivery_folder): - os.makedirs(delivery_folder) - - self.copy_file(repre_path, delivery_path) - - def process_sequence( - self, repre_path, anatomy, anatomy_name, anatomy_data, format_dict, - report_items - ): - dir_path, file_name = os.path.split(str(repre_path)) - - base_name, ext = os.path.splitext(file_name) - file_name_items = None - if "#" in base_name: - file_name_items = [part for part in base_name.split("#") if part] - - elif "%" in base_name: - file_name_items = base_name.split("%") - - if not file_name_items: - msg = "Source file was not found" - report_items[msg].append(repre_path) - self.log.warning("{} <{}>".format(msg, repre_path)) - return - - src_collections, remainder = clique.assemble(os.listdir(dir_path)) - src_collection = None - for col in src_collections: - if col.tail != ext: - continue - - # skip if collection don't have same basename - if not col.head.startswith(file_name_items[0]): - continue - - src_collection = col - break - - if src_collection is None: - # TODO log error! - msg = "Source collection of files was not found" - report_items[msg].append(repre_path) - self.log.warning("{} <{}>".format(msg, repre_path)) - return - - frame_indicator = "@####@" - - anatomy_data["frame"] = frame_indicator - anatomy_filled = anatomy.format(anatomy_data) - - if format_dict: - template_result = anatomy_filled["delivery"][anatomy_name] - delivery_path = template_result.rootless.format(**format_dict) - else: - delivery_path = anatomy_filled["delivery"][anatomy_name] - - delivery_folder = os.path.dirname(delivery_path) - dst_head, dst_tail = delivery_path.split(frame_indicator) - dst_padding = src_collection.padding - dst_collection = clique.Collection( - head=dst_head, - tail=dst_tail, - padding=dst_padding - ) - - if not os.path.exists(delivery_folder): - os.makedirs(delivery_folder) - - src_head = src_collection.head - src_tail = src_collection.tail - for index in src_collection.indexes: - src_padding = src_collection.format("{padding}") % index - src_file_name = "{}{}{}".format(src_head, src_padding, src_tail) - src = os.path.normpath( - os.path.join(dir_path, src_file_name) - ) - - dst_padding = dst_collection.format("{padding}") % index - dst = "{}{}{}".format(dst_head, dst_padding, dst_tail) - - self.copy_file(src, dst) - - def path_from_represenation(self, representation, anatomy): - try: - template = representation["data"]["template"] - - except KeyError: - return None - - try: - context = representation["context"] - context["root"] = anatomy.roots - path = pipeline.format_template_with_optional_keys( - context, template - ) - - except KeyError: - # Template references unavailable data - return None - - return os.path.normpath(path) - - def copy_file(self, src_path, dst_path): - if os.path.exists(dst_path): - return - try: - filelink.create( - src_path, - dst_path, - filelink.HARDLINK - ) - except OSError: - shutil.copyfile(src_path, dst_path) - def report(self, report_items): + """Returns dict with final status of delivery (succes, fail etc.).""" items = [] - title = "Delivery report" + for msg, _items in report_items.items(): if not _items: continue @@ -691,9 +557,8 @@ class Delivery(BaseAction): return { "items": items, - "title": title, - "success": False, - "message": "Delivery Finished" + "title": "Delivery report", + "success": False } diff --git a/openpype/modules/ftrack/ftrack_server/event_server_cli.py b/openpype/modules/ftrack/ftrack_server/event_server_cli.py index b5cc1bef3e..8bba22b475 100644 --- a/openpype/modules/ftrack/ftrack_server/event_server_cli.py +++ b/openpype/modules/ftrack/ftrack_server/event_server_cli.py @@ -422,17 +422,18 @@ def run_event_server( ftrack_url, ftrack_user, ftrack_api_key, - ftrack_events_path, - no_stored_credentials, - store_credentials, legacy, clockify_api_key, clockify_workspace ): - if not no_stored_credentials: + if not ftrack_user or not ftrack_api_key: + print(( + "Ftrack user/api key were not passed." + " Trying to use credentials from user keyring." + )) cred = credentials.get_credentials(ftrack_url) - username = cred.get('username') - api_key = cred.get('api_key') + ftrack_user = cred.get("username") + ftrack_api_key = cred.get("api_key") if clockify_workspace and clockify_api_key: os.environ["CLOCKIFY_WORKSPACE"] = clockify_workspace @@ -445,209 +446,16 @@ def run_event_server( return 1 # Validate entered credentials - if not validate_credentials(ftrack_url, username, api_key): + if not validate_credentials(ftrack_url, ftrack_user, ftrack_api_key): print('Exiting! < Please enter valid credentials >') return 1 - if store_credentials: - credentials.save_credentials(username, api_key, ftrack_url) - # Set Ftrack environments os.environ["FTRACK_SERVER"] = ftrack_url - os.environ["FTRACK_API_USER"] = username - os.environ["FTRACK_API_KEY"] = api_key - # TODO This won't work probably - if ftrack_events_path: - if isinstance(ftrack_events_path, (list, tuple)): - ftrack_events_path = os.pathsep.join(ftrack_events_path) - os.environ["FTRACK_EVENTS_PATH"] = ftrack_events_path + os.environ["FTRACK_API_USER"] = ftrack_user + os.environ["FTRACK_API_KEY"] = ftrack_api_key if legacy: return legacy_server(ftrack_url) return main_loop(ftrack_url) - - -def main(argv): - ''' - There are 4 values neccessary for event server: - 1.) Ftrack url - "studio.ftrackapp.com" - 2.) Username - "my.username" - 3.) API key - "apikey-long11223344-6665588-5565" - 4.) Path/s to events - "X:/path/to/folder/with/events" - - All these values can be entered with arguments or environment variables. - - arguments: - "-ftrackurl {url}" - "-ftrackuser {username}" - "-ftrackapikey {api key}" - "-ftrackeventpaths {path to events}" - - environment variables: - FTRACK_SERVER - FTRACK_API_USER - FTRACK_API_KEY - FTRACK_EVENTS_PATH - - Credentials (Username & API key): - - Credentials can be stored for auto load on next start - - To *Store/Update* these values add argument "-storecred" - - They will be stored to appsdir file when login is successful - - To *Update/Override* values with enviromnet variables is also needed to: - - *don't enter argument for that value* - - add argument "-noloadcred" (currently stored credentials won't be loaded) - - Order of getting values: - 1.) Arguments are always used when entered. - - entered values through args have most priority! (in each case) - 2.) Credentials are tried to load from appsdir file. - - skipped when credentials were entered through args or credentials - are not stored yet - - can be skipped with "-noloadcred" argument - 3.) Environment variables are last source of values. - - will try to get not yet set values from environments - - Best practice: - - set environment variables FTRACK_SERVER & FTRACK_EVENTS_PATH - - launch event_server_cli with args: - ~/event_server_cli.py -ftrackuser "{username}" -ftrackapikey "{API key}" -storecred - - next time launch event_server_cli.py only with set environment variables - FTRACK_SERVER & FTRACK_EVENTS_PATH - ''' - parser = argparse.ArgumentParser(description='Ftrack event server') - parser.add_argument( - "-ftrackurl", type=str, metavar='FTRACKURL', - help=( - "URL to ftrack server where events should handle" - " (default from environment: $FTRACK_SERVER)" - ) - ) - parser.add_argument( - "-ftrackuser", type=str, - help=( - "Username should be the username of the user in ftrack" - " to record operations against." - " (default from environment: $FTRACK_API_USER)" - ) - ) - parser.add_argument( - "-ftrackapikey", type=str, - help=( - "Should be the API key to use for authentication" - " (default from environment: $FTRACK_API_KEY)" - ) - ) - parser.add_argument( - "-ftrackeventpaths", nargs='+', - help=( - "List of paths where events are stored." - " (default from environment: $FTRACK_EVENTS_PATH)" - ) - ) - parser.add_argument( - '-storecred', - help=( - "Entered credentials will be also stored" - " to apps dir for future usage" - ), - action="store_true" - ) - parser.add_argument( - '-noloadcred', - help="Load creadentials from apps dir", - action="store_true" - ) - parser.add_argument( - '-legacy', - help="Load creadentials from apps dir", - action="store_true" - ) - parser.add_argument( - "-clockifyapikey", type=str, - help=( - "Enter API key for Clockify actions." - " (default from environment: $CLOCKIFY_API_KEY)" - ) - ) - parser.add_argument( - "-clockifyworkspace", type=str, - help=( - "Enter workspace for Clockify." - " (default from module presets or " - "environment: $CLOCKIFY_WORKSPACE)" - ) - ) - ftrack_url = os.environ.get("FTRACK_SERVER") - username = os.environ.get("FTRACK_API_USER") - api_key = os.environ.get("FTRACK_API_KEY") - - kwargs, args = parser.parse_known_args(argv) - - if kwargs.ftrackurl: - ftrack_url = kwargs.ftrackurl - - # Load Ftrack url from settings if not set - if not ftrack_url: - ftrack_url = get_ftrack_url_from_settings() - - event_paths = None - if kwargs.ftrackeventpaths: - event_paths = kwargs.ftrackeventpaths - - if not kwargs.noloadcred: - cred = credentials.get_credentials(ftrack_url) - username = cred.get('username') - api_key = cred.get('api_key') - - if kwargs.ftrackuser: - username = kwargs.ftrackuser - - if kwargs.ftrackapikey: - api_key = kwargs.ftrackapikey - - if kwargs.clockifyworkspace: - os.environ["CLOCKIFY_WORKSPACE"] = kwargs.clockifyworkspace - - if kwargs.clockifyapikey: - os.environ["CLOCKIFY_API_KEY"] = kwargs.clockifyapikey - - legacy = kwargs.legacy - - # Check url regex and accessibility - ftrack_url = check_ftrack_url(ftrack_url) - if not ftrack_url: - print('Exiting! < Please enter Ftrack server url >') - return 1 - - # Validate entered credentials - if not validate_credentials(ftrack_url, username, api_key): - print('Exiting! < Please enter valid credentials >') - return 1 - - if kwargs.storecred: - credentials.save_credentials(username, api_key, ftrack_url) - - # Set Ftrack environments - os.environ["FTRACK_SERVER"] = ftrack_url - os.environ["FTRACK_API_USER"] = username - os.environ["FTRACK_API_KEY"] = api_key - if event_paths: - if isinstance(event_paths, (list, tuple)): - event_paths = os.pathsep.join(event_paths) - os.environ["FTRACK_EVENTS_PATH"] = event_paths - - if legacy: - return legacy_server(ftrack_url) - - return main_loop(ftrack_url) - - -if __name__ == "__main__": - # Register interupt signal - def signal_handler(sig, frame): - print("You pressed Ctrl+C. Process ended.") - sys.exit(0) - - signal.signal(signal.SIGINT, signal_handler) - signal.signal(signal.SIGTERM, signal_handler) - - sys.exit(main(sys.argv)) diff --git a/openpype/modules/ftrack/lib/avalon_sync.py b/openpype/modules/ftrack/lib/avalon_sync.py index a3b926464e..5d1da005dc 100644 --- a/openpype/modules/ftrack/lib/avalon_sync.py +++ b/openpype/modules/ftrack/lib/avalon_sync.py @@ -1237,12 +1237,8 @@ class SyncEntitiesFactory: ent_path_items = [ent["name"] for ent in entity["link"]] parents = ent_path_items[1:len(ent_path_items) - 1:] - hierarchy = "" - if len(parents) > 0: - hierarchy = os.path.sep.join(parents) data["parents"] = parents - data["hierarchy"] = hierarchy data["tasks"] = self.entities_dict[id].pop("tasks", {}) self.entities_dict[id]["final_entity"]["data"] = data self.entities_dict[id]["final_entity"]["type"] = "asset" @@ -2169,8 +2165,6 @@ class SyncEntitiesFactory: hierarchy = "/".join(parents) self.entities_dict[ftrack_id][ "final_entity"]["data"]["parents"] = parents - self.entities_dict[ftrack_id][ - "final_entity"]["data"]["hierarchy"] = hierarchy _parents.append(self.entities_dict[ftrack_id]["name"]) for child_id in self.entities_dict[ftrack_id]["children"]: @@ -2181,7 +2175,6 @@ class SyncEntitiesFactory: if "data" not in self.updates[mongo_id]: self.updates[mongo_id]["data"] = {} self.updates[mongo_id]["data"]["parents"] = parents - self.updates[mongo_id]["data"]["hierarchy"] = hierarchy def prepare_project_changes(self): ftrack_ent_dict = self.entities_dict[self.ft_project_id] diff --git a/openpype/modules/ftrack/tray/login_tools.py b/openpype/modules/ftrack/tray/login_tools.py index c6cf5b5f7b..95a072c352 100644 --- a/openpype/modules/ftrack/tray/login_tools.py +++ b/openpype/modules/ftrack/tray/login_tools.py @@ -16,6 +16,18 @@ class LoginServerHandler(BaseHTTPRequestHandler): self.login_callback = login_callback BaseHTTPRequestHandler.__init__(self, *args, **kw) + def log_message(self, format_str, *args): + """Override method of BaseHTTPRequestHandler. + + Goal is to use `print` instead of `sys.stderr.write` + """ + # Change + print("%s - - [%s] %s\n" % ( + self.client_address[0], + self.log_date_time_string(), + format_str % args + )) + def do_GET(self): '''Override to handle requests ourselves.''' parsed_path = parse.urlparse(self.path) diff --git a/openpype/modules/settings_action.py b/openpype/modules/settings_action.py index 5651868f68..f5bcb5342d 100644 --- a/openpype/modules/settings_action.py +++ b/openpype/modules/settings_action.py @@ -67,6 +67,10 @@ class SettingsAction(PypeModule, ITrayAction): return from openpype.tools.settings import MainWidget self.settings_window = MainWidget(self.user_role) + self.settings_window.trigger_restart.connect(self._on_trigger_restart) + + def _on_trigger_restart(self): + self.manager.restart_tray() def show_settings_window(self): """Show settings tool window. diff --git a/openpype/modules/standalonepublish_action.py b/openpype/modules/standalonepublish_action.py index 87f7446341..78d87cb6c7 100644 --- a/openpype/modules/standalonepublish_action.py +++ b/openpype/modules/standalonepublish_action.py @@ -1,5 +1,5 @@ import os -import sys +import platform import subprocess from openpype.lib import get_pype_execute_args from . import PypeModule, ITrayAction @@ -35,4 +35,14 @@ class StandAlonePublishAction(PypeModule, ITrayAction): def run_standalone_publisher(self): args = get_pype_execute_args("standalonepublisher") - subprocess.Popen(args, creationflags=subprocess.DETACHED_PROCESS) + kwargs = {} + if platform.system().lower() == "darwin": + new_args = ["open", "-a", args.pop(0), "--args"] + new_args.extend(args) + args = new_args + + detached_process = getattr(subprocess, "DETACHED_PROCESS", None) + if detached_process is not None: + kwargs["creationflags"] = detached_process + + subprocess.Popen(args, **kwargs) diff --git a/openpype/plugins/load/delivery.py b/openpype/plugins/load/delivery.py new file mode 100644 index 0000000000..3753f1bfc9 --- /dev/null +++ b/openpype/plugins/load/delivery.py @@ -0,0 +1,318 @@ +from collections import defaultdict +import copy + +from Qt import QtWidgets, QtCore, QtGui + +from avalon import api, style +from avalon.api import AvalonMongoDB + +from openpype.api import Anatomy, config +from openpype import resources + +from openpype.lib.delivery import ( + sizeof_fmt, + path_from_representation, + get_format_dict, + check_destination_path, + process_single_file, + process_sequence, + collect_frames +) + + +class Delivery(api.SubsetLoader): + """Export selected versions to folder structure from Template""" + + is_multiple_contexts_compatible = True + sequence_splitter = "__sequence_splitter__" + + representations = ["*"] + families = ["*"] + tool_names = ["library_loader"] + + label = "Deliver Versions" + order = 35 + icon = "upload" + color = "#d8d8d8" + + def message(self, text): + msgBox = QtWidgets.QMessageBox() + msgBox.setText(text) + msgBox.setStyleSheet(style.load_stylesheet()) + msgBox.setWindowFlags( + msgBox.windowFlags() | QtCore.Qt.FramelessWindowHint + ) + msgBox.exec_() + + def load(self, contexts, name=None, namespace=None, options=None): + try: + dialog = DeliveryOptionsDialog(contexts, self.log) + dialog.exec_() + except Exception: + self.log.error("Failed to deliver versions.", exc_info=True) + + +class DeliveryOptionsDialog(QtWidgets.QDialog): + """Dialog to select template where to deliver selected representations.""" + + def __init__(self, contexts, log=None, parent=None): + super(DeliveryOptionsDialog, self).__init__(parent=parent) + + project = contexts[0]["project"]["name"] + self.anatomy = Anatomy(project) + self._representations = None + self.log = log + self.currently_uploaded = 0 + + self.dbcon = AvalonMongoDB() + self.dbcon.Session["AVALON_PROJECT"] = project + self.dbcon.install() + + self._set_representations(contexts) + + self.setWindowTitle("OpenPype - Deliver versions") + icon = QtGui.QIcon(resources.pype_icon_filepath()) + self.setWindowIcon(icon) + + self.setWindowFlags( + QtCore.Qt.WindowCloseButtonHint | + QtCore.Qt.WindowMinimizeButtonHint + ) + self.setStyleSheet(style.load_stylesheet()) + + dropdown = QtWidgets.QComboBox() + self.templates = self._get_templates(self.anatomy) + for name, _ in self.templates.items(): + dropdown.addItem(name) + + template_label = QtWidgets.QLabel() + template_label.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor)) + template_label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse) + + root_line_edit = QtWidgets.QLineEdit() + + repre_checkboxes_layout = QtWidgets.QFormLayout() + repre_checkboxes_layout.setContentsMargins(10, 5, 5, 10) + + self._representation_checkboxes = {} + for repre in self._get_representation_names(): + checkbox = QtWidgets.QCheckBox() + checkbox.setChecked(False) + self._representation_checkboxes[repre] = checkbox + + checkbox.stateChanged.connect(self._update_selected_label) + repre_checkboxes_layout.addRow(repre, checkbox) + + selected_label = QtWidgets.QLabel() + + input_widget = QtWidgets.QWidget(self) + input_layout = QtWidgets.QFormLayout(input_widget) + input_layout.setContentsMargins(10, 15, 5, 5) + + input_layout.addRow("Selected representations", selected_label) + input_layout.addRow("Delivery template", dropdown) + input_layout.addRow("Template value", template_label) + input_layout.addRow("Root", root_line_edit) + input_layout.addRow("Representations", repre_checkboxes_layout) + + btn_delivery = QtWidgets.QPushButton("Deliver") + btn_delivery.setEnabled(bool(dropdown.currentText())) + + progress_bar = QtWidgets.QProgressBar(self) + progress_bar.setMinimum = 0 + progress_bar.setMaximum = 100 + progress_bar.setVisible(False) + + text_area = QtWidgets.QTextEdit() + text_area.setReadOnly(True) + text_area.setVisible(False) + text_area.setMinimumHeight(100) + + layout = QtWidgets.QVBoxLayout(self) + + layout.addWidget(input_widget) + layout.addStretch(1) + layout.addWidget(btn_delivery) + layout.addWidget(progress_bar) + layout.addWidget(text_area) + + self.selected_label = selected_label + self.template_label = template_label + self.dropdown = dropdown + self.root_line_edit = root_line_edit + self.progress_bar = progress_bar + self.text_area = text_area + self.btn_delivery = btn_delivery + + self.files_selected, self.size_selected = \ + self._get_counts(self._get_selected_repres()) + + self._update_selected_label() + self._update_template_value() + + btn_delivery.clicked.connect(self.deliver) + dropdown.currentIndexChanged.connect(self._update_template_value) + + def deliver(self): + """Main method to loop through all selected representations""" + self.progress_bar.setVisible(True) + self.btn_delivery.setEnabled(False) + QtWidgets.QApplication.processEvents() + + report_items = defaultdict(list) + + selected_repres = self._get_selected_repres() + + datetime_data = config.get_datetime_data() + template_name = self.dropdown.currentText() + format_dict = get_format_dict(self.anatomy, self.root_line_edit.text()) + for repre in self._representations: + if repre["name"] not in selected_repres: + continue + + repre_path = path_from_representation(repre, self.anatomy) + + anatomy_data = copy.deepcopy(repre["context"]) + new_report_items = check_destination_path(str(repre["_id"]), + self.anatomy, + anatomy_data, + datetime_data, + template_name) + + report_items.update(new_report_items) + if new_report_items: + continue + + args = [ + repre_path, + repre, + self.anatomy, + template_name, + anatomy_data, + format_dict, + report_items, + self.log + ] + + if repre.get("files"): + src_paths = [] + for repre_file in repre["files"]: + src_path = self.anatomy.fill_root(repre_file["path"]) + src_paths.append(src_path) + sources_and_frames = collect_frames(src_paths) + + for src_path, frame in sources_and_frames.items(): + args[0] = src_path + if frame: + anatomy_data["frame"] = frame + new_report_items, uploaded = process_single_file(*args) + report_items.update(new_report_items) + self._update_progress(uploaded) + else: # fallback for Pype2 and representations without files + frame = repre['context'].get('frame') + if frame: + repre["context"]["frame"] = len(str(frame)) * "#" + + if not frame: + new_report_items, uploaded = process_single_file(*args) + else: + new_report_items, uploaded = process_sequence(*args) + report_items.update(new_report_items) + self._update_progress(uploaded) + + self.text_area.setText(self._format_report(report_items)) + self.text_area.setVisible(True) + + def _get_representation_names(self): + """Get set of representation names for checkbox filtering.""" + return set([repre["name"] for repre in self._representations]) + + def _get_templates(self, anatomy): + """Adds list of delivery templates from Anatomy to dropdown.""" + templates = {} + for template_name, value in anatomy.templates["delivery"].items(): + if not isinstance(value, str) or not value.startswith('{root'): + continue + + templates[template_name] = value + + return templates + + def _set_representations(self, contexts): + version_ids = [context["version"]["_id"] for context in contexts] + + repres = list(self.dbcon.find({ + "type": "representation", + "parent": {"$in": version_ids} + })) + + self._representations = repres + + def _get_counts(self, selected_repres=None): + """Returns tuple of number of selected files and their size.""" + files_selected = 0 + size_selected = 0 + for repre in self._representations: + if repre["name"] in selected_repres: + files = repre.get("files", []) + if not files: # for repre without files, cannot divide by 0 + files_selected += 1 + size_selected += 0 + else: + for repre_file in files: + files_selected += 1 + size_selected += repre_file["size"] + + return files_selected, size_selected + + def _prepare_label(self): + """Provides text with no of selected files and their size.""" + label = "{} files, size {}".format(self.files_selected, + sizeof_fmt(self.size_selected)) + return label + + def _get_selected_repres(self): + """Returns list of representation names filtered from checkboxes.""" + selected_repres = [] + for repre_name, chckbox in self._representation_checkboxes.items(): + if chckbox.isChecked(): + selected_repres.append(repre_name) + + return selected_repres + + def _update_selected_label(self): + """Updates label with list of number of selected files.""" + selected_repres = self._get_selected_repres() + self.files_selected, self.size_selected = \ + self._get_counts(selected_repres) + self.selected_label.setText(self._prepare_label()) + + def _update_template_value(self, _index=None): + """Sets template value to label after selection in dropdown.""" + name = self.dropdown.currentText() + template_value = self.templates.get(name) + if template_value: + self.btn_delivery.setEnabled(True) + self.template_label.setText(template_value) + + def _update_progress(self, uploaded): + """Update progress bar after each repre copied.""" + self.currently_uploaded += uploaded + + ratio = self.currently_uploaded / self.files_selected + self.progress_bar.setValue(ratio * self.progress_bar.maximum()) + + def _format_report(self, report_items): + """Format final result and error details as html.""" + msg = "Delivery finished" + if not report_items: + msg += " successfully" + else: + msg += " with errors" + txt = "

{}

".format(msg) + for header, data in report_items.items(): + txt += "

{}

".format(header) + for item in data: + txt += "{}
".format(item) + + return txt diff --git a/openpype/plugins/publish/collect_resources_path.py b/openpype/plugins/publish/collect_resources_path.py index 04a33cd5be..98b59332da 100644 --- a/openpype/plugins/publish/collect_resources_path.py +++ b/openpype/plugins/publish/collect_resources_path.py @@ -39,7 +39,6 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): "rig", "plate", "look", - "lut", "yetiRig", "yeticache", "nukenodes", @@ -52,7 +51,8 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): "fbx", "textures", "action", - "background" + "background", + "effect" ] def process(self, instance): diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index 76f6ffc608..ef52d51325 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -44,6 +44,7 @@ class ExtractBurnin(openpype.api.Extractor): "harmony", "fusion", "aftereffects", + "tvpaint" # "resolve" ] optional = True diff --git a/openpype/plugins/publish/extract_otio_audio_tracks.py b/openpype/plugins/publish/extract_otio_audio_tracks.py index 43e40097f7..2dc822fb0e 100644 --- a/openpype/plugins/publish/extract_otio_audio_tracks.py +++ b/openpype/plugins/publish/extract_otio_audio_tracks.py @@ -40,12 +40,15 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin): # get sequence otio_timeline = context.data["otioTimeline"] - # temp file - audio_temp_fpath = self.create_temp_file("audio") - # get all audio inputs from otio timeline audio_inputs = self.get_audio_track_items(otio_timeline) + if not audio_inputs: + return + + # temp file + audio_temp_fpath = self.create_temp_file("audio") + # create empty audio with longest duration empty = self.create_empty(audio_inputs) @@ -53,14 +56,14 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin): audio_inputs.insert(0, empty) # create cmd - cmd = self.ffmpeg_path + " " + cmd = '"{}"'.format(self.ffmpeg_path) + " " cmd += self.create_cmd(audio_inputs) - cmd += audio_temp_fpath + cmd += "\"{}\"".format(audio_temp_fpath) # run subprocess self.log.debug("Executing: {}".format(cmd)) openpype.api.run_subprocess( - cmd, shell=True, logger=self.log + cmd, logger=self.log ) # remove empty @@ -97,17 +100,17 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin): audio_fpath = self.create_temp_file(name) cmd = " ".join([ - self.ffmpeg_path, + '"{}"'.format(self.ffmpeg_path), "-ss {}".format(start_sec), "-t {}".format(duration_sec), - "-i {}".format(audio_file), + "-i \"{}\"".format(audio_file), audio_fpath ]) # run subprocess self.log.debug("Executing: {}".format(cmd)) openpype.api.run_subprocess( - cmd, shell=True, logger=self.log + cmd, logger=self.log ) else: audio_fpath = recycling_file.pop() @@ -218,11 +221,11 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin): # create empty cmd cmd = " ".join([ - self.ffmpeg_path, + '"{}"'.format(self.ffmpeg_path), "-f lavfi", "-i anullsrc=channel_layout=stereo:sample_rate=48000", "-t {}".format(max_duration_sec), - empty_fpath + "\"{}\"".format(empty_fpath) ]) # generate empty with ffmpeg @@ -230,7 +233,7 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin): self.log.debug("Executing: {}".format(cmd)) openpype.api.run_subprocess( - cmd, shell=True, logger=self.log + cmd, logger=self.log ) # return dict with output diff --git a/openpype/plugins/publish/extract_otio_review.py b/openpype/plugins/publish/extract_otio_review.py index 07fe6f2731..2f46bcb375 100644 --- a/openpype/plugins/publish/extract_otio_review.py +++ b/openpype/plugins/publish/extract_otio_review.py @@ -209,7 +209,7 @@ class ExtractOTIOReview(openpype.api.Extractor): "frameStart": start, "frameEnd": end, "stagingDir": self.staging_dir, - "tags": ["review", "ftrackreview", "delete"] + "tags": ["review", "delete"] } collection = clique.Collection( @@ -313,7 +313,7 @@ class ExtractOTIOReview(openpype.api.Extractor): out_frame_start += end_offset # start command list - command = [ffmpeg_path] + command = ['"{}"'.format(ffmpeg_path)] if sequence: input_dir, collection = sequence @@ -326,7 +326,7 @@ class ExtractOTIOReview(openpype.api.Extractor): # form command for rendering gap files command.extend([ "-start_number {}".format(in_frame_start), - "-i {}".format(input_path) + "-i \"{}\"".format(input_path) ]) elif video: @@ -341,7 +341,7 @@ class ExtractOTIOReview(openpype.api.Extractor): command.extend([ "-ss {}".format(sec_start), "-t {}".format(sec_duration), - "-i {}".format(video_path) + "-i \"{}\"".format(video_path) ]) elif gap: @@ -360,11 +360,13 @@ class ExtractOTIOReview(openpype.api.Extractor): # add output attributes command.extend([ "-start_number {}".format(out_frame_start), - output_path + "\"{}\"".format(output_path) ]) # execute self.log.debug("Executing: {}".format(" ".join(command))) - output = openpype.api.run_subprocess(" ".join(command), shell=True) + output = openpype.api.run_subprocess( + " ".join(command), logger=self.log + ) self.log.debug("Output: {}".format(output)) def _generate_used_frames(self, duration, end_offset=None): diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py index 048d16fabb..769a0d3919 100644 --- a/openpype/plugins/publish/extract_review.py +++ b/openpype/plugins/publish/extract_review.py @@ -3,6 +3,9 @@ import re import copy import json +from abc import ABCMeta, abstractmethod +import six + import clique import pyblish.api @@ -48,6 +51,8 @@ class ExtractReview(pyblish.api.InstancePlugin): video_exts = ["mov", "mp4"] supported_exts = image_exts + video_exts + alpha_exts = ["exr", "png", "dpx"] + # FFmpeg tools paths ffmpeg_path = get_ffmpeg_tool_path("ffmpeg") @@ -296,6 +301,13 @@ class ExtractReview(pyblish.api.InstancePlugin): ): with_audio = False + input_is_sequence = self.input_is_sequence(repre) + input_allow_bg = False + if input_is_sequence and repre["files"]: + ext = os.path.splitext(repre["files"][0])[1].replace(".", "") + if ext in self.alpha_exts: + input_allow_bg = True + return { "fps": float(instance.data["fps"]), "frame_start": frame_start, @@ -310,7 +322,8 @@ class ExtractReview(pyblish.api.InstancePlugin): "resolution_width": instance.data.get("resolutionWidth"), "resolution_height": instance.data.get("resolutionHeight"), "origin_repre": repre, - "input_is_sequence": self.input_is_sequence(repre), + "input_is_sequence": input_is_sequence, + "input_allow_bg": input_allow_bg, "with_audio": with_audio, "without_handles": without_handles, "handles_are_set": handles_are_set @@ -470,6 +483,39 @@ class ExtractReview(pyblish.api.InstancePlugin): lut_filters = self.lut_filters(new_repre, instance, ffmpeg_input_args) ffmpeg_video_filters.extend(lut_filters) + bg_alpha = 0 + bg_color = output_def.get("bg_color") + if bg_color: + bg_red, bg_green, bg_blue, bg_alpha = bg_color + + if bg_alpha > 0: + if not temp_data["input_allow_bg"]: + self.log.info(( + "Output definition has defined BG color input was" + " resolved as does not support adding BG." + )) + else: + bg_color_hex = "#{0:0>2X}{1:0>2X}{2:0>2X}".format( + bg_red, bg_green, bg_blue + ) + bg_color_alpha = float(bg_alpha) / 255 + bg_color_str = "{}@{}".format(bg_color_hex, bg_color_alpha) + + self.log.info("Applying BG color {}".format(bg_color_str)) + color_args = [ + "split=2[bg][fg]", + "[bg]drawbox=c={}:replace=1:t=fill[bg]".format( + bg_color_str + ), + "[bg][fg]overlay=format=auto" + ] + # Prepend bg color change before all video filters + # NOTE at the time of creation it is required as video filters + # from settings may affect color of BG + # e.g. `eq` can remove alpha from input + for arg in reversed(color_args): + ffmpeg_video_filters.insert(0, arg) + # Add argument to override output file ffmpeg_output_args.append("-y") @@ -547,10 +593,12 @@ class ExtractReview(pyblish.api.InstancePlugin): all_args.append("\"{}\"".format(self.ffmpeg_path)) all_args.extend(input_args) if video_filters: - all_args.append("-filter:v {}".format(",".join(video_filters))) + all_args.append("-filter:v") + all_args.append("\"{}\"".format(",".join(video_filters))) if audio_filters: - all_args.append("-filter:a {}".format(",".join(audio_filters))) + all_args.append("-filter:a") + all_args.append("\"{}\"".format(",".join(audio_filters))) all_args.extend(output_args) @@ -828,12 +876,6 @@ class ExtractReview(pyblish.api.InstancePlugin): """ filters = [] - letter_box_def = output_def["letter_box"] - letter_box_enabled = letter_box_def["enabled"] - - # Get instance data - pixel_aspect = temp_data["pixel_aspect"] - # NOTE Skipped using instance's resolution full_input_path_single_file = temp_data["full_input_path_single_file"] input_data = ffprobe_streams( @@ -842,6 +884,33 @@ class ExtractReview(pyblish.api.InstancePlugin): input_width = int(input_data["width"]) input_height = int(input_data["height"]) + # NOTE Setting only one of `width` or `heigth` is not allowed + # - settings value can't have None but has value of 0 + output_width = output_def.get("width") or None + output_height = output_def.get("height") or None + + # Convert overscan value video filters + overscan_crop = output_def.get("overscan_crop") + overscan = OverscanCrop(input_width, input_height, overscan_crop) + overscan_crop_filters = overscan.video_filters() + # Add overscan filters to filters if are any and modify input + # resolution by it's values + if overscan_crop_filters: + filters.extend(overscan_crop_filters) + input_width = overscan.width() + input_height = overscan.height() + # Use output resolution as inputs after cropping to skip usage of + # instance data resolution + if output_width is None or output_height is None: + output_width = input_width + output_height = input_height + + letter_box_def = output_def["letter_box"] + letter_box_enabled = letter_box_def["enabled"] + + # Get instance data + pixel_aspect = temp_data["pixel_aspect"] + # Make sure input width and height is not an odd number input_width_is_odd = bool(input_width % 2 != 0) input_height_is_odd = bool(input_height % 2 != 0) @@ -866,10 +935,6 @@ class ExtractReview(pyblish.api.InstancePlugin): self.log.debug("input_width: `{}`".format(input_width)) self.log.debug("input_height: `{}`".format(input_height)) - # NOTE Setting only one of `width` or `heigth` is not allowed - # - settings value can't have None but has value of 0 - output_width = output_def.get("width") or None - output_height = output_def.get("height") or None # Use instance resolution if output definition has not set it. if output_width is None or output_height is None: output_width = temp_data["resolution_width"] @@ -1393,3 +1458,291 @@ class ExtractReview(pyblish.api.InstancePlugin): vf_back = "-vf " + ",".join(vf_fixed) return vf_back + + +@six.add_metaclass(ABCMeta) +class _OverscanValue: + def __repr__(self): + return "<{}> {}".format(self.__class__.__name__, str(self)) + + @abstractmethod + def copy(self): + """Create a copy of object.""" + pass + + @abstractmethod + def size_for(self, value): + """Calculate new value for passed value.""" + pass + + +class PixValueExplicit(_OverscanValue): + def __init__(self, value): + self._value = int(value) + + def __str__(self): + return "{}px".format(self._value) + + def copy(self): + return PixValueExplicit(self._value) + + def size_for(self, value): + if self._value == 0: + return value + return self._value + + +class PercentValueExplicit(_OverscanValue): + def __init__(self, value): + self._value = float(value) + + def __str__(self): + return "{}%".format(abs(self._value)) + + def copy(self): + return PercentValueExplicit(self._value) + + def size_for(self, value): + if self._value == 0: + return value + return int((value / 100) * self._value) + + +class PixValueRelative(_OverscanValue): + def __init__(self, value): + self._value = int(value) + + def __str__(self): + sign = "-" if self._value < 0 else "+" + return "{}{}px".format(sign, abs(self._value)) + + def copy(self): + return PixValueRelative(self._value) + + def size_for(self, value): + return value + self._value + + +class PercentValueRelative(_OverscanValue): + def __init__(self, value): + self._value = float(value) + + def __str__(self): + return "{}%".format(self._value) + + def copy(self): + return PercentValueRelative(self._value) + + def size_for(self, value): + if self._value == 0: + return value + + offset = int((value / 100) * self._value) + + return value + offset + + +class PercentValueRelativeSource(_OverscanValue): + def __init__(self, value, source_sign): + self._value = float(value) + if source_sign not in ("-", "+"): + raise ValueError( + "Invalid sign value \"{}\" expected \"-\" or \"+\"".format( + source_sign + ) + ) + self._source_sign = source_sign + + def __str__(self): + return "{}%{}".format(self._value, self._source_sign) + + def copy(self): + return PercentValueRelativeSource(self._value, self._source_sign) + + def size_for(self, value): + if self._value == 0: + return value + return int((value * 100) / (100 - self._value)) + + +class OverscanCrop: + """Helper class to read overscan string and calculate output resolution. + + It is possible to enter single value for both width and heigh or two values + for width and height. Overscan string may have a few variants. Each variant + define output size for input size. + + ### Example + For input size: 2200px + + | String | Output | Description | + |----------|--------|-------------------------------------------------| + | "" | 2200px | Empty string does nothing. | + | "10%" | 220px | Explicit percent size. | + | "-10%" | 1980px | Relative percent size (decrease). | + | "+10%" | 2420px | Relative percent size (increase). | + | "-10%+" | 2000px | Relative percent size to output size. | + | "300px" | 300px | Explicit output size cropped or expanded. | + | "-300px" | 1900px | Relative pixel size (decrease). | + | "+300px" | 2500px | Relative pixel size (increase). | + | "300" | 300px | Value without "%" and "px" is used as has "px". | + + Value without sign (+/-) in is always explicit and value with sign is + relative. Output size for "200px" and "+200px" are not the same. + Values "0", "0px" or "0%" are ignored. + + All values that cause output resolution smaller than 1 pixel are invalid. + + Value "-10%+" is a special case which says that input's resolution is + bigger by 10% than expected output. + + It is possible to combine these variants to define different output for + width and height. + + Resolution: 2000px 1000px + + | String | Output | + |---------------|---------------| + | "100px 120px" | 2100px 1120px | + | "-10% -200px" | 1800px 800px | + """ + + item_regex = re.compile(r"([\+\-])?([0-9]+)(.+)?") + relative_source_regex = re.compile(r"%([\+\-])") + + def __init__(self, input_width, input_height, string_value): + # Make sure that is not None + string_value = string_value or "" + + self.input_width = input_width + self.input_height = input_height + + width, height = self._convert_string_to_values(string_value) + self._width_value = width + self._height_value = height + + self._string_value = string_value + + def __str__(self): + return "{}".format(self._string_value) + + def __repr__(self): + return "<{}>".format(self.__class__.__name__) + + def width(self): + """Calculated width.""" + return self._width_value.size_for(self.input_width) + + def height(self): + """Calculated height.""" + return self._height_value.size_for(self.input_height) + + def video_filters(self): + """FFmpeg video filters to achieve expected result. + + Filter may be empty, use "crop" filter, "pad" filter or combination of + "crop" and "pad". + + Returns: + list: FFmpeg video filters. + """ + # crop=width:height:x:y - explicit start x, y position + # crop=width:height - x, y are related to center by width/height + # pad=width:heigth:x:y - explicit start x, y position + # pad=width:heigth - x, y are set to 0 by default + + width = self.width() + height = self.height() + + output = [] + if self.input_width == width and self.input_height == height: + return output + + # Make sure resolution has odd numbers + if width % 2 == 1: + width -= 1 + + if height % 2 == 1: + height -= 1 + + if width <= self.input_width and height <= self.input_height: + output.append("crop={}:{}".format(width, height)) + + elif width >= self.input_width and height >= self.input_height: + output.append( + "pad={}:{}:(iw-ow)/2:(ih-oh)/2".format(width, height) + ) + + elif width > self.input_width and height < self.input_height: + output.append("crop=iw:{}".format(height)) + output.append("pad={}:ih:(iw-ow)/2:(ih-oh)/2".format(width)) + + elif width < self.input_width and height > self.input_height: + output.append("crop={}:ih".format(width)) + output.append("pad=iw:{}:(iw-ow)/2:(ih-oh)/2".format(height)) + + return output + + def _convert_string_to_values(self, orig_string_value): + string_value = orig_string_value.strip().lower() + if not string_value: + return [PixValueRelative(0), PixValueRelative(0)] + + # Replace "px" (and spaces before) with single space + string_value = re.sub(r"([ ]+)?px", " ", string_value) + string_value = re.sub(r"([ ]+)%", "%", string_value) + # Make sure +/- sign at the beggining of string is next to number + string_value = re.sub(r"^([\+\-])[ ]+", "\g<1>", string_value) + # Make sure +/- sign in the middle has zero spaces before number under + # which belongs + string_value = re.sub( + r"[ ]([\+\-])[ ]+([0-9])", + r" \g<1>\g<2>", + string_value + ) + string_parts = [ + part + for part in string_value.split(" ") + if part + ] + + error_msg = "Invalid string for rescaling \"{}\"".format( + orig_string_value + ) + if 1 > len(string_parts) > 2: + raise ValueError(error_msg) + + output = [] + for item in string_parts: + groups = self.item_regex.findall(item) + if not groups: + raise ValueError(error_msg) + + relative_sign, value, ending = groups[0] + if not relative_sign: + if not ending: + output.append(PixValueExplicit(value)) + else: + output.append(PercentValueExplicit(value)) + else: + source_sign_group = self.relative_source_regex.findall(ending) + if not ending: + output.append(PixValueRelative(int(relative_sign + value))) + + elif source_sign_group: + source_sign = source_sign_group[0] + output.append(PercentValueRelativeSource( + float(relative_sign + value), source_sign + )) + else: + output.append( + PercentValueRelative(float(relative_sign + value)) + ) + + if len(output) == 1: + width = output.pop(0) + height = width.copy() + else: + width, height = output + + return width, height diff --git a/openpype/plugins/publish/integrate_new.py b/openpype/plugins/publish/integrate_new.py index 9769f0d165..3a926789fb 100644 --- a/openpype/plugins/publish/integrate_new.py +++ b/openpype/plugins/publish/integrate_new.py @@ -78,7 +78,6 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "rig", "plate", "look", - "lut", "audio", "yetiRig", "yeticache", @@ -97,7 +96,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "editorial", "background", "camerarig", - "redshiftproxy" + "redshiftproxy", + "effect" ] exclude_families = ["clip"] db_representation_context_keys = [ diff --git a/openpype/settings/defaults/project_settings/aftereffects.json b/openpype/settings/defaults/project_settings/aftereffects.json index f54dbb9612..b272c60d98 100644 --- a/openpype/settings/defaults/project_settings/aftereffects.json +++ b/openpype/settings/defaults/project_settings/aftereffects.json @@ -4,8 +4,12 @@ "enabled": true, "optional": true, "active": true, - "skip_resolution_check": [".*"], - "skip_timelines_check": [".*"] + "skip_resolution_check": [ + ".*" + ], + "skip_timelines_check": [ + ".*" + ] }, "AfterEffectsSubmitDeadline": { "use_published": true, diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json index 1f54bed03c..5f779fccfa 100644 --- a/openpype/settings/defaults/project_settings/global.json +++ b/openpype/settings/defaults/project_settings/global.json @@ -37,11 +37,11 @@ "ftrackreview" ], "ffmpeg_args": { - "video_filters": [ - "eq=gamma=2.2" - ], + "video_filters": [], "audio_filters": [], - "input": [], + "input": [ + "-apply_trc gamma22" + ], "output": [ "-pix_fmt yuv420p", "-crf 18", @@ -55,8 +55,15 @@ "ftrack" ] }, + "overscan_crop": "", "width": 0, "height": 0, + "bg_color": [ + 0, + 0, + 0, + 0 + ], "letter_box": { "enabled": false, "ratio": 0.0, @@ -266,8 +273,7 @@ "active_site": "studio", "remote_site": "studio" }, - "sites": { - } + "sites": {} }, "project_plugins": { "windows": [], diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 779b8bb3f3..ba685ae502 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -293,19 +293,22 @@ }, "Display Options": { "background": [ - 0.7, - 0.7, - 0.7 + 125, + 125, + 125, + 255 ], "backgroundBottom": [ - 0.7, - 0.7, - 0.7 + 125, + 125, + 125, + 255 ], "backgroundTop": [ - 0.7, - 0.7, - 0.7 + 125, + 125, + 125, + 255 ], "override_display": true }, @@ -393,74 +396,88 @@ "load": { "colors": { "model": [ - 0.821, - 0.518, - 0.117 + 209, + 132, + 30, + 255 ], "rig": [ - 0.144, - 0.443, - 0.463 + 59, + 226, + 235, + 255 ], "pointcache": [ - 0.368, - 0.821, - 0.117 + 94, + 209, + 30, + 255 ], "animation": [ - 0.368, - 0.821, - 0.117 + 94, + 209, + 30, + 255 ], "ass": [ - 1.0, - 0.332, - 0.312 + 249, + 135, + 53, + 255 ], "camera": [ - 0.447, - 0.312, - 1.0 + 136, + 114, + 244, + 255 ], "fbx": [ - 1.0, - 0.931, - 0.312 + 215, + 166, + 255, + 255 ], "mayaAscii": [ - 0.312, - 1.0, - 0.747 + 67, + 174, + 255, + 255 ], "setdress": [ - 0.312, - 1.0, - 0.747 + 255, + 250, + 90, + 255 ], "layout": [ - 0.312, - 1.0, - 0.747 + 255, + 250, + 90, + 255 ], "vdbcache": [ - 0.312, - 1.0, - 0.428 + 249, + 54, + 0, + 255 ], "vrayproxy": [ - 0.258, - 0.95, - 0.541 + 255, + 150, + 12, + 255 ], "yeticache": [ - 0.2, - 0.8, - 0.3 + 99, + 206, + 220, + 255 ], "yetiRig": [ - 0.0, - 0.8, - 0.5 + 0, + 205, + 125, + 255 ] } }, diff --git a/openpype/settings/entities/__init__.py b/openpype/settings/entities/__init__.py index 2c71b622ee..f64ca1e98d 100644 --- a/openpype/settings/entities/__init__.py +++ b/openpype/settings/entities/__init__.py @@ -57,6 +57,7 @@ from .exceptions import ( SchemaError, DefaultsNotDefined, StudioDefaultsNotDefined, + BaseInvalidValueType, InvalidValueType, InvalidKeySymbols, SchemaMissingFileInfo, @@ -96,12 +97,13 @@ from .input_entities import ( PathInput, RawJsonEntity ) - +from .color_entity import ColorEntity from .enum_entity import ( BaseEnumEntity, EnumEntity, AppsEnumEntity, ToolsEnumEntity, + TaskTypeEnumEntity, ProvidersEnum ) @@ -115,6 +117,7 @@ from .anatomy_entities import AnatomyEntity __all__ = ( "DefaultsNotDefined", "StudioDefaultsNotDefined", + "BaseInvalidValueType", "InvalidValueType", "InvalidKeySymbols", "SchemaMissingFileInfo", @@ -146,10 +149,13 @@ __all__ = ( "PathInput", "RawJsonEntity", + "ColorEntity", + "BaseEnumEntity", "EnumEntity", "AppsEnumEntity", "ToolsEnumEntity", + "TaskTypeEnumEntity", "ProvidersEnum", "ListEntity", diff --git a/openpype/settings/entities/base_entity.py b/openpype/settings/entities/base_entity.py index b2d0f8224d..c6bff1ff47 100644 --- a/openpype/settings/entities/base_entity.py +++ b/openpype/settings/entities/base_entity.py @@ -9,6 +9,7 @@ from .lib import ( ) from .exceptions import ( + BaseInvalidValueType, InvalidValueType, SchemeGroupHierarchyBug, EntitySchemaError @@ -110,6 +111,8 @@ class BaseItemEntity(BaseEntity): self.file_item = None # Reference to `RootEntity` self.root_item = None + # Change of value requires restart of OpenPype + self._require_restart_on_change = False # Entity is in hierarchy of dynamically created entity self.is_in_dynamic_item = False @@ -170,6 +173,14 @@ class BaseItemEntity(BaseEntity): roles = [roles] self.roles = roles + @property + def require_restart_on_change(self): + return self._require_restart_on_change + + @property + def require_restart(self): + return False + @property def has_studio_override(self): """Says if entity or it's children has studio overrides.""" @@ -260,6 +271,14 @@ class BaseItemEntity(BaseEntity): self, "Dynamic entity has set `is_group` to true." ) + if ( + self.require_restart_on_change + and (self.is_dynamic_item or self.is_in_dynamic_item) + ): + raise EntitySchemaError( + self, "Dynamic entity can't require restart." + ) + @abstractmethod def set_override_state(self, state): """Set override state and trigger it on children. @@ -377,7 +396,7 @@ class BaseItemEntity(BaseEntity): try: new_value = self.convert_to_valid_type(value) - except InvalidValueType: + except BaseInvalidValueType: new_value = NOT_SET if new_value is not NOT_SET: @@ -787,6 +806,15 @@ class ItemEntity(BaseItemEntity): # Root item reference self.root_item = self.parent.root_item + # Item require restart on value change + require_restart_on_change = self.schema_data.get("require_restart") + if ( + require_restart_on_change is None + and not (self.is_dynamic_item or self.is_in_dynamic_item) + ): + require_restart_on_change = self.parent.require_restart_on_change + self._require_restart_on_change = require_restart_on_change + # File item reference if self.parent.is_file: self.file_item = self.parent diff --git a/openpype/settings/entities/color_entity.py b/openpype/settings/entities/color_entity.py new file mode 100644 index 0000000000..7a1b1d9848 --- /dev/null +++ b/openpype/settings/entities/color_entity.py @@ -0,0 +1,54 @@ +from .lib import STRING_TYPE +from .input_entities import InputEntity +from .exceptions import ( + BaseInvalidValueType, + InvalidValueType +) + + +class ColorEntity(InputEntity): + schema_types = ["color"] + + def _item_initalization(self): + self.valid_value_types = (list, ) + self.value_on_not_set = [0, 0, 0, 255] + + def convert_to_valid_type(self, value): + """Conversion to valid type. + + Complexity of entity requires to override BaseEntity implementation. + """ + # Convertion to valid value type `list` + if isinstance(value, (set, tuple)): + value = list(value) + + # Skip other validations if is not `list` + if not isinstance(value, list): + raise InvalidValueType( + self.valid_value_types, type(value), self.path + ) + + # Allow list of len 3 (last aplha is set to max) + if len(value) == 3: + value.append(255) + + if len(value) != 4: + reason = "Color entity expect 4 items in list got {}".format( + len(value) + ) + raise BaseInvalidValueType(reason, self.path) + + new_value = [] + for item in value: + if not isinstance(item, int): + if isinstance(item, (STRING_TYPE, float)): + item = int(item) + + is_valid = isinstance(item, int) and -1 < item < 256 + if not is_valid: + reason = ( + "Color entity expect 4 integers in range 0-255 got {}" + ).format(value) + raise BaseInvalidValueType(reason, self.path) + new_value.append(item) + return new_value diff --git a/openpype/settings/entities/dict_mutable_keys_entity.py b/openpype/settings/entities/dict_mutable_keys_entity.py index 907bf98784..4b221720c3 100644 --- a/openpype/settings/entities/dict_mutable_keys_entity.py +++ b/openpype/settings/entities/dict_mutable_keys_entity.py @@ -439,10 +439,10 @@ class DictMutableKeysEntity(EndpointEntity): new_initial_value = [] for key, value in _settings_value: if key in initial_value: - new_initial_value.append(key, initial_value.pop(key)) + new_initial_value.append([key, initial_value.pop(key)]) for key, value in initial_value.items(): - new_initial_value.append(key, value) + new_initial_value.append([key, value]) initial_value = new_initial_value else: initial_value = _settings_value diff --git a/openpype/settings/entities/enum_entity.py b/openpype/settings/entities/enum_entity.py index c6021b68de..5df365508c 100644 --- a/openpype/settings/entities/enum_entity.py +++ b/openpype/settings/entities/enum_entity.py @@ -219,6 +219,41 @@ class ToolsEnumEntity(BaseEnumEntity): self._current_value = new_value +class TaskTypeEnumEntity(BaseEnumEntity): + schema_types = ["task-types-enum"] + + def _item_initalization(self): + self.multiselection = True + self.value_on_not_set = [] + self.enum_items = [] + self.valid_keys = set() + self.valid_value_types = (list, ) + self.placeholder = None + + def _get_enum_values(self): + anatomy_entity = self.get_entity_from_path( + "project_settings/project_anatomy" + ) + + valid_keys = set() + enum_items = [] + for task_type in anatomy_entity["tasks"].keys(): + enum_items.append({task_type: task_type}) + valid_keys.add(task_type) + + return enum_items, valid_keys + + def set_override_state(self, *args, **kwargs): + super(TaskTypeEnumEntity, self).set_override_state(*args, **kwargs) + + self.enum_items, self.valid_keys = self._get_enum_values() + new_value = [] + for key in self._current_value: + if key in self.valid_keys: + new_value.append(key) + self._current_value = new_value + + class ProvidersEnum(BaseEnumEntity): schema_types = ["providers-enum"] diff --git a/openpype/settings/entities/exceptions.py b/openpype/settings/entities/exceptions.py index 3649e63ab7..f352c94f20 100644 --- a/openpype/settings/entities/exceptions.py +++ b/openpype/settings/entities/exceptions.py @@ -15,20 +15,22 @@ class StudioDefaultsNotDefined(Exception): super(StudioDefaultsNotDefined, self).__init__(msg) -class InvalidValueType(Exception): - msg_template = "{}" +class BaseInvalidValueType(Exception): + def __init__(self, reason, path): + msg = "Path \"{}\". {}".format(path, reason) + self.msg = msg + super(BaseInvalidValueType, self).__init__(msg) + +class InvalidValueType(BaseInvalidValueType): def __init__(self, valid_types, invalid_type, path): - msg = "Path \"{}\". ".format(path) - joined_types = ", ".join( [str(valid_type) for valid_type in valid_types] ) - msg += "Got invalid type \"{}\". Expected: {}".format( + msg = "Got invalid type \"{}\". Expected: {}".format( invalid_type, joined_types ) - self.msg = msg - super(InvalidValueType, self).__init__(msg) + super(InvalidValueType, self).__init__(msg, path) class RequiredKeyModified(KeyError): diff --git a/openpype/settings/entities/input_entities.py b/openpype/settings/entities/input_entities.py index 409e6a66b4..295333eb60 100644 --- a/openpype/settings/entities/input_entities.py +++ b/openpype/settings/entities/input_entities.py @@ -68,8 +68,18 @@ class EndpointEntity(ItemEntity): def on_change(self): for callback in self.on_change_callbacks: callback() + + if self.require_restart_on_change: + if self.require_restart: + self.root_item.add_item_require_restart(self) + else: + self.root_item.remove_item_require_restart(self) self.parent.on_child_change(self) + @property + def require_restart(self): + return self.has_unsaved_changes + def update_default_value(self, value): value = self._check_update_value(value, "default") self._default_value = value @@ -115,6 +125,10 @@ class InputEntity(EndpointEntity): """Entity's value without metadata.""" return self._current_value + @property + def require_restart(self): + return self._value_is_modified + def _settings_value(self): return copy.deepcopy(self.value) diff --git a/openpype/settings/entities/lib.py b/openpype/settings/entities/lib.py index ed3d7aed84..05f4ea64f8 100644 --- a/openpype/settings/entities/lib.py +++ b/openpype/settings/entities/lib.py @@ -17,26 +17,60 @@ WRAPPER_TYPES = ["form", "collapsible-wrap"] NOT_SET = type("NOT_SET", (), {"__bool__": lambda obj: False})() OVERRIDE_VERSION = 1 +DEFAULT_VALUES_KEY = "__default_values__" +TEMPLATE_METADATA_KEYS = ( + DEFAULT_VALUES_KEY, +) + template_key_pattern = re.compile(r"(\{.*?[^{0]*\})") +def _pop_metadata_item(template): + found_idx = None + for idx, item in enumerate(template): + if not isinstance(item, dict): + continue + + for key in TEMPLATE_METADATA_KEYS: + if key in item: + found_idx = idx + break + + if found_idx is not None: + break + + metadata_item = {} + if found_idx is not None: + metadata_item = template.pop(found_idx) + return metadata_item + + def _fill_schema_template_data( - template, template_data, required_keys=None, missing_keys=None + template, template_data, skip_paths, required_keys=None, missing_keys=None ): first = False if required_keys is None: first = True + + if "skip_paths" in template_data: + skip_paths = template_data["skip_paths"] + if not isinstance(skip_paths, list): + skip_paths = [skip_paths] + + # Cleanup skip paths (skip empty values) + skip_paths = [path for path in skip_paths if path] + required_keys = set() missing_keys = set() - _template = [] - default_values = {} - for item in template: - if isinstance(item, dict) and "__default_values__" in item: - default_values = item["__default_values__"] - else: - _template.append(item) - template = _template + # Copy template data as content may change + template = copy.deepcopy(template) + + # Get metadata item from template + metadata_item = _pop_metadata_item(template) + + # Check for default values for template data + default_values = metadata_item.get(DEFAULT_VALUES_KEY) or {} for key, value in default_values.items(): if key not in template_data: @@ -46,21 +80,55 @@ def _fill_schema_template_data( output = template elif isinstance(template, list): + # Store paths by first part if path + # - None value says that whole key should be skipped + skip_paths_by_first_key = {} + for path in skip_paths: + parts = path.split("/") + key = parts.pop(0) + if key not in skip_paths_by_first_key: + skip_paths_by_first_key[key] = [] + + value = "/".join(parts) + skip_paths_by_first_key[key].append(value or None) + output = [] for item in template: - output.append(_fill_schema_template_data( - item, template_data, required_keys, missing_keys - )) + # Get skip paths for children item + _skip_paths = [] + if not isinstance(item, dict): + pass + + elif item.get("type") in WRAPPER_TYPES: + _skip_paths = copy.deepcopy(skip_paths) + + elif skip_paths_by_first_key: + # Check if this item should be skipped + key = item.get("key") + if key and key in skip_paths_by_first_key: + _skip_paths = skip_paths_by_first_key[key] + # Skip whole item if None is in skip paths value + if None in _skip_paths: + continue + + output_item = _fill_schema_template_data( + item, template_data, _skip_paths, required_keys, missing_keys + ) + if output_item: + output.append(output_item) elif isinstance(template, dict): output = {} for key, value in template.items(): output[key] = _fill_schema_template_data( - value, template_data, required_keys, missing_keys + value, template_data, skip_paths, required_keys, missing_keys ) + if output.get("type") in WRAPPER_TYPES and not output.get("children"): + return {} elif isinstance(template, STRING_TYPE): # TODO find much better way how to handle filling template data + template = template.replace("{{", "__dbcb__").replace("}}", "__decb__") for replacement_string in template_key_pattern.findall(template): key = str(replacement_string[1:-1]) required_keys.add(key) @@ -76,7 +144,8 @@ def _fill_schema_template_data( else: # Only replace the key in string template = template.replace(replacement_string, value) - output = template + + output = template.replace("__dbcb__", "{").replace("__decb__", "}") else: output = template @@ -105,11 +174,15 @@ def _fill_schema_template(child_data, schema_collection, schema_templates): if isinstance(template_data, dict): template_data = [template_data] + skip_paths = child_data.get("skip_paths") or [] + if isinstance(skip_paths, STRING_TYPE): + skip_paths = [skip_paths] + output = [] for single_template_data in template_data: try: filled_child = _fill_schema_template_data( - template, single_template_data + template, single_template_data, skip_paths ) except SchemaTemplateMissingKeys as exc: @@ -166,7 +239,7 @@ def _fill_inner_schemas(schema_data, schema_collection, schema_templates): schema_templates ) - elif child_type == "schema_template": + elif child_type in ("template", "schema_template"): for filled_child in _fill_schema_template( child, schema_collection, schema_templates ): diff --git a/openpype/settings/entities/root_entities.py b/openpype/settings/entities/root_entities.py index b89473d9fb..401d3980c9 100644 --- a/openpype/settings/entities/root_entities.py +++ b/openpype/settings/entities/root_entities.py @@ -55,6 +55,8 @@ class RootEntity(BaseItemEntity): def __init__(self, schema_data, reset): super(RootEntity, self).__init__(schema_data) + self._require_restart_callbacks = [] + self._item_ids_require_restart = set() self._item_initalization() if reset: self.reset() @@ -64,6 +66,31 @@ class RootEntity(BaseItemEntity): """Current OverrideState.""" return self._override_state + @property + def require_restart(self): + return bool(self._item_ids_require_restart) + + def add_require_restart_change_callback(self, callback): + self._require_restart_callbacks.append(callback) + + def _on_require_restart_change(self): + for callback in self._require_restart_callbacks: + callback() + + def add_item_require_restart(self, item): + was_empty = len(self._item_ids_require_restart) == 0 + self._item_ids_require_restart.add(item.id) + if was_empty: + self._on_require_restart_change() + + def remove_item_require_restart(self, item): + if item.id not in self._item_ids_require_restart: + return + + self._item_ids_require_restart.remove(item.id) + if not self._item_ids_require_restart: + self._on_require_restart_change() + @abstractmethod def reset(self): """Reset values and entities to initial state. diff --git a/openpype/settings/entities/schemas/README.md b/openpype/settings/entities/schemas/README.md index 18312a8364..6c31b61f59 100644 --- a/openpype/settings/entities/schemas/README.md +++ b/openpype/settings/entities/schemas/README.md @@ -420,6 +420,18 @@ } ``` +### color +- preimplemented entity to store and load color values +- entity store and expect list of 4 integers in range 0-255 + - integers represents rgba [Red, Green, Blue, Alpha] + +``` +{ + "type": "color", + "key": "bg_color", + "label": "Background Color" +} +``` ## Noninteractive widgets - have nothing to do with data diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json index 0efe3b8fea..0c89575d74 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json @@ -173,6 +173,15 @@ { "type": "separator" }, + { + "type": "label", + "label": "Crop input overscan. See the documentation for more information." + }, + { + "type": "text", + "key": "overscan_crop", + "label": "Overscan crop" + }, { "type": "label", "label": "Width and Height must be both set to higher value than 0 else source resolution is used." @@ -193,6 +202,15 @@ "minimum": 0, "maximum": 100000 }, + { + "type": "label", + "label": "Background color is used only when input have transparency and Alpha is higher than 0." + }, + { + "type": "color", + "label": "Background color", + "key": "bg_color" + }, { "key": "letter_box", "label": "Letter box", @@ -228,14 +246,9 @@ ] }, { - "type": "schema_template", - "name": "template_rgba_color", - "template_data": [ - { - "label": "Fill Color", - "name": "fill_color" - } - ] + "type": "color", + "label": "Fill Color", + "key": "fill_color" }, { "key": "line_thickness", @@ -245,14 +258,9 @@ "maximum": 1000 }, { - "type": "schema_template", - "name": "template_rgba_color", - "template_data": [ - { - "label": "Line Color", - "name": "line_color" - } - ] + "type": "color", + "label": "Line Color", + "key": "line_color" } ] } @@ -290,24 +298,14 @@ "minimum": 0 }, { - "type": "schema_template", - "name": "template_rgba_color", - "template_data": [ - { - "label": "Font Color", - "name": "font_color" - } - ] + "type": "color", + "key": "font_color", + "label": "Font Color" }, { - "type": "schema_template", - "name": "template_rgba_color", - "template_data": [ - { - "label": "Background Color", - "name": "bg_color" - } - ] + "type": "color", + "key": "bg_color", + "label": "Background Color" }, { "type": "number", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json new file mode 100644 index 0000000000..d6b81c8687 --- /dev/null +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -0,0 +1,471 @@ +{ + "type": "dict", + "collapsible": true, + "key": "ExtractPlayblast", + "label": "Extract Playblast settings", + "children": [ + { + "type": "dict", + "key": "capture_preset", + "children": [ + { + "type": "dict", + "key": "Codec", + "children": [ + { + "type": "label", + "label": "Codec" + }, + { + "type": "text", + "key": "compression", + "label": "Compression type" + }, + { + "type": "text", + "key": "format", + "label": "Data format" + }, + { + "type": "number", + "key": "quality", + "label": "Quality", + "decimal": 0, + "minimum": 0, + "maximum": 100 + }, + + { + "type": "splitter" + } + ] + }, + { + "type": "dict", + "key": "Display Options", + "children": [ + { + "type": "label", + "label": "Display Options" + }, + + { + "type": "color", + "key": "background", + "label": "Background Color: " + }, + { + "type": "color", + "key": "backgroundBottom", + "label": "Background Bottom: " + }, + { + "type": "color", + "key": "backgroundTop", + "label": "Background Top: " + }, + { + "type": "boolean", + "key": "override_display", + "label": "Override display options" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "dict", + "key": "Generic", + "children": [ + { + "type": "label", + "label": "Generic" + }, + { + "type": "boolean", + "key": "isolate_view", + "label": " Isolate view" + }, + { + "type": "boolean", + "key": "off_screen", + "label": " Off Screen" + } + ] + }, + + { + "type": "dict", + "key": "PanZoom", + "children": [ + { + "type": "boolean", + "key": "pan_zoom", + "label": " Pan Zoom" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "dict", + "key": "Renderer", + "children": [ + { + "type": "label", + "label": "Renderer" + }, + { + "type": "enum", + "key": "rendererName", + "label": "Renderer name", + "enum_items": [ + { "vp2Renderer": "Viewport 2.0" } + ] + } + ] + }, + { + "type": "dict", + "key": "Resolution", + "children": [ + { + "type": "splitter" + }, + { + "type": "label", + "label": "Resolution" + }, + { + "type": "number", + "key": "width", + "label": " Width", + "decimal": 0, + "minimum": 0, + "maximum": 99999 + }, + { + "type": "number", + "key": "height", + "label": "Height", + "decimal": 0, + "minimum": 0, + "maximum": 99999 + }, + { + "type": "number", + "key": "percent", + "label": "percent", + "decimal": 1, + "minimum": 0, + "maximum": 200 + }, + { + "type": "text", + "key": "mode", + "label": "Mode" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "dict", + "collapsible": true, + "key": "Viewport Options", + "label": "Viewport Options", + "children": [ + { + "type": "boolean", + "key": "override_viewport_options", + "label": "override_viewport_options" + }, + { + "type": "enum", + "key": "displayLights", + "label": "Display Lights", + "enum_items": [ + { "default": "Default Lighting"}, + { "all": "All Lights"}, + { "selected": "Selected Lights"}, + { "flat": "Flat Lighting"}, + { "nolights": "No Lights"} + ] + }, + { + "type": "number", + "key": "textureMaxResolution", + "label": "Texture Clamp Resolution", + "decimal": 0 + }, + { + "type": "number", + "key": "multiSample", + "label": "Anti Aliasing Samples", + "decimal": 0, + "minimum": 0, + "maximum": 32 + }, + { + "type": "boolean", + "key": "shadows", + "label": "Display Shadows" + }, + { + "type": "boolean", + "key": "textures", + "label": "Display Textures" + }, + { + "type": "boolean", + "key": "twoSidedLighting", + "label": "Two Sided Lighting" + }, + { + "type": "boolean", + "key": "ssaoEnable", + "label": "Screen Space Ambient Occlusion" + }, + { + "type": "splitter" + }, + { + "type": "boolean", + "key": "cameras", + "label": "cameras" + }, + { + "type": "boolean", + "key": "clipGhosts", + "label": "clipGhosts" + }, + { + "type": "boolean", + "key": "controlVertices", + "label": "controlVertices" + }, + { + "type": "boolean", + "key": "deformers", + "label": "deformers" + }, + { + "type": "boolean", + "key": "dimensions", + "label": "dimensions" + }, + { + "type": "boolean", + "key": "dynamicConstraints", + "label": "dynamicConstraints" + }, + { + "type": "boolean", + "key": "dynamics", + "label": "dynamics" + }, + { + "type": "boolean", + "key": "fluids", + "label": "fluids" + }, + { + "type": "boolean", + "key": "follicles", + "label": "follicles" + }, + { + "type": "boolean", + "key": "gpuCacheDisplayFilter", + "label": "gpuCacheDisplayFilter" + }, + { + "type": "boolean", + "key": "greasePencils", + "label": "greasePencils" + }, + { + "type": "boolean", + "key": "grid", + "label": "grid" + }, + { + "type": "boolean", + "key": "hairSystems", + "label": "hairSystems" + }, + { + "type": "boolean", + "key": "handles", + "label": "handles" + }, + { + "type": "boolean", + "key": "hud", + "label": "hud" + }, + { + "type": "boolean", + "key": "hulls", + "label": "hulls" + }, + { + "type": "boolean", + "key": "ikHandles", + "label": "ikHandles" + }, + { + "type": "boolean", + "key": "imagePlane", + "label": "imagePlane" + }, + { + "type": "boolean", + "key": "joints", + "label": "joints" + }, + { + "type": "boolean", + "key": "lights", + "label": "lights" + }, + { + "type": "boolean", + "key": "locators", + "label": "locators" + }, + { + "type": "boolean", + "key": "manipulators", + "label": "manipulators" + }, + { + "type": "boolean", + "key": "motionTrails", + "label": "motionTrails" + }, + { + "type": "boolean", + "key": "nCloths", + "label": "nCloths" + }, + { + "type": "boolean", + "key": "nParticles", + "label": "nParticles" + }, + { + "type": "boolean", + "key": "nRigids", + "label": "nRigids" + }, + { + "type": "boolean", + "key": "nurbsCurves", + "label": "nurbsCurves" + }, + { + "type": "boolean", + "key": "nurbsSurfaces", + "label": "nurbsSurfaces" + }, + { + "type": "boolean", + "key": "particleInstancers", + "label": "particleInstancers" + }, + { + "type": "boolean", + "key": "pivots", + "label": "pivots" + }, + { + "type": "boolean", + "key": "planes", + "label": "planes" + }, + { + "type": "boolean", + "key": "pluginShapes", + "label": "pluginShapes" + }, + { + "type": "boolean", + "key": "polymeshes", + "label": "polymeshes" + }, + { + "type": "boolean", + "key": "strokes", + "label": "strokes" + }, + { + "type": "boolean", + "key": "subdivSurfaces", + "label": "subdivSurfaces" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "Camera Options", + "label": "Camera Options", + "children": [ + { + "type": "boolean", + "key": "displayGateMask", + "label": "displayGateMask" + }, + { + "type": "boolean", + "key": "displayResolution", + "label": "displayResolution" + }, + { + "type": "boolean", + "key": "displayFilmGate", + "label": "displayFilmGate" + }, + { + "type": "boolean", + "key": "displayFieldChart", + "label": "displayFieldChart" + }, + { + "type": "boolean", + "key": "displaySafeAction", + "label": "displaySafeAction" + }, + { + "type": "boolean", + "key": "displaySafeTitle", + "label": "displaySafeTitle" + }, + { + "type": "boolean", + "key": "displayFilmPivot", + "label": "displayFilmPivot" + }, + { + "type": "boolean", + "key": "displayFilmOrigin", + "label": "displayFilmOrigin" + }, + { + "type": "number", + "key": "overscan", + "label": "overscan", + "decimal": 1, + "minimum": 0, + "maximum": 10 + } + ] + } + ] + } + ] +} diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json index dd9d0508b4..0b09d08700 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json @@ -11,144 +11,74 @@ "label": "Loaded Subsets Outliner Colors", "children": [ { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Model", - "name": "model" - } - ] + "type": "color", + "label": "Model:", + "key": "model" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Rig", - "name": "rig" - } - ] + "type": "color", + "label": "Rig:", + "key": "rig" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Pointcache", - "name": "pointcache" - } - ] + "type": "color", + "label": "Pointcache:", + "key": "pointcache" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Animation", - "name": "animation" - } - ] + "type": "color", + "label": "Animation:", + "key": "animation" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Arnold Standin", - "name": "ass" - } - ] + "type": "color", + "label": "Arnold Standin:", + "key": "ass" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Camera", - "name": "camera" - } - ] + "type": "color", + "label": "Camera:", + "key": "camera" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "FBX", - "name": "fbx" - } - ] + "type": "color", + "label": "FBX:", + "key": "fbx" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Maya Scene", - "name": "mayaAscii" - } - ] + "type": "color", + "label": "Maya Scene:", + "key": "mayaAscii" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Set Dress", - "name": "setdress" - } - ] + "type": "color", + "label": "Set Dress:", + "key": "setdress" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Layout", - "name": "layout" - } - ] + "type": "color", + "label": "Layout:", + "key": "layout" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "VDB Cache", - "name": "vdbcache" - } - ] + "type": "color", + "label": "VDB Cache:", + "key": "vdbcache" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Vray Proxy", - "name": "vrayproxy" - } - ] + "type": "color", + "label": "Vray Proxy:", + "key": "vrayproxy" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Yeti Cache", - "name": "yeticache" - } - ] + "type": "color", + "label": "Yeti Cache:", + "key": "yeticache" }, { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Yeti Rig", - "name": "yetiRig" - } - ] + "type": "color", + "label": "Yeti Rig:", + "key": "yetiRig" } ] } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 4cabf5bb74..0abcdd2965 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -297,8 +297,8 @@ "label": "Extractors" }, { - "type": "schema_template", - "name": "template_maya_capture" + "type": "schema", + "name": "schema_maya_capture" }, { "type": "dict", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_color.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_color.json index 04ce055525..af8fd9dae4 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/template_color.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/template_color.json @@ -2,7 +2,7 @@ { "type": "list-strict", "key": "{name}", - "label": "{label}:", + "label": "{label}", "object_types": [ { "label": "Red", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json deleted file mode 100644 index e4e0b034dd..0000000000 --- a/openpype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json +++ /dev/null @@ -1,541 +0,0 @@ -[ - { - "type": "dict", - "collapsible": true, - "key": "ExtractPlayblast", - "label": "Extract Playblast settings", - "children": [ - { - "type": "dict", - "key": "capture_preset", - "children": [ - { - "type": "dict", - "key": "Codec", - "children": [ - { - "type": "label", - "label": "Codec" - }, - { - "type": "text", - "key": "compression", - "label": "Compression type" - }, - { - "type": "text", - "key": "format", - "label": "Data format" - }, - { - "type": "number", - "key": "quality", - "label": "Quality", - "decimal": 0, - "minimum": 0, - "maximum": 100 - }, - - { - "type": "splitter" - } - ] - }, - { - "type": "dict", - "key": "Display Options", - "children": [ - { - "type": "label", - "label": "Display Options" - }, - { - "type": "list-strict", - "key": "background", - "label": "Background Color: ", - "object_types": [ - { - "label": "Red", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Green", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Blue", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - } - ] - }, - { - "type": "list-strict", - "key": "backgroundBottom", - "label": "Background Bottom: ", - "object_types": [ - { - "label": "Red", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Green", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Blue", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - } - ] - }, - { - "type": "list-strict", - "key": "backgroundTop", - "label": "Background Top: ", - "object_types": [ - { - "label": "Red", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Green", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Blue", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - } - ] - }, - { - "type": "boolean", - "key": "override_display", - "label": "Override display options" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "dict", - "key": "Generic", - "children": [ - { - "type": "label", - "label": "Generic" - }, - { - "type": "boolean", - "key": "isolate_view", - "label": " Isolate view" - }, - { - "type": "boolean", - "key": "off_screen", - "label": " Off Screen" - } - ] - }, - - { - "type": "dict", - "key": "PanZoom", - "children": [ - { - "type": "boolean", - "key": "pan_zoom", - "label": " Pan Zoom" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "dict", - "key": "Renderer", - "children": [ - { - "type": "label", - "label": "Renderer" - }, - { - "type": "enum", - "key": "rendererName", - "label": "Renderer name", - "enum_items": [ - { "vp2Renderer": "Viewport 2.0" } - ] - } - ] - }, - { - "type": "dict", - "key": "Resolution", - "children": [ - { - "type": "splitter" - }, - { - "type": "label", - "label": "Resolution" - }, - { - "type": "number", - "key": "width", - "label": " Width", - "decimal": 0, - "minimum": 0, - "maximum": 99999 - }, - { - "type": "number", - "key": "height", - "label": "Height", - "decimal": 0, - "minimum": 0, - "maximum": 99999 - }, - { - "type": "number", - "key": "percent", - "label": "percent", - "decimal": 1, - "minimum": 0, - "maximum": 200 - }, - { - "type": "text", - "key": "mode", - "label": "Mode" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "dict", - "collapsible": true, - "key": "Viewport Options", - "label": "Viewport Options", - "children": [ - { - "type": "boolean", - "key": "override_viewport_options", - "label": "override_viewport_options" - }, - { - "type": "enum", - "key": "displayLights", - "label": "Display Lights", - "enum_items": [ - { "default": "Default Lighting"}, - { "all": "All Lights"}, - { "selected": "Selected Lights"}, - { "flat": "Flat Lighting"}, - { "nolights": "No Lights"} - ] - }, - { - "type": "number", - "key": "textureMaxResolution", - "label": "Texture Clamp Resolution", - "decimal": 0 - }, - { - "type": "number", - "key": "multiSample", - "label": "Anti Aliasing Samples", - "decimal": 0, - "minimum": 0, - "maximum": 32 - }, - { - "type": "boolean", - "key": "shadows", - "label": "Display Shadows" - }, - { - "type": "boolean", - "key": "textures", - "label": "Display Textures" - }, - { - "type": "boolean", - "key": "twoSidedLighting", - "label": "Two Sided Lighting" - }, - { - "type": "boolean", - "key": "ssaoEnable", - "label": "Screen Space Ambient Occlusion" - }, - { - "type": "splitter" - }, - { - "type": "boolean", - "key": "cameras", - "label": "cameras" - }, - { - "type": "boolean", - "key": "clipGhosts", - "label": "clipGhosts" - }, - { - "type": "boolean", - "key": "controlVertices", - "label": "controlVertices" - }, - { - "type": "boolean", - "key": "deformers", - "label": "deformers" - }, - { - "type": "boolean", - "key": "dimensions", - "label": "dimensions" - }, - { - "type": "boolean", - "key": "dynamicConstraints", - "label": "dynamicConstraints" - }, - { - "type": "boolean", - "key": "dynamics", - "label": "dynamics" - }, - { - "type": "boolean", - "key": "fluids", - "label": "fluids" - }, - { - "type": "boolean", - "key": "follicles", - "label": "follicles" - }, - { - "type": "boolean", - "key": "gpuCacheDisplayFilter", - "label": "gpuCacheDisplayFilter" - }, - { - "type": "boolean", - "key": "greasePencils", - "label": "greasePencils" - }, - { - "type": "boolean", - "key": "grid", - "label": "grid" - }, - { - "type": "boolean", - "key": "hairSystems", - "label": "hairSystems" - }, - { - "type": "boolean", - "key": "handles", - "label": "handles" - }, - { - "type": "boolean", - "key": "hud", - "label": "hud" - }, - { - "type": "boolean", - "key": "hulls", - "label": "hulls" - }, - { - "type": "boolean", - "key": "ikHandles", - "label": "ikHandles" - }, - { - "type": "boolean", - "key": "imagePlane", - "label": "imagePlane" - }, - { - "type": "boolean", - "key": "joints", - "label": "joints" - }, - { - "type": "boolean", - "key": "lights", - "label": "lights" - }, - { - "type": "boolean", - "key": "locators", - "label": "locators" - }, - { - "type": "boolean", - "key": "manipulators", - "label": "manipulators" - }, - { - "type": "boolean", - "key": "motionTrails", - "label": "motionTrails" - }, - { - "type": "boolean", - "key": "nCloths", - "label": "nCloths" - }, - { - "type": "boolean", - "key": "nParticles", - "label": "nParticles" - }, - { - "type": "boolean", - "key": "nRigids", - "label": "nRigids" - }, - { - "type": "boolean", - "key": "nurbsCurves", - "label": "nurbsCurves" - }, - { - "type": "boolean", - "key": "nurbsSurfaces", - "label": "nurbsSurfaces" - }, - { - "type": "boolean", - "key": "particleInstancers", - "label": "particleInstancers" - }, - { - "type": "boolean", - "key": "pivots", - "label": "pivots" - }, - { - "type": "boolean", - "key": "planes", - "label": "planes" - }, - { - "type": "boolean", - "key": "pluginShapes", - "label": "pluginShapes" - }, - { - "type": "boolean", - "key": "polymeshes", - "label": "polymeshes" - }, - { - "type": "boolean", - "key": "strokes", - "label": "strokes" - }, - { - "type": "boolean", - "key": "subdivSurfaces", - "label": "subdivSurfaces" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "Camera Options", - "label": "Camera Options", - "children": [ - { - "type": "boolean", - "key": "displayGateMask", - "label": "displayGateMask" - }, - { - "type": "boolean", - "key": "displayResolution", - "label": "displayResolution" - }, - { - "type": "boolean", - "key": "displayFilmGate", - "label": "displayFilmGate" - }, - { - "type": "boolean", - "key": "displayFieldChart", - "label": "displayFieldChart" - }, - { - "type": "boolean", - "key": "displaySafeAction", - "label": "displaySafeAction" - }, - { - "type": "boolean", - "key": "displaySafeTitle", - "label": "displaySafeTitle" - }, - { - "type": "boolean", - "key": "displayFilmPivot", - "label": "displayFilmPivot" - }, - { - "type": "boolean", - "key": "displayFilmOrigin", - "label": "displayFilmOrigin" - }, - { - "type": "number", - "key": "overscan", - "label": "overscan", - "decimal": 1, - "minimum": 0, - "maximum": 10 - } - ] - } - ] - } - ] - } -] diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_rgba_color.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_rgba_color.json deleted file mode 100644 index ffe530175a..0000000000 --- a/openpype/settings/entities/schemas/projects_schema/schemas/template_rgba_color.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "type": "list-strict", - "key": "{name}", - "label": "{label}", - "object_types": [ - { - "label": "R", - "type": "number", - "minimum": 0, - "maximum": 255 - }, - { - "label": "G", - "type": "number", - "minimum": 0, - "maximum": 255 - }, - { - "label": "B", - "type": "number", - "minimum": 0, - "maximum": 255 - }, - { - "label": "A", - "type": "number", - "minimum": 0, - "maximum": 255 - } - ] - } -] diff --git a/openpype/settings/entities/schemas/system_schema/example_schema.json b/openpype/settings/entities/schemas/system_schema/example_schema.json index 48a21cc0c6..a4ed56df32 100644 --- a/openpype/settings/entities/schemas/system_schema/example_schema.json +++ b/openpype/settings/entities/schemas/system_schema/example_schema.json @@ -4,6 +4,11 @@ "type": "dict", "is_file": true, "children": [ + { + "key": "color", + "label": "Color input", + "type": "color" + }, { "type": "dict", "key": "schema_template_exaples", diff --git a/openpype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json b/openpype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json index 50ec330a11..5f659522c3 100644 --- a/openpype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json +++ b/openpype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json @@ -3,6 +3,7 @@ "key": "ftrack", "label": "Ftrack", "collapsible": true, + "require_restart": true, "checkbox_key": "enabled", "children": [ { diff --git a/openpype/settings/entities/schemas/system_schema/schema_general.json b/openpype/settings/entities/schemas/system_schema/schema_general.json index 568ccad5b9..fe5a8d8203 100644 --- a/openpype/settings/entities/schemas/system_schema/schema_general.json +++ b/openpype/settings/entities/schemas/system_schema/schema_general.json @@ -34,7 +34,8 @@ "key": "environment", "label": "Environment", "type": "raw-json", - "env_group_key": "global" + "env_group_key": "global", + "require_restart": true }, { "type": "splitter" @@ -44,7 +45,8 @@ "key": "openpype_path", "label": "Versions Repository", "multiplatform": true, - "multipath": true + "multipath": true, + "require_restart": true } ] } diff --git a/openpype/settings/entities/schemas/system_schema/schema_modules.json b/openpype/settings/entities/schemas/system_schema/schema_modules.json index b643293c87..16251b5f27 100644 --- a/openpype/settings/entities/schemas/system_schema/schema_modules.json +++ b/openpype/settings/entities/schemas/system_schema/schema_modules.json @@ -10,6 +10,7 @@ "key": "avalon", "label": "Avalon", "collapsible": true, + "require_restart": true, "children": [ { "type": "number", @@ -35,6 +36,7 @@ "key": "timers_manager", "label": "Timers Manager", "collapsible": true, + "require_restart": true, "checkbox_key": "enabled", "children": [ { @@ -66,6 +68,7 @@ "key": "clockify", "label": "Clockify", "collapsible": true, + "require_restart": true, "checkbox_key": "enabled", "children": [ { @@ -84,6 +87,7 @@ "key": "sync_server", "label": "Site Sync", "collapsible": true, + "require_restart": true, "checkbox_key": "enabled", "children": [ { @@ -114,6 +118,7 @@ "type": "dict", "key": "deadline", "label": "Deadline", + "require_restart": true, "collapsible": true, "checkbox_key": "enabled", "children": [ @@ -133,6 +138,7 @@ "type": "dict", "key": "muster", "label": "Muster", + "require_restart": true, "collapsible": true, "checkbox_key": "enabled", "children": [ diff --git a/openpype/tools/settings/settings/categories.py b/openpype/tools/settings/settings/categories.py index 4762aa4b6b..b072a7f337 100644 --- a/openpype/tools/settings/settings/categories.py +++ b/openpype/tools/settings/settings/categories.py @@ -21,6 +21,7 @@ from openpype.settings.entities import ( TextEntity, PathInput, RawJsonEntity, + ColorEntity, DefaultsNotDefined, StudioDefaultsNotDefined, @@ -44,7 +45,7 @@ from .item_widgets import ( PathWidget, PathInputWidget ) - +from .color_widget import ColorWidget from avalon.vendor import qtawesome @@ -72,6 +73,7 @@ class IgnoreInputChangesObj: class SettingsCategoryWidget(QtWidgets.QWidget): state_changed = QtCore.Signal() saved = QtCore.Signal(QtWidgets.QWidget) + restart_required_trigger = QtCore.Signal() def __init__(self, user_role, parent=None): super(SettingsCategoryWidget, self).__init__(parent) @@ -113,6 +115,9 @@ class SettingsCategoryWidget(QtWidgets.QWidget): elif isinstance(entity, RawJsonEntity): return RawJsonWidget(*args) + elif isinstance(entity, ColorEntity): + return ColorWidget(*args) + elif isinstance(entity, BaseEnumEntity): return EnumeratorWidget(*args) @@ -181,9 +186,10 @@ class SettingsCategoryWidget(QtWidgets.QWidget): if self.user_role == "developer": self._add_developer_ui(footer_layout) - save_btn = QtWidgets.QPushButton("Save") - spacer_widget = QtWidgets.QWidget() - footer_layout.addWidget(spacer_widget, 1) + save_btn = QtWidgets.QPushButton("Save", footer_widget) + require_restart_label = QtWidgets.QLabel(footer_widget) + require_restart_label.setAlignment(QtCore.Qt.AlignCenter) + footer_layout.addWidget(require_restart_label, 1) footer_layout.addWidget(save_btn, 0) configurations_layout = QtWidgets.QVBoxLayout(configurations_widget) @@ -201,6 +207,7 @@ class SettingsCategoryWidget(QtWidgets.QWidget): save_btn.clicked.connect(self._save) self.save_btn = save_btn + self.require_restart_label = require_restart_label self.scroll_widget = scroll_widget self.content_layout = content_layout self.content_widget = content_widget @@ -319,6 +326,15 @@ class SettingsCategoryWidget(QtWidgets.QWidget): def _on_reset_start(self): return + def _on_require_restart_change(self): + value = "" + if self.entity.require_restart: + value = ( + "Your changes require restart of" + " all running OpenPype processes to take affect." + ) + self.require_restart_label.setText(value) + def reset(self): self.set_state(CategoryState.Working) @@ -335,6 +351,9 @@ class SettingsCategoryWidget(QtWidgets.QWidget): dialog = None try: self._create_root_entity() + self.entity.add_require_restart_change_callback( + self._on_require_restart_change + ) self.add_children_gui() @@ -429,6 +448,15 @@ class SettingsCategoryWidget(QtWidgets.QWidget): return def _save(self): + # Don't trigger restart if defaults are modified + if ( + self.modify_defaults_checkbox + and self.modify_defaults_checkbox.isChecked() + ): + require_restart = False + else: + require_restart = self.entity.require_restart + self.set_state(CategoryState.Working) if self.items_are_valid(): @@ -438,6 +466,10 @@ class SettingsCategoryWidget(QtWidgets.QWidget): self.saved.emit(self) + if require_restart: + self.restart_required_trigger.emit() + self.require_restart_label.setText("") + def _on_refresh(self): self.reset() diff --git a/openpype/tools/settings/settings/color_widget.py b/openpype/tools/settings/settings/color_widget.py new file mode 100644 index 0000000000..fa0cd2c989 --- /dev/null +++ b/openpype/tools/settings/settings/color_widget.py @@ -0,0 +1,171 @@ +from Qt import QtWidgets, QtCore, QtGui + +from .item_widgets import InputWidget + +from openpype.widgets.color_widgets import ( + ColorPickerWidget, + draw_checkerboard_tile +) + + +class ColorWidget(InputWidget): + def _add_inputs_to_layout(self): + self.input_field = ColorViewer(self.content_widget) + + self.setFocusProxy(self.input_field) + + self.content_layout.addWidget(self.input_field, 1) + + self.input_field.clicked.connect(self._on_click) + + self._dialog = None + + def _on_click(self): + if self._dialog: + self._dialog.open() + return + + dialog = ColorDialog(self.input_field.color(), self) + self._dialog = dialog + + dialog.open() + dialog.finished.connect(self._on_dialog_finish) + + def _on_dialog_finish(self, *_args): + if not self._dialog: + return + + color = self._dialog.result() + if color is not None: + self.input_field.set_color(color) + self._on_value_change() + + self._dialog.deleteLater() + self._dialog = None + + def _on_entity_change(self): + if self.entity.value != self.input_value(): + self.set_entity_value() + + def set_entity_value(self): + self.input_field.set_color(*self.entity.value) + + def input_value(self): + color = self.input_field.color() + return [color.red(), color.green(), color.blue(), color.alpha()] + + def _on_value_change(self): + if self.ignore_input_changes: + return + + self.entity.set(self.input_value()) + + +class ColorViewer(QtWidgets.QWidget): + clicked = QtCore.Signal() + + def __init__(self, parent=None): + super(ColorViewer, self).__init__(parent) + + self.setMinimumSize(10, 10) + + self.actual_pen = QtGui.QPen() + self.actual_color = QtGui.QColor() + self._checkerboard = None + + def mouseReleaseEvent(self, event): + if event.button() == QtCore.Qt.LeftButton: + self.clicked.emit() + super(ColorViewer, self).mouseReleaseEvent(event) + + def checkerboard(self): + if not self._checkerboard: + self._checkerboard = draw_checkerboard_tile(self.height() / 4) + return self._checkerboard + + def color(self): + return self.actual_color + + def set_color(self, *args): + # Create copy of entered color + self.actual_color = QtGui.QColor(*args) + # Repaint + self.update() + + def set_alpha(self, alpha): + # Change alpha of current color + self.actual_color.setAlpha(alpha) + # Repaint + self.update() + + def paintEvent(self, event): + rect = event.rect() + + painter = QtGui.QPainter(self) + painter.setRenderHint(QtGui.QPainter.Antialiasing) + + radius = rect.height() / 2 + rounded_rect = QtGui.QPainterPath() + rounded_rect.addRoundedRect(QtCore.QRectF(rect), radius, radius) + painter.setClipPath(rounded_rect) + + pen = QtGui.QPen(QtGui.QColor(255, 255, 255, 67)) + pen.setWidth(1) + painter.setPen(pen) + painter.drawTiledPixmap(rect, self.checkerboard()) + painter.fillRect(rect, self.actual_color) + painter.drawPath(rounded_rect) + + painter.end() + + +class ColorDialog(QtWidgets.QDialog): + def __init__(self, color=None, parent=None): + super(ColorDialog, self).__init__(parent) + + self.setWindowTitle("Color picker dialog") + + picker_widget = ColorPickerWidget(color, self) + + footer_widget = QtWidgets.QWidget(self) + + ok_btn = QtWidgets.QPushButton("Ok", footer_widget) + cancel_btn = QtWidgets.QPushButton("Cancel", footer_widget) + + footer_layout = QtWidgets.QHBoxLayout(footer_widget) + footer_layout.setContentsMargins(0, 0, 0, 0) + footer_layout.addStretch(1) + footer_layout.addWidget(ok_btn) + footer_layout.addWidget(cancel_btn) + + layout = QtWidgets.QVBoxLayout(self) + + layout.addWidget(picker_widget, 1) + layout.addWidget(footer_widget, 0) + + ok_btn.clicked.connect(self.on_ok_clicked) + cancel_btn.clicked.connect(self.on_cancel_clicked) + + self.picker_widget = picker_widget + self.ok_btn = ok_btn + self.cancel_btn = cancel_btn + + self._result = None + + def showEvent(self, event): + super(ColorDialog, self).showEvent(event) + + btns_width = max(self.ok_btn.width(), self.cancel_btn.width()) + self.ok_btn.setFixedWidth(btns_width) + self.cancel_btn.setFixedWidth(btns_width) + + def on_ok_clicked(self): + self._result = self.picker_widget.color() + self.close() + + def on_cancel_clicked(self): + self._result = None + self.close() + + def result(self): + return self._result diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index 249b4e305d..b20ce5ed66 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -275,8 +275,6 @@ class UnsavedChangesDialog(QtWidgets.QDialog): layout.addWidget(message_label) layout.addWidget(btns_widget) - self.state = None - def on_cancel_pressed(self): self.done(0) @@ -287,6 +285,48 @@ class UnsavedChangesDialog(QtWidgets.QDialog): self.done(2) +class RestartDialog(QtWidgets.QDialog): + message = ( + "Your changes require restart of process to take effect." + " Do you want to restart now?" + ) + + def __init__(self, parent=None): + super(RestartDialog, self).__init__(parent) + message_label = QtWidgets.QLabel(self.message) + + btns_widget = QtWidgets.QWidget(self) + btns_layout = QtWidgets.QHBoxLayout(btns_widget) + + btn_restart = QtWidgets.QPushButton("Restart") + btn_restart.clicked.connect(self.on_restart_pressed) + btn_cancel = QtWidgets.QPushButton("Cancel") + btn_cancel.clicked.connect(self.on_cancel_pressed) + + btns_layout.addStretch(1) + btns_layout.addWidget(btn_restart) + btns_layout.addWidget(btn_cancel) + + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(message_label) + layout.addWidget(btns_widget) + + self.btn_cancel = btn_cancel + self.btn_restart = btn_restart + + def showEvent(self, event): + super(RestartDialog, self).showEvent(event) + btns_width = max(self.btn_cancel.width(), self.btn_restart.width()) + self.btn_cancel.setFixedWidth(btns_width) + self.btn_restart.setFixedWidth(btns_width) + + def on_cancel_pressed(self): + self.done(0) + + def on_restart_pressed(self): + self.done(1) + + class SpacerWidget(QtWidgets.QWidget): def __init__(self, parent=None): super(SpacerWidget, self).__init__(parent) diff --git a/openpype/tools/settings/settings/window.py b/openpype/tools/settings/settings/window.py index 9b368588c3..7a6536fd78 100644 --- a/openpype/tools/settings/settings/window.py +++ b/openpype/tools/settings/settings/window.py @@ -4,7 +4,7 @@ from .categories import ( SystemWidget, ProjectWidget ) -from .widgets import ShadowWidget +from .widgets import ShadowWidget, RestartDialog from . import style from openpype.tools.settings import ( @@ -14,6 +14,8 @@ from openpype.tools.settings import ( class MainWidget(QtWidgets.QWidget): + trigger_restart = QtCore.Signal() + widget_width = 1000 widget_height = 600 @@ -60,6 +62,9 @@ class MainWidget(QtWidgets.QWidget): for tab_widget in tab_widgets: tab_widget.saved.connect(self._on_tab_save) tab_widget.state_changed.connect(self._on_state_change) + tab_widget.restart_required_trigger.connect( + self._on_restart_required + ) self.tab_widgets = tab_widgets @@ -132,3 +137,15 @@ class MainWidget(QtWidgets.QWidget): for tab_widget in self.tab_widgets: tab_widget.reset() + + def _on_restart_required(self): + # Don't show dialog if there are not registered slots for + # `trigger_restart` signal. + # - For example when settings are runnin as standalone tool + if self.receivers(self.trigger_restart) < 1: + return + + dialog = RestartDialog(self) + result = dialog.exec_() + if result == 1: + self.trigger_restart.emit() diff --git a/openpype/tools/tray/pype_tray.py b/openpype/tools/tray/pype_tray.py index 3a10bae3ca..d9806a96fd 100644 --- a/openpype/tools/tray/pype_tray.py +++ b/openpype/tools/tray/pype_tray.py @@ -1,11 +1,14 @@ import collections import os import sys +import atexit +import subprocess import platform from avalon import style from Qt import QtCore, QtGui, QtWidgets from openpype.api import Logger, resources +from openpype.lib import get_pype_execute_args from openpype.modules import TrayModulesManager, ITrayService from openpype.settings.lib import get_system_settings import openpype.version @@ -122,6 +125,34 @@ class TrayManager: self.tray_widget.menu.addAction(version_action) self.tray_widget.menu.addSeparator() + def restart(self): + """Restart Tray tool. + + First creates new process with same argument and close current tray. + """ + args = get_pype_execute_args() + # Create a copy of sys.argv + additional_args = list(sys.argv) + # Check last argument from `get_pype_execute_args` + # - when running from code it is the same as first from sys.argv + if args[-1] == additional_args[0]: + additional_args.pop(0) + args.extend(additional_args) + + kwargs = {} + if platform.system().lower() == "windows": + flags = ( + subprocess.CREATE_NEW_PROCESS_GROUP + | subprocess.DETACHED_PROCESS + ) + kwargs["creationflags"] = flags + + subprocess.Popen(args, **kwargs) + self.exit() + + def exit(self): + self.tray_widget.exit() + def on_exit(self): self.modules_manager.on_exit() @@ -146,6 +177,8 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): super(SystemTrayIcon, self).__init__(icon, parent) + self._exited = False + # Store parent - QtWidgets.QMainWindow() self.parent = parent @@ -164,6 +197,8 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): # Add menu to Context of SystemTrayIcon self.setContextMenu(self.menu) + atexit.register(self.exit) + def on_systray_activated(self, reason): # show contextMenu if left click if reason == QtWidgets.QSystemTrayIcon.Trigger: @@ -175,6 +210,10 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): - Icon won't stay in tray after exit. """ + if self._exited: + return + self._exited = True + self.hide() self.tray_man.on_exit() QtCore.QCoreApplication.exit() diff --git a/openpype/version.py b/openpype/version.py index a88ae329d0..202cb9348e 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.0.0-rc.5" +__version__ = "3.0.0-rc.6" diff --git a/openpype/widgets/color_widgets/__init__.py b/openpype/widgets/color_widgets/__init__.py new file mode 100644 index 0000000000..324b23543d --- /dev/null +++ b/openpype/widgets/color_widgets/__init__.py @@ -0,0 +1,14 @@ +from .color_picker_widget import ( + ColorPickerWidget +) + +from .color_view import ( + draw_checkerboard_tile +) + + +__all__ = ( + "ColorPickerWidget", + + "draw_checkerboard_tile" +) diff --git a/openpype/widgets/color_widgets/color_inputs.py b/openpype/widgets/color_widgets/color_inputs.py new file mode 100644 index 0000000000..eda8c618f1 --- /dev/null +++ b/openpype/widgets/color_widgets/color_inputs.py @@ -0,0 +1,639 @@ +import re +from Qt import QtWidgets, QtCore, QtGui + +from .color_view import draw_checkerboard_tile + + +slide_style = """ +QSlider::groove:horizontal { + background: qlineargradient( + x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #000, stop: 1 #fff + ); + height: 8px; + border-radius: 4px; +} + +QSlider::handle:horizontal { + background: qlineargradient( + x1:0, y1:0, x2:1, y2:1, stop:0 #ddd, stop:1 #bbb + ); + border: 1px solid #777; + width: 8px; + margin-top: -1px; + margin-bottom: -1px; + border-radius: 4px; +} + +QSlider::handle:horizontal:hover { + background: qlineargradient( + x1:0, y1:0, x2:1, y2:1, stop:0 #eee, stop:1 #ddd + ); + border: 1px solid #444;ff + border-radius: 4px; +}""" + + +class AlphaSlider(QtWidgets.QSlider): + def __init__(self, *args, **kwargs): + super(AlphaSlider, self).__init__(*args, **kwargs) + self._mouse_clicked = False + self.setSingleStep(1) + self.setMinimum(0) + self.setMaximum(255) + self.setValue(255) + + self._checkerboard = None + + def checkerboard(self): + if self._checkerboard is None: + self._checkerboard = draw_checkerboard_tile( + 3, QtGui.QColor(173, 173, 173), QtGui.QColor(27, 27, 27) + ) + return self._checkerboard + + def mousePressEvent(self, event): + self._mouse_clicked = True + if event.button() == QtCore.Qt.LeftButton: + self._set_value_to_pos(event.pos().x()) + return event.accept() + return super(AlphaSlider, self).mousePressEvent(event) + + def _set_value_to_pos(self, pos_x): + value = ( + self.maximum() - self.minimum() + ) * pos_x / self.width() + self.minimum() + self.setValue(value) + + def mouseMoveEvent(self, event): + if self._mouse_clicked: + self._set_value_to_pos(event.pos().x()) + super(AlphaSlider, self).mouseMoveEvent(event) + + def mouseReleaseEvent(self, event): + self._mouse_clicked = True + super(AlphaSlider, self).mouseReleaseEvent(event) + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + opt = QtWidgets.QStyleOptionSlider() + self.initStyleOption(opt) + + painter.fillRect(event.rect(), QtCore.Qt.transparent) + + painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform) + rect = self.style().subControlRect( + QtWidgets.QStyle.CC_Slider, + opt, + QtWidgets.QStyle.SC_SliderGroove, + self + ) + final_height = 9 + offset_top = 0 + if rect.height() > final_height: + offset_top = int((rect.height() - final_height) / 2) + rect = QtCore.QRect( + rect.x(), + offset_top, + rect.width(), + final_height + ) + + pix_rect = QtCore.QRect(event.rect()) + pix_rect.setX(rect.x()) + pix_rect.setWidth(rect.width() - (2 * rect.x())) + pix = QtGui.QPixmap(pix_rect.width(), pix_rect.height()) + pix_painter = QtGui.QPainter(pix) + pix_painter.drawTiledPixmap(pix_rect, self.checkerboard()) + gradient = QtGui.QLinearGradient(rect.topLeft(), rect.bottomRight()) + gradient.setColorAt(0, QtCore.Qt.transparent) + gradient.setColorAt(1, QtCore.Qt.white) + pix_painter.fillRect(pix_rect, gradient) + pix_painter.end() + + brush = QtGui.QBrush(pix) + painter.save() + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(brush) + ratio = rect.height() / 2 + painter.drawRoundedRect(rect, ratio, ratio) + painter.restore() + + _handle_rect = self.style().subControlRect( + QtWidgets.QStyle.CC_Slider, + opt, + QtWidgets.QStyle.SC_SliderHandle, + self + ) + + handle_rect = QtCore.QRect(rect) + if offset_top > 1: + height = handle_rect.height() + handle_rect.setY(handle_rect.y() - 1) + handle_rect.setHeight(height + 2) + handle_rect.setX(_handle_rect.x()) + handle_rect.setWidth(handle_rect.height()) + + painter.save() + + gradient = QtGui.QRadialGradient() + radius = handle_rect.height() / 2 + center_x = handle_rect.width() / 2 + handle_rect.x() + center_y = handle_rect.height() + gradient.setCenter(center_x, center_y) + gradient.setCenterRadius(radius) + gradient.setFocalPoint(center_x, center_y) + + gradient.setColorAt(0.9, QtGui.QColor(127, 127, 127)) + gradient.setColorAt(1, QtCore.Qt.transparent) + + painter.setPen(QtCore.Qt.NoPen) + painter.setBrush(gradient) + painter.drawEllipse(handle_rect) + + painter.restore() + + +class AlphaInputs(QtWidgets.QWidget): + alpha_changed = QtCore.Signal(int) + + def __init__(self, parent=None): + super(AlphaInputs, self).__init__(parent) + + self._block_changes = False + self.alpha_value = None + + percent_input = QtWidgets.QDoubleSpinBox(self) + percent_input.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + percent_input.setMinimum(0) + percent_input.setMaximum(100) + percent_input.setDecimals(2) + + int_input = QtWidgets.QSpinBox(self) + int_input.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + int_input.setMinimum(0) + int_input.setMaximum(255) + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(int_input) + layout.addWidget(QtWidgets.QLabel("0-255")) + layout.addWidget(percent_input) + layout.addWidget(QtWidgets.QLabel("%")) + + percent_input.valueChanged.connect(self._on_percent_change) + int_input.valueChanged.connect(self._on_int_change) + + self.percent_input = percent_input + self.int_input = int_input + + self.set_alpha(255) + + def set_alpha(self, alpha): + if alpha == self.alpha_value: + return + self.alpha_value = alpha + + self.update_alpha() + + def _on_percent_change(self): + if self._block_changes: + return + self.alpha_value = int(self.percent_input.value() * 255 / 100) + self.alpha_changed.emit(self.alpha_value) + self.update_alpha() + + def _on_int_change(self): + if self._block_changes: + return + + self.alpha_value = self.int_input.value() + self.alpha_changed.emit(self.alpha_value) + self.update_alpha() + + def update_alpha(self): + self._block_changes = True + if self.int_input.value() != self.alpha_value: + self.int_input.setValue(self.alpha_value) + + percent = round(100 * self.alpha_value / 255, 2) + if self.percent_input.value() != percent: + self.percent_input.setValue(percent) + + self._block_changes = False + + +class RGBInputs(QtWidgets.QWidget): + value_changed = QtCore.Signal() + + def __init__(self, color, parent=None): + super(RGBInputs, self).__init__(parent) + + self._block_changes = False + + self.color = color + + input_red = QtWidgets.QSpinBox(self) + input_green = QtWidgets.QSpinBox(self) + input_blue = QtWidgets.QSpinBox(self) + + input_red.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_green.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_blue.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + + input_red.setMinimum(0) + input_green.setMinimum(0) + input_blue.setMinimum(0) + + input_red.setMaximum(255) + input_green.setMaximum(255) + input_blue.setMaximum(255) + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(input_red, 1) + layout.addWidget(input_green, 1) + layout.addWidget(input_blue, 1) + + input_red.valueChanged.connect(self._on_red_change) + input_green.valueChanged.connect(self._on_green_change) + input_blue.valueChanged.connect(self._on_blue_change) + + self.input_red = input_red + self.input_green = input_green + self.input_blue = input_blue + + def _on_red_change(self, value): + if self._block_changes: + return + self.color.setRed(value) + self._on_change() + + def _on_green_change(self, value): + if self._block_changes: + return + self.color.setGreen(value) + self._on_change() + + def _on_blue_change(self, value): + if self._block_changes: + return + self.color.setBlue(value) + self._on_change() + + def _on_change(self): + self.value_changed.emit() + + def color_changed(self): + if ( + self.input_red.value() == self.color.red() + and self.input_green.value() == self.color.green() + and self.input_blue.value() == self.color.blue() + ): + return + + self._block_changes = True + + self.input_red.setValue(self.color.red()) + self.input_green.setValue(self.color.green()) + self.input_blue.setValue(self.color.blue()) + + self._block_changes = False + + +class CMYKInputs(QtWidgets.QWidget): + value_changed = QtCore.Signal() + + def __init__(self, color, parent=None): + super(CMYKInputs, self).__init__(parent) + + self.color = color + + self._block_changes = False + + input_cyan = QtWidgets.QSpinBox(self) + input_magenta = QtWidgets.QSpinBox(self) + input_yellow = QtWidgets.QSpinBox(self) + input_black = QtWidgets.QSpinBox(self) + + input_cyan.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_magenta.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_yellow.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_black.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + + input_cyan.setMinimum(0) + input_magenta.setMinimum(0) + input_yellow.setMinimum(0) + input_black.setMinimum(0) + + input_cyan.setMaximum(255) + input_magenta.setMaximum(255) + input_yellow.setMaximum(255) + input_black.setMaximum(255) + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(input_cyan, 1) + layout.addWidget(input_magenta, 1) + layout.addWidget(input_yellow, 1) + layout.addWidget(input_black, 1) + + input_cyan.valueChanged.connect(self._on_change) + input_magenta.valueChanged.connect(self._on_change) + input_yellow.valueChanged.connect(self._on_change) + input_black.valueChanged.connect(self._on_change) + + self.input_cyan = input_cyan + self.input_magenta = input_magenta + self.input_yellow = input_yellow + self.input_black = input_black + + def _on_change(self): + if self._block_changes: + return + self.color.setCmyk( + self.input_cyan.value(), + self.input_magenta.value(), + self.input_yellow.value(), + self.input_black.value() + ) + self.value_changed.emit() + + def color_changed(self): + if self._block_changes: + return + _cur_color = QtGui.QColor() + _cur_color.setCmyk( + self.input_cyan.value(), + self.input_magenta.value(), + self.input_yellow.value(), + self.input_black.value() + ) + if ( + _cur_color.red() == self.color.red() + and _cur_color.green() == self.color.green() + and _cur_color.blue() == self.color.blue() + ): + return + + c, m, y, k, _ = self.color.getCmyk() + self._block_changes = True + + self.input_cyan.setValue(c) + self.input_magenta.setValue(m) + self.input_yellow.setValue(y) + self.input_black.setValue(k) + + self._block_changes = False + + +class HEXInputs(QtWidgets.QWidget): + hex_regex = re.compile("^#(([0-9a-fA-F]{2}){3}|([0-9a-fA-F]){3})$") + value_changed = QtCore.Signal() + + def __init__(self, color, parent=None): + super(HEXInputs, self).__init__(parent) + self.color = color + + input_field = QtWidgets.QLineEdit(self) + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(input_field, 1) + + input_field.textChanged.connect(self._on_change) + + self.input_field = input_field + + def _on_change(self): + if self._block_changes: + return + input_value = self.input_field.text() + # TODO what if does not match? + if self.hex_regex.match(input_value): + self.color.setNamedColor(input_value) + self.value_changed.emit() + + def color_changed(self): + input_value = self.input_field.text() + if self.hex_regex.match(input_value): + _cur_color = QtGui.QColor() + _cur_color.setNamedColor(input_value) + if ( + _cur_color.red() == self.color.red() + and _cur_color.green() == self.color.green() + and _cur_color.blue() == self.color.blue() + ): + return + self._block_changes = True + + self.input_field.setText(self.color.name()) + + self._block_changes = False + + +class HSVInputs(QtWidgets.QWidget): + value_changed = QtCore.Signal() + + def __init__(self, color, parent=None): + super(HSVInputs, self).__init__(parent) + + self._block_changes = False + + self.color = color + + input_hue = QtWidgets.QSpinBox(self) + input_sat = QtWidgets.QSpinBox(self) + input_val = QtWidgets.QSpinBox(self) + + input_hue.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_sat.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_val.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + + input_hue.setMinimum(0) + input_sat.setMinimum(0) + input_val.setMinimum(0) + + input_hue.setMaximum(359) + input_sat.setMaximum(255) + input_val.setMaximum(255) + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(input_hue, 1) + layout.addWidget(input_sat, 1) + layout.addWidget(input_val, 1) + + input_hue.valueChanged.connect(self._on_change) + input_sat.valueChanged.connect(self._on_change) + input_val.valueChanged.connect(self._on_change) + + self.input_hue = input_hue + self.input_sat = input_sat + self.input_val = input_val + + def _on_change(self): + if self._block_changes: + return + self.color.setHsv( + self.input_hue.value(), + self.input_sat.value(), + self.input_val.value() + ) + self.value_changed.emit() + + def color_changed(self): + _cur_color = QtGui.QColor() + _cur_color.setHsv( + self.input_hue.value(), + self.input_sat.value(), + self.input_val.value() + ) + if ( + _cur_color.red() == self.color.red() + and _cur_color.green() == self.color.green() + and _cur_color.blue() == self.color.blue() + ): + return + + self._block_changes = True + h, s, v, _ = self.color.getHsv() + + self.input_hue.setValue(h) + self.input_sat.setValue(s) + self.input_val.setValue(v) + + self._block_changes = False + + +class HSLInputs(QtWidgets.QWidget): + value_changed = QtCore.Signal() + + def __init__(self, color, parent=None): + super(HSLInputs, self).__init__(parent) + + self._block_changes = False + + self.color = color + + input_hue = QtWidgets.QSpinBox(self) + input_sat = QtWidgets.QSpinBox(self) + input_light = QtWidgets.QSpinBox(self) + + input_hue.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_sat.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + input_light.setButtonSymbols(QtWidgets.QSpinBox.NoButtons) + + input_hue.setMinimum(0) + input_sat.setMinimum(0) + input_light.setMinimum(0) + + input_hue.setMaximum(359) + input_sat.setMaximum(255) + input_light.setMaximum(255) + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(input_hue, 1) + layout.addWidget(input_sat, 1) + layout.addWidget(input_light, 1) + + input_hue.valueChanged.connect(self._on_change) + input_sat.valueChanged.connect(self._on_change) + input_light.valueChanged.connect(self._on_change) + + self.input_hue = input_hue + self.input_sat = input_sat + self.input_light = input_light + + def _on_change(self): + if self._block_changes: + return + self.color.setHsl( + self.input_hue.value(), + self.input_sat.value(), + self.input_light.value() + ) + self.value_changed.emit() + + def color_changed(self): + _cur_color = QtGui.QColor() + _cur_color.setHsl( + self.input_hue.value(), + self.input_sat.value(), + self.input_light.value() + ) + if ( + _cur_color.red() == self.color.red() + and _cur_color.green() == self.color.green() + and _cur_color.blue() == self.color.blue() + ): + return + + self._block_changes = True + h, s, l, _ = self.color.getHsl() + + self.input_hue.setValue(h) + self.input_sat.setValue(s) + self.input_light.setValue(l) + + self._block_changes = False + + +class ColorInputsWidget(QtWidgets.QWidget): + color_changed = QtCore.Signal(QtGui.QColor) + + def __init__(self, parent=None, **kwargs): + super(ColorInputsWidget, self).__init__(parent) + + color = QtGui.QColor() + + input_fields = [] + + if kwargs.get("use_hex", True): + input_fields.append(HEXInputs(color, self)) + + if kwargs.get("use_rgb", True): + input_fields.append(RGBInputs(color, self)) + + if kwargs.get("use_hsl", True): + input_fields.append(HSLInputs(color, self)) + + if kwargs.get("use_hsv", True): + input_fields.append(HSVInputs(color, self)) + + if kwargs.get("use_cmyk", True): + input_fields.append(CMYKInputs(color, self)) + + inputs_widget = QtWidgets.QWidget(self) + inputs_layout = QtWidgets.QVBoxLayout(inputs_widget) + + for input_field in input_fields: + inputs_layout.addWidget(input_field) + input_field.value_changed.connect(self._on_value_change) + + layout = QtWidgets.QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(inputs_widget, 0) + spacer = QtWidgets.QWidget(self) + layout.addWidget(spacer, 1) + + self.input_fields = input_fields + + self.color = color + + def set_color(self, color): + if ( + color.red() == self.color.red() + and color.green() == self.color.green() + and color.blue() == self.color.blue() + ): + return + self.color.setRed(color.red()) + self.color.setGreen(color.green()) + self.color.setBlue(color.blue()) + self._on_value_change() + + def _on_value_change(self): + for input_field in self.input_fields: + input_field.color_changed() + self.color_changed.emit(self.color) diff --git a/openpype/widgets/color_widgets/color_picker_widget.py b/openpype/widgets/color_widgets/color_picker_widget.py new file mode 100644 index 0000000000..81ec1f87aa --- /dev/null +++ b/openpype/widgets/color_widgets/color_picker_widget.py @@ -0,0 +1,176 @@ +import os +from Qt import QtWidgets, QtCore, QtGui + +from .color_triangle import QtColorTriangle +from .color_view import ColorViewer +from .color_screen_pick import PickScreenColorWidget +from .color_inputs import ( + AlphaSlider, + AlphaInputs, + HEXInputs, + RGBInputs, + HSLInputs, + HSVInputs +) + + +class ColorPickerWidget(QtWidgets.QWidget): + color_changed = QtCore.Signal(QtGui.QColor) + + def __init__(self, color=None, parent=None): + super(ColorPickerWidget, self).__init__(parent) + + # Color triangle + color_triangle = QtColorTriangle(self) + + alpha_slider_proxy = QtWidgets.QWidget(self) + alpha_slider = AlphaSlider(QtCore.Qt.Horizontal, alpha_slider_proxy) + + alpha_slider_layout = QtWidgets.QHBoxLayout(alpha_slider_proxy) + alpha_slider_layout.setContentsMargins(5, 5, 5, 5) + alpha_slider_layout.addWidget(alpha_slider, 1) + + # Eye picked widget + pick_widget = PickScreenColorWidget() + pick_widget.setMaximumHeight(50) + + # Color pick button + btn_pick_color = QtWidgets.QPushButton(self) + icon_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "eyedropper.png" + ) + btn_pick_color.setIcon(QtGui.QIcon(icon_path)) + btn_pick_color.setToolTip("Pick a color") + + # Color preview + color_view = ColorViewer(self) + color_view.setMaximumHeight(50) + + alpha_inputs = AlphaInputs(self) + + color_inputs_color = QtGui.QColor() + col_inputs_by_label = [ + ("HEX", HEXInputs(color_inputs_color, self)), + ("RGB", RGBInputs(color_inputs_color, self)), + ("HSL", HSLInputs(color_inputs_color, self)), + ("HSV", HSVInputs(color_inputs_color, self)) + ] + + layout = QtWidgets.QGridLayout(self) + empty_col = 1 + label_col = empty_col + 1 + input_col = label_col + 1 + empty_widget = QtWidgets.QWidget(self) + empty_widget.setFixedWidth(10) + layout.addWidget(empty_widget, 0, empty_col) + + row = 0 + layout.addWidget(btn_pick_color, row, label_col) + layout.addWidget(color_view, row, input_col) + row += 1 + + color_input_fields = [] + for label, input_field in col_inputs_by_label: + layout.addWidget(QtWidgets.QLabel(label, self), row, label_col) + layout.addWidget(input_field, row, input_col) + input_field.value_changed.connect( + self._on_color_input_value_change + ) + color_input_fields.append(input_field) + row += 1 + + layout.addWidget(color_triangle, 0, 0, row + 1, 1) + layout.setRowStretch(row, 1) + row += 1 + + layout.addWidget(alpha_slider_proxy, row, 0) + + layout.addWidget(QtWidgets.QLabel("Alpha", self), row, label_col) + layout.addWidget(alpha_inputs, row, input_col) + row += 1 + layout.setRowStretch(row, 1) + + color_view.set_color(color_triangle.cur_color) + + color_triangle.color_changed.connect(self.triangle_color_changed) + alpha_slider.valueChanged.connect(self._on_alpha_slider_change) + pick_widget.color_selected.connect(self.on_color_change) + alpha_inputs.alpha_changed.connect(self._on_alpha_inputs_changed) + btn_pick_color.released.connect(self.pick_color) + + self.color_input_fields = color_input_fields + self.color_inputs_color = color_inputs_color + + self.pick_widget = pick_widget + + self.color_triangle = color_triangle + self.alpha_slider = alpha_slider + + self.color_view = color_view + self.alpha_inputs = alpha_inputs + self.btn_pick_color = btn_pick_color + + self._minimum_size_set = False + + if color: + self.set_color(color) + self.alpha_changed(color.alpha()) + + def showEvent(self, event): + super(ColorPickerWidget, self).showEvent(event) + if self._minimum_size_set: + return + + triangle_size = max(int(self.width() / 5 * 3), 180) + self.color_triangle.setMinimumWidth(triangle_size) + self.color_triangle.setMinimumHeight(triangle_size) + self._minimum_size_set = True + + def color(self): + return self.color_view.color() + + def set_color(self, color): + self.alpha_inputs.set_alpha(color.alpha()) + self.on_color_change(color) + + def pick_color(self): + self.pick_widget.pick_color() + + def triangle_color_changed(self, color): + self.color_view.set_color(color) + if self.color_inputs_color != color: + self.color_inputs_color.setRgb( + color.red(), color.green(), color.blue() + ) + for color_input in self.color_input_fields: + color_input.color_changed() + + def on_color_change(self, color): + self.color_view.set_color(color) + self.color_triangle.set_color(color) + if self.color_inputs_color != color: + self.color_inputs_color.setRgb( + color.red(), color.green(), color.blue() + ) + for color_input in self.color_input_fields: + color_input.color_changed() + + def _on_color_input_value_change(self): + for input_field in self.color_input_fields: + input_field.color_changed() + self.on_color_change(QtGui.QColor(self.color_inputs_color)) + + def alpha_changed(self, value): + self.color_view.set_alpha(value) + if self.alpha_slider.value() != value: + self.alpha_slider.setValue(value) + + if self.alpha_inputs.alpha_value != value: + self.alpha_inputs.set_alpha(value) + + def _on_alpha_inputs_changed(self, value): + self.alpha_changed(value) + + def _on_alpha_slider_change(self, value): + self.alpha_changed(value) diff --git a/openpype/widgets/color_widgets/color_screen_pick.py b/openpype/widgets/color_widgets/color_screen_pick.py new file mode 100644 index 0000000000..87f50745eb --- /dev/null +++ b/openpype/widgets/color_widgets/color_screen_pick.py @@ -0,0 +1,248 @@ +import Qt +from Qt import QtWidgets, QtCore, QtGui + + +class PickScreenColorWidget(QtWidgets.QWidget): + color_selected = QtCore.Signal(QtGui.QColor) + + def __init__(self, parent=None): + super(PickScreenColorWidget, self).__init__(parent) + self.labels = [] + self.magnification = 2 + + self._min_magnification = 1 + self._max_magnification = 10 + + def add_magnification_delta(self, delta): + _delta = abs(delta / 1000) + if delta > 0: + self.magnification += _delta + else: + self.magnification -= _delta + + if self.magnification > self._max_magnification: + self.magnification = self._max_magnification + elif self.magnification < self._min_magnification: + self.magnification = self._min_magnification + + def pick_color(self): + if self.labels: + if self.labels[0].isVisible(): + return + self.labels = [] + + for screen in QtWidgets.QApplication.screens(): + label = PickLabel(self) + label.pick_color(screen) + label.color_selected.connect(self.on_color_select) + label.close_session.connect(self.end_pick_session) + self.labels.append(label) + + def end_pick_session(self): + for label in self.labels: + label.close() + self.labels = [] + + def on_color_select(self, color): + self.color_selected.emit(color) + self.end_pick_session() + + +class PickLabel(QtWidgets.QLabel): + color_selected = QtCore.Signal(QtGui.QColor) + close_session = QtCore.Signal() + + def __init__(self, pick_widget): + super(PickLabel, self).__init__() + self.setMouseTracking(True) + + self.pick_widget = pick_widget + + self.radius_pen = QtGui.QPen(QtGui.QColor(27, 27, 27), 2) + self.text_pen = QtGui.QPen(QtGui.QColor(127, 127, 127), 4) + self.text_bg = QtGui.QBrush(QtGui.QColor(27, 27, 27)) + self._mouse_over = False + + self.radius = 100 + self.radius_ratio = 11 + + @property + def magnification(self): + return self.pick_widget.magnification + + def pick_color(self, screen_obj): + self.show() + self.windowHandle().setScreen(screen_obj) + geo = screen_obj.geometry() + args = ( + QtWidgets.QApplication.desktop().winId(), + geo.x(), geo.y(), geo.width(), geo.height() + ) + if Qt.__binding__ in ("PyQt4", "PySide"): + pix = QtGui.QPixmap.grabWindow(*args) + else: + pix = screen_obj.grabWindow(*args) + + if pix.width() > pix.height(): + size = pix.height() + else: + size = pix.width() + + self.radius = int(size / self.radius_ratio) + + self.setPixmap(pix) + self.showFullScreen() + + def wheelEvent(self, event): + y_delta = event.angleDelta().y() + self.pick_widget.add_magnification_delta(y_delta) + self.update() + + def enterEvent(self, event): + self._mouse_over = True + super().enterEvent(event) + + def leaveEvent(self, event): + self._mouse_over = False + super().leaveEvent(event) + self.update() + + def mouseMoveEvent(self, event): + self.update() + + def paintEvent(self, event): + super().paintEvent(event) + if not self._mouse_over: + return + + mouse_pos_to_widet = self.mapFromGlobal(QtGui.QCursor.pos()) + + magnified_half_size = self.radius / self.magnification + magnified_size = magnified_half_size * 2 + + zoom_x_1 = mouse_pos_to_widet.x() - magnified_half_size + zoom_x_2 = mouse_pos_to_widet.x() + magnified_half_size + zoom_y_1 = mouse_pos_to_widet.y() - magnified_half_size + zoom_y_2 = mouse_pos_to_widet.y() + magnified_half_size + pix_width = magnified_size + pix_height = magnified_size + draw_pos_x = 0 + draw_pos_y = 0 + if zoom_x_1 < 0: + draw_pos_x = abs(zoom_x_1) + pix_width -= draw_pos_x + zoom_x_1 = 1 + elif zoom_x_2 > self.pixmap().width(): + pix_width -= zoom_x_2 - self.pixmap().width() + + if zoom_y_1 < 0: + draw_pos_y = abs(zoom_y_1) + pix_height -= draw_pos_y + zoom_y_1 = 1 + elif zoom_y_2 > self.pixmap().height(): + pix_height -= zoom_y_2 - self.pixmap().height() + + new_pix = QtGui.QPixmap(magnified_size, magnified_size) + new_pix.fill(QtCore.Qt.transparent) + new_pix_painter = QtGui.QPainter(new_pix) + new_pix_painter.drawPixmap( + QtCore.QRect(draw_pos_x, draw_pos_y, pix_width, pix_height), + self.pixmap().copy(zoom_x_1, zoom_y_1, pix_width, pix_height) + ) + new_pix_painter.end() + + painter = QtGui.QPainter(self) + + ellipse_rect = QtCore.QRect( + mouse_pos_to_widet.x() - self.radius, + mouse_pos_to_widet.y() - self.radius, + self.radius * 2, + self.radius * 2 + ) + ellipse_rect_f = QtCore.QRectF(ellipse_rect) + path = QtGui.QPainterPath() + path.addEllipse(ellipse_rect_f) + painter.setClipPath(path) + + new_pix_rect = QtCore.QRect( + mouse_pos_to_widet.x() - self.radius + 1, + mouse_pos_to_widet.y() - self.radius + 1, + new_pix.width() * self.magnification, + new_pix.height() * self.magnification + ) + + painter.drawPixmap(new_pix_rect, new_pix) + + painter.setClipping(False) + + painter.setRenderHint(QtGui.QPainter.Antialiasing) + + painter.setPen(self.radius_pen) + painter.drawEllipse(ellipse_rect_f) + + image = self.pixmap().toImage() + if image.valid(mouse_pos_to_widet): + color = QtGui.QColor(image.pixel(mouse_pos_to_widet)) + else: + color = QtGui.QColor() + + color_text = "Red: {} - Green: {} - Blue: {}".format( + color.red(), color.green(), color.blue() + ) + font = painter.font() + font.setPointSize(self.radius / 10) + painter.setFont(font) + + text_rect_height = int(painter.fontMetrics().height() + 10) + text_rect = QtCore.QRect( + ellipse_rect.x(), + ellipse_rect.bottom(), + ellipse_rect.width(), + text_rect_height + ) + if text_rect.bottom() > self.pixmap().height(): + text_rect.moveBottomLeft(ellipse_rect.topLeft()) + + rect_radius = text_rect_height / 2 + path = QtGui.QPainterPath() + path.addRoundedRect( + QtCore.QRectF(text_rect), + rect_radius, + rect_radius + ) + painter.fillPath(path, self.text_bg) + + painter.setPen(self.text_pen) + painter.drawText( + text_rect, + QtCore.Qt.AlignLeft | QtCore.Qt.AlignCenter, + color_text + ) + + color_rect_x = ellipse_rect.x() - text_rect_height + if color_rect_x < 0: + color_rect_x += (text_rect_height + ellipse_rect.width()) + + color_rect = QtCore.QRect( + color_rect_x, + ellipse_rect.y(), + text_rect_height, + ellipse_rect.height() + ) + path = QtGui.QPainterPath() + path.addRoundedRect( + QtCore.QRectF(color_rect), + rect_radius, + rect_radius + ) + painter.fillPath(path, color) + painter.drawRoundedRect(color_rect, rect_radius, rect_radius) + painter.end() + + def mouseReleaseEvent(self, event): + color = QtGui.QColor(self.pixmap().toImage().pixel(event.pos())) + self.color_selected.emit(color) + + def keyPressEvent(self, event): + if event.key() == QtCore.Qt.Key_Escape: + self.close_session.emit() diff --git a/openpype/widgets/color_widgets/color_triangle.py b/openpype/widgets/color_widgets/color_triangle.py new file mode 100644 index 0000000000..d4db175d84 --- /dev/null +++ b/openpype/widgets/color_widgets/color_triangle.py @@ -0,0 +1,1431 @@ +from enum import Enum +from math import floor, sqrt, sin, cos, acos, pi as PI +from Qt import QtWidgets, QtCore, QtGui + +TWOPI = PI * 2 + + +class TriangleState(Enum): + IdleState = object() + SelectingHueState = object() + SelectingSatValueState = object() + + +class DoubleColor: + def __init__(self, r, g=None, b=None): + if g is None: + g = r.g + b = r.b + r = r.r + self.r = float(r) + self.g = float(g) + self.b = float(b) + + +class Vertex: + def __init__(self, color, point): + # Convert GlobalColor to QColor as globals don't have red, green, blue + if isinstance(color, QtCore.Qt.GlobalColor): + color = QtGui.QColor(color) + + # Convert QColor to DoubleColor + if isinstance(color, QtGui.QColor): + color = DoubleColor(color.red(), color.green(), color.blue()) + + self.color = color + self.point = point + + +class QtColorTriangle(QtWidgets.QWidget): + """The QtColorTriangle class provides a triangular color selection widget. + + This widget uses the HSV color model, and is therefore useful for + selecting colors by eye. + + The triangle in the center of the widget is used for selecting + saturation and value, and the surrounding circle is used for + selecting hue. + + Use set_color() and color() to set and get the current color. + """ + color_changed = QtCore.Signal(QtGui.QColor) + + # Thick of color wheel ratio where 1 is fully filled circle + inner_radius_ratio = 5.0 + # Ratio where hue selector on wheel is relative to `inner_radius_ratio` + # - middle of the wheel is twice `inner_radius_ratio` + selector_radius_ratio = inner_radius_ratio * 2 + # Size ratio of selectors on wheel and in triangle + ellipse_size_ratio = 10.0 + # Ration of selectors thickness + ellipse_thick_ratio = 50.0 + # Hue offset on color wheel (0 - 359) + # - red on top if set to "0" + hue_offset = 90 + + def __init__(self, parent=None): + super(QtColorTriangle, self).__init__(parent) + self.setSizePolicy( + QtWidgets.QSizePolicy.Minimum, + QtWidgets.QSizePolicy.Minimum + ) + self.setFocusPolicy(QtCore.Qt.StrongFocus) + + self.angle_a = float() + self.angle_b = float() + self.angle_c = float() + + self.bg_image = QtGui.QImage( + self.sizeHint(), QtGui.QImage.Format_RGB32 + ) + self.cur_color = QtGui.QColor() + self.point_a = QtCore.QPointF() + self.point_b = QtCore.QPointF() + self.point_c = QtCore.QPointF() + self.point_d = QtCore.QPointF() + + self.cur_hue = int() + + self.pen_width = int() + self.ellipse_size = int() + self.outer_radius = int() + self.selector_pos = QtCore.QPointF() + + self.sel_mode = TriangleState.IdleState + + self._triangle_outline_pen = QtGui.QPen( + QtGui.QColor(40, 40, 40, 128), + 2 + ) + # Prepare hue numbers for color circle + _hue_circle_range = [] + for idx in range(11): + # Some Qt versions may require: + # hue = int(idx * 360.0) + percent_idx = idx * 0.1 + hue = int(360.0 - (percent_idx * 360.0)) + _hue_circle_range.append((percent_idx, hue)) + self._hue_circle_range = tuple(_hue_circle_range) + + color = QtGui.QColor() + color.setHsv(0, 255, 255) + self.set_color(color) + + def set_color(self, col): + if ( + col.red() == self.cur_color.red() + and col.green() == self.cur_color.green() + and col.blue() == self.cur_color.blue() + ): + return + + self.cur_color = col + + hue, *_ = self.cur_color.getHsv() + + # Never use an invalid hue to display colors + if hue != -1: + self.cur_hue = hue + + angle_with_offset = (360 - self.cur_hue - self.hue_offset) % 360 + self.angle_a = (angle_with_offset * TWOPI) / 360.0 + self.angle_a += PI / 2.0 + if self.angle_a > TWOPI: + self.angle_a -= TWOPI + + self.angle_b = self.angle_a + TWOPI / 3 + self.angle_c = self.angle_b + TWOPI / 3 + + if self.angle_b > TWOPI: + self.angle_b -= TWOPI + if self.angle_c > TWOPI: + self.angle_c -= TWOPI + + cx = float(self.contentsRect().center().x()) + cy = float(self.contentsRect().center().y()) + inner_radius = ( + self.outer_radius + - (self.outer_radius / self.inner_radius_ratio) + ) + selector_radius = ( + self.outer_radius + - (self.outer_radius / self.selector_radius_ratio) + ) + self.point_a = QtCore.QPointF( + cx + (cos(self.angle_a) * inner_radius), + cy - (sin(self.angle_a) * inner_radius) + ) + self.point_b = QtCore.QPointF( + cx + (cos(self.angle_b) * inner_radius), + cy - (sin(self.angle_b) * inner_radius) + ) + self.point_c = QtCore.QPointF( + cx + (cos(self.angle_c) * inner_radius), + cy - (sin(self.angle_c) * inner_radius) + ) + self.point_d = QtCore.QPointF( + cx + (cos(self.angle_a) * selector_radius), + cy - (sin(self.angle_a) * selector_radius) + ) + + self.selector_pos = self._point_from_color(self.cur_color) + self.update() + + self.color_changed.emit(self.cur_color) + + def heightForWidth(self, width): + return width + + def polish(self): + size_w = self.contentsRect().width() + size_h = self.contentsRect().height() + if size_w < size_h: + size = size_w + else: + size = size_h + + self.outer_radius = (size - 1) / 2 + + self.pen_width = int( + floor(self.outer_radius / self.ellipse_thick_ratio) + ) + self.ellipse_size = int( + floor(self.outer_radius / self.ellipse_size_ratio) + ) + + cx = float(self.contentsRect().center().x()) + cy = float(self.contentsRect().center().y()) + + inner_radius = ( + self.outer_radius + - (self.outer_radius / self.inner_radius_ratio) + ) + selector_radius = ( + self.outer_radius + - (self.outer_radius / self.selector_radius_ratio) + ) + self.point_a = QtCore.QPointF( + cx + (cos(self.angle_a) * inner_radius), + cy - (sin(self.angle_a) * inner_radius) + ) + self.point_b = QtCore.QPointF( + cx + (cos(self.angle_b) * inner_radius), + cy - (sin(self.angle_b) * inner_radius) + ) + self.point_c = QtCore.QPointF( + cx + (cos(self.angle_c) * inner_radius), + cy - (sin(self.angle_c) * inner_radius) + ) + self.point_d = QtCore.QPointF( + cx + (cos(self.angle_a) * selector_radius), + cy - (sin(self.angle_a) * selector_radius) + ) + + self.selector_pos = self._point_from_color(self.cur_color) + + self.update() + + def paintEvent(self, event): + painter = QtGui.QPainter(self) + if event.rect().intersects(self.contentsRect()): + event_region = event.region() + if hasattr(event_region, "intersect"): + clip_region = event_region.intersect(self.contentsRect()) + else: + clip_region = event_region.intersected( + self.contentsRect() + ) + painter.setClipRegion(clip_region) + + self.paint_bg() + + # Blit the static generated background with the hue gradient onto + # the double buffer. + buf = QtGui.QImage(self.bg_image.copy()) + + # Draw the trigon + # Find the color with only the hue, and max value and saturation + hue_color = QtGui.QColor() + hue_color.setHsv(self.cur_hue, 255, 255) + + # Draw the triangle + self.drawTrigon( + buf, self.point_a, self.point_b, self.point_c, hue_color + ) + + # Slow step: convert the image to a pixmap + pix = QtGui.QPixmap.fromImage(buf) + pix_painter = QtGui.QPainter(pix) + pix_painter.setRenderHint(QtGui.QPainter.Antialiasing) + + # Draw an outline of the triangle + pix_painter.setPen(self._triangle_outline_pen) + pix_painter.drawLine(self.point_a, self.point_b) + pix_painter.drawLine(self.point_b, self.point_c) + pix_painter.drawLine(self.point_c, self.point_a) + + # Draw the color wheel selector + pix_painter.setPen(QtGui.QPen(QtCore.Qt.white, self.pen_width)) + pix_painter.drawEllipse( + int(self.point_d.x() - self.ellipse_size / 2.0), + int(self.point_d.y() - self.ellipse_size / 2.0), + self.ellipse_size, self.ellipse_size + ) + + # Draw the triangle selector + pix_painter.setBrush(self.cur_color) + pix_painter.drawEllipse( + QtCore.QRectF( + self.selector_pos.x() - self.ellipse_size / 2.0, + self.selector_pos.y() - self.ellipse_size / 2.0, + self.ellipse_size + 0.5, + self.ellipse_size + 0.5 + ) + ) + + pix_painter.end() + # Blit + painter.drawPixmap(self.contentsRect().topLeft(), pix) + painter.end() + + def mouseMoveEvent(self, event): + if (event.buttons() & QtCore.Qt.LeftButton) == 0: + return + + depos = QtCore.QPointF( + event.pos().x(), + event.pos().y() + ) + new_color = False + + if self.sel_mode is TriangleState.SelectingHueState: + self.angle_a = self._angle_at(depos, self.contentsRect()) + self.angle_b = self.angle_a + (TWOPI / 3.0) + self.angle_c = self.angle_b + (TWOPI / 3.0) + if self.angle_b > TWOPI: + self.angle_b -= TWOPI + if self.angle_c > TWOPI: + self.angle_c -= TWOPI + + am = self.angle_a - (PI / 2) + if am < 0: + am += TWOPI + self.cur_hue = ( + 360 - int((am * 360.0) / TWOPI) - self.hue_offset + ) % 360 + hue, sat, val, _ = self.cur_color.getHsv() + + if self.cur_hue != hue: + new_color = True + self.cur_color.setHsv(self.cur_hue, sat, val) + + cx = float(self.contentsRect().center().x()) + cy = float(self.contentsRect().center().y()) + inner_radius = ( + self.outer_radius + - (self.outer_radius / self.inner_radius_ratio) + ) + selector_radius = ( + self.outer_radius + - (self.outer_radius / self.selector_radius_ratio) + ) + self.point_a = QtCore.QPointF( + cx + (cos(self.angle_a) * inner_radius), + cy - (sin(self.angle_a) * inner_radius) + ) + self.point_b = QtCore.QPointF( + cx + (cos(self.angle_b) * inner_radius), + cy - (sin(self.angle_b) * inner_radius) + ) + self.point_c = QtCore.QPointF( + cx + (cos(self.angle_c) * inner_radius), + cy - (sin(self.angle_c) * inner_radius) + ) + self.point_d = QtCore.QPointF( + cx + (cos(self.angle_a) * selector_radius), + cy - (sin(self.angle_a) * selector_radius) + ) + + self.selector_pos = self._point_from_color(self.cur_color) + else: + aa = Vertex(QtCore.Qt.transparent, self.point_a) + bb = Vertex(QtCore.Qt.transparent, self.point_b) + cc = Vertex(QtCore.Qt.transparent, self.point_c) + + self.selector_pos = self._move_point_to_triangle( + depos.x(), depos.y(), aa, bb, cc + ) + col = self._color_from_point(self.selector_pos) + if col != self.cur_color: + # Ensure that hue does not change when selecting + # saturation and value. + _, sat, val, _ = col.getHsv() + self.cur_color.setHsv(self.cur_hue, sat, val) + new_color = True + + if new_color: + self.color_changed.emit(self.cur_color) + + self.update() + + def mousePressEvent(self, event): + # Only respond to the left mouse button. + if event.button() != QtCore.Qt.LeftButton: + return + + depos = QtCore.QPointF( + event.pos().x(), + event.pos().y() + ) + rad = self._radius_at(depos, self.contentsRect()) + new_color = False + + # As in mouseMoveEvent, either find the a, b, c angles or the + # radian position of the selector, then order an update. + inner_radius = ( + self.outer_radius - (self.outer_radius / self.inner_radius_ratio) + ) + if rad > inner_radius: + self.sel_mode = TriangleState.SelectingHueState + + self.angle_a = self._angle_at(depos, self.contentsRect()) + self.angle_b = self.angle_a + TWOPI / 3.0 + self.angle_c = self.angle_b + TWOPI / 3.0 + if self.angle_b > TWOPI: + self.angle_b -= TWOPI + if self.angle_c > TWOPI: + self.angle_c -= TWOPI + + am = self.angle_a - PI / 2 + if am < 0: + am += TWOPI + + self.cur_hue = ( + 360 - int((am * 360.0) / TWOPI) - self.hue_offset + ) % 360 + hue, sat, val, _ = self.cur_color.getHsv() + + if hue != self.cur_hue: + new_color = True + self.cur_color.setHsv(self.cur_hue, sat, val) + + cx = float(self.contentsRect().center().x()) + cy = float(self.contentsRect().center().y()) + + self.point_a = QtCore.QPointF( + cx + (cos(self.angle_a) * inner_radius), + cy - (sin(self.angle_a) * inner_radius) + ) + self.point_b = QtCore.QPointF( + cx + (cos(self.angle_b) * inner_radius), + cy - (sin(self.angle_b) * inner_radius) + ) + self.point_c = QtCore.QPointF( + cx + (cos(self.angle_c) * inner_radius), + cy - (sin(self.angle_c) * inner_radius) + ) + + selector_radius = ( + self.outer_radius + - (self.outer_radius / self.selector_radius_ratio) + ) + self.point_d = QtCore.QPointF( + cx + (cos(self.angle_a) * selector_radius), + cy - (sin(self.angle_a) * selector_radius) + ) + + self.selector_pos = self._point_from_color(self.cur_color) + self.color_changed.emit(self.cur_color) + else: + self.sel_mode = TriangleState.SelectingSatValueState + + aa = Vertex(QtCore.Qt.transparent, self.point_a) + bb = Vertex(QtCore.Qt.transparent, self.point_b) + cc = Vertex(QtCore.Qt.transparent, self.point_c) + + self.selector_pos = self._move_point_to_triangle( + depos.x(), depos.y(), aa, bb, cc + ) + col = self._color_from_point(self.selector_pos) + if col != self.cur_color: + self.cur_color = col + new_color = True + + if new_color: + self.color_changed.emit(self.cur_color) + + self.update() + + def mouseReleaseEvent(self, event): + if event.button() == QtCore.Qt.LeftButton: + self.sel_mode = TriangleState.IdleState + + def keyPressEvent(self, event): + key = event.key() + if key == QtCore.Qt.Key_Left: + self.cur_hue -= 1 + if self.cur_hue < 0: + self.cur_hue += 360 + _, sat, val, _ = self.cur_color.getHsv() + + tmp = QtGui.QColor() + tmp.setHsv(self.cur_hue, sat, val) + self.set_color(tmp) + + elif key == QtCore.Qt.Key_Right: + self.cur_hue += 1 + if (self.cur_hue > 359): + self.cur_hue -= 360 + _, sat, val, _ = self.cur_color.getHsv() + tmp = QtGui.QColor() + tmp.setHsv(self.cur_hue, sat, val) + self.set_color(tmp) + + elif key == QtCore.Qt.Key_Up: + _, sat, val, _ = self.cur_color.getHsv() + if event.modifiers() & QtCore.Qt.ShiftModifier: + if sat > 5: + sat -= 5 + else: + sat = 0 + else: + if val > 5: + val -= 5 + else: + val = 0 + + tmp = QtGui.QColor() + tmp.setHsv(self.cur_hue, sat, val) + self.set_color(tmp) + + elif key == QtCore.Qt.Key_Down: + _, sat, val, _ = self.cur_color.getHsv() + if event.modifiers() & QtCore.Qt.ShiftModifier: + if sat < 250: + sat += 5 + else: + sat = 255 + else: + if val < 250: + val += 5 + else: + val = 255 + + tmp = QtGui.QColor() + tmp.setHsv(self.cur_hue, sat, val) + self.set_color(tmp) + + def resizeEvent(self, _event): + size_w = self.contentsRect().width() + size_h = self.contentsRect().height() + if size_w < size_h: + size = size_w + else: + size = size_h + + self.outer_radius = (size - 1) / 2 + + self.pen_width = int( + floor(self.outer_radius / self.ellipse_thick_ratio) + ) + self.ellipse_size = int( + floor(self.outer_radius / self.ellipse_size_ratio) + ) + + cx = float(self.contentsRect().center().x()) + cy = float(self.contentsRect().center().y()) + inner_radius = ( + self.outer_radius + - (self.outer_radius / self.inner_radius_ratio) + ) + selector_radius = ( + self.outer_radius + - (self.outer_radius / self.selector_radius_ratio) + ) + self.point_a = QtCore.QPointF( + cx + (cos(self.angle_a) * inner_radius), + cy - (sin(self.angle_a) * inner_radius) + ) + self.point_b = QtCore.QPointF( + cx + (cos(self.angle_b) * inner_radius), + cy - (sin(self.angle_b) * inner_radius) + ) + self.point_c = QtCore.QPointF( + cx + (cos(self.angle_c) * inner_radius), + cy - (sin(self.angle_c) * inner_radius) + ) + self.point_d = QtCore.QPointF( + cx + (cos(self.angle_a) * selector_radius), + cy - (sin(self.angle_a) * selector_radius) + ) + + # Find the current position of the selector + self.selector_pos = self._point_from_color(self.cur_color) + + self.update() + + def drawTrigon(self, buf, pa, pb, pc, color): + # Create three Vertex objects. A Vertex contains a double-point + # coordinate and a color. + # pa is the tip of the arrow + # pb is the black corner + # pc is the white corner + p1 = Vertex(color, pa) + p2 = Vertex(QtCore.Qt.black, pb) + p3 = Vertex(QtCore.Qt.white, pc) + + # Sort. Make p1 above p2, which is above p3 (using y coordinate). + # Bubble sorting is fastest here. + if p1.point.y() > p2.point.y(): + p1, p2 = p2, p1 + if p1.point.y() > p3.point.y(): + p1, p3 = p3, p1 + if p2.point.y() > p3.point.y(): + p2, p3 = p3, p2 + + # All the three y deltas are >= 0 + p1p2ydist = float(p2.point.y() - p1.point.y()) + p1p3ydist = float(p3.point.y() - p1.point.y()) + p2p3ydist = float(p3.point.y() - p2.point.y()) + p1p2xdist = float(p2.point.x() - p1.point.x()) + p1p3xdist = float(p3.point.x() - p1.point.x()) + p2p3xdist = float(p3.point.x() - p2.point.x()) + + # The first x delta decides wether we have a lefty or a righty + # trigon. + lefty = p1p2xdist < 0 + + # Left and right colors and X values. The key in this map is the + # y values. Our goal is to fill these structures with all the + # information needed to do a single pass top-to-bottom, + # left-to-right drawing of the trigon. + leftColors = {} + rightColors = {} + leftX = {} + rightX = {} + + # Scan longy - find all left and right colors and X-values for + # the tallest edge (p1-p3). + # Initialize with known values + x = p1.point.x() + source = p1.color + dest = p3.color + r = source.r + g = source.g + b = source.b + y1 = int(floor(p1.point.y())) + y2 = int(floor(p3.point.y())) + + # Find slopes (notice that if the y dists are 0, we don't care + # about the slopes) + xdelta = 0.0 + rdelta = 0.0 + gdelta = 0.0 + bdelta = 0.0 + if p1p3ydist != 0.0: + xdelta = p1p3xdist / p1p3ydist + rdelta = (dest.r - r) / p1p3ydist + gdelta = (dest.g - g) / p1p3ydist + bdelta = (dest.b - b) / p1p3ydist + + # Calculate gradients using linear approximation + for y in range(y1, y2): + if lefty: + rightColors[y] = DoubleColor(r, g, b) + rightX[y] = x + else: + leftColors[y] = DoubleColor(r, g, b) + leftX[y] = x + + r += rdelta + g += gdelta + b += bdelta + x += xdelta + + # Scan top shorty - find all left and right colors and x-values + # for the topmost of the two not-tallest short edges. + x = p1.point.x() + source = p1.color + dest = p2.color + r = source.r + g = source.g + b = source.b + y1 = int(floor(p1.point.y())) + y2 = int(floor(p2.point.y())) + + # Find slopes (notice that if the y dists are 0, we don't care + # about the slopes) + xdelta = 0.0 + rdelta = 0.0 + gdelta = 0.0 + bdelta = 0.0 + if p1p2ydist != 0.0: + xdelta = p1p2xdist / p1p2ydist + rdelta = (dest.r - r) / p1p2ydist + gdelta = (dest.g - g) / p1p2ydist + bdelta = (dest.b - b) / p1p2ydist + + # Calculate gradients using linear approximation + for y in range(y1, y2): + if lefty: + leftColors[y] = DoubleColor(r, g, b) + leftX[y] = x + else: + rightColors[y] = DoubleColor(r, g, b) + rightX[y] = x + + r += rdelta + g += gdelta + b += bdelta + x += xdelta + + # Scan bottom shorty - find all left and right colors and + # x-values for the bottommost of the two not-tallest short edges. + x = p2.point.x() + source = p2.color + dest = p3.color + r = source.r + g = source.g + b = source.b + y1 = int(floor(p2.point.y())) + y2 = int(floor(p3.point.y())) + + # Find slopes (notice that if the y dists are 0, we don't care + # about the slopes) + xdelta = 0.0 + rdelta = 0.0 + gdelta = 0.0 + bdelta = 0.0 + if p2p3ydist != 0.0: + xdelta = p2p3xdist / p2p3ydist + rdelta = (dest.r - r) / p2p3ydist + gdelta = (dest.g - g) / p2p3ydist + bdelta = (dest.b - b) / p2p3ydist + + # Calculate gradients using linear approximation + for y in range(y1, y2): + if lefty: + leftColors[y] = DoubleColor(r, g, b) + leftX[y] = x + else: + rightColors[y] = DoubleColor(r, g, b) + rightX[y] = x + + r += rdelta + g += gdelta + b += bdelta + x += xdelta + + # Inner loop. For each y in the left map of x-values, draw one + # line from left to right. + p3yfloor = int(floor(p3.point.y())) + p1yfloor = int(floor(p1.point.y())) + for y in range(p1yfloor, p3yfloor): + lx = leftX[y] + rx = rightX[y] + + lxi = int(floor(lx)) + rxi = int(floor(rx)) + rc = rightColors[y] + lc = leftColors[y] + + # if the xdist is 0, don't draw anything. + xdist = rx - lx + if xdist != 0.0: + r = lc.r + g = lc.g + b = lc.b + rdelta = (rc.r - r) / xdist + gdelta = (rc.g - g) / xdist + bdelta = (rc.b - b) / xdist + + # Inner loop 2. Draws the line from left to right. + for x in range(lxi, rxi + 1): + buf.setPixel(x, y, QtGui.qRgb(int(r), int(g), int(b))) + r += rdelta + g += gdelta + b += bdelta + + def _radius_at(self, pos, rect): + mousexdist = pos.x() - float(rect.center().x()) + mouseydist = pos.y() - float(rect.center().y()) + return sqrt(mousexdist ** 2 + mouseydist ** 2) + + def _angle_at(self, pos, rect): + mousexdist = pos.x() - float(rect.center().x()) + mouseydist = pos.y() - float(rect.center().y()) + mouserad = sqrt(mousexdist ** 2 + mouseydist ** 2) + if mouserad == 0.0: + return 0.0 + + angle = acos(mousexdist / mouserad) + if mouseydist >= 0: + angle = TWOPI - angle + + return angle + + def _point_from_color(self, col): + # Simplifications for the corner cases. + if col == QtCore.Qt.black: + return self.point_b + elif col == QtCore.Qt.white: + return self.point_c + + # Find the x and y slopes + ab_deltax = self.point_b.x() - self.point_a.x() + ab_deltay = self.point_b.y() - self.point_a.y() + bc_deltax = self.point_c.x() - self.point_b.x() + bc_deltay = self.point_c.y() - self.point_b.y() + ac_deltax = self.point_c.x() - self.point_a.x() + ac_deltay = self.point_c.y() - self.point_a.y() + + # Extract the h,s,v values of col. + _, sat, val, _ = col.getHsv() + + # Find the line that passes through the triangle where the value + # is equal to our color's value. + p1 = self.point_a.x() + (ab_deltax * float(255 - val)) / 255.0 + q1 = self.point_a.y() + (ab_deltay * float(255 - val)) / 255.0 + p2 = self.point_b.x() + (bc_deltax * float(val)) / 255.0 + q2 = self.point_b.y() + (bc_deltay * float(val)) / 255.0 + + # Find the line that passes through the triangle where the + # saturation is equal to our color's value. + p3 = self.point_a.x() + (ac_deltax * float(255 - sat)) / 255.0 + q3 = self.point_a.y() + (ac_deltay * float(255 - sat)) / 255.0 + p4 = self.point_b.x() + q4 = self.point_b.y() + + # Find the intersection between these lines. + if p1 != p2: + a = (q2 - q1) / (p2 - p1) + c = (q4 - q3) / (p4 - p3) + b = q1 - a * p1 + d = q3 - c * p3 + + x = (d - b) / (a - c) + y = a * x + b + else: + x = p1 + p4_p3 = p4 - p3 + if p4_p3 == 0: + y = 0 + else: + y = q3 + (x - p3) * (q4 - q3) / p4_p3 + + return QtCore.QPointF(x, y) + + def _color_from_point(self, p): + # Find the outer radius of the hue gradient. + size_w = self.contentsRect().width() + size_h = self.contentsRect().height() + if size_w < size_h: + size = size_w + else: + size = size_h + outer_radius = (size - 1) / 2 + + # Find the center coordinates + cx = float(self.contentsRect().center().x()) + cy = float(self.contentsRect().center().y()) + + # Find the a, b and c from their angles, the center of the rect + # and the radius of the hue gradient donut. + inner_radius = outer_radius - (outer_radius / self.inner_radius_ratio) + pa = QtCore.QPointF( + cx + (cos(self.angle_a) * inner_radius), + cy - (sin(self.angle_a) * inner_radius) + ) + pb = QtCore.QPointF( + cx + (cos(self.angle_b) * inner_radius), + cy - (sin(self.angle_b) * inner_radius) + ) + pc = QtCore.QPointF( + cx + (cos(self.angle_c) * inner_radius), + cy - (sin(self.angle_c) * inner_radius) + ) + + # Find the hue value from the angle of the 'a' point. + angle = self.angle_a - PI / 2.0 + if angle < 0: + angle += TWOPI + hue = ( + 360 + - int(floor((360.0 * angle) / TWOPI)) + - self.hue_offset + ) % 360 + + # Create the color of the 'a' corner point. We know that b is + # black and c is white. + color = QtGui.QColor() + color.setHsv(hue, 255, 255) + + # See also drawTrigon(), which basically does exactly the same to + # determine all colors in the trigon. + p1 = Vertex(color, pa) + p2 = Vertex(QtCore.Qt.black, pb) + p3 = Vertex(QtCore.Qt.white, pc) + + # Make sure p1 is above p2, which is above p3. + if p1.point.y() > p2.point.y(): + p1, p2 = p2, p1 + if p1.point.y() > p3.point.y(): + p1, p3 = p3, p1 + if p2.point.y() > p3.point.y(): + p2, p3 = p3, p2 + + # Find the slopes of all edges in the trigon. All the three y + # deltas here are positive because of the above sorting. + p1p2ydist = p2.point.y() - p1.point.y() + p1p3ydist = p3.point.y() - p1.point.y() + p2p3ydist = p3.point.y() - p2.point.y() + p1p2xdist = p2.point.x() - p1.point.x() + p1p3xdist = p3.point.x() - p1.point.x() + p2p3xdist = p3.point.x() - p2.point.x() + + # The first x delta decides wether we have a lefty or a righty + # trigon. A lefty trigon has its tallest edge on the right hand + # side of the trigon. The righty trigon has it on its left side. + # This property determines wether the left or the right set of x + # coordinates will be continuous. + lefty = p1p2xdist < 0 + + # Find whether the selector's y is in the first or second shorty, + # counting from the top and downwards. This is used to find the + # color at the selector point. + firstshorty = (p.y() >= p1.point.y() and p.y() < p2.point.y()) + + # From the y value of the selector's position, find the left and + # right x values. + if lefty: + if firstshorty: + if (floor(p1p2ydist) != 0.0): + leftx = ( + p1.point.x() + + ((p1p2xdist * (p.y() - p1.point.y())) / p1p2ydist) + ) + else: + leftx = min(p1.point.x(), p2.point.x()) + + else: + if (floor(p2p3ydist) != 0.0): + leftx = ( + p2.point.x() + + (p2p3xdist * (p.y() - p2.point.y())) / p2p3ydist + ) + else: + leftx = min(p2.point.x(), p3.point.x()) + + rightx = ( + p1.point.x() + + ((p1p3xdist * (p.y() - p1.point.y())) / p1p3ydist) + ) + else: + leftx = ( + p1.point.x() + + ((p1p3xdist * (p.y() - p1.point.y())) / p1p3ydist) + ) + if firstshorty: + if floor(p1p2ydist) != 0.0: + rightx = ( + p1.point.x() + + ((p1p2xdist * (p.y() - p1.point.y())) / p1p2ydist) + ) + else: + rightx = max(p1.point.x(), p2.point.x()) + + else: + if floor(p2p3ydist) != 0.0: + rightx = ( + p2.point.x() + + ((p2p3xdist * (p.y() - p2.point.y())) / p2p3ydist) + ) + else: + rightx = max(p2.point.x(), p3.point.x()) + + # Find the r,g,b values of the points on the trigon's edges that + # are to the left and right of the selector. + if firstshorty: + if floor(p1p2ydist) != 0.0: + p_p1_ratio = (p.y() - p1.point.y()) / p1p2ydist + p2_p_ratio = (p2.point.y() - p.y()) / p1p2ydist + rshort = (p2.color.r * p_p1_ratio) + (p1.color.r * p2_p_ratio) + gshort = (p2.color.g * p_p1_ratio) + (p1.color.g * p2_p_ratio) + bshort = (p2.color.b * p_p1_ratio) + (p1.color.b * p2_p_ratio) + elif lefty: + if p1.point.x() <= p2.point.x(): + rshort = p1.color.r + gshort = p1.color.g + bshort = p1.color.b + else: + rshort = p2.color.r + gshort = p2.color.g + bshort = p2.color.b + + else: + if p1.point.x() > p2.point.x(): + rshort = p1.color.r + gshort = p1.color.g + bshort = p1.color.b + else: + rshort = p2.color.r + gshort = p2.color.g + bshort = p2.color.b + + else: + if floor(p2p3ydist) != 0.0: + p_p2_ratio = (p.y() - p2.point.y()) / p2p3ydist + p3_p_ratio = (p3.point.y() - p.y()) / p2p3ydist + rshort = (p3.color.r * p_p2_ratio) + (p2.color.r * p3_p_ratio) + gshort = (p3.color.g * p_p2_ratio) + (p2.color.g * p3_p_ratio) + bshort = (p3.color.b * p_p2_ratio) + (p2.color.b * p3_p_ratio) + elif lefty: + if p2.point.x() <= p3.point.x(): + rshort = p2.color.r + gshort = p2.color.g + bshort = p2.color.b + else: + rshort = p3.color.r + gshort = p3.color.g + bshort = p3.color.b + + else: + if p2.point.x() > p3.point.x(): + rshort = p2.color.r + gshort = p2.color.g + bshort = p2.color.b + else: + rshort = p3.color.r + gshort = p3.color.g + bshort = p3.color.b + + # p1p3ydist is never 0 + p_p1_ratio = (p.y() - p1.point.y()) / p1p3ydist + p3_p_ratio = (p3.point.y() - p.y()) / p1p3ydist + rlong = (p3.color.r * p_p1_ratio) + (p1.color.r * p3_p_ratio) + glong = (p3.color.g * p_p1_ratio) + (p1.color.g * p3_p_ratio) + blong = (p3.color.b * p_p1_ratio) + (p1.color.b * p3_p_ratio) + + # rshort,gshort,bshort is the color on one of the shortys. + # rlong,glong,blong is the color on the longy. So depending on + # wether we have a lefty trigon or not, we can determine which + # colors are on the left and right edge. + if lefty: + rl = rshort + gl = gshort + bl = bshort + rr = rlong + gr = glong + br = blong + else: + rl = rlong + gl = glong + bl = blong + rr = rshort + gr = gshort + br = bshort + + # Find the distance from the left x to the right x (xdist). Then + # find the distances from the selector to each of these (saxdist + # and saxdist2). These distances are used to find the color at + # the selector. + xdist = rightx - leftx + saxdist = p.x() - leftx + saxdist2 = xdist - saxdist + + # Now determine the r,g,b values of the selector using a linear + # approximation. + if xdist != 0.0: + r = (saxdist2 * rl / xdist) + (saxdist * rr / xdist) + g = (saxdist2 * gl / xdist) + (saxdist * gr / xdist) + b = (saxdist2 * bl / xdist) + (saxdist * br / xdist) + else: + # In theory, the left and right color will be equal here. But + # because of the loss of precision, we get an error on both + # colors. The best approximation we can get is from adding + # the two errors, which in theory will eliminate the error + # but in practise will only minimize it. + r = (rl + rr) / 2 + g = (gl + gr) / 2 + b = (bl + br) / 2 + + # Now floor the color components and fit them into proper + # boundaries. This again is to compensate for the error caused by + # loss of precision. + ri = int(floor(r)) + gi = int(floor(g)) + bi = int(floor(b)) + if ri < 0: + ri = 0 + elif ri > 255: + ri = 255 + + if gi < 0: + gi = 0 + elif gi > 255: + gi = 255 + + if bi < 0: + bi = 0 + elif bi > 255: + bi = 255 + + # Voila, we have the color at the point of the selector. + return QtGui.QColor(ri, gi, bi) + + def paint_bg(self): + bg_image = QtGui.QPixmap(self.contentsRect().size()) + bg_image.fill(QtCore.Qt.transparent) + self.bg_image = bg_image + + painter = QtGui.QPainter(self.bg_image) + + painter.setRenderHint(QtGui.QPainter.Antialiasing) + + hue_gradient = QtGui.QConicalGradient( + bg_image.rect().center(), 90 - self.hue_offset + ) + sat_val_gradient = QtGui.QConicalGradient( + bg_image.rect().center(), 90 - self.hue_offset + ) + + hue_color = QtGui.QColor() + sat_val_color = QtGui.QColor() + _, sat, val, _ = self.cur_color.getHsv() + + for idx, hue in self._hue_circle_range: + hue_color.setHsv(hue, 255, 255) + sat_val_color.setHsv(hue, sat, val) + + hue_gradient.setColorAt(idx, hue_color) + sat_val_gradient.setColorAt(idx, sat_val_color) + + inner_radius = self.outer_radius - ( + self.outer_radius / self.inner_radius_ratio + ) + half_radius = self.outer_radius - ( + (self.outer_radius - inner_radius) / 2 + ) + + hue_inner_radius_rect = QtCore.QRectF( + bg_image.rect().center().x() - inner_radius, + bg_image.rect().center().y() - inner_radius, + inner_radius * 2 + 1, + inner_radius * 2 + 1 + ) + hue_outer_radius_rect = QtCore.QRectF( + bg_image.rect().center().x() - half_radius - 1, + bg_image.rect().center().y() - half_radius - 1, + half_radius * 2 + 3, + half_radius * 2 + 3 + ) + sat_val_inner_radius_rect = QtCore.QRectF( + bg_image.rect().center().x() - half_radius, + bg_image.rect().center().y() - half_radius, + half_radius * 2 + 1, + half_radius * 2 + 1 + ) + sat_val_outer_radius_rect = QtCore.QRectF( + bg_image.rect().center().x() - self.outer_radius, + bg_image.rect().center().y() - self.outer_radius, + self.outer_radius * 2 + 1, + self.outer_radius * 2 + 1 + ) + hue_path = QtGui.QPainterPath() + hue_path.addEllipse(hue_inner_radius_rect) + hue_path.addEllipse(hue_outer_radius_rect) + + sat_val_path = QtGui.QPainterPath() + sat_val_path.addEllipse(sat_val_inner_radius_rect) + sat_val_path.addEllipse(sat_val_outer_radius_rect) + + painter.save() + painter.setClipPath(hue_path) + painter.fillRect(self.bg_image.rect(), hue_gradient) + painter.restore() + + painter.save() + painter.setClipPath(sat_val_path) + painter.fillRect(self.bg_image.rect(), sat_val_gradient) + painter.restore() + + painter.end() + + @staticmethod + def vlen(x, y): + return sqrt((x ** 2) + (y ** 2)) + + @staticmethod + def vprod(x1, y1, x2, y2): + return x1 * x2 + y1 * y2 + + @staticmethod + def _angle_between_angles(p, a1, a2): + if a1 > a2: + a2 += TWOPI + if p < PI: + p += TWOPI + + return p >= a1 and p < a2 + + @staticmethod + def _point_above_point(x, y, px, py, ax, ay, bx, by): + floored_ax = floor(ax) + floored_bx = floor(bx) + floored_ay = floor(ay) + floored_by = floor(by) + + if floored_ax == floored_bx: + # line is vertical + if floored_ay < floored_by: + return x < ax + elif floored_ay > floored_by: + return x > ax + return not (x == ax and y == ay) + + if floored_ax > floored_bx: + if floored_ay < floored_by: + # line is draw upright-to-downleft + return (floor(x) < floor(px) or floor(y) < floor(py)) + elif floored_ay > floored_by: + # line is draw downright-to-upleft + return (floor(x) > floor(px) or floor(y) < floor(py)) + # line is flat horizontal + return y < ay + + if floored_ay < floored_by: + # line is draw upleft-to-downright + return (floor(x) < floor(px) or floor(y) > floor(py)) + elif floored_ay > floored_by: + # line is draw downleft-to-upright + return (floor(x) > floor(px) or floor(y) > floor(py)) + # line is flat horizontal + return y > ay + + @staticmethod + def _point_in_line(x, y, ax, ay, bx, by): + if ax > bx: + if ay < by: + # line is draw upright-to-downleft + + # if (x,y) is in on or above the upper right point, + # return -1. + if y <= ay and x >= ax: + return -1 + + # if (x,y) is in on or below the lower left point, + # return 1. + if y >= by and x <= bx: + return 1 + else: + # line is draw downright-to-upleft + + # If the line is flat, only use the x coordinate. + if floor(ay) == floor(by): + # if (x is to the right of the rightmost point, + # return -1. otherwise if x is to the left of the + # leftmost point, return 1. + if x >= ax: + return -1 + elif x <= bx: + return 1 + else: + # if (x,y) is on or below the lower right point, + # return -1. + if y >= ay and x >= ax: + return -1 + + # if (x,y) is on or above the upper left point, return 1. + if y <= by and x <= bx: + return 1 + else: + if ay < by: + # line is draw upleft-to-downright + + # If (x,y) is on or above the upper left point, return -1. + if y <= ay and x <= ax: + return -1 + + # If (x,y) is on or below the lower right point, return 1. + if y >= by and x >= bx: + return 1 + else: + # line is draw downleft-to-upright + + # If the line is flat, only use the x coordinate. + if floor(ay) == floor(by): + if x <= ax: + return -1 + elif x >= bx: + return 1 + else: + # If (x,y) is on or below the lower left point, return -1. + if y >= ay and x <= ax: + return -1 + + # If (x,y) is on or above the upper right point, return 1. + if y <= by and x >= bx: + return 1 + + # No tests proved that (x,y) was outside [(ax,ay),(bx,by)], so we + # assume it's inside the line's bounds. + return 0 + + def _move_point_to_triangle(self, x, y, a, b, c): + # Let v1A be the vector from (x,y) to a. + # Let v2A be the vector from a to b. + # Find the angle alphaA between v1A and v2A. + v1xA = x - a.point.x() + v1yA = y - a.point.y() + v2xA = b.point.x() - a.point.x() + v2yA = b.point.y() - a.point.y() + vpA = self.vprod(v1xA, v1yA, v2xA, v2yA) + cosA = vpA / (self.vlen(v1xA, v1yA) * self.vlen(v2xA, v2yA)) + alphaA = acos(cosA) + + # Let v1B be the vector from x to b. + # Let v2B be the vector from b to c. + v1xB = x - b.point.x() + v1yB = y - b.point.y() + v2xB = c.point.x() - b.point.x() + v2yB = c.point.y() - b.point.y() + vpB = self.vprod(v1xB, v1yB, v2xB, v2yB) + cosB = vpB / (self.vlen(v1xB, v1yB) * self.vlen(v2xB, v2yB)) + alphaB = acos(cosB) + + # Let v1C be the vector from x to c. + # Let v2C be the vector from c back to a. + v1xC = x - c.point.x() + v1yC = y - c.point.y() + v2xC = a.point.x() - c.point.x() + v2yC = a.point.y() - c.point.y() + vpC = self.vprod(v1xC, v1yC, v2xC, v2yC) + cosC = vpC / (self.vlen(v1xC, v1yC) * self.vlen(v2xC, v2yC)) + alphaC = acos(cosC) + + # Find the radian angles between the (1,0) vector and the points + # A, B, C and (x,y). Use this information to determine which of + # the edges we should project (x,y) onto. + angleA = self._angle_at(a.point, self.contentsRect()) + angleB = self._angle_at(b.point, self.contentsRect()) + angleC = self._angle_at(c.point, self.contentsRect()) + angleP = self._angle_at(QtCore.QPointF(x, y), self.contentsRect()) + + # If (x,y) is in the a-b area, project onto the a-b vector. + if self._angle_between_angles(angleP, angleA, angleB): + # Find the distance from (x,y) to a. Then use the slope of + # the a-b vector with this distance and the angle between a-b + # and a-(x,y) to determine the point of intersection of the + # perpendicular projection from (x,y) onto a-b. + pdist = sqrt( + ((x - a.point.x()) ** 2) + ((y - a.point.y()) ** 2) + ) + + # the length of all edges is always > 0 + p0x = ( + a.point.x() + + ((b.point.x() - a.point.x()) / self.vlen(v2xB, v2yB)) + * cos(alphaA) * pdist + ) + p0y = ( + a.point.y() + + ((b.point.y() - a.point.y()) / self.vlen(v2xB, v2yB)) + * cos(alphaA) * pdist + ) + + # If (x,y) is above the a-b line, which basically means it's + # outside the triangle, then return its projection onto a-b. + if self._point_above_point( + x, y, + p0x, p0y, + a.point.x(), a.point.y(), + b.point.x(), b.point.y() + ): + # If the projection is "outside" a, return a. If it is + # outside b, return b. Otherwise return the projection. + n = self._point_in_line( + p0x, p0y, + a.point.x(), a.point.y(), + b.point.x(), b.point.y() + ) + if n < 0: + return a.point + elif n > 0: + return b.point + + return QtCore.QPointF(p0x, p0y) + + elif self._angle_between_angles(angleP, angleB, angleC): + # If (x,y) is in the b-c area, project onto the b-c vector. + pdist = sqrt( + ((x - b.point.x()) ** 2) + ((y - b.point.y()) ** 2) + ) + + # the length of all edges is always > 0 + p0x = ( + b.point.x() + + ((c.point.x() - b.point.x()) / self.vlen(v2xC, v2yC)) + * cos(alphaB) * pdist + ) + p0y = ( + b.point.y() + + ((c.point.y() - b.point.y()) / self.vlen(v2xC, v2yC)) + * cos(alphaB) + * pdist + ) + + if self._point_above_point( + x, y, + p0x, p0y, + b.point.x(), b.point.y(), + c.point.x(), c.point.y() + ): + n = self._point_in_line( + p0x, p0y, + b.point.x(), b.point.y(), + c.point.x(), c.point.y() + ) + if n < 0: + return b.point + elif n > 0: + return c.point + return QtCore.QPointF(p0x, p0y) + + elif self._angle_between_angles(angleP, angleC, angleA): + # If (x,y) is in the c-a area, project onto the c-a vector. + pdist = sqrt( + ((x - c.point.x()) ** 2) + ((y - c.point.y()) ** 2) + ) + + # the length of all edges is always > 0 + p0x = ( + c.point.x() + + ((a.point.x() - c.point.x()) / self.vlen(v2xA, v2yA)) + * cos(alphaC) + * pdist + ) + p0y = ( + c.point.y() + + ((a.point.y() - c.point.y()) / self.vlen(v2xA, v2yA)) + * cos(alphaC) * pdist + ) + + if self._point_above_point( + x, y, + p0x, p0y, + c.point.x(), c.point.y(), + a.point.x(), a.point.y() + ): + n = self._point_in_line( + p0x, p0y, + c.point.x(), c.point.y(), + a.point.x(), a.point.y() + ) + if n < 0: + return c.point + elif n > 0: + return a.point + return QtCore.QPointF(p0x, p0y) + + # (x,y) is inside the triangle (inside a-b, b-c and a-c). + return QtCore.QPointF(x, y) diff --git a/openpype/widgets/color_widgets/color_view.py b/openpype/widgets/color_widgets/color_view.py new file mode 100644 index 0000000000..8644281a1d --- /dev/null +++ b/openpype/widgets/color_widgets/color_view.py @@ -0,0 +1,83 @@ +from Qt import QtWidgets, QtCore, QtGui + + +def draw_checkerboard_tile(piece_size=None, color_1=None, color_2=None): + if piece_size is None: + piece_size = 7 + + if color_1 is None: + color_1 = QtGui.QColor(188, 188, 188) + + if color_2 is None: + color_2 = QtGui.QColor(90, 90, 90) + + pix = QtGui.QPixmap(piece_size * 2, piece_size * 2) + pix_painter = QtGui.QPainter(pix) + + rect = QtCore.QRect( + 0, 0, piece_size, piece_size + ) + pix_painter.fillRect(rect, color_1) + rect.moveTo(piece_size, piece_size) + pix_painter.fillRect(rect, color_1) + rect.moveTo(piece_size, 0) + pix_painter.fillRect(rect, color_2) + rect.moveTo(0, piece_size) + pix_painter.fillRect(rect, color_2) + pix_painter.end() + + return pix + + +class ColorViewer(QtWidgets.QWidget): + def __init__(self, parent=None): + super(ColorViewer, self).__init__(parent) + + self.setMinimumSize(10, 10) + + self.alpha = 255 + self.actual_pen = QtGui.QPen() + self.actual_color = QtGui.QColor() + self._checkerboard = None + + def checkerboard(self): + if not self._checkerboard: + self._checkerboard = draw_checkerboard_tile(4) + return self._checkerboard + + def color(self): + return self.actual_color + + def set_color(self, color): + if color == self.actual_color: + return + + # Create copy of entered color + self.actual_color = QtGui.QColor(color) + # Set alpha by current alpha value + self.actual_color.setAlpha(self.alpha) + # Repaint + self.update() + + def set_alpha(self, alpha): + if alpha == self.alpha: + return + # Change alpha of current color + self.actual_color.setAlpha(alpha) + # Store the value + self.alpha = alpha + # Repaint + self.update() + + def paintEvent(self, event): + clip_rect = event.rect() + rect = clip_rect.adjusted(0, 0, -1, -1) + + painter = QtGui.QPainter(self) + painter.setClipRect(clip_rect) + painter.drawTiledPixmap(rect, self.checkerboard()) + painter.setBrush(self.actual_color) + pen = QtGui.QPen(QtGui.QColor(255, 255, 255, 67)) + painter.setPen(pen) + painter.drawRect(rect) + painter.end() diff --git a/openpype/widgets/color_widgets/eyedropper.png b/openpype/widgets/color_widgets/eyedropper.png new file mode 100644 index 0000000000..baf6209e0b Binary files /dev/null and b/openpype/widgets/color_widgets/eyedropper.png differ diff --git a/pyproject.toml b/pyproject.toml index f7eeafd04f..7ba869e50e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.0.0-rc.5" +version = "3.0.0-rc.6" description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" diff --git a/start.py b/start.py index 660d0c9006..7b7e6885e4 100644 --- a/start.py +++ b/start.py @@ -6,10 +6,11 @@ Bootstrapping process of OpenPype is as follows: `OPENPYPE_PATH` is checked for existence - either one from environment or from user settings. Precedence takes the one set by environment. -On this path we try to find OpenPype in directories version string in their names. -For example: `openpype-v3.0.1-foo` is valid name, or even `foo_3.0.2` - as long -as version can be determined from its name _AND_ file `openpype/openpype/version.py` -can be found inside, it is considered OpenPype installation. +On this path we try to find OpenPype in directories version string in their +names. For example: `openpype-v3.0.1-foo` is valid name, or +even `foo_3.0.2` - as long as version can be determined from its name +_AND_ file `openpype/openpype/version.py` can be found inside, it is +considered OpenPype installation. If no OpenPype repositories are found in `OPENPYPE_PATH` (user data dir) then **Igniter** (OpenPype setup tool) will launch its GUI. @@ -20,19 +21,19 @@ appdata dir in user home and extract it there. Version will be determined by version specified in OpenPype module. If OpenPype repository directories are found in default install location -(user data dir) or in `OPENPYPE_PATH`, it will get list of those dirs there and -use latest one or the one specified with optional `--use-version` command -line argument. If the one specified doesn't exist then latest available -version will be used. All repositories in that dir will be added +(user data dir) or in `OPENPYPE_PATH`, it will get list of those dirs +there and use latest one or the one specified with optional `--use-version` +command line argument. If the one specified doesn't exist then latest +available version will be used. All repositories in that dir will be added to `sys.path` and `PYTHONPATH`. -If OpenPype is live (not frozen) then current version of OpenPype module will be -used. All directories under `repos` will be added to `sys.path` and +If OpenPype is live (not frozen) then current version of OpenPype module +will be used. All directories under `repos` will be added to `sys.path` and `PYTHONPATH`. -OpenPype depends on connection to `MongoDB`_. You can specify MongoDB connection -string via `OPENPYPE_MONGO` set in environment or it can be set in user -settings or via **Igniter** GUI. +OpenPype depends on connection to `MongoDB`_. You can specify MongoDB +connection string via `OPENPYPE_MONGO` set in environment or it can be set +in user settings or via **Igniter** GUI. So, bootstrapping OpenPype looks like this:: @@ -99,7 +100,6 @@ import traceback import subprocess import site from pathlib import Path -import platform # OPENPYPE_ROOT is variable pointing to build (or code) directory @@ -112,17 +112,6 @@ if not getattr(sys, 'frozen', False): else: OPENPYPE_ROOT = os.path.dirname(sys.executable) - # FIX #1469: Certificates from certifi are not available in some - # macos builds, so connection to ftrack/mongo will fail with - # unable to verify certificate issuer error. This will add certifi - # certificates so ssl can see them. - # WARNING: this can break stuff if custom certificates are used. In that - # case they need to be merged to certificate bundle and SSL_CERT_FILE - # should point to them. - if not os.getenv("SSL_CERT_FILE") and platform.system().lower() == "darwin": # noqa: E501 - ssl_cert_file = Path(OPENPYPE_ROOT) / "dependencies" / "certifi" / "cacert.pem" # noqa: E501 - os.environ["SSL_CERT_FILE"] = ssl_cert_file.as_posix() - # add dependencies folder to sys.pat for frozen code frozen_libs = os.path.normpath( os.path.join(OPENPYPE_ROOT, "dependencies") @@ -135,6 +124,41 @@ else: paths.append(frozen_libs) os.environ["PYTHONPATH"] = os.pathsep.join(paths) + +import blessed # noqa: E402 +import certifi # noqa: E402 + + +term = blessed.Terminal() + + +def _print(message: str): + if message.startswith("!!! "): + print("{}{}".format(term.orangered2("!!! "), message[4:])) + if message.startswith(">>> "): + print("{}{}".format(term.aquamarine3(">>> "), message[4:])) + if message.startswith("--- "): + print("{}{}".format(term.darkolivegreen3("--- "), message[4:])) + if message.startswith(" "): + print("{}{}".format(term.darkseagreen3(" "), message[4:])) + if message.startswith("*** "): + print("{}{}".format(term.gold("*** "), message[4:])) + if message.startswith(" - "): + print("{}{}".format(term.wheat(" - "), message[4:])) + if message.startswith(" . "): + print("{}{}".format(term.tan(" . "), message[4:])) + + +# if SSL_CERT_FILE is not set prior to OpenPype launch, we set it to point +# to certifi bundle to make sure we have reasonably new CA certificates. +if os.getenv("SSL_CERT_FILE") and \ + os.getenv("SSL_CERT_FILE") != certifi.where(): + _print("--- your system is set to use custom CA certificate bundle.") +else: + ssl_cert_file = certifi.where() + os.environ["SSL_CERT_FILE"] = ssl_cert_file + + import igniter # noqa: E402 from igniter import BootstrapRepos # noqa: E402 from igniter.tools import ( @@ -197,7 +221,7 @@ def run(arguments: list, env: dict = None) -> int: p = subprocess.Popen(interpreter, env=env) p.wait() - print(f">>> done [{p.returncode}]") + _print(f">>> done [{p.returncode}]") return p.returncode @@ -278,11 +302,12 @@ def _process_arguments() -> tuple: use_staging = False for arg in sys.argv: if arg == "--use-version": - print("!!! Please use option --use-version like:") - print(" --use-version=3.0.0") + _print("!!! Please use option --use-version like:") + _print(" --use-version=3.0.0") sys.exit(1) - m = re.search(r"--use-version=(?P\d+\.\d+\.\d*.+?)", arg) + m = re.search( + r"--use-version=(?P\d+\.\d+\.\d+(?:\S*)?)", arg) if m and m.group('version'): use_version = m.group('version') sys.argv.remove(arg) @@ -336,12 +361,12 @@ def _determine_mongodb() -> str: if openpype_mongo: result, msg = validate_mongo_connection(openpype_mongo) if not result: - print(msg) + _print(msg) openpype_mongo = None if not openpype_mongo: - print("*** No DB connection string specified.") - print("--- launching setup UI ...") + _print("*** No DB connection string specified.") + _print("--- launching setup UI ...") result = igniter.open_dialog() if result == 0: @@ -366,7 +391,7 @@ def _initialize_environment(openpype_version: OpenPypeVersion) -> None: version_path.as_posix() ) # inject version to Python environment (sys.path, ...) - print(">>> Injecting OpenPype version to running environment ...") + _print(">>> Injecting OpenPype version to running environment ...") bootstrap.add_paths_from_directory(version_path) # Additional sys paths related to OPENPYPE_REPOS_ROOT directory @@ -414,6 +439,7 @@ def _find_frozen_openpype(use_version: str = None, (if requested). """ + version_path = None openpype_version = None openpype_versions = bootstrap.find_openpype(include_zips=True, staging=use_staging) @@ -433,9 +459,8 @@ def _find_frozen_openpype(use_version: str = None, if local_version == openpype_versions[-1]: os.environ["OPENPYPE_TRYOUT"] = "1" openpype_versions = [] - else: - print("!!! Warning: cannot determine current running version.") + _print("!!! Warning: cannot determine current running version.") if not os.getenv("OPENPYPE_TRYOUT"): try: @@ -443,8 +468,8 @@ def _find_frozen_openpype(use_version: str = None, openpype_version = openpype_versions[-1] except IndexError: # no OpenPype version found, run Igniter and ask for them. - print('*** No OpenPype versions found.') - print("--- launching setup UI ...") + _print('*** No OpenPype versions found.') + _print("--- launching setup UI ...") import igniter return_code = igniter.open_dialog() if return_code == 2: @@ -452,25 +477,25 @@ def _find_frozen_openpype(use_version: str = None, if return_code == 3: # run OpenPype after installation - print('>>> Finding OpenPype again ...') + _print('>>> Finding OpenPype again ...') openpype_versions = bootstrap.find_openpype( staging=use_staging) try: openpype_version = openpype_versions[-1] except IndexError: - print(("!!! Something is wrong and we didn't " + _print(("!!! Something is wrong and we didn't " "found it again.")) sys.exit(1) elif return_code != 2: - print(f" . finished ({return_code})") + _print(f" . finished ({return_code})") sys.exit(return_code) if not openpype_versions: # no openpype versions found anyway, lets use then the one # shipped with frozen OpenPype if not os.getenv("OPENPYPE_TRYOUT"): - print("*** Still no luck finding OpenPype.") - print(("*** We'll try to use the one coming " + _print("*** Still no luck finding OpenPype.") + _print(("*** We'll try to use the one coming " "with OpenPype installation.")) version_path = _bootstrap_from_code(use_version) openpype_version = OpenPypeVersion( @@ -480,17 +505,25 @@ def _find_frozen_openpype(use_version: str = None, return version_path # get path of version specified in `--use-version` - version_path = BootstrapRepos.get_version_path_from_list( - use_version, openpype_versions) + local_version = bootstrap.get_version(OPENPYPE_ROOT) + if use_version and use_version != local_version: + # force the one user has selected + openpype_version = None + openpype_versions = bootstrap.find_openpype(include_zips=True, + staging=use_staging) + v: OpenPypeVersion + found = [v for v in openpype_versions if str(v) == use_version] + if found: + openpype_version = sorted(found)[-1] + if not openpype_version: + _print(f"!!! requested version {use_version} was not found.") + if openpype_versions: + _print(" - found: ") + for v in sorted(openpype_versions): + _print(f" - {v}: {v.path}") - if not version_path: - if use_version is not None and openpype_version: - print(("!!! Specified version was not found, using " - "latest available")) - # specified version was not found so use latest detected. - version_path = openpype_version.path - print(f">>> Using version [ {openpype_version} ]") - print(f" From {version_path}") + _print(f" - local version {local_version}") + sys.exit(1) # test if latest detected is installed (in user data dir) is_inside = False @@ -508,11 +541,11 @@ def _find_frozen_openpype(use_version: str = None, openpype_version, force=True) if openpype_version.path.is_file(): - print(">>> Extracting zip file ...") + _print(">>> Extracting zip file ...") try: version_path = bootstrap.extract_openpype(openpype_version) except OSError as e: - print("!!! failed: {}".format(str(e))) + _print("!!! failed: {}".format(str(e))) sys.exit(1) else: # cleanup zip after extraction @@ -521,7 +554,7 @@ def _find_frozen_openpype(use_version: str = None, openpype_version.path = version_path _initialize_environment(openpype_version) - return version_path + return openpype_version.path def _bootstrap_from_code(use_version): @@ -536,36 +569,53 @@ def _bootstrap_from_code(use_version): """ # run through repos and add them to `sys.path` and `PYTHONPATH` # set root + _openpype_root = OPENPYPE_ROOT if getattr(sys, 'frozen', False): - local_version = bootstrap.get_version(Path(OPENPYPE_ROOT)) - print(f" - running version: {local_version}") + local_version = bootstrap.get_version(Path(_openpype_root)) + _print(f" - running version: {local_version}") assert local_version else: # get current version of OpenPype local_version = bootstrap.get_local_live_version() - os.environ["OPENPYPE_VERSION"] = local_version if use_version and use_version != local_version: + version_to_use = None openpype_versions = bootstrap.find_openpype(include_zips=True) - version_path = BootstrapRepos.get_version_path_from_list( - use_version, openpype_versions) - if version_path: - # use specified - bootstrap.add_paths_from_directory(version_path) - os.environ["OPENPYPE_VERSION"] = use_version - else: - version_path = OPENPYPE_ROOT + v: OpenPypeVersion + found = [v for v in openpype_versions if str(v) == use_version] + if found: + version_to_use = sorted(found)[-1] - repos = os.listdir(os.path.join(OPENPYPE_ROOT, "repos")) - repos = [os.path.join(OPENPYPE_ROOT, "repos", repo) for repo in repos] + if version_to_use: + # use specified + if version_to_use.path.is_file(): + version_to_use.path = bootstrap.extract_openpype( + version_to_use) + bootstrap.add_paths_from_directory(version_to_use.path) + os.environ["OPENPYPE_VERSION"] = use_version + version_path = version_to_use.path + os.environ["OPENPYPE_REPOS_ROOT"] = (version_path / "openpype").as_posix() # noqa: E501 + _openpype_root = version_to_use.path.as_posix() + else: + _print(f"!!! requested version {use_version} was not found.") + if openpype_versions: + _print(" - found: ") + for v in sorted(openpype_versions): + _print(f" - {v}: {v.path}") + + _print(f" - local version {local_version}") + sys.exit(1) + else: + os.environ["OPENPYPE_VERSION"] = local_version + version_path = Path(_openpype_root) + os.environ["OPENPYPE_REPOS_ROOT"] = _openpype_root + + repos = os.listdir(os.path.join(_openpype_root, "repos")) + repos = [os.path.join(_openpype_root, "repos", repo) for repo in repos] # add self to python paths - repos.insert(0, OPENPYPE_ROOT) + repos.insert(0, _openpype_root) for repo in repos: sys.path.insert(0, repo) - - # Set OPENPYPE_REPOS_ROOT to code root - os.environ["OPENPYPE_REPOS_ROOT"] = OPENPYPE_ROOT - # add venv 'site-packages' to PYTHONPATH python_path = os.getenv("PYTHONPATH", "") split_paths = python_path.split(os.pathsep) @@ -580,11 +630,11 @@ def _bootstrap_from_code(use_version): # point to same hierarchy from code and from frozen OpenPype additional_paths = [ # add OpenPype tools - os.path.join(OPENPYPE_ROOT, "openpype", "tools"), + os.path.join(_openpype_root, "openpype", "tools"), # add common OpenPype vendor # (common for multiple Python interpreter versions) os.path.join( - OPENPYPE_ROOT, + _openpype_root, "openpype", "vendor", "python", @@ -597,7 +647,7 @@ def _bootstrap_from_code(use_version): os.environ["PYTHONPATH"] = os.pathsep.join(split_paths) - return Path(version_path) + return version_path def boot(): @@ -624,6 +674,10 @@ def boot(): use_version, use_staging = _process_arguments() + if os.getenv("OPENPYPE_VERSION"): + use_staging = "staging" in os.getenv("OPENPYPE_VERSION") + use_version = os.getenv("OPENPYPE_VERSION") + # ------------------------------------------------------------------------ # Determine mongodb connection # ------------------------------------------------------------------------ @@ -632,7 +686,7 @@ def boot(): openpype_mongo = _determine_mongodb() except RuntimeError as e: # without mongodb url we are done for. - print(f"!!! {e}") + _print(f"!!! {e}") sys.exit(1) os.environ["OPENPYPE_MONGO"] = openpype_mongo @@ -642,7 +696,7 @@ def boot(): # find its versions there and bootstrap them. openpype_path = get_openpype_path_from_db(openpype_mongo) if not openpype_path: - print("*** Cannot get OpenPype path from database.") + _print("*** Cannot get OpenPype path from database.") if not os.getenv("OPENPYPE_PATH") and openpype_path: os.environ["OPENPYPE_PATH"] = openpype_path @@ -658,7 +712,7 @@ def boot(): version_path = _find_frozen_openpype(use_version, use_staging) except RuntimeError as e: # no version to run - print(f"!!! {e}") + _print(f"!!! {e}") sys.exit(1) else: version_path = _bootstrap_from_code(use_version) @@ -683,13 +737,13 @@ def boot(): except KeyError: pass - print(">>> loading environments ...") + _print(">>> loading environments ...") # Avalon environments must be set before avalon module is imported - print(" - for Avalon ...") + _print(" - for Avalon ...") set_avalon_environments() - print(" - global OpenPype ...") + _print(" - global OpenPype ...") set_openpype_global_environments() - print(" - for modules ...") + _print(" - for modules ...") set_modules_environments() from openpype import cli @@ -719,7 +773,7 @@ def boot(): cli.main(obj={}, prog_name="openpype") except Exception: # noqa exc_info = sys.exc_info() - print("!!! OpenPype crashed:") + _print("!!! OpenPype crashed:") traceback.print_exception(*exc_info) sys.exit(1) diff --git a/tools/build.ps1 b/tools/build.ps1 index d9fef0f471..c8c2f392ad 100644 --- a/tools/build.ps1 +++ b/tools/build.ps1 @@ -175,9 +175,9 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) { Write-Host ">>> " -NoNewline -ForegroundColor green Write-Host "Cleaning cache files ... " -NoNewline -Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Remove-Item -Force -Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Remove-Item -Force -Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Remove-Item -Force -Recurse +Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force +Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force +Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force -Recurse Write-Host "OK" -ForegroundColor green Write-Host ">>> " -NoNewline -ForegroundColor green diff --git a/tools/build.sh b/tools/build.sh index ccd97ea4c1..aa8f0121ea 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -122,7 +122,8 @@ clean_pyc () { local path path=$openpype_root echo -e "${BIGreen}>>>${RST} Cleaning pyc at [ ${BIWhite}$path${RST} ] ... \c" - find "$path" -regex '^.*\(__pycache__\|\.py[co]\)$' -delete + find "$path" -path ./build -prune -o -regex '^.*\(__pycache__\|\.py[co]\)$' -delete + echo -e "${BIGreen}DONE${RST}" } diff --git a/tools/create_env.ps1 b/tools/create_env.ps1 index 7ada92c1e8..94a91ce48f 100644 --- a/tools/create_env.ps1 +++ b/tools/create_env.ps1 @@ -76,16 +76,20 @@ print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1])) Set-Location -Path $current_dir Exit-WithCode 1 } - # We are supporting python 3.6 and up - if(($matches[1] -lt 3) -or ($matches[2] -lt 7)) { + # We are supporting python 3.7 only + if (($matches[1] -lt 3) -or ($matches[2] -lt 7)) { Write-Host "FAILED Version [ $p ] is old and unsupported" -ForegroundColor red Set-Location -Path $current_dir Exit-WithCode 1 + } elseif (($matches[1] -eq 3) -and ($matches[2] -gt 7)) { + Write-Host "WARNING Version [ $p ] is unsupported, use at your own risk." -ForegroundColor yellow + Write-Host "*** " -NoNewline -ForegroundColor yellow + Write-Host "OpenPype supports only Python 3.7" -ForegroundColor white + } else { + Write-Host "OK [ $p ]" -ForegroundColor green } - Write-Host "OK [ $p ]" -ForegroundColor green } - $current_dir = Get-Location $script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent $openpype_root = (Get-Item $script_dir).parent.FullName diff --git a/tools/create_env.sh b/tools/create_env.sh index d6a6828718..226a26e199 100755 --- a/tools/create_env.sh +++ b/tools/create_env.sh @@ -126,7 +126,7 @@ clean_pyc () { local path path=$openpype_root echo -e "${BIGreen}>>>${RST} Cleaning pyc at [ ${BIWhite}$path${RST} ] ... \c" - find "$path" -regex '^.*\(__pycache__\|\.py[co]\)$' -delete + find "$path" -path ./build -prune -o -regex '^.*\(__pycache__\|\.py[co]\)$' -delete echo -e "${BIGreen}DONE${RST}" } diff --git a/tools/create_zip.ps1 b/tools/create_zip.ps1 index a34af89159..1a7520eb11 100644 --- a/tools/create_zip.ps1 +++ b/tools/create_zip.ps1 @@ -98,9 +98,9 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) { Write-Host ">>> " -NoNewline -ForegroundColor green Write-Host "Cleaning cache files ... " -NoNewline -Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Remove-Item -Force -Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Remove-Item -Force -Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Remove-Item -Force -Recurse +Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force +Get-ChildItem $openpype_root -Filter "*.pyo" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force +Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse| Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force -Recurse Write-Host "OK" -ForegroundColor green Write-Host ">>> " -NoNewline -ForegroundColor green diff --git a/tools/create_zip.sh b/tools/create_zip.sh index adaf9431a7..ec0276b040 100755 --- a/tools/create_zip.sh +++ b/tools/create_zip.sh @@ -89,23 +89,6 @@ detect_python () { fi } -############################################################################## -# Clean pyc files in specified directory -# Globals: -# None -# Arguments: -# Optional path to clean -# Returns: -# None -############################################################################### -clean_pyc () { - local path - path=$openpype_root - echo -e "${BIGreen}>>>${RST} Cleaning pyc at [ ${BIWhite}$path${RST} ] ... \c" - find "$path" -regex '^.*\(__pycache__\|\.py[co]\)$' -delete - echo -e "${BIGreen}DONE${RST}" -} - ############################################################################## # Return absolute path # Globals: diff --git a/tools/run_project_manager.ps1 b/tools/run_project_manager.ps1 index 67c2d2eb5e..9886a80316 100644 --- a/tools/run_project_manager.ps1 +++ b/tools/run_project_manager.ps1 @@ -10,9 +10,51 @@ PS> .\run_project_manager.ps1 #> + +$art = @" + + . . .. . .. + _oOOP3OPP3Op_. . + .PPpo~. .. ~2p. .. .... . . + .Ppo . .pPO3Op.. . O:. . . . + .3Pp . oP3'. 'P33. . 4 .. . . . .. . . . + .~OP 3PO. .Op3 : . .. _____ _____ _____ + .P3O . oP3oP3O3P' . . . . / /./ /./ / + O3:. O3p~ . .:. . ./____/./____/ /____/ + 'P . 3p3. oP3~. ..P:. . . .. . . .. . . . + . ': . Po' .Opo'. .3O. . o[ by Pype Club ]]]==- - - . . + . '_ .. . . _OP3.. . .https://openpype.io.. . + ~P3.OPPPO3OP~ . .. . + . ' '. . .. . . . .. . + +"@ + +Write-Host $art -ForegroundColor DarkGreen + $current_dir = Get-Location $script_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent $openpype_root = (Get-Item $script_dir).parent.FullName + +$env:_INSIDE_OPENPYPE_TOOL = "1" + +# make sure Poetry is in PATH +if (-not (Test-Path 'env:POETRY_HOME')) { + $env:POETRY_HOME = "$openpype_root\.poetry" +} +$env:PATH = "$($env:PATH);$($env:POETRY_HOME)\bin" + Set-Location -Path $openpype_root + +Write-Host ">>> " -NoNewline -ForegroundColor Green +Write-Host "Reading Poetry ... " -NoNewline +if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) { + Write-Host "NOT FOUND" -ForegroundColor Yellow + Write-Host "*** " -NoNewline -ForegroundColor Yellow + Write-Host "We need to install Poetry create virtual env first ..." + & "$openpype_root\tools\create_env.ps1" +} else { + Write-Host "OK" -ForegroundColor Green +} + & poetry run python "$($openpype_root)\start.py" projectmanager Set-Location -Path $current_dir diff --git a/tools/run_projectmanager.sh b/tools/run_projectmanager.sh new file mode 100755 index 0000000000..312f321d67 --- /dev/null +++ b/tools/run_projectmanager.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +# Run OpenPype Settings GUI + + +art () { + cat <<-EOF + + . . .. . .. + _oOOP3OPP3Op_. . + .PPpo~· ·· ~2p. ·· ···· · · + ·Ppo · .pPO3Op.· · O:· · · · + .3Pp · oP3'· 'P33· · 4 ·· · · · ·· · · · + ·~OP 3PO· .Op3 : · ·· _____ _____ _____ + ·P3O · oP3oP3O3P' · · · · / /·/ /·/ / + O3:· O3p~ · ·:· · ·/____/·/____/ /____/ + 'P · 3p3· oP3~· ·.P:· · · ·· · · ·· · · · + · ': · Po' ·Opo'· .3O· . o[ by Pype Club ]]]==- - - · · + · '_ .. · . _OP3·· · ·https://openpype.io·· · + ~P3·OPPPO3OP~ · ·· · + · ' '· · ·· · · · ·· · + +EOF +} + +# Colors for terminal + +RST='\033[0m' # Text Reset + +# Regular Colors +Black='\033[0;30m' # Black +Red='\033[0;31m' # Red +Green='\033[0;32m' # Green +Yellow='\033[0;33m' # Yellow +Blue='\033[0;34m' # Blue +Purple='\033[0;35m' # Purple +Cyan='\033[0;36m' # Cyan +White='\033[0;37m' # White + +# Bold +BBlack='\033[1;30m' # Black +BRed='\033[1;31m' # Red +BGreen='\033[1;32m' # Green +BYellow='\033[1;33m' # Yellow +BBlue='\033[1;34m' # Blue +BPurple='\033[1;35m' # Purple +BCyan='\033[1;36m' # Cyan +BWhite='\033[1;37m' # White + +# Bold High Intensity +BIBlack='\033[1;90m' # Black +BIRed='\033[1;91m' # Red +BIGreen='\033[1;92m' # Green +BIYellow='\033[1;93m' # Yellow +BIBlue='\033[1;94m' # Blue +BIPurple='\033[1;95m' # Purple +BICyan='\033[1;96m' # Cyan +BIWhite='\033[1;97m' # White + + +############################################################################## +# Return absolute path +# Globals: +# None +# Arguments: +# Path to resolve +# Returns: +# None +############################################################################### +realpath () { + echo $(cd $(dirname "$1"); pwd)/$(basename "$1") +} + +# Main +main () { + + # Directories + openpype_root=$(realpath $(dirname $(dirname "${BASH_SOURCE[0]}"))) + + _inside_openpype_tool="1" + + # make sure Poetry is in PATH + if [[ -z $POETRY_HOME ]]; then + export POETRY_HOME="$openpype_root/.poetry" + fi + export PATH="$POETRY_HOME/bin:$PATH" + + pushd "$openpype_root" > /dev/null || return > /dev/null + + echo -e "${BIGreen}>>>${RST} Reading Poetry ... \c" + if [ -f "$POETRY_HOME/bin/poetry" ]; then + echo -e "${BIGreen}OK${RST}" + else + echo -e "${BIYellow}NOT FOUND${RST}" + echo -e "${BIYellow}***${RST} We need to install Poetry and virtual env ..." + . "$openpype_root/tools/create_env.sh" || { echo -e "${BIRed}!!!${RST} Poetry installation failed"; return; } + fi + + echo -e "${BIGreen}>>>${RST} Generating zip from current sources ..." + poetry run python "$openpype_root/start.py" projectmanager +} + +main diff --git a/tools/run_tests.ps1 b/tools/run_tests.ps1 index 30e1f29e59..a6882e2a09 100644 --- a/tools/run_tests.ps1 +++ b/tools/run_tests.ps1 @@ -94,8 +94,8 @@ if (-not (Test-Path -PathType Container -Path "$openpype_root\.poetry\bin")) { Write-Host ">>> " -NoNewline -ForegroundColor green Write-Host "Cleaning cache files ... " -NoNewline -Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Remove-Item -Force -Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Remove-Item -Force -Recurse +Get-ChildItem $openpype_root -Filter "*.pyc" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force +Get-ChildItem $openpype_root -Filter "__pycache__" -Force -Recurse | Where-Object { $_.FullName -inotmatch 'build' } | Remove-Item -Force -Recurse Write-Host "OK" -ForegroundColor green Write-Host ">>> " -NoNewline -ForegroundColor green diff --git a/tools/run_tests.sh b/tools/run_tests.sh index 3620ebc0e5..90977edc83 100755 --- a/tools/run_tests.sh +++ b/tools/run_tests.sh @@ -70,7 +70,7 @@ clean_pyc () { local path path=$openpype_root echo -e "${BIGreen}>>>${RST} Cleaning pyc at [ ${BIWhite}$path${RST} ] ... \c" - find "$path" -regex '^.*\(__pycache__\|\.py[co]\)$' -delete + find "$path" -path ./build -prune -o -regex '^.*\(__pycache__\|\.py[co]\)$' -delete echo -e "${BIGreen}DONE${RST}" } diff --git a/website/docs/admin_distribute.md b/website/docs/admin_distribute.md index b0ab71e2f3..b574a21cb2 100644 --- a/website/docs/admin_distribute.md +++ b/website/docs/admin_distribute.md @@ -41,10 +41,26 @@ version to run for the artist, until a higher version is detected in the update #### Manual Updates If for some reason you don't want to use the automatic updates, you can distribute your -zips manually. Your artist will then have to unpack them to the correct place on their disk. +zips manually. Your artist will then have to put them to the correct place on their disk. +Zips will be automatically unzipped there. The default locations are: -- Windows: `C:\Users\%USERNAME%\AppData\Local\pypeclub\openpype` -- Linux: ` ` -- Mac: ` ` +- Windows: `%LOCALAPPDATA%\pypeclub\openpype` +- Linux: `~/.local/share/pypeclub/openpype` +- Mac: `~/Library/Application Support/pypeclub/openpype` + + +### Staging vs. Production +You can have version of OpenPype with experimental features you want to try somewhere but you +don't want to disrupt your production. You can tag version as **staging** simply by appending `+staging` +to its name. + +So if you have OpenPype version like `OpenPype-v3.0.0.zip` just name it `OpenPype-v3.0.0+staging.zip`. +When both these versions are present, production one will always take precedence over staging. + +You can run OpenPype with `--use-staging` argument to add use staging versions. + +:::note +Running staging version is identified by orange **P** icon in system tray. +::: \ No newline at end of file diff --git a/website/docs/admin_openpype_commands.md b/website/docs/admin_openpype_commands.md index 6e187c3c8a..324e0e8481 100644 --- a/website/docs/admin_openpype_commands.md +++ b/website/docs/admin_openpype_commands.md @@ -4,137 +4,154 @@ title: OpenPype Commands Reference sidebar_label: OpenPype Commands --- +:::info +You can substitute `openpype_console` with `poetry run python start.py` if you want to run it +directly from sources. +::: -## `tray` +:::note +Running OpenPype without any commands will default to `tray`. +::: -To launch Tray: -```sh -pype tray +## Common arguments +`--use-version` to specify explicit version to use: +```shell +openpype_console --use-version=3.0.0-foo+bar ``` -### `--debug` +`--use-staging` - to use staging versions of OpenPype. + +For more information [see here](admin_use#run-openpype). + +## Commands + +| Command | Description | Arguments | +| --- | --- |: --- :| +| tray | Launch OpenPype Tray. | [📑](#tray-arguments) +| eventserver | This should be ideally used by system service (such as systemd or upstart on linux and window service). | [📑](#eventserver-arguments) | +| launch | Launch application in Pype environment. | [📑](#launch-arguments) | +| publish | Pype takes JSON from provided path and use it to publish data in it. | [📑](#publish-arguments) | +| extractenvironments | Extract environment variables for entered context to a json file. | [📑](#extractenvironments-arguments) | +| run | Execute given python script within OpenPype environment. | [📑](#run-arguments) | +| projectmanager | Launch Project Manager UI | [📑](#projectmanager-arguments) | +| settings | Open Settings UI | [📑](#settings-arguments) | +| standalonepublisher | Open Standalone Publisher UI | [📑](#standalonepublisher-arguments) | + +--- +### `tray` arguments {#tray-arguments} +| Argument | Description | +| --- | --- | +| `--debug` | print verbose information useful for debugging (works with `openpype_console`) | To launch Tray with debugging information: -```sh -pype tray --debug +```shell +openpype_console tray --debug ``` +--- +### `launch` arguments {#eventserver-arguments} +You have to set either proper environment variables to provide URL and credentials or use +option to specify them. If you use `--store_credentials` provided credentials will be stored for later use. --------------------- - - -## `eventserver` - -This command launches ftrack event server. - -This should be ideally used by system service (such us systemd or upstart -on linux and window service). - -You have to set either proper environment variables to provide URL and -credentials or use option to specify them. If you use `--store_credentials` -provided credentials will be stored for later use. +| Argument | Description | +| --- | --- | +| `--debug` | print debug info | +| `--ftrack-url` | URL to ftrack server (can be set with `FTRACK_SERVER`) | +| `--ftrack-user` |user name to log in to ftrack (can be set with `FTRACK_API_USER`) | +| `--ftrack-api-key` | ftrack api key (can be set with `FTRACK_API_KEY`) | +| `--ftrack-events-path` | path to event server plugins (can be set with `FTRACK_EVENTS_PATH`) | +| `--no-stored-credentials` | will use credential specified with options above | +| `--store-credentials` | will store credentials to file for later use | +| `--legacy` | run event server without mongo storing | +| `--clockify-api-key` | Clockify API key (can be set with `CLOCKIFY_API_KEY`) | +| `--clockify-workspace` | Clockify workspace (can be set with `CLOCKIFY_WORKSPACE`) | To run ftrack event server: -```sh -pype eventserver --ftrack-url= --ftrack-user= --ftrack-api-key= --ftrack-events-path= --no-stored-credentials --store-credentials +```shell +openpype_console eventserver --ftrack-url= --ftrack-user= --ftrack-api-key= --ftrack-events-path= --no-stored-credentials --store-credentials ``` +--- +### `launch` arguments {#launch-arguments} -### `--debug` -- print debug info - -### `--ftrack-url` -- URL to ftrack server - -### `--ftrack-user` -- user name to log in to ftrack - -### `--ftrack-api-key` -- ftrack api key - -### `--ftrack-events-path` -- path to event server plugins - -### `--no-stored-credentials` -- will use credential specified with options above - -### `--store-credentials` -- will store credentials to file for later use - --------------------- - -## `launch` - -Launch application in Pype environment. - -### `--app` - -Application name - this should be the same as it's [defining toml](admin_hosts#launchers) file (without .toml) - -### `--project` -Project name - -### `--asset` -Asset name - -### `--task` -Task name - -### `--tools` -*Optional: Additional tools environment files to add* - -### `--user` -*Optional: User on behalf to run* - -### `--ftrack-server` / `-fs` -*Optional: Ftrack server URL* - -### `--ftrack-user` / `-fu` -*Optional: Ftrack user* - -### `--ftrack-key` / `-fk` -*Optional: Ftrack API key* +| Argument | Description | +| --- | --- | +| `--app` | Application name - this should be the key for application from Settings. | +| `--project` | Project name (default taken from `AVALON_PROJECT` if set) | +| `--asset` | Asset name (default taken from `AVALON_ASSET` if set) | +| `--task` | Task name (default taken from `AVALON_TASK` is set) | +| `--tools` | *Optional: Additional tools to add* | +| `--user` | *Optional: User on behalf to run* | +| `--ftrack-server` / `-fs` | *Optional: Ftrack server URL* | +| `--ftrack-user` / `-fu` | *Optional: Ftrack user* | +| `--ftrack-key` / `-fk` | *Optional: Ftrack API key* | For example to run Python interactive console in Pype context: -```sh +```shell pype launch --app python --project my_project --asset my_asset --task my_task ``` --------------------- +--- +### `publish` arguments {#publish-arguments} +| Argument | Description | +| --- | --- | +| `--debug` | print more verbose infomation | -## `publish` - -Pype takes JSON from provided path and use it to publish data in it. -```sh +```shell pype publish ``` -### `--debug` -- print more verbose infomation - --------------------- - -## `extractenvironments` - -Extract environment variables for entered context to a json file. +--- +### `extractenvironments` arguments {#extractenvironments-arguments} Entered output filepath will be created if does not exists. - All context options must be passed otherwise only openpype's global environments will be extracted. +Context options are `project`, `asset`, `task`, `app` -Context options are "project", "asset", "task", "app" +| Argument | Description | +| --- | --- | +| `output_json_path` | Absolute path to the exported json file | +| `--project` | Project name | +| `--asset` | Asset name | +| `--task` | Task name | +| `--app` | Application name | -### `output_json_path` -- Absolute path to the exported json file +```shell +openpype_console /home/openpype/env.json --project Foo --asset Bar --task modeling --app maya-2019 +``` -### `--project` -- Project name +--- +### `run` arguments {#run-arguments} -### `--asset` -- Asset name +| Argument | Description | +| `--script` | run specified python script | -### `--task` -- Task name +Note that additional arguments are passed to the script. -### `--app` -- Application name \ No newline at end of file +```shell +openpype_console run --script /foo/bar/baz.py arg1 arg2 +``` + +--- +### `projectmanager` arguments {#projectmanager-arguments} +`projectmanager` has no command-line arguments. +```shell +openpype_console projectmanager +``` + +--- +### `settings` arguments {#settings-arguments} + +| Argument | Description | +| `-d` / `--dev` | Run settings in developer mode. | + +```shell +openpypeconsole settings +``` + +--- +### `standalonepublisher` arguments {#standalonepublisher-arguments} +`standalonepublisher` has no command-line arguments. +```shell +openpype_console standalonepublisher +``` \ No newline at end of file diff --git a/website/docs/admin_use.md b/website/docs/admin_use.md index 376e9397a1..4a2b56e6f4 100644 --- a/website/docs/admin_use.md +++ b/website/docs/admin_use.md @@ -32,6 +32,60 @@ Once artist enters the Mongo URL address, OpenPype will remember the connection next launch, so it is a one time process.From that moment OpenPype will do it's best to always keep up to date with the latest studio updates. -If the launch was successfull, the artist should see a green OpenPype logo in their +If the launch was successful, the artist should see a green OpenPype logo in their tray menu. Keep in mind that on Windows this icon might be hidden by default, in which case, -the artist can simply drag the icon down to the tray. \ No newline at end of file +the artist can simply drag the icon down to the tray. + +You can use following command line arguments: + +`--use-version` - to specify version you want to run explicitly, like: +```shell +openpype_console --use-version=3.0.1 +``` + +`--use-staging` - to specify you prefer staging version. In that case it will be used +(if found) instead of production one. + +### Details +When you run OpenPype from executable, few check are made: + +#### Check for mongoDB database connection +MongoDB connection string is in format: +```shell +mongodb[+srv]://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options] +``` +More on that in [MongoDB documentation](https://docs.mongodb.com/manual/reference/connection-string/). + +Example connection strings are `mongodb://local-unprotected-server:2707` or +`mongodb+srv://user:superpassword:some.mongodb-hosted-on.net:27072`. + +When you start OpenPype first time, Igniter UI will show up and ask you for this string. It will then +save it in secure way to your systems keyring - on Windows it is **Credential Manager**, on MacOS it will use its +**Keychain**, on Linux it can be **GNOME Keyring** or other software, depending on your distribution. + +This can be also set beforehand with environment variable `OPENPYPE_MONGO`. If set it takes precedence +over the one set in keyring. + +#### Check for OpenPype version path +When connection to MongoDB is made, OpenPype will get various settings from there - one among them is +directory location where OpenPype versions are stored. If this directory exists OpenPype tries to +find the latest version there and if succeed it will copy it to user system and use it. + +This path can be set is OpenPype settings, but also with environment variable `OPENPYPE_PATH` or with +`openPypePath` in json file located application directory depending on your system. + +- Windows: `%LOCALAPPDATA%\pypeclub\openpype` +- Linux: `~/.local/share/pypeclub/openpype` +- Mac: `~/Library/Application Support/pypeclub/openpype` + +### Runtime provided environment variables +OpenPype is providing following environment variables for its subprocesses that can be used +in various places, like scripting, etc. + +- `OPENPYPE_ROOT` - this will point to currently running code. +- `OPENPYPE_VERSION` - string of current version - like `3.0.0-foo+bar` +- `OPENPYPE_REPOS_ROOT` - this is path where all components can be find (like Avalon Core and OpenPype) +- `OPENPYPE_DATABASE_NAME` - database name in MongoDB used by OpenPype +- `OPENPYPE_EXECUTABLE` - path to executable used to run OpenPype - when run from sources it will point +to **python** stored in virtual environment. If run from frozen code, it will point to either `openpype_gui` or + `openpype_console`. diff --git a/website/docs/artist_hosts_maya.md b/website/docs/artist_hosts_maya.md index fc94f20f02..6fbd59ae1e 100644 --- a/website/docs/artist_hosts_maya.md +++ b/website/docs/artist_hosts_maya.md @@ -531,7 +531,10 @@ OpenPype supports creating review video for almost any type of data you want to What we call review video is actually _playblast_ or _capture_ (depending on terminology you are familiar with) made from pre-defined camera in scene. This is very useful in cases where you want to add turntable preview of your model for example. But it can -be used to generate preview for animation, simulations, and so on. +be used to generate preview for animation, simulations, and so on. You can either +publish review as separate subset version, or you can attach generated video to subset you +are publishing - for example attach video of turntable rotation to published model as in +following example. ### Setting scene for review extraction @@ -570,10 +573,14 @@ on this set to control review video generation: * `Step` - number of steps * `Fps` - framerate +Next step is to move your model set to review set so it will be connected to each other. + This is my scene: ![Maya - Review model setup](assets/maya-model_review_setup.jpg) +You see that `modelMain` in under `reviewMain` with `reviewCamera`. + _* note that I had to fix UVs and normals on Stanford dragon model as it wouldn't pass model validators_ @@ -588,6 +595,8 @@ version. All parts of this process - like what burnins, what type of video file, settings for Maya playblast - can be customized by your TDs. For more information about customizing review process refer to [admin section](admin_presets_plugins). +If you don't move `modelMain` into `reviewMain`, review will be generated but it will +be published as separate entity. ## Working with Yeti in OpenPype diff --git a/website/docs/artist_tools.md b/website/docs/artist_tools.md index 5bc3f4c1fd..f099b48a9a 100644 --- a/website/docs/artist_tools.md +++ b/website/docs/artist_tools.md @@ -177,6 +177,22 @@ Library loader is extended [loader](#loader) which allows to load published subs +### Delivery Action ### + +Library Loader contains functionality to export any selected asset, subsets and their version to configurable folder. +Delivery follows structure based on defined template, this template must be configured first by Admin in the Settings. + +![delivery_action](assets/tools/tools_delivery_loader.png) + +* Usage +- Select all required subsets for export (you can change theirs versions by double clicking on 'Version' value) +- Right click and select **Deliver Versions** from context menu +- Select predefined Delivery template (must be configured by Admin system or project wide) +- Fill value for root folder (folder will be created if it doesn't exist) +- Filter out type of representation you are not interested in +- Push **Deliver** button +- Dialog must be kept open until export is finished +- In a case of problems with any of the representation, that one will be skipped, description of error will be provided in the dialog * * * ## Publisher diff --git a/website/docs/assets/maya-model_review_setup.jpg b/website/docs/assets/maya-model_review_setup.jpg index 6c43807596..16576894b1 100644 Binary files a/website/docs/assets/maya-model_review_setup.jpg and b/website/docs/assets/maya-model_review_setup.jpg differ diff --git a/website/docs/assets/tools/tools_delivery_loader.png b/website/docs/assets/tools/tools_delivery_loader.png new file mode 100644 index 0000000000..511cd24fbb Binary files /dev/null and b/website/docs/assets/tools/tools_delivery_loader.png differ diff --git a/website/docs/dev_build.md b/website/docs/dev_build.md index 14efeaa850..2c4bd1e9af 100644 --- a/website/docs/dev_build.md +++ b/website/docs/dev_build.md @@ -7,14 +7,31 @@ sidebar_label: Build import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +## Introduction To build Pype you currently need (on all platforms): - **[Python 3.7](https://www.python.org/downloads/)** as we are following [vfx platform](https://vfxplatform.com). - **[git](https://git-scm.com/downloads)** -We use [CX_Freeze](https://cx-freeze.readthedocs.io/en/latest) to freeze the code and all dependencies. +We use [CX_Freeze](https://cx-freeze.readthedocs.io/en/latest) to freeze the code and all dependencies and +[Poetry](https://python-poetry.org/) for virtual environment management. +This is outline of build steps. Most of them are done automatically via scripts: +- Virtual environment is created using **Poetry** in `.venv` +- Necessary third-party tools (like [ffmpeg](https://www.ffmpeg.org/), [OpenImageIO](https://github.com/OpenImageIO/oiio) + and [usd libraries](https://developer.nvidia.com/usd)) are downloaded to `./vendor/bin` +- OpenPype code is frozen with **cx_freeze** to `./build` +- Modules are moved from `lib` to `dependencies` to solve some Python 2 / Python 3 clashes +- On Mac application bundle and dmg image will be created from built code. +- On Windows, you can create executable installer with `./tools/build_win_installer.ps1` + +### Clone OpenPype repository: +```powershell +git clone --recurse-submodules https://github.com/pypeclub/OpenPype.git +``` + +## Platform specific steps +### Windows More tools might be needed for installing some dependencies (for example for **OpenTimelineIO**) - mostly development tools like [CMake](https://cmake.org/) and [Visual Studio](https://visualstudio.microsoft.com/cs/downloads/) -### Clone repository: -```sh -git clone --recurse-submodules git@github.com:pypeclub/pype.git -``` - -### Run from source +#### Run from source For development purposes it is possible to run OpenPype directly from the source. We provide a simple launcher script for this. To start OpenPype from source you need to -1) Run `.\tools\create_env.ps1` to create virtual environment in `.\venv` -2) Run `.\tools\run_tray.ps1` if you have all required dependencies on your machine you should be greeted with OpenPype igniter window and once you give it your Mongo URL, with OpenPype icon in the system tray. +1. Run `.\tools\create_env.ps1` to create virtual environment in `.venv` +2. Run `.\tools\fetch_thirdparty_libs.ps1` to get **ffmpeg**, **oiio** and other tools needed. +3. Run `.\tools\run_tray.ps1` if you have all required dependencies on your machine you should be greeted with OpenPype igniter window and once you give it your Mongo URL, with OpenPype icon in the system tray. + +Step 1 and 2 needs to be run only once (or when something was changed). + +#### To build OpenPype: +1. Run `.\tools\create_env.ps1` to create virtual environment in `.venv` +2. Run `.\tools\fetch_thirdparty_libs.ps1` to get **ffmpeg**, **oiio** and other tools needed. +3. `.\tools\build.ps1` to build OpenPype to `.\build` -### To build OpenPype: - -1) Run `.\tools\create_env.ps1` to create virtual environment in `.\venv` -2) Run `.\tools\build.ps1` to build pype executables in `.\build\` - -To create distributable OpenPype versions, run `./tools/create_zip.ps1` - that will +To create distributable OpenPype versions, run `.\tools\create_zip.ps1` - that will create zip file with name `pype-vx.x.x.zip` parsed from current pype repository and -copy it to user data dir. You can specify `--path /path/to/zip` to force it into a different +copy it to user data dir. You can specify `--path \path\to\zip` to force it into a different location. This can be used to prepare new version releases for artists in the studio environment without the need to re-build the whole package @@ -61,27 +77,33 @@ without the need to re-build the whole package +### Linux + #### Docker You can use Docker to build OpenPype. Just run: -```sh -sudo ./tools/docker_build.sh +```shell +$ sudo ./tools/docker_build.sh ``` and you should have built OpenPype in `build` directory. It is using **Centos 7** as a base image. You can pull the image: -```sh +```shell # replace 3.0.0 tag with version you want -docker pull pypeclub/openpype:3.0.0 +$ docker pull pypeclub/openpype:3.0.0 ``` See https://hub.docker.com/r/pypeclub/openpype/tag for more. +Beware that as Python is built against some libraries version in Centos 7 base image, +those might not be available in linux version you are using. We try to handle those we +found (libffi, libcrypto/ssl, etc.) but there might be more. + #### Manual build -To build OpenPype on Linux you wil need: + +To build OpenPype on Linux you will need: - **[curl](https://curl.se)** on systems that doesn't have one preinstalled. -- Python header files installed (**python3-dev** on Ubuntu for example). - **bzip2**, **readline**, **sqlite3** and other libraries. Because some Linux distros come with newer Python version pre-installed, you might @@ -90,117 +112,283 @@ Your best bet is probably using [pyenv](https://github.com/pyenv/pyenv). You can use your package manager to install **git** and other packages to your build environment. -Use curl for pyenv installation +#### Common steps for all Distros + +Use pyenv to prepare Python version for Pype build + +```shell +$ curl https://pyenv.run | bash + +# you can add those to ~/.bashrc +$ export PATH="$HOME/.pyenv/bin:$PATH" +$ eval "$(pyenv init -)" +$ eval "$(pyenv virtualenv-init -)" + +# reload shell +$ exec $SHELL + +# install Python 3.7.10 +# python will be downloaded and build so please make sure +# you have all necessary requirements installed (see bellow). +$ pyenv install -v 3.7.10 + +# change path to pype 3 +$ cd /path/to/pype-3 + +# set local python version +$ pyenv local 3.7.9 +``` :::note Install build requirements for **Ubuntu** -```sh +```shell sudo apt-get update; sudo apt-get install --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev git ``` In case you run in error about `xcb` when running Pype, you'll need also additional libraries for Qt5: -```sh +```shell sudo apt install qt5-default ``` ::: -:::note Install build requirements for **Centos** +:::note Install build requirements for **Centos 7** -```sh -yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel git +```shell +$ sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm +$ sudo yum install centos-release-scl +$ sudo yum install bash which git devtoolset-7-gcc* \ + make cmake curl wget gcc zlib-devel bzip2 \ + bzip2-devel readline-devel sqlite sqlite-devel \ + openssl-devel tk-devel libffi-devel qt5-qtbase-devel \ + patchelf ``` - -In case you run in error about `xcb` when running Pype, -you'll need also additional libraries for Qt5: - -```sh -sudo yum install qt5-qtbase-devel -``` - ::: -For more information about setting your build environmet please refer to [pyenv suggested build environment](https://github.com/pyenv/pyenv/wiki#suggested-build-environment) +:::note Install build requirements for other distros -#### Common steps for all Distros +Build process usually needs some reasonably recent versions of libraries and tools. You +can follow what's needed for Ubuntu and change it for your package manager. Centos 7 steps +have additional magic to overcame very old versions. +::: -Use pyenv to prepare Python version for Pype build +For more information about setting your build environment please refer to [pyenv suggested build environment](https://github.com/pyenv/pyenv/wiki#suggested-build-environment). -```sh -curl https://pyenv.run | bash - -# you can add those to ~/.bashrc -export PATH="$HOME/.pyenv/bin:$PATH" -eval "$(pyenv init -)" -eval "$(pyenv virtualenv-init -)" - -# reload shell -exec $SHELL - -# install Python 3.7.9 -pyenv install -v 3.7.9 - -# change path to pype 3 -cd /path/to/pype-3 - -# set local python version -pyenv local 3.7.9 - -``` #### To build Pype: - -1. Run `.\tools\create_env.sh` to create virtual environment in `.\venv` -2. Run `.\tools\build.sh` to build pype executables in `.\build\` +1. Run `./tools/create_env.sh` to create virtual environment in `./venv` +2. Run `./tools/fetch_thirdparty_libs.sh` to get **ffmpeg**, **oiio** and other tools needed. +3. Run `./tools/build.sh` to build pype executables in `.\build\` +### MacOS To build pype on MacOS you wil need: -- **[Homebrew](https://brew.sh)**, Easy way of installing everything necessary is to use. +- **[Homebrew](https://brew.sh)** - easy way of installing everything necessary. - **[CMake](https://cmake.org/)** to build some external OpenPype dependencies. - **XCode Command Line Tools** (or some other build system) +- **[create-dmg](https://formulae.brew.sh/formula/create-dmg)** to create dmg image from application +bundle. 1) Install **Homebrew**: -```sh -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +```shell +$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``` 2) Install **cmake**: -```sh -brew install cmake +```shell +$ brew install cmake ``` 3) Install [pyenv](https://github.com/pyenv/pyenv): -```sh -brew install pyenv -echo 'eval "$(pypenv init -)"' >> ~/.zshrc -pyenv init -exec "$SHELL" -PATH=$(pyenv root)/shims:$PATH +```shell +$ brew install pyenv +$ echo 'eval "$(pypenv init -)"' >> ~/.zshrc +$ pyenv init +$ exec "$SHELL" +$ PATH=$(pyenv root)/shims:$PATH ``` 4) Pull in required Python version 3.7.x -```sh +```shell # install Python build dependences -brew install openssl readline sqlite3 xz zlib +$ brew install openssl readline sqlite3 xz zlib # replace with up-to-date 3.7.x version -pyenv install 3.7.9 +$ pyenv install 3.7.9 ``` 5) Set local Python version -```sh +```shell # switch to Pype source directory -pyenv local 3.7.9 +$ pyenv local 3.7.9 +``` + +6) Install `create-dmg` +```shell +$ brew install create-dmg ``` #### To build Pype: -1. Run `.\tools\create_env.sh` to create virtual environment in `.\venv` -2. Run `.\tools\build.sh` to build Pype executables in `.\build\` +1. Run `./tools/create_env.sh` to create virtual environment in `./venv`. +2. Run `./tools/fetch_thirdparty_libs.sh` to get **ffmpeg**, **oiio** and other tools needed. +3. Run `./tools/build.sh` to build OpenPype Application bundle in `./build/`. + +## Adding dependencies +### Python modules +If you are extending OpenPype and you need some new modules not included, you can add them +to `pyproject.toml` to `[tool.poetry.dependencies]` section. + +```toml title="/pyproject.toml" +[tool.poetry.dependencies] +python = "3.7.*" +aiohttp = "^3.7" +aiohttp_json_rpc = "*" # TVPaint server +acre = { git = "https://github.com/pypeclub/acre.git" } +opentimelineio = { version = "0.14.0.dev1", source = "openpype" } +#... +``` +It is useful to add comment to it so others can see why this was added and where it is used. +As you can see you can add git repositories or custom wheels (those must be +added to `[[tool.poetry.source]]` section). + +To add something only for specific platform, you can use markers like: +```toml title="Install pywin32 only on Windows" +pywin32 = { version = "300", markers = "sys_platform == 'win32'" } +``` + +For more information see [Poetry documentation](https://python-poetry.org/docs/dependency-specification/). + +### Binary dependencies +To add some binary tool or something that doesn't fit standard Python distribution methods, you +can use [fetch_thirdparty_libs](#fetch_thirdparty_libs) script. It will take things defined in +`pyproject.toml` under `[openpype]` section like this: + +```toml title="/pyproject.toml" +[openpype] + +[openpype.thirdparty.ffmpeg.windows] +url = "https://distribute.openpype.io/thirdparty/ffmpeg-4.4-windows.zip" +hash = "dd51ba29d64ee238e7c4c3c7301b19754c3f0ee2e2a729c20a0e2789e72db925" +# ... +``` +This defines FFMpeg for Windows. It will be downloaded from specified url, its checksum will +be validated (it's sha256) and it will be extracted to `/vendor/bin/ffmpeg/windows` (partly taken +from its section name). + +## Script tools +(replace extension with the one for your system - `ps1` for windows, `sh` for linux/macos) + +### build +This will build OpenPype to `build` directory. If virtual environment is not created yet, it will +install [Poetry](https://python-poetry.org/) and using it download and install necessary +packages needed for build. It is recommended that you run [fetch_thirdparty_libs](#fetch_thirdparty_libs) +to download FFMpeg, OpenImageIO and others that are needed by OpenPype and are copied during the build. + +#### Arguments +`--no-submodule-update` - to disable updating submodules. This allows to make custom-builds for testing +feature changes in submodules. + +### build_win_installer +This will take already existing build in `build` directory and create executable installer using +[Inno Setup](https://jrsoftware.org/isinfo.php) and definitions in `./inno_setup.iss`. You need OpenPype +build using [build script](#build), Inno Setup installed and in PATH before running this script. + +:::note +Windows only +::: + +### create_env +Script to create virtual environment for build and running OpenPype from sources. It is using +[Poetry](https://python-poetry.org/). All dependencies are defined in `pyproject.toml`, resolved by +Poetry into `poetry.lock` file and then installed. Running this script without Poetry will download +it, install it to `.poetry` and then install virtual environment from `poetry.lock` file. If you want +to update packages version, just run `poetry update` or delete lock file. + +#### Arguments +`--verbose` - to increase verbosity of Poetry. This can be useful for debugging package conflicts. + +### create_zip +Script to create packaged OpenPype version from current sources. This will strip developer stuff and +package it into zip that can be used for [auto-updates for studio wide distributions](admin_distribute#automatic-updates), etc. +Same as: +```shell +poetry run python ./tools/create_zip.py +``` + +### docker_build.sh +Script to build OpenPype on [Docker](https://www.docker.com/) enabled systems - usually Linux and Windows +with [Docker Desktop](https://docs.docker.com/docker-for-windows/install/) +and [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/about) (WSL) installed. + +It must be run with administrative privileges - `sudo ./docker_build.sh`. + +It will use **Centos 7** base image to build OpenPype. You'll see your build in `./build` folder. + +### fetch_thirdparty_libs +This script will download necessary tools for OpenPype defined in `pyproject.toml` like FFMpeg, +OpenImageIO and USD libraries and put them to `./vendor/bin`. Those are then included in build. +Running it will overwrite everything on their respective paths. +Same as: +```shell +poetry run python ./tools/fetch_thirdparty_libs.py +``` + +### make_docs +Script will run [sphinx](https://www.sphinx-doc.org/) to build api documentation in html. You +should see it then under `./docs/build/html`. + +### run_documentation +This will start up [Docusaurus](https://docusaurus.io/) to display OpenPype user documentation. +Useful for offline browsing or editing documentation itself. You will need [Node.js](https://nodejs.org/) +and [Yarn](https://yarnpkg.com/) to run this script. After executing it, you'll see new +browser window with current OpenPype documentation. +Same as: +```shell +cd ./website +yarn start +``` + +### run_mongo +Helper script to run local mongoDB server for development and testing. You will need +[mongoDB server](https://www.mongodb.com/try/download/community) installed in standard location +or in PATH (standard location works only on Windows). It will start by default on port `2707` and +it will put its db files to `../mongo_db_data` relative to OpenPype sources. + +### run_project_manager +Helper script to start OpenPype Project Manager tool. +Same as: +```shell +poetry run python start.py projectmanager +``` + +### run_settings +Helper script to open OpenPype Settings UI. +Same as: +```shell +poetry run python start.py settings --dev +``` + +### run_tests +Runs OpenPype test suite. + +### run_tray +Helper script to run OpenPype Tray. +Same as: +```shell +poetry run python start.py tray +``` + +### update_submodules +Helper script to update OpenPype git submodules. +Same as: +```shell +git submodule update --recursive --remote +``` diff --git a/website/docs/project_settings/assets/global_extract_review_letter_box.png b/website/docs/project_settings/assets/global_extract_review_letter_box.png index 7cd9ecbdd6..45c1942f24 100644 Binary files a/website/docs/project_settings/assets/global_extract_review_letter_box.png and b/website/docs/project_settings/assets/global_extract_review_letter_box.png differ diff --git a/website/docs/project_settings/assets/global_extract_review_letter_box_settings.png b/website/docs/project_settings/assets/global_extract_review_letter_box_settings.png index 9ad9c05f43..80e00702e6 100644 Binary files a/website/docs/project_settings/assets/global_extract_review_letter_box_settings.png and b/website/docs/project_settings/assets/global_extract_review_letter_box_settings.png differ diff --git a/website/docs/project_settings/assets/global_extract_review_output_defs.png b/website/docs/project_settings/assets/global_extract_review_output_defs.png index 0dc8329324..ce3c00ca40 100644 Binary files a/website/docs/project_settings/assets/global_extract_review_output_defs.png and b/website/docs/project_settings/assets/global_extract_review_output_defs.png differ diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index 4fee57d575..6a08c79582 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -69,6 +69,49 @@ Profile may generate multiple outputs from a single input. Each output must defi - it is possible to rescale output to specified resolution and keep aspect ratio. - If value is set to 0, source resolution will be used. +- **`Overscan crop`** + - Crop input resolution before rescaling. + + - Value is text may have a few variants. Each variant define output size for input size. + + - All values that cause output resolution smaller than 1 pixel are invalid. + + - Value without sign (+/-) in is always explicit and value with sign is + relative. Output size for values "200px" and "+200px" are not the same "+200px" will add 200 pixels to source and "200px" will keep only 200px from source. Value of "0", "0px" or "0%" are automatically converted to "+0px" as 0px is invalid ouput. + + - Cropped value is related to center. It is better to avoid odd numbers if + possible. + + **Example outputs for input size: 2200px** + + | String | Output | Description | + |---|---|---| + | ` ` | 2200px | Empty string keep resolution unchanged. | + | `50%` | 1100px | Crop 25% of input width on left and right side. | + | `300px` | 300px | Keep 300px in center of input and crop rest on left adn right. | + | `300` | 300px | Values without units are used as pixels (`px`). | + | `+0px` | 2200px | Keep resolution unchanged. | + | `0px` | 2200px | Same as `+0px`. | + | `+300px` | 2500px | Add black pillars of 150px width on left and right side. | + | `-300px` | 1900px | Crop 150px on left and right side | + | `+10%` | 2420px | Add black pillars of 5% size of input on left and right side. | + | `-10%` | 1980px | Crop 5% of input size by on left and right side. | + | `-10%+` | 2000px | Input width is 110% of output width. | + + **Value "-10%+" is a special case which says that input's resolution is + bigger by 10% than expected output.** + + - It is possible to enter single value for both width and height or + combination of two variants for width and height separated with space. + + **Example for resolution: 2000px 1000px** + + | String | Output | + |---------------|---------------| + | "100px 120px" | 2100px 1120px | + | "-10% -200px" | 1800px 800px | + | "-10% -0px" | 1800px 1000px | + - **`Letter Box`** - **Enabled** - Enable letter boxes - **Ratio** - Ratio of letter boxes diff --git a/website/package.json b/website/package.json index 7bd8b4e77b..604eb69591 100644 --- a/website/package.json +++ b/website/package.json @@ -1,5 +1,6 @@ { "name": "pype-documentation", + "license": "MIT", "scripts": { "examples": "docusaurus-examples", "start": "docusaurus start", @@ -13,8 +14,8 @@ "docusaurus": "docusaurus" }, "dependencies": { - "@docusaurus/core": "2.0.0-alpha.72", - "@docusaurus/preset-classic": "2.0.0-alpha.72", + "@docusaurus/core": "2.0.0-beta.0", + "@docusaurus/preset-classic": "2.0.0-beta.0", "classnames": "^2.2.6", "clsx": "^1.1.1", "react": "^16.10.2", diff --git a/website/yarn.lock b/website/yarn.lock index d29fe48fce..e23e29c0e5 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -472,7 +472,7 @@ "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.13", "@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8": version "7.13.8" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz#3730a31dafd3c10d8ccd10648ed80a2ac5472ef3" integrity sha512-iePlDPBn//UhxExyS9KyeYU7RM9WScAG+D3Hhno0PLJebAEpDZMocbDe64eqynhNAnwz/vZoL/q/QB2T1OH39A== @@ -516,7 +516,7 @@ "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.12.16", "@babel/plugin-proposal-optional-chaining@^7.13.12": +"@babel/plugin-proposal-optional-chaining@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.12.tgz#ba9feb601d422e0adea6760c2bd6bbb7bfec4866" integrity sha512-fcEdKOkIB7Tf4IxrgEVeFC4zeJSTr78no9wTdBuZZbqF64kzllU0ybo2zrzm7gUQfxGhBgq4E39oRs8Zx/RMYQ== @@ -1109,18 +1109,6 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@choojs/findup@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@choojs/findup/-/findup-0.2.1.tgz#ac13c59ae7be6e1da64de0779a0a7f03d75615a3" - integrity sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw== - dependencies: - commander "^2.15.1" - -"@csstools/convert-colors@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" - integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== - "@docsearch/css@3.0.0-alpha.34": version "3.0.0-alpha.34" resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0-alpha.34.tgz#5d5c39955956e237884a9997eb29e28c8adc99fa" @@ -1136,15 +1124,13 @@ "@docsearch/css" "3.0.0-alpha.34" algoliasearch "^4.0.0" -"@docusaurus/core@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-alpha.72.tgz#f1acff2d84b3cbca9c35906186c49ba16d019ce3" - integrity sha512-PV0rlvVRvVEdqs1I4PktwZBJkhFg4O4bVeqseaTYuA1u/poQSiiZ+rhrZRJ+/OcTHZ8VlYZw7tCHaRH4RLbP2g== +"@docusaurus/core@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.0.tgz#05506ee02e7d40e9f4c8d7b4f918d26d3b191159" + integrity sha512-xWwpuEwFRKJmZvNGOpr/dyRDnx/psckLPsozQTg2hu3u81Wqu9gigWgYK/C2fPlEjxMcVw0/2WH+zwpbyWmF2Q== dependencies: "@babel/core" "^7.12.16" "@babel/generator" "^7.12.15" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.13" - "@babel/plugin-proposal-optional-chaining" "^7.12.16" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-transform-runtime" "^7.12.15" "@babel/preset-env" "^7.12.16" @@ -1153,25 +1139,26 @@ "@babel/runtime" "^7.12.5" "@babel/runtime-corejs3" "^7.12.13" "@babel/traverse" "^7.12.13" - "@docusaurus/cssnano-preset" "2.0.0-alpha.72" + "@docusaurus/cssnano-preset" "2.0.0-beta.0" "@docusaurus/react-loadable" "5.5.0" - "@docusaurus/types" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" - "@docusaurus/utils-validation" "2.0.0-alpha.72" + "@docusaurus/types" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" + "@docusaurus/utils-validation" "2.0.0-beta.0" "@endiliey/static-site-generator-webpack-plugin" "^4.0.0" "@svgr/webpack" "^5.5.0" autoprefixer "^10.2.5" babel-loader "^8.2.2" babel-plugin-dynamic-import-node "2.3.0" boxen "^5.0.0" - cache-loader "^4.1.0" chalk "^4.1.0" chokidar "^3.5.1" clean-css "^5.1.1" commander "^5.1.0" - copy-webpack-plugin "^6.4.1" + copy-webpack-plugin "^8.1.0" core-js "^3.9.1" css-loader "^5.1.1" + css-minimizer-webpack-plugin "^2.0.0" + cssnano "^5.0.1" del "^6.0.0" detect-port "^1.3.0" eta "^1.12.1" @@ -1182,62 +1169,61 @@ globby "^11.0.2" html-minifier-terser "^5.1.1" html-tags "^3.1.0" - html-webpack-plugin "^4.5.0" + html-webpack-plugin "^5.2.0" import-fresh "^3.3.0" is-root "^2.1.0" - joi "^17.4.0" leven "^3.1.0" lodash "^4.17.20" - mini-css-extract-plugin "^0.8.0" + mini-css-extract-plugin "^1.4.0" module-alias "^2.2.2" nprogress "^0.2.0" - null-loader "^4.0.0" - optimize-css-assets-webpack-plugin "^5.0.4" - pnp-webpack-plugin "^1.6.4" - postcss "^8.2.7" - postcss-loader "^4.1.0" - postcss-preset-env "^6.7.0" + postcss "^8.2.10" + postcss-loader "^5.2.0" prompts "^2.4.0" react-dev-utils "^11.0.1" + react-error-overlay "^6.0.9" react-helmet "^6.1.0" react-loadable "^5.5.0" - react-loadable-ssr-addon "^0.3.0" + react-loadable-ssr-addon-v5-slorber "^1.0.1" react-router "^5.2.0" react-router-config "^5.1.1" react-router-dom "^5.2.0" resolve-pathname "^3.0.0" + rtl-detect "^1.0.2" semver "^7.3.4" serve-handler "^6.1.3" shelljs "^0.8.4" std-env "^2.2.1" - terser-webpack-plugin "^4.1.0" + strip-ansi "^6.0.0" + terser-webpack-plugin "^5.1.1" + tslib "^2.1.0" update-notifier "^5.1.0" url-loader "^4.1.1" wait-on "^5.2.1" - webpack "^4.44.1" + webpack "^5.28.0" webpack-bundle-analyzer "^4.4.0" webpack-dev-server "^3.11.2" - webpack-merge "^4.2.2" + webpack-merge "^5.7.3" webpackbar "^5.0.0-3" -"@docusaurus/cssnano-preset@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-alpha.72.tgz#03433315207b5f43f5ba280a75b8c00f2e02b461" - integrity sha512-7W/dlemTaipVd/zrd9Fjq/xp6IX/qn2z/GDaPbJ2SPklHbts5nWuRAt++wkG8Ue+Qxc9Q5uOBjW0ihVb4478+A== +"@docusaurus/cssnano-preset@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.0.tgz#a79223479666059565d60a505bed2bbcac770384" + integrity sha512-gqQHeQCDHZDd5NaiKZwDiyg75sBCqDyAsvmFukkDAty8xE7u9IhzbOQKvCAtwseuvzu2BNN41gnJ8bz7vZzQiw== dependencies: - cssnano-preset-advanced "^4.0.7" - postcss "^7.0.2" - postcss-sort-media-queries "^1.7.26" + cssnano-preset-advanced "^5.0.0" + postcss "^8.2.10" + postcss-sort-media-queries "^3.8.9" -"@docusaurus/mdx-loader@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-alpha.72.tgz#03369c9fc156318a4696ece15b65b78f8ba727d0" - integrity sha512-tG8EZc3w4xt7IKJIniPFChfVY1/adpn6w6vsXVxE96Y/1PmqKjIp6mtVKdzTShaf6MCnKrAOtEUSQR0eCRHOjQ== +"@docusaurus/mdx-loader@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.0.tgz#7a58933994b2face62e34698db2f9c88c53c6d61" + integrity sha512-oQLS2ZeUnqw79CV37glglZpaYgFfA5Az5lT83m5tJfMUZjoK4ehG1XWBeUzWy8QQNI452yAID8jz8jihEQeCcw== dependencies: "@babel/parser" "^7.12.16" "@babel/traverse" "^7.12.13" - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" "@mdx-js/mdx" "^1.6.21" "@mdx-js/react" "^1.6.21" escape-html "^1.0.3" @@ -1245,128 +1231,130 @@ fs-extra "^9.1.0" github-slugger "^1.3.0" gray-matter "^4.0.2" - loader-utils "^2.0.0" mdast-util-to-string "^2.0.0" remark-emoji "^2.1.0" stringify-object "^3.3.0" unist-util-visit "^2.0.2" url-loader "^4.1.1" - webpack "^4.44.1" + webpack "^5.28.0" -"@docusaurus/plugin-content-blog@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-alpha.72.tgz#478fe3c1011b8cfdb3ba7d782f8e192206954aee" - integrity sha512-q1noOyULAQ5CkSNciUZDf1v0ly234jX3Ts6ckAy/XK5B3F340Ou8UuEFNbVap2fkRC1hOXe7RnEmFwW1PxmqmA== +"@docusaurus/plugin-content-blog@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.0.tgz#ea7d3679ab252e8f0e58aaf80f1fc6001c72c755" + integrity sha512-lz63i5k/23RJ3Rk/2fIsYAoD8Wua3b5b0AbH2JoOhQu1iAIQiV8m91Z3XALBSzA3nBtAOIweNI7yzWL+JFSTvw== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/mdx-loader" "2.0.0-alpha.72" - "@docusaurus/types" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" - "@docusaurus/utils-validation" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/mdx-loader" "2.0.0-beta.0" + "@docusaurus/types" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" + "@docusaurus/utils-validation" "2.0.0-beta.0" chalk "^4.1.0" feed "^4.2.2" fs-extra "^9.1.0" globby "^11.0.2" - joi "^17.4.0" - loader-utils "^1.2.3" + loader-utils "^2.0.0" lodash "^4.17.20" reading-time "^1.3.0" remark-admonitions "^1.2.1" - webpack "^4.44.1" + tslib "^2.1.0" + webpack "^5.28.0" -"@docusaurus/plugin-content-docs@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-alpha.72.tgz#65255a0fa4fabbc5f3469b04c07f263ec93c67ac" - integrity sha512-EpMt0z/Z7SsOuQFIZlo31XsndxJ0blp7n0bVNcIlcFiNHYoBVVPbYb4VKP2W+1Sfw5K1XouUxoXRM30FyDrjhw== +"@docusaurus/plugin-content-docs@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.0.tgz#a5a1e0e95e499eefee53e4f61aeb99ac4a669648" + integrity sha512-WdDQUh2rRCbfJswVc0vY9EaAspxgziqpVEZja8+BmQR/TZh7HuLplT6GJbiFbE4RvwM3+PwG/jHMPglYDK60kw== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/mdx-loader" "2.0.0-alpha.72" - "@docusaurus/types" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" - "@docusaurus/utils-validation" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/mdx-loader" "2.0.0-beta.0" + "@docusaurus/types" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" + "@docusaurus/utils-validation" "2.0.0-beta.0" chalk "^4.1.0" + combine-promises "^1.1.0" execa "^5.0.0" fs-extra "^9.1.0" globby "^11.0.2" import-fresh "^3.2.2" - joi "^17.4.0" + js-yaml "^4.0.0" loader-utils "^1.2.3" lodash "^4.17.20" remark-admonitions "^1.2.1" shelljs "^0.8.4" + tslib "^2.1.0" utility-types "^3.10.0" - webpack "^4.44.1" + webpack "^5.28.0" -"@docusaurus/plugin-content-pages@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-alpha.72.tgz#5b1ddf48f5270b8295f9b20d18f76cd230147c2b" - integrity sha512-ETBx+3+U+1sj0C/E8C3huQj5lGcSlmj0ZHBrBb3qP3zHS8+gWHAyUiXst3bvFs5mJX7JHkxfaHZc2hLxXLpaJg== +"@docusaurus/plugin-content-pages@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.0.tgz#1cab3ebe0a08be74576f10c95675291bf84f848e" + integrity sha512-mk5LVVSvn+HJPKBaAs/Pceq/hTGxF2LVBvJEquuQz0NMAW3QdBWaYRRpOrL9CO8v+ygn5RuLslXsyZBsDNuhww== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/mdx-loader" "2.0.0-alpha.72" - "@docusaurus/types" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" - "@docusaurus/utils-validation" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/mdx-loader" "2.0.0-beta.0" + "@docusaurus/types" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" + "@docusaurus/utils-validation" "2.0.0-beta.0" globby "^11.0.2" - joi "^17.4.0" - loader-utils "^1.2.3" lodash "^4.17.20" minimatch "^3.0.4" remark-admonitions "^1.2.1" slash "^3.0.0" - webpack "^4.44.1" + tslib "^2.1.0" + webpack "^5.28.0" -"@docusaurus/plugin-debug@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-alpha.72.tgz#79f31decce97094117924875dfe267ae7572f48c" - integrity sha512-j2xR7i0Hw8v4SBtNvf8H5zoeKFZHScLdfJ93aUHe4ERf3AfACZuG8/tjnsarrfQK59HjbwWqbRC1mUgc2nFfwA== +"@docusaurus/plugin-debug@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.0.tgz#bee672b8858d88bdb229d4301785ff4692ebd17f" + integrity sha512-m75sZdF8Yccxfih3qfdQg9DucMTrYBnmeTA8GNmdVaK701Ip8t50d1pDJchtu0FSEh6vzVB9C6D2YD5YgVFp8A== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/types" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/types" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" react-json-view "^1.21.1" + tslib "^2.1.0" -"@docusaurus/plugin-google-analytics@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-alpha.72.tgz#57b66682e6aad5cd5a70c9bf9ab8ef7177832aae" - integrity sha512-A73FA1hRHxbCZ7WVUthrEty5jRAdWlWAg9pijwSFFg5YG2kb0thNqGqMU/P5dqcV/ytE4907WvXMpKYmLtFVOg== +"@docusaurus/plugin-google-analytics@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.0.tgz#ee287fb991202d8e9b792129dcc5542ef3ccd6c9" + integrity sha512-7lHrg1L+adc8VbiaLexa15i4fdq4MRPUTLMxRPAWz+QskhisW89Ryi2/gDmfMNqLblX84Qg2RASa+2gqO4wepw== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" -"@docusaurus/plugin-google-gtag@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-alpha.72.tgz#c7cbc4daa1be148b607ac3d1df3d396eede344f6" - integrity sha512-161+C6XZAziT/MRF9HZFCzg0ybzzkW/NHIuIKPmiQjeBB+DXYopvEmldKcPlZbs8YCSD9nMxkTx39pr1AWjffw== +"@docusaurus/plugin-google-gtag@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.0.tgz#4836770130cf54ff2cd83affbff9644ee7293e9e" + integrity sha512-V7zaYbhAMv0jexm5H/5sAnoM1GHibcn9QQk5UWC++x1kE0KRuLDZHV+9OyvW5wr0wWFajod/b88SpUpSMF5u+g== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" -"@docusaurus/plugin-sitemap@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-alpha.72.tgz#6ad55c894c19315c91847d17f0c9dcfb145132f8" - integrity sha512-ZaMeJFDdey+PDMxg7qI2u9Wm7ylZb30FBR14wPSH5da+yMnNtl8wAlWEW8RkEgKYo04mE7DMvdEZ1YdsPF7cQg== +"@docusaurus/plugin-sitemap@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.0.tgz#985d4cc3af86499f616ced024ba1fab8329e601d" + integrity sha512-dvmk8Sr+6pBkiKDb7Rjdp0GeFDWPUlayoJWK3fN3g0Fno6uxFfYhNZyXJ+ObyCA7HoW5rzeBMiO+uAja19JXTg== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/types" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/types" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" + "@docusaurus/utils-validation" "2.0.0-beta.0" fs-extra "^9.1.0" - joi "^17.4.0" sitemap "^6.3.6" + tslib "^2.1.0" -"@docusaurus/preset-classic@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-alpha.72.tgz#8f20437207d53718387676cddccdb8d6f2eaf055" - integrity sha512-Z5XKcgyrZWyUvqQZ7cAJ+E3rHkXZPRo8/23vOV5f/5sM7HeW871e+FU37RXIEFu8E8fhpCgQQ6FPEVMyiVS7Uw== +"@docusaurus/preset-classic@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.0.tgz#79eb4366e6b5eb7061370019127e40172432d770" + integrity sha512-cFpR0UaAeUt5qVx1bpidhlar6tiRNITIQlxP4bOVsjbxVTZhZ/cNuIz7C+2zFPCuKIflGXdTIQOrucPmd7z51Q== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/plugin-content-blog" "2.0.0-alpha.72" - "@docusaurus/plugin-content-docs" "2.0.0-alpha.72" - "@docusaurus/plugin-content-pages" "2.0.0-alpha.72" - "@docusaurus/plugin-debug" "2.0.0-alpha.72" - "@docusaurus/plugin-google-analytics" "2.0.0-alpha.72" - "@docusaurus/plugin-google-gtag" "2.0.0-alpha.72" - "@docusaurus/plugin-sitemap" "2.0.0-alpha.72" - "@docusaurus/theme-classic" "2.0.0-alpha.72" - "@docusaurus/theme-search-algolia" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/plugin-content-blog" "2.0.0-beta.0" + "@docusaurus/plugin-content-docs" "2.0.0-beta.0" + "@docusaurus/plugin-content-pages" "2.0.0-beta.0" + "@docusaurus/plugin-debug" "2.0.0-beta.0" + "@docusaurus/plugin-google-analytics" "2.0.0-beta.0" + "@docusaurus/plugin-google-gtag" "2.0.0-beta.0" + "@docusaurus/plugin-sitemap" "2.0.0-beta.0" + "@docusaurus/theme-classic" "2.0.0-beta.0" + "@docusaurus/theme-search-algolia" "2.0.0-beta.0" "@docusaurus/react-loadable@5.5.0": version "5.5.0" @@ -1375,92 +1363,91 @@ dependencies: prop-types "^15.6.2" -"@docusaurus/theme-classic@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-alpha.72.tgz#355ed24e4252ad6e24b774496e4a52598013116a" - integrity sha512-X5kDmMG6xCw+PpkOysnulcq9OuSsljR7Z/JiAkOeAFfd6LNeMk983q+Eu72xWxpmhmBBBkE56rhdxuBXKQJCsw== +"@docusaurus/theme-classic@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.0.tgz#0ad74264dc592590bd7d8a6f6327cb83bbabc665" + integrity sha512-cBNtwAyg3be7Gk41FazMtgyibAcfuYaGHhGHIDRsXfc/qp3RhbiGiei7tyh200QT0NgKZxiVQy/r4d0mtjC++Q== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/plugin-content-blog" "2.0.0-alpha.72" - "@docusaurus/plugin-content-docs" "2.0.0-alpha.72" - "@docusaurus/plugin-content-pages" "2.0.0-alpha.72" - "@docusaurus/theme-common" "2.0.0-alpha.72" - "@docusaurus/types" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" - "@docusaurus/utils-validation" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/plugin-content-blog" "2.0.0-beta.0" + "@docusaurus/plugin-content-docs" "2.0.0-beta.0" + "@docusaurus/plugin-content-pages" "2.0.0-beta.0" + "@docusaurus/theme-common" "2.0.0-beta.0" + "@docusaurus/types" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" + "@docusaurus/utils-validation" "2.0.0-beta.0" "@mdx-js/mdx" "^1.6.21" "@mdx-js/react" "^1.6.21" - "@types/react-toggle" "^4.0.2" chalk "^4.1.0" clsx "^1.1.1" copy-text-to-clipboard "^3.0.0" fs-extra "^9.1.0" globby "^11.0.2" - infima "0.2.0-alpha.21" - joi "^17.4.0" + infima "0.2.0-alpha.23" lodash "^4.17.20" parse-numeric-range "^1.2.0" - postcss "^7.0.2" + postcss "^8.2.10" prism-react-renderer "^1.1.1" prismjs "^1.23.0" prop-types "^15.7.2" react-router-dom "^5.2.0" - react-toggle "^4.1.2" - rtlcss "^2.6.2" + rtlcss "^3.1.2" -"@docusaurus/theme-common@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-alpha.72.tgz#509426c81986676038e8300d457d1dc1bdda6c65" - integrity sha512-4NI3VCIBVJvOUk1YhBs2V4QwH1CR65sQQt2MFhHbeAmkKh1V0dYDFF8bVxrTSl7NhTICVk2Azn+tItRNkAXbdg== +"@docusaurus/theme-common@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.0.tgz#3674ef6482cc39efa034fd8d8b1c831588896329" + integrity sha512-2rcVmQpvbdAgnzTWuM7Bfpu+2TQm928bhlvxn226jQy7IYz8ySRlIode63HhCtpx03hpdMCkrK6HxhfEcvHjQg== dependencies: - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/plugin-content-blog" "2.0.0-alpha.72" - "@docusaurus/plugin-content-docs" "2.0.0-alpha.72" - "@docusaurus/plugin-content-pages" "2.0.0-alpha.72" - "@docusaurus/types" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/plugin-content-blog" "2.0.0-beta.0" + "@docusaurus/plugin-content-docs" "2.0.0-beta.0" + "@docusaurus/plugin-content-pages" "2.0.0-beta.0" + "@docusaurus/types" "2.0.0-beta.0" + tslib "^2.1.0" -"@docusaurus/theme-search-algolia@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-alpha.72.tgz#3b9e074f6dd38b4fe0b51ac42eec64a4735b37ec" - integrity sha512-K+7WvYx0vkclaCN6nvcX4rFD/M+0b0YpjAbg+aFLzeAo77vIJESgByOc6RuK3XNALX4H2U8k7j0+wWIPsJtM1Q== +"@docusaurus/theme-search-algolia@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.0.tgz#bfdee3981d8da72377b9045459950686d28a01fd" + integrity sha512-/GhgAm4yuwqTXWTsWnqpFYxpjTv+t45Wk8q/LmTVINa+A7b6jkMkch2lygagIt69/ufDm2Uw6eYhgrmF4DJqfQ== dependencies: "@docsearch/react" "^3.0.0-alpha.33" - "@docusaurus/core" "2.0.0-alpha.72" - "@docusaurus/theme-common" "2.0.0-alpha.72" - "@docusaurus/utils" "2.0.0-alpha.72" + "@docusaurus/core" "2.0.0-beta.0" + "@docusaurus/theme-common" "2.0.0-beta.0" + "@docusaurus/utils" "2.0.0-beta.0" + "@docusaurus/utils-validation" "2.0.0-beta.0" algoliasearch "^4.8.4" algoliasearch-helper "^3.3.4" clsx "^1.1.1" eta "^1.12.1" - joi "^17.4.0" lodash "^4.17.20" -"@docusaurus/types@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.0.0-alpha.72.tgz#5805b0536d584b67b914b937b0f08b17a47b8c18" - integrity sha512-/AfFD2Kdfm2rvG5j1v0w0L5gVuTPIE2vGOgLZh6EGzJT/Xx6CDdso9aAbhHiGfQkQS3bu1BPpLWqKlX9Ovi/aw== +"@docusaurus/types@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.0.0-beta.0.tgz#f473f417bdf690cfd52611ddf6d89ff939d1f2a4" + integrity sha512-z9PI+GbtYwqTXnkX4/a/A6psDX2p8N2uWlN2f4ifrm8WY4WhR9yiTOh0uo0pIqqaUQQvkEq3o5hOXuXLECEs+w== dependencies: - "@types/webpack" "^4.41.0" commander "^5.1.0" joi "^17.4.0" querystring "0.2.0" - webpack-merge "^4.2.2" + webpack "^5.28.0" + webpack-merge "^5.7.3" -"@docusaurus/utils-validation@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-alpha.72.tgz#38f2fa7907a57e3c5a1427b6ba0a514df1ea1d48" - integrity sha512-qhpyCVCCCTy0ui62GxXz6vLazcRCGal/jBGcgnxSgQ4AyXrU2NpPQH2hunOLknL6D3BivTb+w+IAFHE9JAMX0Q== +"@docusaurus/utils-validation@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.0.tgz#3e6491c269a397fed29717a1cb69109df9483461" + integrity sha512-ELl/FVJ6xBz35TisZ1NmJhjbiVXDeU++K531PEFPCPmwnQPh7S6hZXdPnR71/Kc3BmuN9X2ZkwGOqNKVfys2Bg== dependencies: - "@docusaurus/utils" "2.0.0-alpha.72" + "@docusaurus/utils" "2.0.0-beta.0" chalk "^4.1.0" joi "^17.4.0" + tslib "^2.1.0" -"@docusaurus/utils@2.0.0-alpha.72": - version "2.0.0-alpha.72" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-alpha.72.tgz#04469cd9fee615d76b74b01680368af41129e916" - integrity sha512-seWNBdX9LI1jREiogh0azXZaf2HStzb3MECsjAVrtEikQFbfG7K7S27C9WXDlUeQw6LVL/q0JEjHFOJD+cTSLA== +"@docusaurus/utils@2.0.0-beta.0": + version "2.0.0-beta.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.0.tgz#6f2690fd6fcd942f0d690db1dffb96742762deb3" + integrity sha512-bvrT1EQu0maavr0Hb/lke9jmpzgVL/9tn5VQtbyahf472eJFY0bQDExllDrHK+l784SUvucqX0iaQeg0q6ySUw== dependencies: - "@docusaurus/types" "2.0.0-alpha.72" + "@docusaurus/types" "2.0.0-beta.0" "@types/github-slugger" "^1.3.0" chalk "^4.1.0" escape-string-regexp "^4.0.0" @@ -1468,6 +1455,7 @@ gray-matter "^4.0.2" lodash "^4.17.20" resolve-pathname "^3.0.0" + tslib "^2.1.0" "@endiliey/static-site-generator-webpack-plugin@^4.0.0": version "4.0.0" @@ -1548,14 +1536,6 @@ "@nodelib/fs.scandir" "2.1.4" fastq "^1.6.0" -"@npmcli/move-file@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - "@polka/url@^1.0.0-next.9": version "1.0.0-next.11" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.11.tgz#aeb16f50649a91af79dbe36574b66d0f9e4d9f71" @@ -1693,10 +1673,31 @@ dependencies: defer-to-connect "^1.0.1" -"@types/anymatch@*": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" - integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== +"@trysound/sax@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669" + integrity sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow== + +"@types/eslint-scope@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86" + integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "7.2.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.10.tgz#4b7a9368d46c0f8cd5408c23288a59aa2394d917" + integrity sha512-kUEPnMKrqbtpCq/KTaGFFKAcz6Ethm2EjCoKIDaCmfRBWLbFuTcOJfTlorwbnboXBzahqWLgUp1BQeKHiJzPUQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^0.0.47": + version "0.0.47" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4" + integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg== "@types/github-slugger@^1.3.0": version "1.3.0" @@ -1723,7 +1724,7 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50" integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA== -"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.7" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== @@ -1755,32 +1756,11 @@ resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== -"@types/prop-types@*": - version "15.7.3" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" - integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== - "@types/q@^1.5.1": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/react-toggle@^4.0.2": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/react-toggle/-/react-toggle-4.0.2.tgz#46ffa5af1a55de5f25d0aa78ef0b557b5c8bf276" - integrity sha512-sHqfoKFnL0YU2+OC4meNEC8Ptx9FE8/+nFeFvNcdBa6ANA8KpAzj3R9JN8GtrvlLgjKDoYgI7iILgXYcTPo2IA== - dependencies: - "@types/react" "*" - -"@types/react@*": - version "17.0.3" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79" - integrity sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - "@types/sax@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.1.tgz#e0248be936ece791a82db1a57f3fb5f7c87e8172" @@ -1788,197 +1768,130 @@ dependencies: "@types/node" "*" -"@types/scheduler@*": - version "0.16.1" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" - integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== - -"@types/source-list-map@*": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" - integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== - -"@types/tapable@*", "@types/tapable@^1.0.5": - version "1.0.6" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74" - integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA== - -"@types/uglify-js@*": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.0.tgz#1cad8df1fb0b143c5aba08de5712ea9d1ff71124" - integrity sha512-EGkrJD5Uy+Pg0NUR8uA4bJ5WMfljyad0G+784vLCNUkD+QwOJXUbBYExXfVGf7YtyzdQp3L/XMYcliB987kL5Q== - dependencies: - source-map "^0.6.1" - "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== -"@types/webpack-sources@*": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.1.0.tgz#8882b0bd62d1e0ce62f183d0d01b72e6e82e8c10" - integrity sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg== +"@webassemblyjs/ast@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f" + integrity sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg== dependencies: - "@types/node" "*" - "@types/source-list-map" "*" - source-map "^0.7.3" + "@webassemblyjs/helper-numbers" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" -"@types/webpack@^4.41.0", "@types/webpack@^4.41.8": - version "4.41.26" - resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.26.tgz#27a30d7d531e16489f9c7607c747be6bc1a459ef" - integrity sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA== +"@webassemblyjs/floating-point-hex-parser@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz#34d62052f453cd43101d72eab4966a022587947c" + integrity sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA== + +"@webassemblyjs/helper-api-error@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz#aaea8fb3b923f4aaa9b512ff541b013ffb68d2d4" + integrity sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w== + +"@webassemblyjs/helper-buffer@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz#d026c25d175e388a7dbda9694e91e743cbe9b642" + integrity sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA== + +"@webassemblyjs/helper-numbers@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz#7ab04172d54e312cc6ea4286d7d9fa27c88cd4f9" + integrity sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ== dependencies: - "@types/anymatch" "*" - "@types/node" "*" - "@types/tapable" "*" - "@types/uglify-js" "*" - "@types/webpack-sources" "*" - source-map "^0.6.0" + "@webassemblyjs/floating-point-hex-parser" "1.11.0" + "@webassemblyjs/helper-api-error" "1.11.0" + "@xtuc/long" "4.2.2" -"@webassemblyjs/ast@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" - integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== +"@webassemblyjs/helper-wasm-bytecode@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz#85fdcda4129902fe86f81abf7e7236953ec5a4e1" + integrity sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA== + +"@webassemblyjs/helper-wasm-section@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz#9ce2cc89300262509c801b4af113d1ca25c1a75b" + integrity sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew== dependencies: - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" -"@webassemblyjs/floating-point-hex-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" - integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== - -"@webassemblyjs/helper-api-error@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" - integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== - -"@webassemblyjs/helper-buffer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" - integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== - -"@webassemblyjs/helper-code-frame@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" - integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== - dependencies: - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/helper-fsm@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" - integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== - -"@webassemblyjs/helper-module-context@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" - integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== - dependencies: - "@webassemblyjs/ast" "1.9.0" - -"@webassemblyjs/helper-wasm-bytecode@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" - integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== - -"@webassemblyjs/helper-wasm-section@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" - integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - -"@webassemblyjs/ieee754@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" - integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== +"@webassemblyjs/ieee754@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz#46975d583f9828f5d094ac210e219441c4e6f5cf" + integrity sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" - integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== +"@webassemblyjs/leb128@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.0.tgz#f7353de1df38aa201cba9fb88b43f41f75ff403b" + integrity sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" - integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== +"@webassemblyjs/utf8@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.0.tgz#86e48f959cf49e0e5091f069a709b862f5a2cadf" + integrity sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw== -"@webassemblyjs/wasm-edit@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" - integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== +"@webassemblyjs/wasm-edit@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz#ee4a5c9f677046a210542ae63897094c2027cb78" + integrity sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ== dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/helper-wasm-section" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-opt" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - "@webassemblyjs/wast-printer" "1.9.0" + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/helper-wasm-section" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" + "@webassemblyjs/wasm-opt" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" + "@webassemblyjs/wast-printer" "1.11.0" -"@webassemblyjs/wasm-gen@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" - integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== +"@webassemblyjs/wasm-gen@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz#3cdb35e70082d42a35166988dda64f24ceb97abe" + integrity sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ== dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/ieee754" "1.11.0" + "@webassemblyjs/leb128" "1.11.0" + "@webassemblyjs/utf8" "1.11.0" -"@webassemblyjs/wasm-opt@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" - integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== +"@webassemblyjs/wasm-opt@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz#1638ae188137f4bb031f568a413cd24d32f92978" + integrity sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg== dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-buffer" "1.11.0" + "@webassemblyjs/wasm-gen" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" -"@webassemblyjs/wasm-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" - integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== +"@webassemblyjs/wasm-parser@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz#3e680b8830d5b13d1ec86cc42f38f3d4a7700754" + integrity sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw== dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/helper-api-error" "1.11.0" + "@webassemblyjs/helper-wasm-bytecode" "1.11.0" + "@webassemblyjs/ieee754" "1.11.0" + "@webassemblyjs/leb128" "1.11.0" + "@webassemblyjs/utf8" "1.11.0" -"@webassemblyjs/wast-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" - integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== +"@webassemblyjs/wast-printer@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz#680d1f6a5365d6d401974a8e949e05474e1fab7e" + integrity sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ== dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/floating-point-hex-parser" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-code-frame" "1.9.0" - "@webassemblyjs/helper-fsm" "1.9.0" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/wast-printer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" - integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" + "@webassemblyjs/ast" "1.11.0" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -2004,16 +1917,16 @@ acorn-walk@^8.0.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.0.2.tgz#d4632bfc63fd93d0f15fd05ea0e984ffd3f5a8c3" integrity sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A== -acorn@^6.4.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - acorn@^8.0.4: version "8.1.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe" integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA== +acorn@^8.2.1: + version "8.2.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.2.4.tgz#caba24b08185c3b56e3168e97d15ed17f4d31fd0" + integrity sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg== + address@1.1.2, address@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" @@ -2032,12 +1945,12 @@ ajv-errors@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: +ajv-keywords@^3.1.0, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.1.0, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2074,7 +1987,7 @@ algoliasearch@^4.0.0, algoliasearch@^4.8.4: "@algolia/requester-node-http" "4.8.6" "@algolia/transporter" "4.8.6" -alphanum-sort@^1.0.0: +alphanum-sort@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= @@ -2148,11 +2061,6 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -aproba@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - arg@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.0.tgz#a20e2bb5710e82950a516b3f933fee5ed478be90" @@ -2165,6 +2073,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -2217,24 +2130,6 @@ asap@~2.0.3: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2267,7 +2162,7 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@^10.2.5: +autoprefixer@^10.0.2, autoprefixer@^10.2.5: version "10.2.5" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.2.5.tgz#096a0337dbc96c0873526d7fef5de4428d05382d" integrity sha512-7H4AJZXvSsn62SqZyJCP+1AWwOuoYpUfK6ot9vm0e87XD6mT8lDywc9D9OTJPMULyGcvmIxzTAMeG2Cc+YX+fA== @@ -2279,19 +2174,6 @@ autoprefixer@^10.2.5: normalize-range "^0.1.2" postcss-value-parser "^4.1.0" -autoprefixer@^9.4.7, autoprefixer@^9.6.1: - version "9.8.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" - integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== - dependencies: - browserslist "^4.12.0" - caniuse-lite "^1.0.30001109" - colorette "^1.2.1" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.32" - postcss-value-parser "^4.1.0" - axios@^0.21.1: version "0.21.1" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" @@ -2377,11 +2259,6 @@ base16@^1.0.0: resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA= -base64-js@^1.0.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -2422,21 +2299,11 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bluebird@^3.5.5, bluebird@^3.7.1: +bluebird@^3.7.1: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.0.0, bn.js@^5.1.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - body-parser@1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -2515,72 +2382,6 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - browserslist@4.14.2: version "4.14.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.2.tgz#1b3cec458a1ba87588cc5e9be62f19b6d48813ce" @@ -2591,7 +2392,7 @@ browserslist@4.14.2: escalade "^3.0.2" node-releases "^1.1.61" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.3, browserslist@^4.6.4: +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.3: version "4.16.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== @@ -2602,6 +2403,17 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4 escalade "^3.1.1" node-releases "^1.1.70" +browserslist@^4.16.0: + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== + dependencies: + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" + escalade "^3.1.1" + node-releases "^1.1.71" + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2612,30 +2424,6 @@ buffer-indexof@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== -buffer-json@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/buffer-json/-/buffer-json-2.0.0.tgz#f73e13b1e42f196fe2fd67d001c7d7107edd7c23" - integrity sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -2646,50 +2434,6 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@^12.0.2: - version "12.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" - integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - infer-owner "^1.0.3" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - -cacache@^15.0.5: - version "15.0.6" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.6.tgz#65a8c580fda15b59150fb76bf3f3a8e45d583099" - integrity sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w== - dependencies: - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -2705,18 +2449,6 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -cache-loader@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-4.1.0.tgz#9948cae353aec0a1fcb1eafda2300816ec85387e" - integrity sha512-ftOayxve0PwKzBF/GLsZNC9fJBXl8lkZE3TOsjkboHfVHVkL39iUEs1FO07A33mizmci5Dudt38UZrrYXDtbhw== - dependencies: - buffer-json "^2.0.0" - find-cache-dir "^3.0.0" - loader-utils "^1.2.3" - mkdirp "^0.5.1" - neo-async "^2.6.1" - schema-utils "^2.0.0" - cacheable-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" @@ -2738,25 +2470,6 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2795,17 +2508,22 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001181, caniuse-lite@^1.0.30001196: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001181, caniuse-lite@^1.0.30001196: version "1.0.30001204" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001204.tgz#256c85709a348ec4d175e847a3b515c66e79f2aa" integrity sha512-JUdjWpcxfJ9IPamy2f5JaRDCaqJOxDzOSKtbdx4rH9VivMd1vIzoPumsJa9LoMIi4Fx2BV2KZOxWhNkBjaYivQ== +caniuse-lite@^1.0.30001219: + version "1.0.30001228" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa" + integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A== + ccount@^1.0.0, ccount@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== -chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2878,7 +2596,7 @@ chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.4.1, chokidar@^3.5.1: +chokidar@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== @@ -2893,16 +2611,6 @@ chokidar@^3.4.1, chokidar@^3.5.1: optionalDependencies: fsevents "~2.3.1" -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - chrome-trace-event@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" @@ -2920,14 +2628,6 @@ ci-info@^3.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.1.1.tgz#9a32fcefdf7bcdb6f0a7e1c0f8098ec57897b80a" integrity sha512-kdRWLBIJwdsYJWYJFtAFFYxybguqeF91qpZaggjG5Nf8QKdizFG2hjqvaTXbxFIcYbSaD74KpAXv6BSm17DHEQ== -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -2938,7 +2638,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.5, classnames@^2.2.6: +classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -2985,6 +2685,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -3051,7 +2760,7 @@ color-string@^1.5.4: color-name "^1.0.0" simple-swizzle "^0.2.2" -color@^3.0.0: +color@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== @@ -3064,12 +2773,17 @@ colorette@^1.2.1, colorette@^1.2.2: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== +combine-promises@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.1.0.tgz#72db90743c0ca7aab7d0d8d2052fd7b0f674de71" + integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg== + comma-separated-tokens@^1.0.0: version "1.0.8" resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@^2.15.1, commander@^2.20.0: +commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -3089,6 +2803,11 @@ commander@^6.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== +commander@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -3124,16 +2843,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - configstore@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" @@ -3156,16 +2865,6 @@ consola@^2.15.0: resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" @@ -3200,18 +2899,6 @@ cookie@0.4.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== - dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" - copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" @@ -3222,22 +2909,18 @@ copy-text-to-clipboard@^3.0.0: resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== -copy-webpack-plugin@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz#138cd9b436dbca0a6d071720d5414848992ec47e" - integrity sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA== +copy-webpack-plugin@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-8.1.1.tgz#3f697e162764925c2f0d235f380676125508fd26" + integrity sha512-rYM2uzRxrLRpcyPqGceRBDpxxUV8vcDqIKxAUKfcnFpcrPxT5+XvhTxv7XLjo5AvEJFPdAE3zCogG2JVahqgSQ== dependencies: - cacache "^15.0.5" - fast-glob "^3.2.4" - find-cache-dir "^3.3.1" + fast-glob "^3.2.5" glob-parent "^5.1.1" - globby "^11.0.1" - loader-utils "^2.0.0" + globby "^11.0.3" normalize-path "^3.0.0" - p-limit "^3.0.2" + p-limit "^3.1.0" schema-utils "^3.0.0" serialize-javascript "^5.0.1" - webpack-sources "^1.4.3" core-js-compat@^3.8.1, core-js-compat@^3.9.0: version "3.9.1" @@ -3262,16 +2945,6 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - cosmiconfig@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" @@ -3283,37 +2956,6 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - cross-fetch@^3.0.4: version "3.1.2" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.2.tgz#ee0c2f18844c4fde36150c2a4ddc068d20c1bc41" @@ -3341,55 +2983,27 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -css-blank-pseudo@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" - integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== - dependencies: - postcss "^7.0.5" - -css-color-names@0.0.4, css-color-names@^0.0.4: +css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== - dependencies: - postcss "^7.0.1" - timsort "^0.3.0" +css-color-names@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-1.0.1.tgz#6ff7ee81a823ad46e020fa2fd6ab40a887e2ba67" + integrity sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA== -css-has-pseudo@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" - integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== +css-declaration-sorter@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.0.0.tgz#eb21f75860078627e9e3cc6f5535ccfcea445817" + integrity sha512-S0TE4E0ha5+tBHdLWPc5n+S8E4dFBS5xScPvgHkLNZwWvX4ISoFGhGeerLC9uS1cKA/sC+K2wHq6qEbcagT/fg== dependencies: - postcss "^7.0.6" - postcss-selector-parser "^5.0.0-rc.4" + timsort "^0.3.0" css-loader@^5.1.1: version "5.1.4" @@ -3409,12 +3023,18 @@ css-loader@^5.1.1: schema-utils "^3.0.0" semver "^7.3.4" -css-prefers-color-scheme@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" - integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== +css-minimizer-webpack-plugin@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-2.0.0.tgz#3c42f6624ed4cf4780dd963e23ee649e5a25c1a8" + integrity sha512-cG/uc94727tx5pBNtb1Sd7gvUPzwmcQi1lkpfqTpdkuNq75hJCw7bIVsCNijLm4dhDcr1atvuysl2rZqOG8Txw== dependencies: - postcss "^7.0.5" + cssnano "^5.0.0" + jest-worker "^26.3.0" + p-limit "^3.0.2" + postcss "^8.2.9" + schema-utils "^3.0.0" + serialize-javascript "^5.0.1" + source-map "^0.6.1" css-select-base-adapter@^0.1.1: version "0.1.1" @@ -3431,6 +3051,17 @@ css-select@^2.0.0, css-select@^2.0.2: domutils "^1.7.0" nth-check "^1.0.2" +css-select@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-3.1.2.tgz#d52cbdc6fee379fba97fb0d3925abbd18af2d9d8" + integrity sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA== + dependencies: + boolbase "^1.0.0" + css-what "^4.0.0" + domhandler "^4.0.0" + domutils "^2.4.3" + nth-check "^2.0.0" + css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" @@ -3467,118 +3098,84 @@ css-what@^3.2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== -cssdb@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" - integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== - -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== +css-what@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-4.0.0.tgz#35e73761cab2eeb3d3661126b23d7aa0e8432233" + integrity sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A== cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-advanced@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-4.0.7.tgz#d981527b77712e2f3f3f09c73313e9b71b278b88" - integrity sha512-j1O5/DQnaAqEyFFQfC+Z/vRlLXL3LxJHN+lvsfYqr7KgPH74t69+Rsy2yXkovWNaJjZYBpdz2Fj8ab2nH7pZXw== +cssnano-preset-advanced@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.0.1.tgz#b551bb9ad3abf7a9a79f0cace3bf50264018df64" + integrity sha512-g+LB6GcihLXcBEdDh+mzk1qX9jgtBkVpzAg1OlgrH6C+qKIQYRHwAPyaoXy95Ci83sYYXlwJ0OrqLYTIUEBLZQ== dependencies: - autoprefixer "^9.4.7" - cssnano-preset-default "^4.0.7" - postcss-discard-unused "^4.0.1" - postcss-merge-idents "^4.0.1" - postcss-reduce-idents "^4.0.2" - postcss-zindex "^4.0.1" + autoprefixer "^10.0.2" + cssnano-preset-default "^5.0.1" + postcss-discard-unused "^5.0.0" + postcss-merge-idents "^5.0.0" + postcss-reduce-idents "^5.0.0" + postcss-zindex "^5.0.0" -cssnano-preset-default@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" - integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== +cssnano-preset-default@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.0.1.tgz#76adc00f7aae36ae80552b8356e21bec4b233ca2" + integrity sha512-cfmfThYODGqhpQKDq9H0MTAqkMvZ3dGbOUTBKw0xWZiIycMqHid22LsJXJl4r1qX4qzDeKxcSyQ/Xb5Mu3Z//Q== dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.1" - postcss-colormin "^4.0.3" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.2" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.11" - postcss-merge-rules "^4.0.3" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.2" - postcss-minify-params "^4.0.2" - postcss-minify-selectors "^4.0.2" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.2" - postcss-normalize-positions "^4.0.2" - postcss-normalize-repeat-style "^4.0.2" - postcss-normalize-string "^4.0.2" - postcss-normalize-timing-functions "^4.0.2" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.2" - postcss-ordered-values "^4.1.2" - postcss-reduce-initial "^4.0.3" - postcss-reduce-transforms "^4.0.2" - postcss-svgo "^4.0.2" - postcss-unique-selectors "^4.0.1" + css-declaration-sorter "6.0.0" + cssnano-utils "^2.0.0" + postcss-calc "^8.0.0" + postcss-colormin "^5.0.0" + postcss-convert-values "^5.0.0" + postcss-discard-comments "^5.0.0" + postcss-discard-duplicates "^5.0.0" + postcss-discard-empty "^5.0.0" + postcss-discard-overridden "^5.0.0" + postcss-merge-longhand "^5.0.1" + postcss-merge-rules "^5.0.0" + postcss-minify-font-values "^5.0.0" + postcss-minify-gradients "^5.0.0" + postcss-minify-params "^5.0.0" + postcss-minify-selectors "^5.0.0" + postcss-normalize-charset "^5.0.0" + postcss-normalize-display-values "^5.0.0" + postcss-normalize-positions "^5.0.0" + postcss-normalize-repeat-style "^5.0.0" + postcss-normalize-string "^5.0.0" + postcss-normalize-timing-functions "^5.0.0" + postcss-normalize-unicode "^5.0.0" + postcss-normalize-url "^5.0.0" + postcss-normalize-whitespace "^5.0.0" + postcss-ordered-values "^5.0.0" + postcss-reduce-initial "^5.0.0" + postcss-reduce-transforms "^5.0.0" + postcss-svgo "^5.0.0" + postcss-unique-selectors "^5.0.0" -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= +cssnano-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-2.0.0.tgz#b04baaa312aa3dd5a854b7f61d76b9d94be07f74" + integrity sha512-xvxmTszdrvSyTACdPe8VU5J6p4sm3egpgw54dILvNqt5eBUv6TFjACLhSxtRuEsxYrgy8uDy269YjScO5aKbGA== -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== +cssnano@^5.0.0, cssnano@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.2.tgz#3f6de4fd5ecb7b5fb636c1a606de5f38cd241493" + integrity sha512-8JK3EnPsjQsULme9/e5M2hF564f/480hwsdcHvQ7ZtAIMfQ1O3SCfs+b8Mjf5KJxhYApyRshR2QSovEJi2K72Q== dependencies: - postcss "^7.0.0" + cosmiconfig "^7.0.0" + cssnano-preset-default "^5.0.1" + is-resolvable "^1.1.0" -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^4.1.10: - version "4.1.10" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" - integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.7" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -csso@^4.0.2: +csso@^4.0.2, csso@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== dependencies: css-tree "^1.1.2" -csstype@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b" - integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g== - -cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3657,7 +3254,7 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== -define-properties@^1.1.2, define-properties@^1.1.3: +define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -3723,14 +3320,6 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" @@ -3764,15 +3353,6 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3786,9 +3366,9 @@ dns-equal@^1.0.0: integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= dns-packet@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" - integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== dependencies: ip "^1.1.0" safe-buffer "^5.0.1" @@ -3815,6 +3395,15 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" +dom-serializer@^1.0.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" + integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + dom-serializer@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" @@ -3823,11 +3412,6 @@ dom-serializer@~0.1.0: domelementtype "^1.3.0" entities "^1.1.1" -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" @@ -3838,6 +3422,11 @@ domelementtype@^2.0.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w== +domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== + domhandler@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" @@ -3845,6 +3434,13 @@ domhandler@^2.3.0: dependencies: domelementtype "1" +domhandler@^4.0.0, domhandler@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" + integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA== + dependencies: + domelementtype "^2.2.0" + domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" @@ -3861,6 +3457,15 @@ domutils@^1.5.1, domutils@^1.7.0: dom-serializer "0" domelementtype "1" +domutils@^2.4.3: + version "2.6.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.6.0.tgz#2e15c04185d43fb16ae7057cb76433c6edb938b7" + integrity sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -3886,16 +3491,6 @@ duplexer@^0.1.1, duplexer@^0.1.2: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== -duplexify@^3.4.2, duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -3906,18 +3501,10 @@ electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.649: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.698.tgz#5de813960f23581a268718a0058683dffa15d221" integrity sha512-VEXDzYblnlT+g8Q3gedwzgKOso1evkeJzV8lih7lV8mL8eAnGVnKyC3KsFT6S+R5PQO4ffdr1PI16/ElibY/kQ== -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" +electron-to-chromium@^1.3.723: + version "1.3.732" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.732.tgz#2a07a8d61f74f2084b6f6bf2a908605a7a0b2d8d" + integrity sha512-qKD5Pbq+QMk4nea4lMuncUMhpEiQwaJyCW7MrvissnRcBDENhVfDmAqQYRQ3X525oTzhar9Zh1cK0L2d1UKYcw== "emoji-regex@>=6.0.0 <=6.1.1": version "6.1.1" @@ -3949,21 +3536,20 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.0.0, end-of-stream@^1.1.0: +end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -enhanced-resolve@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" - integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== +enhanced-resolve@^5.8.0: + version "5.8.2" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz#15ddc779345cbb73e97c611cd00c01c1e7bf4d8b" + integrity sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA== dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" + graceful-fs "^4.2.4" + tapable "^2.2.0" entities@^1.1.1, entities@~1.1.1: version "1.1.2" @@ -3975,7 +3561,7 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -errno@^0.1.3, errno@~0.1.7: +errno@^0.1.3: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== @@ -4011,6 +3597,11 @@ es-abstract@^1.17.2, es-abstract@^1.18.0-next.2: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.0" +es-module-lexer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e" + integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA== + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -4050,12 +3641,12 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - esrecurse "^4.1.0" + esrecurse "^4.3.0" estraverse "^4.1.1" esprima@^4.0.0: @@ -4063,7 +3654,7 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esrecurse@^4.1.0: +esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== @@ -4112,7 +3703,7 @@ events@^1.1.1: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= -events@^3.0.0: +events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -4124,14 +3715,6 @@ eventsource@^1.0.7: dependencies: original "^1.0.0" -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -4248,7 +3831,7 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.4: +fast-glob@^3.1.1, fast-glob@^3.2.5: version "3.2.5" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg== @@ -4318,11 +3901,6 @@ feed@^4.2.2: dependencies: xml-js "^1.6.11" -figgy-pudding@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" - integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== - figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -4378,16 +3956,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-cache-dir@^3.0.0, find-cache-dir@^3.3.1: +find-cache-dir@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== @@ -4411,18 +3980,13 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -flatten@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" - integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== - -flush-write-stream@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" + locate-path "^6.0.0" + path-exists "^4.0.0" flux@^4.0.1: version "4.0.1" @@ -4477,14 +4041,6 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -from2@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -4495,23 +4051,6 @@ fs-extra@^9.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - -fs-write-stream-atomic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= - dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -4605,7 +4144,12 @@ glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.3, glob@^7.1.4: +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.0.0, glob@^7.0.3, glob@^7.1.3: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -4657,7 +4201,7 @@ globby@11.0.1: merge2 "^1.3.0" slash "^3.0.0" -globby@^11.0.1, globby@^11.0.2: +globby@^11.0.1, globby@^11.0.2, globby@^11.0.3: version "11.0.3" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb" integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg== @@ -4704,7 +4248,7 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.6" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== @@ -4795,30 +4339,13 @@ has-yarn@^2.1.0: resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== -has@^1.0.0, has@^1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - hast-to-hyperscript@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" @@ -4930,15 +4457,6 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - hoist-non-react-statics@^3.1.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -4966,11 +4484,6 @@ hsla-regex@^1.0.0: resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= -html-comment-regex@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== - html-entities@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" @@ -4999,20 +4512,16 @@ html-void-elements@^1.0.0: resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== -html-webpack-plugin@^4.5.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz#76fc83fa1a0f12dd5f7da0404a54e2699666bc12" - integrity sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A== +html-webpack-plugin@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.3.1.tgz#8797327548e3de438e3494e0c6d06f181a7f20d1" + integrity sha512-rZsVvPXUYFyME0cuGkyOHfx9hmkFa4pWfxY/mdY38PsBEaVNsRoA+Id+8z6DBDgyv3zaw6XQszdF8HLwfQvcdQ== dependencies: "@types/html-minifier-terser" "^5.0.0" - "@types/tapable" "^1.0.5" - "@types/webpack" "^4.41.8" html-minifier-terser "^5.0.1" - loader-utils "^1.2.3" lodash "^4.17.20" pretty-error "^2.1.1" - tapable "^1.1.3" - util.promisify "1.0.0" + tapable "^2.0.0" htmlparser2@^3.10.1, htmlparser2@^3.9.1: version "3.10.1" @@ -5092,11 +4601,6 @@ http-proxy@^1.17.0: follow-redirects "^1.0.0" requires-port "^1.0.0" -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -5114,16 +4618,6 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= - ignore@^5.1.4: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" @@ -5134,14 +4628,6 @@ immer@8.0.1: resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -5178,15 +4664,10 @@ indexes-of@^1.0.1: resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= -infer-owner@^1.0.3, infer-owner@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -infima@0.2.0-alpha.21: - version "0.2.0-alpha.21" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.21.tgz#53cc49dbcaf5a8d165cbe4acf214eee02bca6154" - integrity sha512-32uq+rWIrLNZx0jzNrwJWE8Go9NvpP0JTRKMXJ8aYlWZ0vm9OCgAEcVquwFBSW6ZP7R2rjBUjPy/nJ3PK7MhUA== +infima@0.2.0-alpha.23: + version "0.2.0-alpha.23" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.23.tgz#2c17b473784ae8244fd985f126f9c27a49b24523" + integrity sha512-V0RTjB1otjpH3E2asbydx3gz7ovdSJsuV7r9JTdBggqRilnelTJUcXxLawBQQKsjQi5qPcRTjxnlaV8xyyKhhw== inflight@^1.0.4: version "1.0.6" @@ -5196,16 +4677,11 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -5254,11 +4730,6 @@ ipaddr.js@1.9.1, ipaddr.js@^1.9.0: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= - is-absolute-url@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" @@ -5356,7 +4827,7 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-color-stop@^1.0.0: +is-color-stop@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= @@ -5417,11 +4888,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - is-docker@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" @@ -5542,11 +5008,6 @@ is-path-inside@^3.0.2: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-plain-obj@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - is-plain-obj@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" @@ -5572,7 +5033,7 @@ is-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= -is-resolvable@^1.0.0: +is-resolvable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== @@ -5597,13 +5058,6 @@ is-string@^1.0.5: resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== -is-svg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== - dependencies: - html-comment-regex "^1.1.0" - is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -5653,7 +5107,7 @@ isarray@0.0.1: resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -5675,7 +5129,7 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -jest-worker@^26.5.0: +jest-worker@^26.3.0, jest-worker@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== @@ -5708,6 +5162,13 @@ js-yaml@^3.11.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -5723,7 +5184,7 @@ json-buffer@3.0.0: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: +json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== @@ -5812,14 +5273,6 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== -last-call-webpack-plugin@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" - integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== - dependencies: - lodash "^4.17.5" - webpack-sources "^1.1.0" - latest-version@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -5837,10 +5290,10 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= -loader-runner@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" - integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== +loader-runner@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" + integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== loader-utils@2.0.0, loader-utils@^2.0.0: version "2.0.0" @@ -5851,7 +5304,7 @@ loader-utils@2.0.0, loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" -loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -5875,10 +5328,12 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" lodash.assignin@^4.0.9: version "4.2.0" @@ -5960,21 +5415,6 @@ lodash.some@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= -lodash.template@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.toarray@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" @@ -5985,7 +5425,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6019,13 +5459,6 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -6033,14 +5466,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -make-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -6065,15 +5490,6 @@ markdown-escapes@^1.0.0: resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - mdast-squeeze-paragraphs@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" @@ -6135,14 +5551,6 @@ memory-fs@^0.4.1: errno "^0.1.3" readable-stream "^2.0.1" -memory-fs@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" - integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -6195,14 +5603,6 @@ micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - mime-db@1.46.0, "mime-db@>= 1.43.0 < 2": version "1.46.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" @@ -6255,26 +5655,20 @@ mini-create-react-context@^0.4.0: "@babel/runtime" "^7.12.1" tiny-warning "^1.0.3" -mini-css-extract-plugin@^0.8.0: - version "0.8.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.2.tgz#a875e169beb27c88af77dd962771c9eedc3da161" - integrity sha512-a3Y4of27Wz+mqK3qrcd3VhYz6cU0iW5x3Sgvqzbj+XmlrSizmvu8QQMl5oMYJjgHOC4iyt+w7l4umP+dQeW3bw== +mini-css-extract-plugin@^1.4.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.0.tgz#b4db2525af2624899ed64a23b0016e0036411893" + integrity sha512-nPFKI7NSy6uONUo9yn2hIfb9vyYvkFu95qki0e21DQ9uaqNKDP15DGpK0KnV6wDroWxPHtExrdEwx/yDQ8nVRw== dependencies: - loader-utils "^1.1.0" - normalize-url "1.9.1" - schema-utils "^1.0.0" + loader-utils "^2.0.0" + schema-utils "^3.0.0" webpack-sources "^1.1.0" -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: +minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -6287,58 +5681,6 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -minipass-collect@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" - integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== - dependencies: - minipass "^3.0.0" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass@^3.0.0, minipass@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" - integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== - dependencies: - yallist "^4.0.0" - -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mississippi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^3.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -6347,14 +5689,14 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: +mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" -mkdirp@^1.0.3, mkdirp@^1.0.4: +mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -6364,18 +5706,6 @@ module-alias@^2.2.2: resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0" integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q== -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6414,10 +5744,10 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@^3.1.20: - version "3.1.22" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844" - integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ== +nanoid@^3.1.23: + version "3.1.23" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" + integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== nanomatch@^1.2.9: version "1.2.13" @@ -6441,7 +5771,7 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.1: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -6476,40 +5806,16 @@ node-forge@^0.10.0: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - node-releases@^1.1.61, node-releases@^1.1.70: version "1.1.71" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== +node-releases@^1.1.71: + version "1.1.72" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" + integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== + normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -6527,22 +5833,7 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-url@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= - dependencies: - object-assign "^4.0.1" - prepend-http "^1.0.0" - query-string "^4.1.0" - sort-keys "^1.0.0" - -normalize-url@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - -normalize-url@^4.1.0: +normalize-url@^4.1.0, normalize-url@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== @@ -6573,18 +5864,12 @@ nth-check@^1.0.2, nth-check@~1.0.1: dependencies: boolbase "~1.0.0" -null-loader@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/null-loader/-/null-loader-4.0.1.tgz#8e63bd3a2dd3c64236a4679428632edd0a6dbc6a" - integrity sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg== +nth-check@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125" + integrity sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q== dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= + boolbase "^1.0.0" object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" @@ -6635,7 +5920,7 @@ object.assign@^4.1.0, object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" -object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: +object.getownpropertydescriptors@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== @@ -6712,14 +5997,6 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" -optimize-css-assets-webpack-plugin@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz#85883c6528aaa02e30bbad9908c92926bb52dc90" - integrity sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A== - dependencies: - cssnano "^4.1.10" - last-call-webpack-plugin "^3.0.0" - original@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" @@ -6727,11 +6004,6 @@ original@^1.0.0: dependencies: url-parse "^1.4.3" -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -6749,7 +6021,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2: +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -6770,6 +6042,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -6804,20 +6083,6 @@ package-json@^6.3.0: registry-url "^5.0.0" semver "^6.2.0" -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parallel-transform@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" - integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== - dependencies: - cyclist "^1.0.1" - inherits "^2.0.3" - readable-stream "^2.1.5" - param-case@^3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" @@ -6833,17 +6098,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - parse-entities@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" @@ -6856,14 +6110,6 @@ parse-entities@^2.0.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - parse-json@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -6907,11 +6153,6 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -6974,17 +6215,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pbkdf2@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" - integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -7033,13 +6263,6 @@ pkg-up@3.1.0: dependencies: find-up "^3.0.0" -pnp-webpack-plugin@^1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" - integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== - dependencies: - ts-pnp "^1.1.6" - portfinder@^1.0.26: version "1.0.28" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" @@ -7054,317 +6277,128 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -postcss-attribute-case-insensitive@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" - integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== +postcss-calc@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.0.0.tgz#a05b87aacd132740a5db09462a3612453e5df90a" + integrity sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g== dependencies: - postcss "^7.0.2" - postcss-selector-parser "^6.0.2" - -postcss-calc@^7.0.1: - version "7.0.5" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" - integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== - dependencies: - postcss "^7.0.27" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.0.2" -postcss-color-functional-notation@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" - integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-gray@^5.0.0: +postcss-colormin@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" - integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.0.0.tgz#283b8934c8bdbc531e7648aeb0970107f6d06d0e" + integrity sha512-Yt84+5V6CgS/AhK7d7MA58vG8dSZ7+ytlRtWLaQhag3HXOncTfmYpuUOX4cDoXjvLfw1sHRCHMiBjYhc35CymQ== dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.5" - postcss-values-parser "^2.0.0" + browserslist "^4.16.0" + color "^3.1.1" + postcss-value-parser "^4.1.0" -postcss-color-hex-alpha@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" - integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== - dependencies: - postcss "^7.0.14" - postcss-values-parser "^2.0.1" - -postcss-color-mod-function@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" - integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-rebeccapurple@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" - integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-colormin@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== - dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-custom-media@^7.0.8: - version "7.0.8" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" - integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== - dependencies: - postcss "^7.0.14" - -postcss-custom-properties@^8.0.11: - version "8.0.11" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" - integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== - dependencies: - postcss "^7.0.17" - postcss-values-parser "^2.0.1" - -postcss-custom-selectors@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" - integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-dir-pseudo-class@^5.0.0: +postcss-convert-values@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" - integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.0.tgz#cd77e1d23ebe8fcf508640551eed08e232784cba" + integrity sha512-V5kmYm4xoBAjNs+eHY/6XzXJkkGeg4kwNf2ocfqhLb1WBPEa4oaSmoi1fnVO7Dkblqvus9h+AenDvhCKUCK7uQ== dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" + postcss-value-parser "^4.1.0" -postcss-discard-comments@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== +postcss-discard-comments@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.0.tgz#6c27310e0657c0b9e38a6175ad001b5aa28964bc" + integrity sha512-Umig6Gxs8m20RihiXY6QkePd6mp4FxkA1Dg+f/Kd6uw0gEMfKRjDeQOyFkLibexbJJGHpE3lrN/Q0R9SMrUMbQ== + +postcss-discard-duplicates@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.0.tgz#6a2c4f779e8d20da6781e90730f234f9e650c51c" + integrity sha512-vEJJ+Y3pFUnO1FyCBA6PSisGjHtnphL3V6GsNvkASq/VkP3OX5/No5RYXXLxHa2QegStNzg6HYrYdo71uR4caQ== + +postcss-discard-empty@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.0.tgz#0f0a9baee415f5f7be4ae046ba235e98626ba821" + integrity sha512-+wigy099Y1xZxG36WG5L1f2zeH1oicntkJEW4TDIqKKDO2g9XVB3OhoiHTu08rDEjLnbcab4rw0BAccwi2VjiQ== + +postcss-discard-overridden@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.0.tgz#ac00f695a60001eda52135a11fac87376b8da9ee" + integrity sha512-hybnScTaZM2iEA6kzVQ6Spozy7kVdLw+lGw8hftLlBEzt93uzXoltkYp9u0tI8xbfhxDLTOOzHsHQCkYdmzRUg== + +postcss-discard-unused@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.0.0.tgz#6aad1061a53088d4b4d4363496d85b9b0de34f7e" + integrity sha512-C+bchjnGRoGlSQjACMts/FlpY3LMDEUS5+9rHKxvl/NFUY/5OYWjkA1AEUo9HDWnFB44CFgcm6khLMSIbrjVEQ== dependencies: - postcss "^7.0.0" + postcss-selector-parser "^6.0.4" -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" - -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" - -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" - -postcss-discard-unused@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-4.0.1.tgz#ee7cc66af8c7e8c19bd36f12d09c4bde4039abea" - integrity sha512-/3vq4LU0bLH2Lj4NYN7BTf2caly0flUB7Xtrk9a5K3yLuXMkHMqMO/x3sDq8W2b1eQFSCyY0IVz2L+0HP8kUUA== - dependencies: - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - uniqs "^2.0.0" - -postcss-double-position-gradients@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" - integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== - dependencies: - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-env-function@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" - integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-focus-visible@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" - integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== - dependencies: - postcss "^7.0.2" - -postcss-focus-within@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" - integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== - dependencies: - postcss "^7.0.2" - -postcss-font-variant@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" - integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA== - dependencies: - postcss "^7.0.2" - -postcss-gap-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" - integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== - dependencies: - postcss "^7.0.2" - -postcss-image-set-function@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" - integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-initial@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" - integrity sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA== - dependencies: - lodash.template "^4.5.0" - postcss "^7.0.2" - -postcss-lab-function@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" - integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-loader@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-4.2.0.tgz#f6993ea3e0f46600fb3ee49bbd010448123a7db4" - integrity sha512-mqgScxHqbiz1yxbnNcPdKYo/6aVt+XExURmEbQlviFVWogDbM4AJ0A/B+ZBpYsJrTRxKw7HyRazg9x0Q9SWwLA== +postcss-loader@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-5.3.0.tgz#1657f869e48d4fdb018a40771c235e499ee26244" + integrity sha512-/+Z1RAmssdiSLgIZwnJHwBMnlABPgF7giYzTN2NOfr9D21IJZ4mQC1R2miwp80zno9M4zMD/umGI8cR+2EL5zw== dependencies: cosmiconfig "^7.0.0" klona "^2.0.4" - loader-utils "^2.0.0" - schema-utils "^3.0.0" semver "^7.3.4" -postcss-logical@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" - integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== +postcss-merge-idents@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.0.0.tgz#13b6598912a96e93552c778bbfeaaf2cfaf46b68" + integrity sha512-s8wwhAB/SJDPkcVxj31s2SGzgrO66ktUYjWh6j4qwY67Mzxx3/TkK+m/+v6tU/xyW4TmGd4yuyTXsHaaLC0jLg== dependencies: - postcss "^7.0.2" + cssnano-utils "^2.0.0" + postcss-value-parser "^4.1.0" -postcss-media-minmax@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" - integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== +postcss-merge-longhand@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.1.tgz#1a008ff72d14cd3e2f3d32accc2ad37948bcabf4" + integrity sha512-H1RO8le5deFGumQzuhJjuL0bIXPRysa+w7xtk5KrHe38oiaSS9ksPXDo24+IOS3SETPhip0J5+1uCOW+ALs3Yw== dependencies: - postcss "^7.0.2" + css-color-names "^1.0.1" + postcss-value-parser "^4.1.0" + stylehacks "^5.0.0" -postcss-merge-idents@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-4.0.1.tgz#b7df282a92f052ea0a66c62d8f8812e6d2cbed23" - integrity sha512-43S/VNdF6II0NZ31YxcvNYq4gfURlPAAsJW/z84avBXQCaP4I4qRHUH18slW/SOlJbcxxCobflPNUApYDddS7A== +postcss-merge-rules@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.0.tgz#e0d0c0d45c98376f4adb49eb1f1dfe2aebfd7048" + integrity sha512-TfsXbKjNYCGfUPEXGIGPySnMiJbdS+3gcVeV8gwmJP4RajyKZHW8E0FYDL1WmggTj3hi+m+WUCAvqRpX2ut4Kg== dependencies: - cssnano-util-same-parent "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-merge-longhand@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== - dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" - -postcss-merge-rules@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== - dependencies: - browserslist "^4.0.0" + browserslist "^4.16.0" caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" + cssnano-utils "^2.0.0" + postcss-selector-parser "^6.0.4" + vendors "^1.0.3" -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== +postcss-minify-font-values@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.0.tgz#fee5d0fa192fae8757cb744870a0ad02be5f402e" + integrity sha512-zi2JhFaMOcIaNxhndX5uhsqSY1rexKDp23wV8EOmC9XERqzLbHsoRye3aYF716Zm+hkcR4loqKDt8LZlmihwAg== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-minify-gradients@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== +postcss-minify-gradients@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.0.tgz#95dbe61567a45c0cd7ab897d78fb65d5096844ed" + integrity sha512-/jPtNgs6JySMwgsE5dPOq8a2xEopWTW3RyqoB9fLqxgR+mDUNLSi7joKd+N1z7FXWgVkc4l/dEBMXHgNAaUbvg== dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.0" + is-color-stop "^1.1.0" + postcss-value-parser "^4.1.0" -postcss-minify-params@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== +postcss-minify-params@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.0.tgz#12c7f75d69b0b4827fafbd6649970a53784a9c24" + integrity sha512-KvZYIxTPBVKjdd+XgObq9A+Sfv8lMkXTpbZTsjhr42XbfWIeLaTItMlygsDWfjArEc3muUfDaUFgNSeDiJ5jug== dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + alphanum-sort "^1.0.2" + browserslist "^4.16.0" + cssnano-utils "^2.0.0" + postcss-value-parser "^4.1.0" uniqs "^2.0.0" -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== +postcss-minify-selectors@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.0.0.tgz#d3e43d97fd0ba83ba0010950fc5acfa420f7caa9" + integrity sha512-cEM0O0eWwFIvmo6nfB0lH0vO/XFwgqIvymODbfPXZ1gTA3i76FKnb7TGUrEpiTxaXH6tgYQ6DcTHwRiRS+YQLQ== dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" + alphanum-sort "^1.0.2" + postcss-selector-parser "^3.1.2" postcss-modules-extract-imports@^3.0.0: version "3.0.0" @@ -7394,228 +6428,105 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-nesting@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" - integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== - dependencies: - postcss "^7.0.2" +postcss-normalize-charset@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.0.tgz#59e1fe2094fb2e3371cc5b054cbc39828a41a710" + integrity sha512-pqsCkgo9KmQP0ew6DqSA+uP9YN6EfsW20pQ3JU5JoQge09Z6Too4qU0TNDsTNWuEaP8SWsMp+19l15210MsDZQ== -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== +postcss-normalize-display-values@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.0.tgz#4ff2d3b3b5146a366de28ec9e24131a1868f1933" + integrity sha512-t4f2d//gH1f7Ns0Jq3eNdnWuPT7TeLuISZ6RQx4j8gpl5XrhkdshdNcOnlrEK48YU6Tcb6jqK7dorME3N4oOGA== dependencies: - postcss "^7.0.0" + cssnano-utils "^2.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-display-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== +postcss-normalize-positions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.0.tgz#fe1d9a8122dd385b9c6908bd2008140dea17750d" + integrity sha512-0o6/qU5ky74X/eWYj/tv4iiKCm3YqJnrhmVADpIMNXxzFZywsSQxl8F7cKs8jQEtF3VrJBgcDHTexZy1zgDoYg== dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-positions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== +postcss-normalize-repeat-style@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.0.tgz#e11d88fbf63f89179c6a7391853b2fe7f46e589d" + integrity sha512-KRT14JbrXKcFMYuc4q7lh8lvv8u22wLyMrq+UpHKLtbx2H/LOjvWXYdoDxmNrrrJzomAWL+ViEXr48/IhSUJnQ== dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-repeat-style@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== +postcss-normalize-string@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.0.tgz#2ea08ff4cb8817ce160755e9fdc7e6ef6d495002" + integrity sha512-wSO4pf7GNcDZpmelREWYADF1+XZWrAcbFLQCOqoE92ZwYgaP/RLumkUTaamEzdT2YKRZAH8eLLKGWotU/7FNPw== dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-string@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== +postcss-normalize-timing-functions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.0.tgz#380eb1c9b179f96efc307c659a8049116f16f381" + integrity sha512-TwPaDX+wl9wO3MUm23lzGmOzGCGKnpk+rSDgzB2INpakD5dgWR3L6bJq1P1LQYzBAvz8fRIj2NWdnZdV4EV98Q== dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-timing-functions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== +postcss-normalize-unicode@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.0.tgz#aa46a89c86ae51a01cbca13e73c1ed7b0b38807e" + integrity sha512-2CpVoz/67rXU5s9tsPZDxG1YGS9OFHwoY9gsLAzrURrCxTAb0H7Vp87/62LvVPgRWTa5ZmvgmqTp2rL8tlm72A== dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + browserslist "^4.16.0" + postcss-value-parser "^4.1.0" -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== +postcss-normalize-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.0.tgz#626a4c7d30007f94466cdf245e7ed9f253f1dbd9" + integrity sha512-ICDaGFBqLgA3dlrCIRuhblLl80D13YtgEV9NJPTYJtgR72vu61KgxAHv+z/lKMs1EbwfSQa3ALjOFLSmXiE34A== dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + is-absolute-url "^3.0.3" + normalize-url "^4.5.0" + postcss-value-parser "^4.1.0" -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== +postcss-normalize-whitespace@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.0.tgz#1faf147a4f8d3d93a3c75109d120b4eefa00589b" + integrity sha512-KRnxQvQAVkJfaeXSz7JlnD9nBN9sFZF9lrk9452Q2uRoqrRSkinqifF8Iex7wZGei2DZVG/qpmDFDmRvbNAOGA== dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-whitespace@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== +postcss-ordered-values@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.0.tgz#a50f224c5f40c566b338b0663655478737dcebee" + integrity sha512-dPr+SRObiHueCIc4IUaG0aOGQmYkuNu50wQvdXTGKy+rzi2mjmPsbeDsheLk5WPb9Zyf2tp8E+I+h40cnivm6g== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.0" + postcss-value-parser "^4.1.0" -postcss-ordered-values@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== +postcss-reduce-idents@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.0.0.tgz#a6fbc9369b955daa756fe578de2ed916c01eed56" + integrity sha512-wDth7wkXAZ91i7GNe+/PJKyC9NOR2n04U0t5nnqlvlkKhMhnRn/8NJLYQRa7ZZHPGOZcOfvugrhblioTTg2X8A== dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-overflow-shorthand@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" - integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== +postcss-reduce-initial@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.0.tgz#c724e5513b0ae7f3d7bff16f0fc82133fb2f820a" + integrity sha512-wR6pXUaFbSMG1oCKx8pKVA+rnSXCHlca5jMrlmkmif+uig0HNUTV9oGN5kjKsM3mATQAldv2PF9Tbl2vqLFjnA== dependencies: - postcss "^7.0.2" - -postcss-page-break@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" - integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== - dependencies: - postcss "^7.0.2" - -postcss-place@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" - integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-preset-env@^6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" - integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== - dependencies: - autoprefixer "^9.6.1" - browserslist "^4.6.4" - caniuse-lite "^1.0.30000981" - css-blank-pseudo "^0.1.4" - css-has-pseudo "^0.10.0" - css-prefers-color-scheme "^3.1.1" - cssdb "^4.4.0" - postcss "^7.0.17" - postcss-attribute-case-insensitive "^4.0.1" - postcss-color-functional-notation "^2.0.1" - postcss-color-gray "^5.0.0" - postcss-color-hex-alpha "^5.0.3" - postcss-color-mod-function "^3.0.3" - postcss-color-rebeccapurple "^4.0.1" - postcss-custom-media "^7.0.8" - postcss-custom-properties "^8.0.11" - postcss-custom-selectors "^5.1.2" - postcss-dir-pseudo-class "^5.0.0" - postcss-double-position-gradients "^1.0.0" - postcss-env-function "^2.0.2" - postcss-focus-visible "^4.0.0" - postcss-focus-within "^3.0.0" - postcss-font-variant "^4.0.0" - postcss-gap-properties "^2.0.0" - postcss-image-set-function "^3.0.1" - postcss-initial "^3.0.0" - postcss-lab-function "^2.0.1" - postcss-logical "^3.0.0" - postcss-media-minmax "^4.0.0" - postcss-nesting "^7.0.0" - postcss-overflow-shorthand "^2.0.0" - postcss-page-break "^2.0.0" - postcss-place "^4.0.1" - postcss-pseudo-class-any-link "^6.0.0" - postcss-replace-overflow-wrap "^3.0.0" - postcss-selector-matches "^4.0.0" - postcss-selector-not "^4.0.0" - -postcss-pseudo-class-any-link@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" - integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-reduce-idents@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-4.0.2.tgz#30447a6ec20941e78e21bd4482a11f569c4f455b" - integrity sha512-Tz70Ri10TclPoCtFfftjFVddx3fZGUkr0dEDbIEfbYhFUOFQZZ77TEqRrU0e6TvAvF+Wa5VVzYTpFpq0uwFFzw== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-reduce-initial@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== - dependencies: - browserslist "^4.0.0" + browserslist "^4.16.0" caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" -postcss-reduce-transforms@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== +postcss-reduce-transforms@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.0.tgz#5c820f71fbd4eec82b323523642b7b2d1c7d29ef" + integrity sha512-iHdGODW4YzM3WjVecBhPQt6fpJC4lGQZxJKjkBNHpp2b8dzmvj0ogKThqya+IRodQEFzjfXgYeESkf172FH5Lw== dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.0" + postcss-value-parser "^4.1.0" -postcss-replace-overflow-wrap@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" - integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== - dependencies: - postcss "^7.0.2" - -postcss-selector-matches@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" - integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-not@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf" - integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-parser@^3.0.0: +postcss-selector-parser@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== @@ -7624,15 +6535,6 @@ postcss-selector-parser@^3.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== - dependencies: - cssesc "^2.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" @@ -7643,92 +6545,51 @@ postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: uniq "^1.0.1" util-deprecate "^1.0.2" -postcss-sort-media-queries@^1.7.26: - version "1.31.21" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-1.31.21.tgz#3225ec6eb490402602284ac99963b80461783cee" - integrity sha512-h+HbXXfOVFeLvCJOzl/Z9SqQ25MNpG/73k71756ftisaaJy75h06/Dn6KOwC4OCMN10ewT2PXMzHV03JNKwBbg== +postcss-sort-media-queries@^3.8.9: + version "3.10.11" + resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-3.10.11.tgz#9e06c220c752c69d3ea4a6d55ac7d4960e201c4a" + integrity sha512-78Ak5YSnalr+UTdZa2OCSNAxvEnHg3GRqWccStljJW7MqeU0cJtMA5OzaMmn+upM+iI5vykWzibVEAYaaAlSzw== dependencies: - postcss "^7.0.27" - sort-css-media-queries "1.5.0" + sort-css-media-queries "1.5.4" -postcss-svgo@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" - integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== +postcss-svgo@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.0.tgz#c8d806e573394ab24f1e233cac5be4c199e9f1b2" + integrity sha512-M3/VS4sFI1Yp9g0bPL+xzzCNz5iLdRUztoFaugMit5a8sMfkVzzhwqbsOlD8IFFymCdJDmXmh31waYHWw1K4BA== dependencies: - is-svg "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" + postcss-value-parser "^4.1.0" + svgo "^2.3.0" -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== +postcss-unique-selectors@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.0.tgz#17856278f6c38d024defc9694d568bb09dd7f771" + integrity sha512-o9l4pF8SRn7aCMTmzb/kNv/kjV7wPZpZ8Nlb1Gq8v/Qvw969K1wanz1RVA0ehHzWe9+wHXaC2DvZlak/gdMJ5w== dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" + alphanum-sort "^1.0.2" + postcss-selector-parser "^6.0.2" uniqs "^2.0.0" -postcss-value-parser@^3.0.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" - integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== +postcss-zindex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.0.0.tgz#ffed3576b5a9f0001a9d78fdc075466e1da1839c" + integrity sha512-thJp90qNZedxzfljsAnu7V35L/Zue/nVvWzPDLKZuqHmwDuy1vd3xkFVYfEa8WZZQaetvHtsi3uwjVD3UJAVeg== dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-zindex@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-4.0.1.tgz#8db6a4cec3111e5d3fd99ea70abeda61873d10c1" - integrity sha512-d/8BlQcUdEugZNRM9AdCA2V4fqREUtn/wcixLN3L6ITgc2P/FMcVVYz8QZkhItWT9NB5qr8wuN2dJCE4/+dlrA== - dependencies: - has "^1.0.0" - postcss "^7.0.0" + has "^1.0.3" uniqs "^2.0.0" -postcss@^6.0.23: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.35" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" - integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -postcss@^8.2.7, postcss@^8.2.8: - version "8.2.8" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.8.tgz#0b90f9382efda424c4f0f69a2ead6f6830d08ece" - integrity sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw== +postcss@^8.2.10, postcss@^8.2.4, postcss@^8.2.8, postcss@^8.2.9: + version "8.3.0" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.0.tgz#b1a713f6172ca427e3f05ef1303de8b65683325f" + integrity sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ== dependencies: colorette "^1.2.2" - nanoid "^3.1.20" - source-map "^0.6.1" - -prepend-http@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + nanoid "^3.1.23" + source-map-js "^0.6.2" prepend-http@^2.0.0: version "2.0.0" @@ -7765,16 +6626,6 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" @@ -7819,26 +6670,6 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -7847,21 +6678,12 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -pumpify@^1.3.3: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.3.2: +punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -7893,19 +6715,6 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== -query-string@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -7921,21 +6730,13 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: +randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - range-parser@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -8056,10 +6857,10 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-loadable-ssr-addon@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon/-/react-loadable-ssr-addon-0.3.0.tgz#ae9b2d3b11721930f8d8255476d288c0e9f9290f" - integrity sha512-E+lnmDakV0k6ut6R2J77vurwCOwTKEwKlHs9S62G8ez+ujecLPcqjt3YAU8M58kIGjp2QjFlZ7F9QWkq/mr6Iw== +react-loadable-ssr-addon-v5-slorber@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz#2cdc91e8a744ffdf9e3556caabeb6e4278689883" + integrity sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A== dependencies: "@babel/runtime" "^7.10.3" @@ -8128,13 +6929,6 @@ react-textarea-autosize@^8.3.2: use-composed-ref "^1.0.0" use-latest "^1.0.0" -react-toggle@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/react-toggle/-/react-toggle-4.1.2.tgz#b00500832f925ad524356d909821821ae39f6c52" - integrity sha512-4Ohw31TuYQdhWfA6qlKafeXx3IOH7t4ZHhmRdwsm1fQREwOBGxJT+I22sgHqR/w8JRdk+AeMCJXPImEFSrNXow== - dependencies: - classnames "^2.2.5" - react@^16.10.2, react@^16.3.1: version "16.14.0" resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" @@ -8144,7 +6938,7 @@ react@^16.10.2, react@^16.3.1: object-assign "^4.1.1" prop-types "^15.6.2" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.1, readable-stream@^2.0.2: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -8157,7 +6951,7 @@ react@^16.10.2, react@^16.3.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.1.1: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -8477,7 +7271,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@^2.5.4, rimraf@^2.6.3: +rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -8491,24 +7285,21 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" +rtl-detect@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.3.tgz#42145b9a4f9cf0b94c4542aba90d57f0d18559bf" + integrity sha512-2sMcZO60tL9YDEFe24gqddg3hJ+xSmJFN8IExcQUxeHxQzydQrN6GHPL+yAWgzItXSI7es53hcZC9pJneuZDKA== -rtlcss@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-2.6.2.tgz#55b572b52c70015ba6e03d497e5c5cb8137104b4" - integrity sha512-06LFAr+GAPo+BvaynsXRfoYTJvSaWRyOhURCQ7aeI1MKph9meM222F+Zkt3bDamyHHJuGi3VPtiRkpyswmQbGA== +rtlcss@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.1.2.tgz#4800d3d03525791a720f676a8ad2c6acf8efdfb2" + integrity sha512-b04YSX37siupPOWUEguEBReWX2w4QT89C0PI9g2JzZycbq7zrgPmTr1DA1pizSWpKRFdCjjnrx/SSvU4fOHmGg== dependencies: - "@choojs/findup" "^0.2.1" - chalk "^2.4.2" - mkdirp "^0.5.1" - postcss "^6.0.23" - strip-json-comments "^2.0.0" + chalk "^4.1.0" + find-up "^5.0.0" + mkdirp "^1.0.4" + postcss "^8.2.4" + strip-json-comments "^3.1.1" run-parallel@^1.1.9: version "1.2.0" @@ -8517,13 +7308,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= - dependencies: - aproba "^1.1.1" - rxjs@^6.6.3: version "6.6.6" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.6.tgz#14d8417aa5a07c5e633995b525e1e3c0dec03b70" @@ -8536,7 +7320,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -8548,7 +7332,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: +"safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -8575,7 +7359,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.0.0, schema-utils@^2.6.5: +schema-utils@^2.6.5: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== @@ -8666,13 +7450,6 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" -serialize-javascript@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== - dependencies: - randombytes "^2.1.0" - serialize-javascript@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" @@ -8732,7 +7509,7 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4, setimmediate@^1.0.5: +setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= @@ -8747,13 +7524,12 @@ setprototypeof@1.1.1: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + kind-of "^6.0.2" shebang-command@^1.2.0: version "1.2.0" @@ -8885,23 +7661,21 @@ sockjs@^0.3.21: uuid "^3.4.0" websocket-driver "^0.7.4" -sort-css-media-queries@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-1.5.0.tgz#8f605ad372caad0b81be010311882c046e738093" - integrity sha512-QofNE7CEVH1AKdhS7L9IPbV9UtyQYNXyw++8lC+xG6iOLlpzsmncZRiKbihTAESvZ8wOhwnPoesHbMrehrQyyw== +sort-css-media-queries@1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-1.5.4.tgz#24182b12002a13d01ba943ddf74f5098d7c244ce" + integrity sha512-YP5W/h4Sid/YP7Lp87ejJ5jP13/Mtqt2vx33XyhO+IAugKlufRPbOrPlIiEUuxmpNBSBd3EeeQpFhdu3RfI2Ag== -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" - -source-list-map@^2.0.0: +source-list-map@^2.0.0, source-list-map@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +source-map-js@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" + integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -8936,7 +7710,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.3, source-map@~0.7.2: +source-map@~0.7.2: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== @@ -8981,20 +7755,6 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== - dependencies: - figgy-pudding "^3.5.1" - -ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" @@ -9025,43 +7785,6 @@ std-env@^2.2.1: dependencies: ci-info "^3.0.0" -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-each@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -9096,7 +7819,7 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -string_decoder@^1.0.0, string_decoder@^1.1.1: +string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -9155,7 +7878,12 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -9167,16 +7895,15 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -stylehacks@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== +stylehacks@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.0.tgz#c49b0b2cf9917fe37dc030b96a4c34698b932933" + integrity sha512-QOWm6XivDLb+fqffTZP8jrmPmPITVChl2KCY2R05nsCWwLi3VGhCdVc3IVGNwd1zzTt1jPd67zIKjpQfxzQZeA== dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" + browserslist "^4.16.0" + postcss-selector-parser "^6.0.4" -supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -9202,7 +7929,7 @@ svg-parser@^2.0.2: resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== -svgo@^1.0.0, svgo@^1.2.2: +svgo@^1.2.2: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== @@ -9221,54 +7948,42 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" -tapable@^1.0.0, tapable@^1.1.3: +svgo@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.3.0.tgz#6b3af81d0cbd1e19c83f5f63cec2cb98c70b5373" + integrity sha512-fz4IKjNO6HDPgIQxu4IxwtubtbSfGEAJUq/IXyTPIkGhWck/faiiwfkvsB8LnBkKLvSoyNNIY6d13lZprJMc9Q== + dependencies: + "@trysound/sax" "0.1.1" + chalk "^4.1.0" + commander "^7.1.0" + css-select "^3.1.2" + css-tree "^1.1.2" + csso "^4.2.0" + stable "^0.1.8" + +tapable@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83" - integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^3.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" + integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== -terser-webpack-plugin@^1.4.3: - version "1.4.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" - integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== +terser-webpack-plugin@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.2.tgz#51d295eb7cc56785a67a372575fdc46e42d5c20c" + integrity sha512-6QhDaAiVHIQr5Ab3XUWZyDmrIPCHMiqJVljMF91YKyqwKkL5QHnYMkrMBy96v9Z7ev1hGhSEw1HQZc2p/s5Z8Q== dependencies: - cacache "^12.0.2" - find-cache-dir "^2.1.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^4.0.0" - source-map "^0.6.1" - terser "^4.1.2" - webpack-sources "^1.4.0" - worker-farm "^1.7.0" - -terser-webpack-plugin@^4.1.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a" - integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ== - dependencies: - cacache "^15.0.5" - find-cache-dir "^3.3.1" - jest-worker "^26.5.0" - p-limit "^3.0.2" + jest-worker "^26.6.2" + p-limit "^3.1.0" schema-utils "^3.0.0" serialize-javascript "^5.0.1" source-map "^0.6.1" - terser "^5.3.4" - webpack-sources "^1.4.3" + terser "^5.7.0" -terser@^4.1.2, terser@^4.6.3: +terser@^4.6.3: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== @@ -9277,10 +7992,10 @@ terser@^4.1.2, terser@^4.6.3: source-map "~0.6.1" source-map-support "~0.5.12" -terser@^5.3.4: - version "5.6.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.1.tgz#a48eeac5300c0a09b36854bf90d9c26fb201973c" - integrity sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw== +terser@^5.7.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.0.tgz#a761eeec206bc87b605ab13029876ead938ae693" + integrity sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g== dependencies: commander "^2.20.0" source-map "~0.7.2" @@ -9291,26 +8006,11 @@ text-table@0.2.0, text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -timers-browserify@^2.0.4: - version "2.0.12" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== - dependencies: - setimmediate "^1.0.4" - timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" @@ -9331,11 +8031,6 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -9408,11 +8103,6 @@ ts-essentials@^2.0.3: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== -ts-pnp@^1.1.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" - integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== - tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -9423,10 +8113,10 @@ tslib@^2.0.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= +tslib@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" + integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== type-fest@^0.20.2: version "0.20.2" @@ -9453,11 +8143,6 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - ua-parser-js@^0.7.18: version "0.7.25" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.25.tgz#67689fa263a87a52dabbc251ede89891f59156ce" @@ -9547,20 +8232,6 @@ uniqs@^2.0.0: resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - unique-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" @@ -9747,14 +8418,6 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util.promisify@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - util.promisify@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" @@ -9765,20 +8428,6 @@ util.promisify@~1.0.0: has-symbols "^1.0.1" object.getownpropertydescriptors "^2.1.0" -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" @@ -9809,7 +8458,7 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= -vendors@^1.0.0: +vendors@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== @@ -9837,11 +8486,6 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - wait-on@^5.2.1: version "5.3.0" resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.3.0.tgz#584e17d4b3fe7b46ac2b9f8e5e102c005c2776c7" @@ -9853,23 +8497,13 @@ wait-on@^5.2.1: minimist "^1.2.5" rxjs "^6.6.3" -watchpack-chokidar2@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" - integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== - dependencies: - chokidar "^2.1.8" - -watchpack@^1.7.4: - version "1.7.5" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" - integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== +watchpack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce" + integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA== dependencies: + glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" - neo-async "^2.5.0" - optionalDependencies: - chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.1" wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3" @@ -9956,14 +8590,15 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== +webpack-merge@^5.7.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.7.3.tgz#2a0754e1877a25a8bbab3d2475ca70a052708213" + integrity sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA== dependencies: - lodash "^4.17.15" + clone-deep "^4.0.1" + wildcard "^2.0.0" -webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: +webpack-sources@^1.1.0, webpack-sources@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== @@ -9971,34 +8606,42 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack- source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.44.1: - version "4.46.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" - integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== +webpack-sources@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac" + integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w== dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/wasm-edit" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - acorn "^6.4.1" - ajv "^6.10.2" - ajv-keywords "^3.4.1" + source-list-map "^2.0.1" + source-map "^0.6.1" + +webpack@^5.28.0: + version "5.37.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.37.1.tgz#2deb5acd350583c1ab9338471f323381b0b0c14b" + integrity sha512-btZjGy/hSjCAAVHw+cKG+L0M+rstlyxbO2C+BOTaQ5/XAnxkDrP5sVbqWhXgo4pL3X2dcOib6rqCP20Zr9PLow== + dependencies: + "@types/eslint-scope" "^3.7.0" + "@types/estree" "^0.0.47" + "@webassemblyjs/ast" "1.11.0" + "@webassemblyjs/wasm-edit" "1.11.0" + "@webassemblyjs/wasm-parser" "1.11.0" + acorn "^8.2.1" + browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.5.0" - eslint-scope "^4.0.3" + enhanced-resolve "^5.8.0" + es-module-lexer "^0.4.0" + eslint-scope "^5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.4" json-parse-better-errors "^1.0.2" - loader-runner "^2.4.0" - loader-utils "^1.2.3" - memory-fs "^0.4.1" - micromatch "^3.1.10" - mkdirp "^0.5.3" - neo-async "^2.6.1" - node-libs-browser "^2.2.1" - schema-utils "^1.0.0" - tapable "^1.1.3" - terser-webpack-plugin "^1.4.3" - watchpack "^1.7.4" - webpack-sources "^1.4.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.0.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.1" + watchpack "^2.0.0" + webpack-sources "^2.1.1" webpackbar@^5.0.0-3: version "5.0.0-3" @@ -10065,12 +8708,10 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -worker-farm@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" - integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== - dependencies: - errno "~0.1.7" +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== worker-rpc@^0.1.0: version "0.1.1" @@ -10136,7 +8777,7 @@ xml-js@^1.6.11: dependencies: sax "^1.2.4" -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: +xtend@^4.0.0, xtend@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== @@ -10146,11 +8787,6 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"