diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..d9ffad24 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,12 @@ +# Since version 2.23 (released in August 2019), git-blame has a feature +# to ignore or bypass certain commits. +# +# This file contains a list of commits that are not likely what you +# are looking for in a blame, such as mass reformatting or renaming. +# You can set this file as a default ignore file for blame by running +# the following command. +# +# $ git config blame.ignoreRevsFile .git-blame-ignore-revs + +# Apply ruff autoformatting +7d5ca3b70bf57cded4e43e5211cf064a71d120aa diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 587d883c..37ab721a 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -56,4 +56,4 @@ jobs: - uses: actions/checkout@v3 - run: | pip install pip-audit - pip-audit -r ${GITHUB_WORKSPACE}/requirements.txt + pip-audit --desc on . diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 74d5a6fb..44f25782 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: trailing-whitespace files: "wiki.*" @@ -20,17 +20,15 @@ repos: - id: check-yaml - id: debug-statements - - repo: https://github.com/asottile/pyupgrade - rev: v3.15.2 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.5.7 hooks: - - id: pyupgrade - args: ['--py310-plus'] + - id: ruff + name: "Run ruff linter and apply fixes" + args: ["--fix"] - - repo: https://github.com/adityahase/black - rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119 - hooks: - - id: black - additional_dependencies: ['click==8.0.4'] + - id: ruff-format + name: "Format Python code" - repo: https://github.com/pre-commit/mirrors-prettier rev: v4.0.0-alpha.8 @@ -47,22 +45,6 @@ repos: wiki/templates/includes/.*| wiki/public/js/lib/.* )$ - - repo: https://github.com/timothycrosley/isort - rev: 5.13.2 - hooks: - - id: isort - - - repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 - hooks: - - id: flake8 - # W191 - Doesn't like indentation with tabs - # E501 - Doesn't like lines > 79 (some sql queries are ~140) - # E203 - Doesn't like space infront of ':' (isn't pep8 compliant) - # W503 - Doesn't like line break before binary operator (isn't pep8 compliant) - args: ['--ignore=W191,E501,E203,W503'] - additional_dependencies: ['flake8-bugbear',] - ci: autoupdate_schedule: weekly skip: [] diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index aee88f53..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,18 +0,0 @@ -include MANIFEST.in -include requirements.txt -include *.json -include *.md -include *.py -include *.txt -recursive-include wiki *.css -recursive-include wiki *.csv -recursive-include wiki *.html -recursive-include wiki *.ico -recursive-include wiki *.js -recursive-include wiki *.json -recursive-include wiki *.md -recursive-include wiki *.png -recursive-include wiki *.py -recursive-include wiki *.svg -recursive-include wiki *.txt -recursive-exclude wiki *.pyc \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index b757a537..97d86a8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,56 @@ -[tool.black] -line-length = 99 - -[tool.isort] -line_length = 99 -multi_line_output = 3 -include_trailing_comma = true -force_grid_wrap = 0 -use_parentheses = true -ensure_newline_before_comments = true -indent = "\t" -profile = "black" +[project] +name = "wiki" +authors = [ + { name = "Frappe Technologies Pvt Ltd", email = "developers@frappe.io"} +] +description = "Simple Wiki App" +requires-python = ">=3.10,<3.13" +readme = "README.md" +dynamic = ["version"] + +[project.urls] +Homepage = "https://frappe.io/wiki" +Repository = "https://github.com/frappe/wiki.git" +"Bug Reports" = "https://github.com/frappe/wiki/issues" + +[build-system] +requires = ["flit_core >=3.4,<4"] +build-backend = "flit_core.buildapi" + + +[tool.ruff] +line-length = 110 +target-version = "py310" + +[tool.ruff.lint] +select = [ + "F", + "E", + "W", + "I", + "UP", + "B", + "RUF", +] +ignore = [ + "B017", # assertRaises(Exception) - should be more specific + "B018", # useless expression, not assigned to anything + "B023", # function doesn't bind loop variable - will have last iteration's value + "B904", # raise inside except without from + "E101", # indentation contains mixed spaces and tabs + "E402", # module level import not at top of file + "E501", # line too long + "E741", # ambiguous variable name + "F401", # "unused" imports + "F403", # can't detect undefined names from * import + "F405", # can't detect undefined names from * import + "F722", # syntax error in forward type annotation + "W191", # indentation contains tabs + "RUF001", # string contains ambiguous unicode character +] +typing-modules = ["frappe.types.DF"] + +[tool.ruff.format] +quote-style = "double" +indent-style = "tab" +docstring-code-format = true diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/setup.py b/setup.py deleted file mode 100644 index 9e2d2b28..00000000 --- a/setup.py +++ /dev/null @@ -1,19 +0,0 @@ -from setuptools import find_packages, setup - -with open("requirements.txt") as f: - install_requires = f.read().strip().split("\n") - -# get version from __version__ variable in wiki/__init__.py -from wiki import __version__ as version - -setup( - name="wiki", - version=version, - description="Simple Wiki App", - author="Frappe", - author_email="developers@frappe.io", - packages=find_packages(), - zip_safe=False, - include_package_data=True, - install_requires=install_requires, -) diff --git a/wiki/public/js/wiki.js b/wiki/public/js/wiki.js index 9f08808a..a95e0c42 100644 --- a/wiki/public/js/wiki.js +++ b/wiki/public/js/wiki.js @@ -15,7 +15,8 @@ window.Wiki = class Wiki { let active_sidebar_item = $(".doc-sidebar .sidebar-item.active"); if (active_sidebar_item.length > 0) { setTimeout(function () { - let position = active_sidebar_item.offset().top - $(".doc-sidebar").offset().top; + let position = + active_sidebar_item.offset().top - $(".doc-sidebar").offset().top; $(".doc-sidebar .web-sidebar").get(0).scrollTo(0, position); }, 50); } @@ -84,7 +85,6 @@ window.Wiki = class Wiki { switchBanner(); $("body").toggleClass("dark"); - }); } diff --git a/wiki/wiki/doctype/migrate_to_wiki/migrate_to_wiki.py b/wiki/wiki/doctype/migrate_to_wiki/migrate_to_wiki.py index c01d69c5..e68ddc21 100644 --- a/wiki/wiki/doctype/migrate_to_wiki/migrate_to_wiki.py +++ b/wiki/wiki/doctype/migrate_to_wiki/migrate_to_wiki.py @@ -77,9 +77,7 @@ def migrate_dir(self, root, dirs, files): wiki_sidebar = frappe.new_doc("Wiki Sidebar") parent_wiki_sidebar = f"{self.documentation_route}{os.sep}{root[root.find(self.docs_directory) + len(self.docs_directory) + 1: ]}".replace( "//", "/" - ).strip( - "/" - ) + ).strip("/") wiki_sidebar_dict = { "route": f"{parent_wiki_sidebar}{os.sep}{directory}".replace("//", "/"), "title": directory.capitalize(), @@ -101,7 +99,6 @@ def migrate_dir(self, root, dirs, files): wiki_sidebar_item.save() def migrate_file(self, root, file, files): - if file == "index.md" and "contents.md" in files: return heading_index = -1 @@ -116,14 +113,10 @@ def migrate_file(self, root, file, files): parent = f"{self.documentation_route}{os.sep}{root[root.find(self.docs_directory) + len(self.docs_directory) + 1: ]}".replace( "//", "/" - ).strip( - "/" - ) + ).strip("/") route = f"{parent}{os.sep}{file[:-3]}" - title = ( - lines[heading_index].strip("#").strip(" ") if heading_index != -1 else route.split(os.sep)[-1] - ) + title = lines[heading_index].strip("#").strip(" ") if heading_index != -1 else route.split(os.sep)[-1] content = "".join(lines[heading_index + 1 :]) if heading_index != -1 else "".join(lines) if "shifted to landing page" in content: return @@ -134,7 +127,6 @@ def migrate_file(self, root, file, files): content = content.replace(self.docs_directory.strip("w"), f"/{self.documentation_route}") if file.endswith("index.md") or file.endswith("contents.md"): - try: with open(f"{root}{os.sep}index.txt") as f: lines = f.readlines() @@ -221,11 +213,8 @@ def create_files(self): folder = f"{folder}{os.sep}{directory}" for root, dirs, files in self.assets_tree_generator: - for directory in dirs: - fold = ( - f"{folder}{os.sep}{root[root.find(self.assets_directory) + len(self.assets_directory) + 1:]}" - ) + fold = f"{folder}{os.sep}{root[root.find(self.assets_directory) + len(self.assets_directory) + 1:]}" fold = fold.replace(f"{os.sep}{os.sep}", os.sep) if fold.endswith(f"{os.sep}"): fold = fold[:-1] @@ -257,7 +246,9 @@ def create_files(self): with open(f"{root}{os.sep}{file}", "rb") as f: content_hash = get_content_hash(f.read()) except OSError: - frappe.msgprint(frappe._("File {0} does not exist").format(f"{root}{os.sep}{file}")) + frappe.msgprint( + frappe._("File {0} does not exist").format(f"{root}{os.sep}{file}") + ) raise new_file_name = get_file_name(file, content_hash[-6:]) @@ -299,6 +290,6 @@ def create_files(self): orig_file_url = f"{self.assets_prepend}{os.sep}{root[root.find(self.assets_directory) + len(self.assets_directory) + 1:] }{os.sep}{file}" self.docs_change_dict[orig_file_url] = file_url - self.docs_change_dict[ - orig_file_url.replace("{{docs_base_url}}", self.docs_base_url) - ] = file_url + self.docs_change_dict[orig_file_url.replace("{{docs_base_url}}", self.docs_base_url)] = ( + file_url + ) diff --git a/wiki/wiki/doctype/wiki_page/search.py b/wiki/wiki/doctype/wiki_page/search.py index 0a86d0ad..10c24808 100644 --- a/wiki/wiki/doctype/wiki_page/search.py +++ b/wiki/wiki/doctype/wiki_page/search.py @@ -12,7 +12,7 @@ _redisearch_available = False try: - from redis.commands.search.query import Query # noqa: F401 + from redis.commands.search.query import Query _redisearch_available = True except ImportError: @@ -39,7 +39,7 @@ def search(query, path, space): return {"docs": result, "search_engine": "frappe_web_search"} - from redis.commands.search.query import Query # noqa: F811 + from redis.commands.search.query import Query from redis.exceptions import ResponseError # if redisearch enabled use redisearch @@ -58,8 +58,7 @@ def search(query, path, space): names = list(set(names)) data_by_name = { - d.name: d - for d in frappe.db.get_all("Wiki Page", fields=["name"], filters={"name": ["in", names]}) + d.name: d for d in frappe.db.get_all("Wiki Page", fields=["name"], filters={"name": ["in", names]}) } docs = [] @@ -148,9 +147,7 @@ def remove_index_for_records(records, space): def update_index(doc): - record = frappe._dict( - {"name": doc.name, "title": doc.title, "content": doc.content, "route": doc.route} - ) + record = frappe._dict({"name": doc.name, "title": doc.title, "content": doc.content, "route": doc.route}) space = get_space_route(doc.route) create_index_for_records([record], space) diff --git a/wiki/wiki/doctype/wiki_page/test_wiki_page.py b/wiki/wiki/doctype/wiki_page/test_wiki_page.py index 7a6b0a18..02888d69 100644 --- a/wiki/wiki/doctype/wiki_page/test_wiki_page.py +++ b/wiki/wiki/doctype/wiki_page/test_wiki_page.py @@ -27,7 +27,6 @@ def tearDown(self): self.wiki_page.delete() def test_wiki_page_lifecycle(self): - self.assertEqual( frappe.db.get_value("Wiki Page", {"route": "wiki/page"}, "name"), self.wiki_page.name ) @@ -77,7 +76,5 @@ def test_wiki_page_deletion(self): patches = frappe.get_all("Wiki Page Patch", {"wiki_page": self.wiki_page.name}, pluck="name") self.assertEqual(patches, []) - sidebar_items = frappe.get_all( - "Wiki Group Item", {"wiki_page": self.wiki_page.name}, pluck="name" - ) + sidebar_items = frappe.get_all("Wiki Group Item", {"wiki_page": self.wiki_page.name}, pluck="name") self.assertEqual(sidebar_items, []) diff --git a/wiki/wiki/doctype/wiki_page/wiki_page.py b/wiki/wiki/doctype/wiki_page/wiki_page.py index 84dda32d..0fc1acea 100644 --- a/wiki/wiki/doctype/wiki_page/wiki_page.py +++ b/wiki/wiki/doctype/wiki_page/wiki_page.py @@ -50,7 +50,6 @@ def on_update(self): update_index(self) def on_trash(self): - frappe.db.sql("DELETE FROM `tabWiki Page Revision Item` WHERE wiki_page = %s", self.name) frappe.db.sql( @@ -185,9 +184,7 @@ def get_space_route(self): if space := frappe.get_value("Wiki Group Item", {"wiki_page": self.name}, "parent"): return frappe.get_value("Wiki Space", space, "route") else: - frappe.throw( - "Wiki Page doesn't have a Wiki Space associated with it. Please add them via Desk." - ) + frappe.throw("Wiki Page doesn't have a Wiki Space associated with it. Please add them via Desk.") def calculate_toc_html(self, html): from bs4 import BeautifulSoup @@ -238,9 +235,7 @@ def get_context(self, context): context.edit_wiki_page = frappe.form_dict.get("editWiki") context.new_wiki_page = frappe.form_dict.get("newWiki") context.last_revision = self.get_last_revision() - context.number_of_revisions = frappe.db.count( - "Wiki Page Revision Item", {"wiki_page": self.name} - ) + context.number_of_revisions = frappe.db.count("Wiki Page Revision Item", {"wiki_page": self.name}) # TODO: group all context values context.hide_on_sidebar = frappe.get_value( "Wiki Group Item", {"wiki_page": self.name}, "hide_on_sidebar" @@ -353,7 +348,6 @@ def get_last_revision(self): return frappe.get_doc("Wiki Page Revision", last_revision) def clone(self, original_space, new_space): - # used in after_insert of Wiki Page to resist create of Wiki Page Revision frappe.local.in_clone = True @@ -439,9 +433,7 @@ def _save_file(match): mtype = headers.split(";")[0] filename = get_random_filename(content_type=mtype) - _file = frappe.get_doc( - {"doctype": "File", "file_name": filename, "content": content, "decode": True} - ) + _file = frappe.get_doc({"doctype": "File", "file_name": filename, "content": content, "decode": True}) _file.save(ignore_permissions=True) file_url = _file.file_url file_ids["name"] += [_file.name] diff --git a/wiki/wiki/doctype/wiki_page/wiki_renderer.py b/wiki/wiki/doctype/wiki_page/wiki_renderer.py index 094cb817..44ed080e 100644 --- a/wiki/wiki/doctype/wiki_page/wiki_renderer.py +++ b/wiki/wiki/doctype/wiki_page/wiki_renderer.py @@ -15,9 +15,7 @@ class WikiPageRenderer(DocumentPage): def can_render(self): if wiki_space_name := frappe.get_value("Wiki Space", {"route": self.path}): wiki_space = frappe.get_doc("Wiki Space", wiki_space_name) - topmost_wiki_route = frappe.get_value( - "Wiki Page", wiki_space.wiki_sidebars[0].wiki_page, "route" - ) + topmost_wiki_route = frappe.get_value("Wiki Page", wiki_space.wiki_sidebars[0].wiki_page, "route") frappe.redirect(f"/{quote(topmost_wiki_route)}") return self.search_in_doctypes_with_web_view() diff --git a/wiki/wiki/doctype/wiki_page_patch/wiki_page_patch.py b/wiki/wiki/doctype/wiki_page_patch/wiki_page_patch.py index d8fecc99..aa433830 100644 --- a/wiki/wiki/doctype/wiki_page_patch/wiki_page_patch.py +++ b/wiki/wiki/doctype/wiki_page_patch/wiki_page_patch.py @@ -77,7 +77,9 @@ def update_sidebars(self): self.insert_on_sidebar(list(sidebars)[-1], self.new_wiki_page.name) frappe.db.set_value( - "Wiki Group Item", {"wiki_page": str(item["name"])}, {"parent_label": sidebar, "idx": idx} + "Wiki Group Item", + {"wiki_page": str(item["name"])}, + {"parent_label": sidebar, "idx": idx}, ) def insert_on_sidebar(self, parent_label: str, wiki_page: str): @@ -97,9 +99,7 @@ def insert_on_sidebar(self, parent_label: str, wiki_page: str): @frappe.whitelist() def add_comment_to_patch(reference_name, content): email = frappe.session.user - name = frappe.db.get_value("User", frappe.session.user, ["first_name"], as_dict=True).get( - "first_name" - ) + name = frappe.db.get_value("User", frappe.session.user, ["first_name"], as_dict=True).get("first_name") comment = add_comment("Wiki Page Patch", reference_name, content, email, name) comment.timepassed = frappe.utils.pretty_date(comment.creation) return comment diff --git a/wiki/wiki/doctype/wiki_page_revision/patches/add_usernames.py b/wiki/wiki/doctype/wiki_page_revision/patches/add_usernames.py index d87ab50b..a5c7fe4e 100644 --- a/wiki/wiki/doctype/wiki_page_revision/patches/add_usernames.py +++ b/wiki/wiki/doctype/wiki_page_revision/patches/add_usernames.py @@ -2,7 +2,6 @@ def execute(): - frappe.reload_doctype("Wiki Page Revision") revision = frappe.qb.DocType("Wiki Page Revision") diff --git a/wiki/wiki/doctype/wiki_space/patches/wiki_sidebar_migration.py b/wiki/wiki/doctype/wiki_space/patches/wiki_sidebar_migration.py index 6a8d2c8c..5b241d27 100644 --- a/wiki/wiki/doctype/wiki_space/patches/wiki_sidebar_migration.py +++ b/wiki/wiki/doctype/wiki_space/patches/wiki_sidebar_migration.py @@ -40,9 +40,7 @@ def execute(): elif hasattr(wiki_settings, "sidebar"): # get sidebar from legacy version of wiki - if not ( - all_sidebars := frappe.db.get_all("Wiki Sidebar", pluck="name", order_by="creation asc") - ): + if not (all_sidebars := frappe.db.get_all("Wiki Sidebar", pluck="name", order_by="creation asc")): return # find all root sidebars @@ -143,9 +141,7 @@ def get_sidebar_items(doc): def get_root_parent_title(name, last_parent=""): - if parent := frappe.db.get_value( - "Wiki Sidebar Item", {"item": name, "type": "Wiki Sidebar"}, "parent" - ): + if parent := frappe.db.get_value("Wiki Sidebar Item", {"item": name, "type": "Wiki Sidebar"}, "parent"): return get_root_parent_title(parent, name) else: if last_parent: diff --git a/yarn.lock b/yarn.lock index fd8c5ce6..621438ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -49,7 +49,7 @@ dependencies: type-fest "^2.0.0" -"@tiptap/core@^2.0.0", "@tiptap/core@^2.0.2": +"@tiptap/core@^2.0.2": version "2.0.2" resolved "https://registry.npmjs.org/@tiptap/core/-/core-2.0.2.tgz" integrity sha512-DBry6tpX7mYaTJkEDjVA4WmF8Kgthr275L0uIIOVdwW5nG5PAnOvREKyVOoMQnN3vR7CjtaCK+c3y+MCQhMA/g== @@ -74,7 +74,7 @@ resolved "https://registry.npmjs.org/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.2.tgz" integrity sha512-7BbRCKJE2oxsZ5n7HIjS0r/y1S/bSxEJgAFF1Tj3KN2IG3x48w+sqYxRMYmCZdoTexmmBpNF64uYXngKXB9/Ig== -"@tiptap/extension-code-block@^2.0.0", "@tiptap/extension-code-block@^2.0.2": +"@tiptap/extension-code-block@^2.0.2": version "2.0.2" resolved "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.0.2.tgz" integrity sha512-GL8ogok1tl1FkXwk0P0ZWYh6oAmSA+R3oubtDZJG1fLlezKLcLYCN/Q2jgYDHDwEOnxMc4JIiT7EYwJ0pqmNaQ== @@ -201,7 +201,7 @@ resolved "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.0.2.tgz" integrity sha512-kAO+WurWOyHIV/x8qHMF3bSlWrdlPtjEYmf+w8wHKy3FzE55eF6SsGt4FymClNkJmyXdgflXBB3Wv/Z53myy8g== -"@tiptap/pm@^2.0.0", "@tiptap/pm@^2.0.2": +"@tiptap/pm@^2.0.2": version "2.0.2" resolved "https://registry.npmjs.org/@tiptap/pm/-/pm-2.0.2.tgz" integrity sha512-vXlI82bZ4XrmVD6m/pO27gqlm+tU57mpjy9WjkJpEUOifQZK8LihR3l5k55Z0RqalV4/E79iU1cp8mw0v13nhA== @@ -575,7 +575,7 @@ prosemirror-menu@^1.2.1: prosemirror-history "^1.0.0" prosemirror-state "^1.0.0" -prosemirror-model@^1, prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.18.1, prosemirror-model@^1.19.0, prosemirror-model@^1.8.1: +prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.18.1, prosemirror-model@^1.19.0, prosemirror-model@^1.8.1: version "1.19.0" resolved "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.19.0.tgz" integrity sha512-/CvFGJnwc41EJSfDkQLly1cAJJJmBpZwwUJtwZPTjY2RqZJfM8HVbCreOY/jti8wTRbVyjagcylyGoeJH/g/3w== @@ -598,7 +598,7 @@ prosemirror-schema-list@^1.2.2: prosemirror-state "^1.0.0" prosemirror-transform "^1.0.0" -prosemirror-state@^1, prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.4.1: +prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.4.1: version "1.4.2" resolved "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.2.tgz" integrity sha512-puuzLD2mz/oTdfgd8msFbe0A42j5eNudKAAPDB0+QJRw8cO1ygjLmhLrg9RvDpf87Dkd6D4t93qdef00KKNacQ== @@ -635,7 +635,7 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor dependencies: prosemirror-model "^1.0.0" -prosemirror-view@^1, prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.27.0, prosemirror-view@^1.28.2: +prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.27.0, prosemirror-view@^1.28.2: version "1.30.2" resolved "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.30.2.tgz" integrity sha512-nTNzZvalQf9kHeEyO407LiV6DoOs/pXsid88UqW9Vvybo4ozJW2PJhkfZUxCUF1hR/9vJLdhxX84wuw9P9HsXA== @@ -734,7 +734,7 @@ w3c-keyname@^2.2.0: resolved "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz" integrity sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg== -which@^1.2.9, which@1.2.x: +which@1.2.x, which@^1.2.9: version "1.2.14" resolved "https://registry.npmjs.org/which/-/which-1.2.14.tgz" integrity sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==