1515import base64
1616import traceback
1717from urllib .parse import urlparse
18- from textwrap import dedent
1918
2019import flask
2120
6463
6564from . import _pages
6665from ._pages import (
67- _infer_module_name ,
68- _parse_path_variables ,
6966 _parse_query_string ,
67+ _page_meta_tags ,
68+ _path_to_page ,
69+ _import_layouts_from_pages ,
7070)
7171
7272# Add explicit mapping for map files
@@ -210,6 +210,9 @@ class Dash:
210210 to be True. Default `None`.
211211 :type use_pages: boolean
212212
213+ :param include_pages_meta: Include the page meta tags for twitter cards.
214+ :type include_pages_meta: bool
215+
213216 :param assets_url_path: The local urls for assets will be:
214217 ``requests_pathname_prefix + assets_url_path + '/' + asset_path``
215218 where ``asset_path`` is the path to a file inside ``assets_folder``.
@@ -348,6 +351,7 @@ def __init__( # pylint: disable=too-many-statements
348351 assets_external_path = None ,
349352 eager_loading = False ,
350353 include_assets_files = True ,
354+ include_pages_meta = True ,
351355 url_base_pathname = None ,
352356 requests_pathname_prefix = None ,
353357 routes_pathname_prefix = None ,
@@ -418,6 +422,7 @@ def __init__( # pylint: disable=too-many-statements
418422 extra_hot_reload_paths = extra_hot_reload_paths or [],
419423 title = title ,
420424 update_title = update_title ,
425+ include_pages_meta = include_pages_meta ,
421426 )
422427 self .config .set_read_only (
423428 [
@@ -854,67 +859,24 @@ def _generate_config_html(self):
854859 def _generate_renderer (self ):
855860 return f'<script id="_dash-renderer" type="application/javascript">{ self .renderer } </script>'
856861
857- def _generate_meta_html (self ):
858- meta_tags = self . config . meta_tags
862+ def _generate_meta (self ):
863+ meta_tags = []
859864 has_ie_compat = any (
860- x .get ("http-equiv" , "" ) == "X-UA-Compatible" for x in meta_tags
865+ x .get ("http-equiv" , "" ) == "X-UA-Compatible" for x in self . config . meta_tags
861866 )
862- has_charset = any ("charset" in x for x in meta_tags )
863- has_viewport = any (x .get ("name" ) == "viewport" for x in meta_tags )
867+ has_charset = any ("charset" in x for x in self . config . meta_tags )
868+ has_viewport = any (x .get ("name" ) == "viewport" for x in self . config . meta_tags )
864869
865- tags = []
866870 if not has_ie_compat :
867- tags .append ('<meta http-equiv=" X-UA-Compatible" content=" IE=edge">' )
871+ meta_tags .append ({ " http-equiv" : " X-UA-Compatible", " content" : " IE=edge"} )
868872 if not has_charset :
869- tags .append ('<meta charset=" UTF-8">' )
873+ meta_tags .append ({ " charset" : " UTF-8"} )
870874 if not has_viewport :
871- tags .append (
872- '<meta name=" viewport" content=" width=device-width, initial-scale=1">'
875+ meta_tags .append (
876+ { " name" : " viewport", " content" : " width=device-width, initial-scale=1"}
873877 )
874878
875- tags += [format_tag ("meta" , x , opened = True ) for x in meta_tags ]
876-
877- return "\n " .join (tags )
878-
879- def _pages_meta_tags (self ):
880- start_page , path_variables = self ._path_to_page (flask .request .path .strip ("/" ))
881-
882- # use the supplied image_url or create url based on image in the assets folder
883- image = start_page .get ("image" , "" )
884- if image :
885- image = self .get_asset_url (image )
886- assets_image_url = (
887- "" .join ([flask .request .url_root , image .lstrip ("/" )]) if image else None
888- )
889- supplied_image_url = start_page .get ("image_url" )
890- image_url = supplied_image_url if supplied_image_url else assets_image_url
891-
892- title = start_page .get ("title" , self .title )
893- if callable (title ):
894- title = title (** path_variables ) if path_variables else title ()
895-
896- description = start_page .get ("description" , "" )
897- if callable (description ):
898- description = (
899- description (** path_variables ) if path_variables else description ()
900- )
901-
902- return dedent (
903- f"""
904- <meta name="description" content="{ description } " />
905- <!-- Twitter Card data -->
906- <meta property="twitter:card" content="summary_large_image">
907- <meta property="twitter:url" content="{ flask .request .url } ">
908- <meta property="twitter:title" content="{ title } ">
909- <meta property="twitter:description" content="{ description } ">
910- <meta property="twitter:image" content="{ image_url } ">
911- <!-- Open Graph data -->
912- <meta property="og:title" content="{ title } " />
913- <meta property="og:type" content="website" />
914- <meta property="og:description" content="{ description } " />
915- <meta property="og:image" content="{ image_url } ">
916- """
917- )
879+ return meta_tags + self .config .meta_tags
918880
919881 # Serve the JS bundles for each package
920882 def serve_component_suites (self , package_name , fingerprinted_path ):
@@ -959,14 +921,14 @@ def index(self, *args, **kwargs): # pylint: disable=unused-argument
959921 scripts = self ._generate_scripts_html ()
960922 css = self ._generate_css_dist_html ()
961923 config = self ._generate_config_html ()
962- metas = self ._generate_meta_html ()
924+ metas = self ._generate_meta ()
963925 renderer = self ._generate_renderer ()
964926
965927 # use self.title instead of app.config.title for backwards compatibility
966928 title = self .title
967- pages_metas = ""
968- if self .use_pages :
969- pages_metas = self . _pages_meta_tags ()
929+
930+ if self .use_pages and self . config . include_pages_meta :
931+ metas = _page_meta_tags ( self ) + metas
970932
971933 if self ._favicon :
972934 favicon_mod_time = os .path .getmtime (
@@ -983,8 +945,12 @@ def index(self, *args, **kwargs): # pylint: disable=unused-argument
983945 opened = True ,
984946 )
985947
948+ tags = "\n " .join (
949+ format_tag ("meta" , x , opened = True , sanitize = True ) for x in metas
950+ )
951+
986952 index = self .interpolate_index (
987- metas = pages_metas + metas ,
953+ metas = tags ,
988954 title = title ,
989955 css = css ,
990956 config = config ,
@@ -1988,57 +1954,11 @@ def verify_url_part(served_part, url_part, part_name):
19881954
19891955 self .server .run (host = host , port = port , debug = debug , ** flask_run_options )
19901956
1991- def _import_layouts_from_pages (self ):
1992- for root , dirs , files in os .walk (self .config .pages_folder ):
1993- dirs [:] = [
1994- d for d in dirs if not d .startswith ("." ) and not d .startswith ("_" )
1995- ]
1996- for file in files :
1997- if (
1998- file .startswith ("_" )
1999- or file .startswith ("." )
2000- or not file .endswith (".py" )
2001- ):
2002- continue
2003- page_path = os .path .join (root , file )
2004- with open (page_path , encoding = "utf-8" ) as f :
2005- content = f .read ()
2006- if "register_page" not in content :
2007- continue
2008-
2009- module_name = _infer_module_name (page_path )
2010- spec = importlib .util .spec_from_file_location (module_name , page_path )
2011- page_module = importlib .util .module_from_spec (spec )
2012- spec .loader .exec_module (page_module )
2013- sys .modules [module_name ] = page_module
2014-
2015- if (
2016- module_name in _pages .PAGE_REGISTRY
2017- and not _pages .PAGE_REGISTRY [module_name ]["supplied_layout" ]
2018- ):
2019- _validate .validate_pages_layout (module_name , page_module )
2020- _pages .PAGE_REGISTRY [module_name ]["layout" ] = getattr (
2021- page_module , "layout"
2022- )
2023-
2024- @staticmethod
2025- def _path_to_page (path_id ):
2026- path_variables = None
2027- for page in _pages .PAGE_REGISTRY .values ():
2028- if page ["path_template" ]:
2029- template_id = page ["path_template" ].strip ("/" )
2030- path_variables = _parse_path_variables (path_id , template_id )
2031- if path_variables :
2032- return page , path_variables
2033- if path_id == page ["path" ].strip ("/" ):
2034- return page , path_variables
2035- return {}, None
2036-
20371957 def enable_pages (self ):
20381958 if not self .use_pages :
20391959 return
20401960 if self .pages_folder :
2041- self . _import_layouts_from_pages ()
1961+ _import_layouts_from_pages (self . config . pages_folder )
20421962
20431963 @self .server .before_request
20441964 def router ():
@@ -2060,9 +1980,7 @@ def update(pathname, search):
20601980 """
20611981
20621982 query_parameters = _parse_query_string (search )
2063- page , path_variables = self ._path_to_page (
2064- self .strip_relative_path (pathname )
2065- )
1983+ page , path_variables = _path_to_page (self .strip_relative_path (pathname ))
20661984
20671985 # get layout
20681986 if page == {}:
0 commit comments