77from Crypto import Random
88from jinja2 import Template
99from Crypto .Cipher import AES
10+ from bs4 import BeautifulSoup
1011from mkdocs .plugins import BasePlugin
1112
1213try :
@@ -56,6 +57,7 @@ class encryptContentPlugin(BasePlugin):
5657 ('tag_encrypted_page' , mkdocs .config .config_options .Type (bool , default = False )),
5758 ('password_button' , mkdocs .config .config_options .Type (bool , default = False )),
5859 ('password_button_text' , mkdocs .config .config_options .Type (string_types , default = str (settings ['password_button_text' ]))),
60+ ('encrypted_toc' , mkdocs .config .config_options .Type (bool , default = False )),
5961 )
6062
6163 def __hash_md5__ (self , text ):
@@ -100,6 +102,7 @@ def __encrypt_content__(self, content):
100102 'hljs' : self .hljs ,
101103 'remember_password' : self .remember_password ,
102104 'disable_cookie_protection' : self .disable_cookie_protection ,
105+ 'encrypted_toc' : self .encrypted_toc ,
103106 })
104107 return decrypt_form
105108
@@ -164,6 +167,12 @@ def on_pre_build(self, config):
164167 if 'password_button_text' in plugin_config .keys ():
165168 password_button_text = plugin_config .get ('password_button_text' )
166169 setattr (self , 'password_button_text' , password_button_text )
170+ # Check if encrypted_toc feature is enable: encrypt table of content (PoC)
171+ setattr (self , 'encrypted_toc' , False )
172+ if 'encrypted_toc' in plugin_config .keys ():
173+ encrypted_toc = self .config .get ('encrypted_toc' )
174+ setattr (self , 'encrypted_toc' , encrypted_toc )
175+
167176
168177 def on_page_markdown (self , markdown , page , config , ** kwargs ):
169178 """
@@ -212,5 +221,39 @@ def on_page_content(self, html, page, config, **kwargs):
212221 if self .tag_encrypted_page :
213222 # Set attribute on page to identify encrypted page on template rendering
214223 setattr (page , 'encrypted' , True )
224+ if self .encrypted_toc :
225+ # Set attributes on page to retrieve password on POST context
226+ setattr (page , 'password' , self .password )
215227 html = self .__encrypt_content__ (html )
216228 return html
229+
230+ def on_post_page (self , output_content , page , config , ** kwargs ):
231+ """
232+ The post_page event is called after the template is rendered,
233+ but before it is written to disc and can be used to alter the output of the page.
234+ If an empty string is returned, the page is skipped and nothing is written to disc.
235+ :param output_content: output of rendered template as string
236+ :param page: mkdocs.nav.Page instance
237+ :param config: global configuration object
238+ :return: output of rendered template as string
239+ """
240+ # limit this process only if encrypted_toc feature is enable *(speedup x4)*
241+ if self .encrypted_toc and hasattr (page , 'encrypted' ):
242+ soup = BeautifulSoup (output_content , 'html.parser' )
243+ toc_search = soup .find ("div" , { "id" : "mkdocs-encrypted-toc" })
244+ if toc_search is not None and len (toc_search .contents ) > 0 :
245+ # Remove '\n', ' ' useless content generated by bs4 parsing...
246+ toc_search .contents = [content for content in toc_search .contents if not content in ['\n ' , ' ' ]]
247+ # Select childs items on tags div and encrypt all content with page password
248+ ciphertoc_bundle = self .__encrypt_text_aes__ (toc_search .contents [0 ], page .password )
249+ encrypted_toc = b';' .join (ciphertoc_bundle ).decode ('ascii' )
250+ toc_search .contents [0 ].replaceWith (encrypted_toc )
251+ if toc_search .has_attr ('style' ):
252+ if isinstance (toc_search ['style' ], list ):
253+ toc_search ['style' ].append ("display:none" )
254+ else :
255+ toc_search ['style' ] = toc_search ['class' ] + "display:none"
256+ else :
257+ toc_search ['style' ] = "display:none"
258+ output_content = str (soup )
259+ return output_content
0 commit comments