Skip to content

Commit

Permalink
Add filename filter for performance gain
Browse files Browse the repository at this point in the history
closes: #25
  • Loading branch information
pedro-psb committed May 16, 2024
1 parent 58465ea commit ade0f07
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 77 deletions.
177 changes: 101 additions & 76 deletions mkdocs_swagger_ui_tag/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@
from mkdocs.config import config_options
from mkdocs.plugins import BasePlugin

log = logging.getLogger(__name__)
try:
# mkdocs logging utility for mkdocs 1.5+
# https://www.mkdocs.org/dev-guide/plugins/#logging-in-plugins
from mkdocs.plugins import get_plugin_logger

log = get_plugin_logger(__name__)
except ImportError:
# compat
log = logging.getLogger(f"mkdocs.plugins.{__name__}") # type: ignore

base_path = os.path.dirname(os.path.abspath(__file__))


Expand Down Expand Up @@ -56,6 +65,10 @@ class SwaggerUIPlugin(BasePlugin):
("validatorUrl", config_options.Type(str, default="none")),
("extra_css", config_options.Type(list, default=[])),
("dark_scheme_name", config_options.Type(str, default="slate")),
(
"filter_filenames",
config_options.ListOfItems(config_options.Type(str), default=[]),
),
)

def on_pre_page(self, page, config, files, **kwargs):
Expand Down Expand Up @@ -107,94 +120,105 @@ def on_post_page(self, output, page, config, **kwargs):
Add javascript code to update iframe height
Create a html with Swagger UI for iframe
"""
# Using filename filter for performance
# https://github.com/blueswen/mkdocs-swagger-ui-tag/issues/25
if filter_list := self.config["filter_filenames"]:
if page.file.name not in filter_list:
return output

soup = BeautifulSoup(output, "html.parser")
swagger_ui_list = soup.find_all("swagger-ui")

# No tags found, we can return earlier
if len(swagger_ui_list) == 0:
return output

# Regular processing
iframe_id_list = []
grouped_list = []

if len(swagger_ui_list) > 0:
css_dir = utils.get_relative_url(
utils.normalize_url("assets/stylesheets/"), page.url
)
js_dir = utils.get_relative_url(
utils.normalize_url("assets/javascripts/"), page.url
log.info(f"Processing file '{page.file.src_uri}'")
css_dir = utils.get_relative_url(
utils.normalize_url("assets/stylesheets/"), page.url
)
js_dir = utils.get_relative_url(
utils.normalize_url("assets/javascripts/"), page.url
)
default_oauth2_redirect_file = utils.get_relative_url(
utils.normalize_url("assets/swagger-ui/oauth2-redirect.html"), page.url
)
env = Environment(
loader=FileSystemLoader(os.path.join(base_path, "swagger-ui"))
)
template = env.get_template("swagger.html")
extra_css_files = list(
map(
lambda f: utils.get_relative_url(utils.normalize_url(f), page.url),
self.config["extra_css"],
)
default_oauth2_redirect_file = utils.get_relative_url(
utils.normalize_url("assets/swagger-ui/oauth2-redirect.html"), page.url
)

page_dir = os.path.dirname(
os.path.join(config["site_dir"], urlunquote(page.url))
)
if not os.path.exists(page_dir):
os.makedirs(page_dir)

def render_template(openapi_spec_url, swagger_ui_ele):
cur_options = self.process_options(config, swagger_ui_ele)
cur_oath2_prop = self.process_oath2_prop(swagger_ui_ele)
oauth2_redirect_url = cur_options.pop("oauth2RedirectUrl", "")
if not oauth2_redirect_url:
oauth2_redirect_url = default_oauth2_redirect_file

template_output = template.render(
css_dir=css_dir,
extra_css_files=extra_css_files,
js_dir=js_dir,
background=self.config["background"],
id="{{ID_PLACEHOLDER}}", # ID is unknown yet - it's the hash of the content.
openapi_spec_url=openapi_spec_url,
oauth2_redirect_url=oauth2_redirect_url,
validatorUrl=self.config["validatorUrl"],
options_str=json.dumps(cur_options, indent=4)[1:-1],
oath2_prop_str=json.dumps(cur_oath2_prop),
)
env = Environment(
loader=FileSystemLoader(os.path.join(base_path, "swagger-ui"))
cur_id = hashlib.sha256(template_output.encode()).hexdigest()[:8]
iframe_filename = f"swagger-{cur_id}.html"
template_output = template_output.replace("{{ID_PLACEHOLDER}}", cur_id)
with open(os.path.join(page_dir, iframe_filename), "w") as f:
f.write(template_output)
self.replace_with_iframe(soup, swagger_ui_ele, cur_id, iframe_filename)
return cur_id

for swagger_ui_ele in swagger_ui_list:
if swagger_ui_ele.has_attr("grouped"):
grouped_list.append(swagger_ui_ele)
continue

openapi_spec_url = self.path_to_url(
page.file, swagger_ui_ele.get("src", "")
)
template = env.get_template("swagger.html")
extra_css_files = list(
map(
lambda f: utils.get_relative_url(utils.normalize_url(f), page.url),
self.config["extra_css"],
iframe_id_list.append(
render_template(
openapi_spec_url=openapi_spec_url, swagger_ui_ele=swagger_ui_ele
)
)

page_dir = os.path.dirname(
os.path.join(config["site_dir"], urlunquote(page.url))
)
if not os.path.exists(page_dir):
os.makedirs(page_dir)

def render_template(openapi_spec_url, swagger_ui_ele):
cur_options = self.process_options(config, swagger_ui_ele)
cur_oath2_prop = self.process_oath2_prop(swagger_ui_ele)
oauth2_redirect_url = cur_options.pop("oauth2RedirectUrl", "")
if not oauth2_redirect_url:
oauth2_redirect_url = default_oauth2_redirect_file

template_output = template.render(
css_dir=css_dir,
extra_css_files=extra_css_files,
js_dir=js_dir,
background=self.config["background"],
id="{{ID_PLACEHOLDER}}", # ID is unknown yet - it's the hash of the content.
openapi_spec_url=openapi_spec_url,
oauth2_redirect_url=oauth2_redirect_url,
validatorUrl=self.config["validatorUrl"],
options_str=json.dumps(cur_options, indent=4)[1:-1],
oath2_prop_str=json.dumps(cur_oath2_prop),
)
cur_id = hashlib.sha256(template_output.encode()).hexdigest()[:8]
iframe_filename = f"swagger-{cur_id}.html"
template_output = template_output.replace("{{ID_PLACEHOLDER}}", cur_id)
with open(os.path.join(page_dir, iframe_filename), "w") as f:
f.write(template_output)
self.replace_with_iframe(soup, swagger_ui_ele, cur_id, iframe_filename)
return cur_id

for swagger_ui_ele in swagger_ui_list:
if swagger_ui_ele.has_attr("grouped"):
grouped_list.append(swagger_ui_ele)
continue

openapi_spec_url = self.path_to_url(
page.file, swagger_ui_ele.get("src", "")
)
iframe_id_list.append(
render_template(
openapi_spec_url=openapi_spec_url, swagger_ui_ele=swagger_ui_ele
)
)

if grouped_list:
openapi_spec_url = []
for swagger_ui_ele in grouped_list:
cur_url = self.path_to_url(page.file, swagger_ui_ele.get("src", ""))
cur_name = swagger_ui_ele.get("name", swagger_ui_ele.get("src", ""))
openapi_spec_url.append({"url": cur_url, "name": cur_name})
if grouped_list:
openapi_spec_url = []
for swagger_ui_ele in grouped_list:
cur_url = self.path_to_url(page.file, swagger_ui_ele.get("src", ""))
cur_name = swagger_ui_ele.get("name", swagger_ui_ele.get("src", ""))
openapi_spec_url.append({"url": cur_url, "name": cur_name})

# only use options from first grouped swagger ui tag
render_template(
openapi_spec_url=openapi_spec_url, swagger_ui_ele=grouped_list[0]
)
# only keep first grouped swagger ui tag
for rest_swagger_ui_ele in grouped_list[1:]:
rest_swagger_ui_ele.extract()
# only use options from first grouped swagger ui tag
render_template(
openapi_spec_url=openapi_spec_url, swagger_ui_ele=grouped_list[0]
)
# only keep first grouped swagger ui tag
for rest_swagger_ui_ele in grouped_list[1:]:
rest_swagger_ui_ele.extract()

js_code = soup.new_tag("script")
# trigger from iframe body ResizeObserver
Expand Down Expand Up @@ -371,6 +395,7 @@ def process_oath2_prop(self, swagger_ui_ele):
def on_post_build(self, config, **kwargs):
"""Copy Swagger UI css and js files to assets directory"""

log.info("Copying swagger ui assets.")
output_base_path = os.path.join(config["site_dir"], "assets")
css_path = os.path.join(output_base_path, "stylesheets")
for file_name in os.listdir(
Expand Down
6 changes: 6 additions & 0 deletions tests/fixtures/mkdocs-filter-filenames.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
site_name: test mkdocs_swagger_ui_tag
use_directory_urls: true

plugins:
- swagger-ui-tag:
filter_filenames: ["index"]
22 changes: 21 additions & 1 deletion tests/test_builds.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def test_empty(tmp_path):
file = testproject_path / "site/empty/index.html"
contents = file.read_text(encoding="utf8")

validate_additional_script_code(contents, exists=True)
validate_additional_script_code(contents, exists=False)


def test_error(tmp_path):
Expand All @@ -548,3 +548,23 @@ def test_template(tmp_path):

iframe_content_list = validate_iframe(contents, file.parent)
assert len(iframe_content_list) == 2


def test_filter_filenames(tmp_path):
mkdocs_file = "mkdocs-filter-filenames.yml"
testproject_path = validate_mkdocs_file(
tmp_path,
f"tests/fixtures/{mkdocs_file}",
)
file = testproject_path / "site/index.html"
contents = file.read_text(encoding="utf8")
iframe_content_list = validate_iframe(contents, file.parent)
assert len(iframe_content_list) == 1

file = testproject_path / "site/empty/index.html"
contents = file.read_text(encoding="utf8")
validate_additional_script_code(contents, exists=False)

file = testproject_path / "site/multiple/index.html"
contents = file.read_text(encoding="utf8")
validate_additional_script_code(contents, exists=False)

0 comments on commit ade0f07

Please sign in to comment.