penguin/AstroJS

Javascript framework for my blog

commit b0ecbe42c3f3c09b3e7118fe1f9275598bc496f0

author斟酌 鵬兄 <tgckpg@gmail.com>
date2022-04-09T12:45:48Z
subjectVarious bug fix due to CSP headers
commit b0ecbe42c3f3c09b3e7118fe1f9275598bc496f0
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2022-04-09T12:45:48Z

    Various bug fix due to CSP headers
    
    SiteLibrary added name display on album view
    Optimizations & removed some obsolete files
---
 botanjs/config.py                                  |   2 +-
 botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.css   |  43 +++++-
 botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.js    |  12 +-
 .../AstroEdit/Visualizer/Snippet/AcquireLib.css    |   5 +
 .../AstroEdit/Visualizer/Snippet/AcquireLib.js     |   7 +-
 .../Blog/AstroEdit/Visualizer/Snippet/Meta.css     |   5 +
 .../Blog/AstroEdit/Visualizer/Snippet/Meta.js      |   7 +-
 .../Blog/AstroEdit/Visualizer/Snippet/RespH.css    |   5 +
 .../Blog/AstroEdit/Visualizer/Snippet/Video.css    |  18 +++
 .../Blog/AstroEdit/Visualizer/Snippet/Video.js     |  70 ++++-----
 .../src/Astro/Blog/AstroEdit/Visualizer/_this.css  |  16 ++
 .../src/Astro/Blog/AstroEdit/Visualizer/_this.js   |  52 +++----
 botanjs/src/Astro/Blog/Components/Album.js         |   5 +-
 botanjs/src/Astro/Blog/Components/Comment.css      |  10 +-
 botanjs/src/Astro/Blog/Components/Comment.js       |   9 +-
 botanjs/src/Astro/Blog/Components/Entry/Block.css  | 162 ---------------------
 botanjs/src/Astro/Blog/Components/Entry/Block.js   |  91 ------------
 botanjs/src/Astro/Blog/Components/Entry/Mega.css   | 125 ----------------
 botanjs/src/Astro/Blog/Components/Entry/Mega.js    |   1 -
 botanjs/src/Astro/Blog/Components/VerticalNote.css |  83 -----------
 botanjs/src/Astro/Blog/Components/VerticalNote.js  |  82 -----------
 botanjs/src/Astro/Blog/Components/Video.css        |  40 ++---
 botanjs/src/Astro/Blog/Components/Video.js         |   9 +-
 botanjs/src/Astro/Blog/Layout/MainFrame.css        |   2 +
 botanjs/src/Astro/Blog/Layout/Subs/Manage.css      |   1 +
 botanjs/src/Dandelion/StarticRes.js                |   5 +
 k8s/deployments.yaml                               |  12 +-
 27 files changed, 214 insertions(+), 665 deletions(-)

diff --git a/botanjs/config.py b/botanjs/config.py
index 6daa295..4582157 100644
--- a/botanjs/config.py
+++ b/botanjs/config.py
@@ -8,7 +8,7 @@ DEBUG = os.getenv( "DEBUG" )
 if DEBUG is None:
 	DEBUG = Config[ "Env" ][ "Debug" ]
 else:
-	Config[ "Env" ][ "Debug" ] = DEBUG
+	Config[ "Env" ][ "Debug" ] = str( DEBUG == "1" )
 
 REDIS_CONN = os.getenv( "REDIS_CONN" )
 if not REDIS_CONN is None:
diff --git a/botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.css b/botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.css
index dc40590..af8c58b 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.css
+++ b/botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.css
@@ -146,14 +146,55 @@
 .canvasImage > span {
 	width: 100px;
 	height: 100px;
-	float: left;
+
 	margin: 0.2em;
 
 	background-repeat: no-repeat;
 	background-position: center;
 
 	border: 1px solid transparent;
+	display: inline-block;
+	vertical-align: middle;
+
+	position: relative;
+	overflow: hidden;
+}
+
+.canvasImage > span:before {
+    content: '';
+    display: inline-block;
+    height: 100%;
+    vertical-align: middle;
+}
+
+.canvasImage > span img {
+    vertical-align: middle;
+    display: inline-block;
+}
+
+.canvasImage > span:after {
+    content: attr(data-title);
+    background-color: rgba(0,0,0,0.6);
+    color: white;
+    position: absolute;
+    left: 0;
+    bottom: -2em;
+    font-size: 0.8em;
+    width: 100%;
+    padding-left: 0.5em;
+
+	overflow: hidden;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+
+    -webkit-transition: all .25s ease-out;
+    -moz-transition: all .25s ease-out;
+    -o-transition: all .25s ease-out;
+    transition: all .25s ease-out;
+}
 
+.canvasImage > span:hover:after {
+    bottom: 0%;
 }
 
 .canvasImage > span[selected] {
diff --git a/botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.js b/botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.js
index f37e34d..3478892 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.js
+++ b/botanjs/src/Astro/Blog/AstroEdit/SiteLibrary.js
@@ -145,10 +145,10 @@
 
 					////// Album item
 					? Dand.wrap(
-						"span", "img_" + Perf.uuid, "ci_album", Dand.wrap("span")
+						"span", "img_" + Perf.uuid, "ci_album"
+						, Dand.wrapna( "img", new IKey( "src", basePath + "image/s100/" + file.hash + ".jpg" ) )
 						, [
-							new IKey("style", "background-image: url(" + basePath + "image/s100/" + file.hash + ".jpg);" )
-							, new IKey("title"
+							new IKey("title"
 								, "Album: " + file.name
 									+ "\n" + file.cCount + " file(s)"
 									+ "\nDate: " + prettyDate( new Date( file.date_created ), true )
@@ -159,10 +159,10 @@
 					)
 					//////// Normal filele
 					: Dand.wrap(
-						"span", "img_" + Perf.uuid, null, Dand.wrap( "span" )
+						"span", "img_" + Perf.uuid, null
+						, Dand.wrapna( "img", new IKey( "src", basePath + "image/s100/" + file.hash + ".jpg" ) )
 						, [
-							new IKey("style", "background-image: url(" + basePath + "image/s100/" + file.hash + ".jpg);" )
-							, new IKey("title"
+							new IKey("title"
 								, "File: " + file.name
 								+ "\nDate: " + prettyDate( new Date( file.date_created ), true )
 								+ "\nCreated by: " + file.author
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/AcquireLib.css b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/AcquireLib.css
new file mode 100644
index 0000000..f2d9d1b
--- /dev/null
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/AcquireLib.css
@@ -0,0 +1,5 @@
+.v_boundary[data-type="AcquireLib"] > span {
+	background-color: #444;
+	color: white;
+	padding: 0.2em 0.5em;
+}
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/AcquireLib.js b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/AcquireLib.js
index b7ab016..4ed7e08 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/AcquireLib.js
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/AcquireLib.js
@@ -54,12 +54,7 @@
 					temp = Dand.wrap(
 						'span', null, "flsf"
 						, "AcquireLib: " + src
-						, [
-							new DataKey( "value", src )
-							, new IKey(
-								"style", "background-color: #444; color: white; padding: 0.2em 0.5em;"
-							)
-						]
+						, [ new DataKey( "value", src ) ]
 					);
 					insertSnippet(j = snippetWrap("AcquireLib", temp, false, 'span'), Boolean(override));
 				}
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Meta.css b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Meta.css
new file mode 100644
index 0000000..80e4f4c
--- /dev/null
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Meta.css
@@ -0,0 +1,5 @@
+.v_boundary[data-type="Meta"] > span {
+	background-color: #444;
+	color: white;
+	padding: 0.2em 0.5em;
+}
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Meta.js b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Meta.js
index 495ae3b..6b909f8 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Meta.js
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Meta.js
@@ -53,12 +53,7 @@
 					temp = Dand.wrap(
 						'span', null, "flsf"
 						, "Meta Tags"
-						, [
-							new DataKey( "value", code )
-							, new IKey(
-								"style", "background-color: #444; color: white; padding: 0.2em 0.5em;"
-							)
-						]
+						, [ new DataKey( "value", code ) ]
 					);
 					insertSnippet(j = snippetWrap( "Meta", temp, false, "span" ), Boolean(override));
 				}
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/RespH.css b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/RespH.css
new file mode 100644
index 0000000..503d369
--- /dev/null
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/RespH.css
@@ -0,0 +1,5 @@
+.v_boundary[data-type="RespH"] > span {
+	background-color: #444;
+	color: white;
+	padding: 0.2em 0.5em;
+}
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Video.css b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Video.css
new file mode 100644
index 0000000..bb9868c
--- /dev/null
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Video.css
@@ -0,0 +1,18 @@
+.v_boundary[data-type="Video"] {
+	width: 640px; height: 390px;
+	background-color: black;
+	padding: 0;
+}
+
+.v_boundary[data-type="Video"] .v_box {
+	width: 640px; height: 390px;
+	position: relative;
+	display: table-cell;
+	text-align: center;
+	vertical-align: middle;
+}
+
+.v_boundary[data-type="Video"] .v_description {
+	text-align: left;
+	padding-left: 0.5em;
+}
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Video.js b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Video.js
index 58781ab..12f49eb 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Video.js
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/Snippet/Video.js
@@ -14,43 +14,46 @@
 	var MessageBox                        = __import( "Components.MessageBox" );
 
 	var getData                           = __import( "System.Net.getData" );
+	var BLANK_IMG = __import( "Dandelion.StaticRes.BLANK_IMG" );
 
 	var video = function (insertSnippet, snippetWrap, createContext, override)
 	{
-		var temp, i, j
-		
-		, getVimeoThumbnail = function (vtag)
+		var temp, i, j, imgSrc
+
+		, getVimeoThumbnail = function( v )
 		{
-			getData("//vimeo.com/api/oembed.json?url=https%3A//vimeo.com/" + vtag.getAttribute("data-value"), setThumbnail.bind(vtag), noThumb.bind(vtag));
+			getData(
+				"//vimeo.com/api/oembed.json?url=https%3A//vimeo.com/" + v
+				, setThumbnail
+				, noThumb
+			);
 		}
-	
-		, noThumb = function ()
+		, setImgSrc = function( url )
 		{
-			
+			if( imgSrc ) imgSrc.src = url;
 		}
-		
+		, noThumb = function () { }
 		, setThumbnail = function (str)
 		{
-			this.style.background = "black url(" + JSON.parse(str)["thumbnail_url"] + ") center center no-repeat";
-			
+			setImgSrc( JSON.parse(str)["thumbnail_url"] );
 		}
-		
+
 		, handler = function ()
 		{
 			// Input fields
 			var input_url = Dand.wrap('input', null, "v_snippet_input_single", null, new IKey("type", "text"));
-			
+
 			// Popup MessageBox
 			new MessageBox("Insert video snippet"
 				, Dand.wrape([ Dand.wrapc("v_instruction flsf", "Paste a vimeo/Youtube link below:"), input_url ])
 				, "OK", "Cancel", visualizer.bind(input_url)
 			).show();
 		}
-	
+
 		, visualizer = function (submitted, override)
 		{
 			var t, v;
-			
+
 			if (override)
 			{
 				v = override.value;
@@ -83,35 +86,34 @@
 					}
 				}
 			}
-			
+
 			if (submitted)
 			{
-				
 				// Visualize component
-				temp =  Dand.wrapc('v_box', Dand.wrapc('v_description', "Video(url): " + t)
-				, [
-					new DataKey("value", v)
-					, new DataKey("type", i)
-					, new IKey("style"
-						, "width: 640px; height: 390px;"
-						+ ( (i[0] == "v") ? "" : ("background: black url(//img.youtube.com/vi/" + v + "/hqdefault.jpg) no-repeat center center;") )
-					)
-				  ]
+				temp =  Dand.wrapc('v_box'
+					, [
+						Dand.wrapc( 'v_description', i[0].toUpperCase() + i.substr(1) + ": " + v )
+						, imgSrc = Dand.wrapna( "img", [ new IKey( "src", BLANK_IMG ) ] )
+					]
+					, [ new DataKey("value", v), new DataKey("type", i) ]
 				);
-				
-				if (i[0] == "v")
+
+				if( i[0] == "v" )
 				{
-					getVimeoThumbnail(temp);
+					getVimeoThumbnail( v );
 				}
-				
+				else
+				{
+					setImgSrc( "//img.youtube.com/vi/" + v + "/hqdefault.jpg" );
+				}
+
 				insertSnippet(j = snippetWrap("Video", temp), Boolean(override));
-				
+
 				// Set context menu
 				createContext(null, j);
 			}
 		}
-		;
-		
+
 		if (override)
 		{
 			visualizer(true, override);
@@ -123,13 +125,13 @@
 		}
 		return true;
 	};
-	
+
 	var compile = function (stage)
 	{
 		// [video type=\"youtube\"]" + v[2] + "[/video]
 		var element = IDOMElement(stage)
 		, type = element.getDAttribute("type");
-		
+
 		return "[video type=\"" + type + "\"]" + element.getDAttribute("value") + "[/video]";
 	};
 
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.css b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.css
index 5ede39e..75c76a3 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.css
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.css
@@ -104,3 +104,19 @@ div[data-type="token"]:after {
 div[data-type="token"]:hover:after {
 	color: rgba( 255, 255, 255, 0.5 );
 }
+
+#ae_visual_snippets > span[data-name="code"] { background: white; color: cornflowerblue; }
+#ae_visual_snippets > span[data-name="image"] { background: #ff0084; }
+#ae_visual_snippets > span[data-name="sound"] { background: YellowGreen; }
+#ae_visual_snippets > span[data-name="video"] { background: Crimson; }
+#ae_visual_snippets > span[data-name="spoiler"] { background: cornflowerblue; }
+#ae_visual_snippets > span[data-name="link"] { background: blue; }
+#ae_visual_snippets > span[data-name="acquirelib"] { background: black; }
+#ae_visual_snippets > span[data-name="html"] { background: coral; }
+#ae_visual_snippets > span[data-name="sitefile"] { background: royalblue; }
+#ae_visual_snippets > span[data-name="heading"] {  }
+#ae_visual_snippets > span[data-name="footnote"] {  }
+#ae_visual_snippets > span[data-name="resph"] {  }
+#ae_visual_snippets > span[data-name="meta"] {  }
+#ae_visual_snippets > span[data-name="articlelink"] {  }
+#ae_visual_snippets > span[data-name="articlecontent"] {  }
diff --git a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.js b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.js
index 4c46fad..6287fe9 100644
--- a/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.js
+++ b/botanjs/src/Astro/Blog/AstroEdit/Visualizer/_this.js
@@ -26,23 +26,23 @@
 	/** @type {Astro.Blog.Config} */
 	var Config                                  = __import( "Astro.Blog.Config" );
 
-	var snippetList = IKey.quickDef(
-		  "Code"             , "background: white; color: cornflowerblue;"
-		  , "Image"          , "background: #ff0084;"
-		  , "Sound"          , "background: YellowGreen;"
-		  , "Video"          , "background: Crimson;"
-		  , "Spoiler"        , "background: cornflowerblue;"
-		  , "Link"           , "background: blue;"
-		  , "AcquireLib"     , "background: black;"
-		  , "Html"           , "background: coral;"
-		  , "SiteFile"       , "background: royalblue;"
-		  , "Heading"        , ""
-		  , "Footnote"       , ""
-		  , "RespH"          , ""
-		  , "Meta"           , ""
-		  , "ArticleLink"    , ""
-		  , "ArticleContent" , ""
-	);
+	var snippetList = [
+		  "Code"
+		  , "Image"
+		  , "Sound"
+		  , "Video"
+		  , "Spoiler"
+		  , "Link"
+		  , "AcquireLib"
+		  , "Html"
+		  , "SiteFile"
+		  , "Heading"
+		  , "Footnote"
+		  , "RespH"
+		  , "Meta"
+		  , "ArticleLink"
+		  , "ArticleContent"
+	];
 
 	var snippetNs = "Astro.Blog.AstroEdit.Visualizer.Snippet.";
 	//// Document Visualizer visualize snippets, used in AstroEdit and comments
@@ -388,19 +388,7 @@
 				}
 
 				// Append module"s control
-				temp = Dand.wrapne(
-					"span"
-					, mod_name
-					, new IKey(
-						"style"
-						, utils.objSearch(
-							snippetList
-							/** @param {System.utils.IKey} a */
-							, function( a ) { return a.keyName.toLowerCase() == mod_name }
-							, "keyValue"
-						)
-					)
-				);
+				temp = Dand.wrapne( "span", mod_name, new IKey( "data-name", mod_name ) );
 
 				snippetControls.appendChild( temp );
 				snippetControls.appendChild( Dand.textNode( "\t" ) );
@@ -502,9 +490,9 @@
 		article.invoke(this);
 
 		var modules = [];
-		for( var i in snippetList )
+		for( var i = 0; i < snippetList.length; i ++ )
 		{
-			modules[ modules.length ] = snippetNs + snippetList[i].keyName;
+			modules[ modules.length ] = snippetNs + snippetList[i];
 		}
 
 		var ldr = new Loader( service_uri, "o" );
diff --git a/botanjs/src/Astro/Blog/Components/Album.js b/botanjs/src/Astro/Blog/Components/Album.js
index f783950..38d7ba4 100644
--- a/botanjs/src/Astro/Blog/Components/Album.js
+++ b/botanjs/src/Astro/Blog/Components/Album.js
@@ -22,6 +22,7 @@
 	var config = null;
 
 	var SiteFile = ns[ NS_INVOKE ]( "SiteFile" );
+	var BLANK_IMG = __import( "Dandelion.StaticRes.BLANK_IMG" );
 
 	var Album = function ( id, hash )
 	{
@@ -56,9 +57,7 @@
 
 				ostage.appendChild( Dand.wrapne(
 					"div"
-					, Dand.wrapna( "img", [
-						new IKey( "src", "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" )
-					] )
+					, Dand.wrapna( "img", [ new IKey( "src", BLANK_IMG ) ] )
 					, [ new IKey( "id", uuid ), new DataKey( "size", "medium" ) ]
 				) );
 
diff --git a/botanjs/src/Astro/Blog/Components/Comment.css b/botanjs/src/Astro/Blog/Components/Comment.css
index 9597cac..37591ea 100644
--- a/botanjs/src/Astro/Blog/Components/Comment.css
+++ b/botanjs/src/Astro/Blog/Components/Comment.css
@@ -159,10 +159,12 @@
 	border-bottom: 1em solid white;
 	
 	position: absolute;
-	top: -1em;
+	top: 0;
 	right: 1em;
 }
 
+#ri_switch[data-pointy="1"] { top: -1em; }
+
 .c_relative_wrap {
 	position: relative;
 	padding: 1em;
@@ -247,10 +249,14 @@
 	margin: 1em;
 }
 
-.info_field  > div{
+.info_field > div{
 	margin: 0.2em 0;
+	text-align: right;
 }
 
+.info_field .website span { width: 20%; }
+.info_field .website input { width: 80%; }
+
 #capcha_wrapper {
 	overflow: hidden;
 	height: 0;
diff --git a/botanjs/src/Astro/Blog/Components/Comment.js b/botanjs/src/Astro/Blog/Components/Comment.js
index e53d898..8c84620 100644
--- a/botanjs/src/Astro/Blog/Components/Comment.js
+++ b/botanjs/src/Astro/Blog/Components/Comment.js
@@ -107,7 +107,6 @@
 			}
 		}
 
-
 		, doReply = function ()
 		{
 			var c_reply = this;
@@ -116,13 +115,12 @@
 			// Set comment id
 			submit_button.setAttribute( new DataKey( "cid", c_reply.getAttribute( "value" ) ) );
 
-			// Close reply indicator
-			Dand.id("ri_switch").style.top = "0";
+			// close the triangle in the top rigth corner
+			Dand.id( "ri_switch", true ).removeAttribute( "data-pointy" );
 
 			// If this button is not that button
 			button && ( c_reply != button ) && releaseReplyButton();
 
-
 			// Lock reply button
 			c_reply.setAttribute("locked", "1");
 			c_reply.onclick = null;
@@ -313,7 +311,8 @@
 				cp.style.height = "";
 				cp.style.overflow = "";
 
-				Dand.id("ri_switch").style.top = "";
+				// Pop back up the pointy triangle
+				Dand.id( "ri_switch", true ).setAttribute( new DataKey( "pointy", "1" ) );
 
 				fieldReady = false;
 				fieldReadyTrigger();
diff --git a/botanjs/src/Astro/Blog/Components/Entry/Block.css b/botanjs/src/Astro/Blog/Components/Entry/Block.css
deleted file mode 100644
index 631502e..0000000
--- a/botanjs/src/Astro/Blog/Components/Entry/Block.css
+++ /dev/null
@@ -1,162 +0,0 @@
-.block-entries .block {
-	float: left;
-
-	width: 225px;
-	height: 325px;
-
-	margin: 0 2em 2em 0;
-
-	position: relative;
-
-	color: #666;
-	border: 2px solid transparent;
-
-	display: block;
-}
-
-.block-entries .block:hover {
-	border-width: 2px;
-	border-color: purple;
-}
-
-.block-entries .slide-wrapper {
-	position: absolute;
-	overflow: hidden;
-	width: 100%;
-	height: 100%;
-
-	border: 1px solid #D4D7C9;
-	margin: -1px;
-}
-
-.block-entries .slide-wrapper:hover {
-	border-color: purple;
-}
-
-.block-entries .date {
-	font-size: 0.8em;
-	text-align: right;
-}
-
-.block-entries .title {
-	font-size: 1.2em;
-	max-height: 2.4em;
-	overflow: hidden;
-	text-overflow: ellipsis;
-	color: #444;
-}
-
-.block-entries .content {
-	text-overflow: ellipsis;
-	overflow: hidden;
-}
-
-.block-entries .author {
-	color: crimson;
-	text-align: right;
-}
-
-.block-entries .c-count {
-	position: absolute;
-	bottom: 1em;
-	left: 0.5em;
-
-	font-size: 0.8em;
-	font-family: sans-serif;
-	color: orangered;
-}
-
-
-.block-entries .slide {
-	position: absolute;
-	width: 100%;
-	height: 150%;
-
-	top: 0;
-}
-
-.block-entries .slide:after, .block-entries[on] .slide {
-	content: attr(data-content);
-
-	position: absolute;
-
-	top: 100%;
-
-	width: 100%;
-	height: 50%;
-
-	padding: 0 0.5em;
-
-	color: #EEE;
-	background: purple;
-
-	overflow: hidden;
-	text-overflow: ellipsis;
-
-	-webkit-box-shadow: inset 0px 15px 15px -15px black;
-	-moz-box-sizing: inset 0px 15px 15px -15px black;
-	box-shadow: inset 0px 15px 15px -15px black;
-
-	-webkit-box-sizing: border-box;
-	-moz-box-sizing: border-box;
-	box-sizing: border-box;
-
-	-webkit-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-moz-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-ms-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-o-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
-
-	-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-moz-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-ms-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-o-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
-}
-
-.block-entries .slide:hover:after, .slide[on]:after {
-	top: 62.5%;
-	padding: 0.5em;
-}
-
-.block-entries .slide:hover, .slide[on] {
-	top: -50%;
-}
-
-.block-entries .front {
-	position: absolute;
-	background: white;
-
-	width: 100%;
-	height: 100%;
-}
-
-.block-entries .block-wrapper {
-	position: relative;
-	background-image: repeating-linear-gradient(
-		135deg
-		, transparent, transparent 1px
-		, rgba( 85, 85, 85, .1 ) 1px
-		, rgba( 85, 85, 85, .1 ) 30px
-	);
-	background-color: black;
-}
-
-.block-entries .block-info {
-	padding: 0.5em;
-	background: white;
-}
-
-.block-entries .banner {
-	width: 50%;
-	padding: 50%;
-
-	background-position: center;
-	background-repeat: no-repeat;
-
-	border-bottom: 1px solid #D4D7C9;
-
-	-webkit-box-sizing: border-box;
-	-moz-box-sizing: border-box;
-	box-sizing: border-box;
-}
diff --git a/botanjs/src/Astro/Blog/Components/Entry/Block.js b/botanjs/src/Astro/Blog/Components/Entry/Block.js
deleted file mode 100644
index 69b07f6..0000000
--- a/botanjs/src/Astro/Blog/Components/Entry/Block.js
+++ /dev/null
@@ -1,91 +0,0 @@
-(function(){
-	var ns = __namespace( "Astro.Blog.Components.Entry" );
-
-	/** @type {System.Cycle} */
-	var Cycle                            = __import( "System.Cycle" );
-	/** @type {System.utils.Perf} */
-	var Perf                             = __import( "System.utils.Perf" );
-	/** @type {Dandelion} */
-	var Dand                             = __import( "Dandelion" );
-	/** @type {Astro.Bootstrap} */
-	var Bootstrap                        = __import( "Astro.Bootstrap" );
-
-	/** @type {Astro.Blog.Config} */
-	var Conf                                      = __import( "Astro.Blog.Config" );
-	/** @type {Astro.Blog.Components.SiteFile} */
-	var SiteFile                                  = __import( "Astro.Blog.Components.SiteFile" );
-
-	/** @type {_AstConf_.SiteFile} */
-	var config = null;
-
-	var Block  = function ( element )
-	{
-		if( !config ) throw new Error( "Config is not defined" );
-		var slide = Dand.glass( "slide", false, element )[0];
-		var delayCont = function( firstTime )
-		{
-			Cycle.delay(
-				function()
-				{
-					slide.getAttribute( "on" )
-						? slide.removeAttribute( "on" )
-						: slide.setAttribute( "on", 1 )
-						;
-					delayCont( false );
-				}
-				, firstTime
-					? Math.random()*10000
-					: ( 5500 + Math.random()*4500 )
-			);
-		};
-
-		delayCont( true );
-
-		var banner = Dand.glass( "banner", false, element )[0];
-		var bId = banner.getAttribute( "id" );
-
-		var placeBackground = function( obj )
-		{
-			/** @type {_AstJson_.SiteFile} */
-			var finfo = JSON.parse( obj );
-
-			/** @type {_AstJson_.SiteFile} */
-			var file = finfo.files[0];
-
-			var path = config.path.image.medium + file.hash + ".jpg";
-			banner.style.backgroundImage = "url(" + path  + ")"; 
-		};
-
-		var placeError = function( obj )
-		{
-			throw new Error( obj );
-		};
-
-		var SFOs = Conf.get( "SFObjects" );
-		for( var i in SFOs )
-		{
-			var f = SFOs[i];
-			var id = f[0];
-			if( id == bId )
-			{
-				new SiteFile( id, f[1] ).loadInfo( placeBackground, placeError );
-			}
-		}
-	};
-
-	var init = function()
-	{
-		config = Conf.get( "SiteFile" );
-
-		var stage = Dand.glass( "block-entries" )[0];
-		var everyEntries = Dand.glass( "block", false, stage );
-		for( var i = 0; i < everyEntries.length; i ++ )
-		{
-			new Block( everyEntries[ i ] );
-		}
-	};
-
-	Bootstrap.regInit( init );
-
-	ns[ NS_EXPORT ]( EX_CLASS, "Block", Block );
-})();
diff --git a/botanjs/src/Astro/Blog/Components/Entry/Mega.css b/botanjs/src/Astro/Blog/Components/Entry/Mega.css
deleted file mode 100644
index 6c9805f..0000000
--- a/botanjs/src/Astro/Blog/Components/Entry/Mega.css
+++ /dev/null
@@ -1,125 +0,0 @@
-.it-shucks > a {
-	float: right;
-}
-
-.mega-entry {
-	border: 6px solid white;
-	background: white;
-	color: black;
-
-	position: relative;
-	margin: 0.5em;
-
-	display: block;
-
-	word-wrap: break-word;
-
-	box-shadow: 0 0 0 1px #D4D7C9;
-
-	max-width: 80%;
-	width: 600px;
-}
-
-.mega-entry:hover {
-	text-decoration: none;
-}
-
-.mega-entry .cCont img {
-	position: absolute;
-	margin-top: -25%;
-	max-width: 100%;
-}
-
-.mega-entry .cCont:after {
-	content: attr(data-content);
-
-	width: 100%;
-	height: 0;
-
-	top: 100%;
-
-	position: absolute;
-
-	color: white;
-	background: rgba(0, 0, 0, 0.65);
-
-	font-family: custom-serif;
-
-	padding: 0 0.5em;
-
-	-webkit-box-sizing: border-box;
-	-moz-box-sizing: border-box;
-	box-sizing: border-box;
-
-	-webkit-transition: all 300ms cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-moz-transition: all 300ms cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-ms-transition: all 300ms cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-o-transition: all 300ms cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	transition: all 300ms cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
-
-	-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-moz-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-ms-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	-o-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 
-	transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
-}
-
-.mega-entry .cCont:focus:after, .mega-entry .cCont:hover:after {
-	top: 50%;
-	height: 50%;
-	padding: 0.5em;
-}
-
-.mega-entry > #noteTag {
-	background: black;
-}
-
-.noteTag {
-	color: white;
-	padding: 0.2em;
-	overflow: hidden;
-
-	-moz-box-shadow: 0 2px 2px 0 black;
-	-webkit-box-shadow: 0 2px 2px 0 black;
-	box-shadow: 0 2px 2px 0 black;
-
-	position: absolute;
-	background: slategrey;
-	right: -6px;
-	top: 10px;
-}
-
-.mega-entry > .cCont {
-    position: relative;
-	color: white;
-	overflow: hidden;
-	height: 130px;
-}
-
-.mega-entry .cCont > h2 {
-	position: absolute;
-	font-family: custom-sans;
-
-	padding: 0 0.2em;
-	text-shadow: 2px 2px 8px black;
-
-	color: #DDD;
-	z-index: 1;
-}
-
-.cDate {
-	padding: 0.2em 0.5em;
-	font-size: 0.9em;
-}
-.cEOF {
-	height: 10px;
-}
-
-
-.Sun { background: #FF1D25; }
-.Mon { background: #662D91; }
-.Tue { background: #3FA9F5; }
-.Wed { background: #7AC943; }
-.Thu { background: #FF7BAC; }
-.Fri { background: #603813; }
-.Sat { background: #FF931E; }
diff --git a/botanjs/src/Astro/Blog/Components/Entry/Mega.js b/botanjs/src/Astro/Blog/Components/Entry/Mega.js
deleted file mode 100644
index 3c902f5..0000000
--- a/botanjs/src/Astro/Blog/Components/Entry/Mega.js
+++ /dev/null
@@ -1 +0,0 @@
-// __namespace( "Astro.Blog.Components.Entry.Mega" );
diff --git a/botanjs/src/Astro/Blog/Components/VerticalNote.css b/botanjs/src/Astro/Blog/Components/VerticalNote.css
deleted file mode 100644
index 88318c9..0000000
--- a/botanjs/src/Astro/Blog/Components/VerticalNote.css
+++ /dev/null
@@ -1,83 +0,0 @@
-.vsign {
-	position: relative;
-}
-.vertical-text {
-	float: right;
-
-	color: #777;
-
-	padding: 1em 0.5em;
-	margin: 0.5em 1em;
-
-	position: relative;
-}
-
-.vertical-text.block {
-	background-color: #FAFAFA;
-}
-
-.vertical-text > a.more {
-	display: block;
-
-	top: 0;
-	left: 0;
-
-	width: 100%;
-	height: 100%;
-
-	padding: 0;
-
-	position: absolute;
-
-	border: 1px solid #D4D7C9;
-}
-.vertical-text > a.more:hover {
-	border-width: 2px;
-	border-color: purple;
-
-	cursor: pointer;
-}
-
-.vertical-text p
-, .vertical-text a
-, .vertical-text h1 , .vertical-text h2, .vertical-text h3
-, .vertical-text h4, .vertical-text h5, .vertical-text h6 {
-	padding: 0.1em;
-	margin: 0;
-	width: 1em;
-    letter-spacing: 1em;
-
-    word-break: break-all;
-	word-wrap: break-word;
-}
-
-.vertical-text > .block {
-	overflow: hidden;
-	width: 4.5em;
-}
-
-.vertical-text > * {
-    display: inline-block;
-    float: right;
-    height: 390px;
-}
-
-.vertical-text > p {
-    height: 400px;
-}
-
-.vertical-text > p[data-flag="date"] {
-	color: #BBB;
-}
-
-.vertical-text.source > * {
-    height: auto;
-}
-
-.vertical-text.source {
-    height: 360px;
-	border: 0;
-	padding: 0;
-	visibility: hidden;
-}
-
diff --git a/botanjs/src/Astro/Blog/Components/VerticalNote.js b/botanjs/src/Astro/Blog/Components/VerticalNote.js
deleted file mode 100644
index dfa2558..0000000
--- a/botanjs/src/Astro/Blog/Components/VerticalNote.js
+++ /dev/null
@@ -1,82 +0,0 @@
-(function(){
-	var ns = __namespace( "Astro.Blog.Components.VerticalNote" );
-	/** @type {Dandelion} */
-	var Dand                             = __import( "Dandelion" );
-	/** @type {Dandelion.IDOMElement} */
-	var IDOMElement                      = __import( "Dandelion.IDOMElement" );
-	/** @type {Astro.Bootstrap} */
-	var Bootstrap                        = __import( "Astro.Bootstrap" );
-	/** @type {Astro.Blog.Config} */
-	var Config                           = __import( "Astro.Blog.Config" );
-	/** @type {Astro.utils.Date} */
-	var XDate                            = __import( "Astro.utils.Date" );
-
-	/** @param {Dandelion.IDOMElement} elem */
-	var VerticalNote = function( elem )
-	{
-		var relem = elem.element;
-		var maxHeight = relem.clientHeight;
-
-		// Break for elements that are too long
-		var formatted = Dand.wrapc( relem.className.replace( / *source */, " " ) );
-
-		elem.foreach( 1, function( child )
-		{
-			var ichild = IDOMElement( child );
-			switch( ichild.getDAttribute( "flag" ) )
-			{
-				case "date":
-					child.innerHTML = XDate.chinese( new Date( child.innerHTML ) );
-				break;
-				case "anchor":
-				case "image":
-					formatted.appendChild( child );
-					child.style.display = null;
-				return;
-			}
-
-			var content = child.innerHTML;
-			var len = content.length;
-			var blockh = Math.ceil( child.clientHeight / len );
-
-			var opLen = Math.floor( maxHeight / blockh );
-
-			var i = 0;
-
-			var doBreak = function( i )
-			{
-				var nLine = Dand.wrapne(
-					child.nodeName
-					, content.substr( opLen * i, opLen )
-					, ichild.aKeys()
-				);
-
-				formatted.appendChild( nLine );
-
-				if( elem.getDAttribute( "href" ) )
-				{
-					formatted.addEventListener(
-						"click"
-						, function( e ) {
-							window.location = this.loc;
-						}.bind({ loc: elem.getDAttribute( "href" ) })
-					);
-				}
-
-				len -= opLen;
-			};
-
-			for( var i = 0; opLen < len; i ++ ) doBreak( i );
-			if( 0 < len ) doBreak( i );
-		} );
-
-		relem.style.display = "none";
-		relem.parentNode.insertBefore( formatted, relem.nextSibling );
-	};
-
-	Bootstrap.regInit(function() {
-		Dand.glass( "vertical-text", true )
-			.forEach( function( e ) { new VerticalNote( e ); } );
-	});
-
-})();
diff --git a/botanjs/src/Astro/Blog/Components/Video.css b/botanjs/src/Astro/Blog/Components/Video.css
index 9bd9641..c651688 100644
--- a/botanjs/src/Astro/Blog/Components/Video.css
+++ b/botanjs/src/Astro/Blog/Components/Video.css
@@ -1,32 +1,34 @@
 .v_wrapper {
 	width: 640px;
 	height: 390px;
+	position: relative;
+	text-align: center;
+	vertical-align: middle;
+	display: table-cell;
+	overflow: hidden;
 }
 
-.v_wrapper  > div{
-	position: relative;
+.v_wrapper[data-loaded="1"]:after {
+	display: none;
+}
+
+.v_wrapper[data-loaded="1"] img {
+	display: none;
+}
+
+.v_wrapper:after {
+	content: "\25BA";
+	position: absolute;
 	width: 100%;
 	height: 100%;
 	opacity: 0.6;
+	color: white;
 	background: black;
+	top: 0; left: 0;
+	font-size: 700%;
+	padding-top: 19%;
 }
 
-.v_wrapper  > div:hover {
+.v_wrapper:hover:after {
 	opacity: 0.2;
 }
-
-.v_wrapper > div > div {
-	width: 0;
-	height: 0;
-	border-top: 3.5em solid transparent;
-	border-bottom: 3.5em solid transparent;
-	border-left: 5em solid white;
-	
-	position: absolute;
-	
-	left: 50%;
-	top: 50%;
-	margin-top: -3.5em;
-	margin-left: -1.8em;
-	
- }
\ No newline at end of file
diff --git a/botanjs/src/Astro/Blog/Components/Video.js b/botanjs/src/Astro/Blog/Components/Video.js
index 93b3e1a..7d7e208 100644
--- a/botanjs/src/Astro/Blog/Components/Video.js
+++ b/botanjs/src/Astro/Blog/Components/Video.js
@@ -14,7 +14,7 @@
 
 	var getData = __import( "System.Net.getData" );
 
-	var v_current = { player: false, mask: false, stage: false, listener: false };
+	var v_current = { player: false, stage: false, listener: false };
 
 	var init = function()
 	{
@@ -49,13 +49,14 @@
 		if( v_current.stage )
 		{
 			v_current.stage.removeChild( v_current.player );
-			v_current.stage.appendChild( v_current.mask );
 			v_current.stage.onclick = v_current.listener;
+			v_current.stage.removeAttribute( "data-loaded" );
 		}
 		
 		// Remove mask
-		( v_current.stage = vtag ).removeChild( v_current.mask = vtag.firstChild );
-		
+		IDOMElement( v_current.stage = vtag )
+			.setAttribute( "data-loaded", 1 );
+
 		v_current.player = Dand.wrapna(
 			"iframe"
 			, IKey.quickDef(	
diff --git a/botanjs/src/Astro/Blog/Layout/MainFrame.css b/botanjs/src/Astro/Blog/Layout/MainFrame.css
index 6b33d6c..5a03859 100644
--- a/botanjs/src/Astro/Blog/Layout/MainFrame.css
+++ b/botanjs/src/Astro/Blog/Layout/MainFrame.css
@@ -36,6 +36,8 @@ div#header, div#mbody, div#contact, div#horizon {
     animation-name: aspin;
 }
 
+.err { color: orangered; }
+
 .cw { animation-name: spin; }
 
 .mbody {
diff --git a/botanjs/src/Astro/Blog/Layout/Subs/Manage.css b/botanjs/src/Astro/Blog/Layout/Subs/Manage.css
index 01397a9..ecba2d8 100644
--- a/botanjs/src/Astro/Blog/Layout/Subs/Manage.css
+++ b/botanjs/src/Astro/Blog/Layout/Subs/Manage.css
@@ -1,5 +1,6 @@
 .ban-btn { color: red; }
 .subs-type { margin: 1em; }
+.subs-addr { color: grey; }
 
 .subs-item {
 	position: relative;
diff --git a/botanjs/src/Dandelion/StarticRes.js b/botanjs/src/Dandelion/StarticRes.js
new file mode 100644
index 0000000..8f3581e
--- /dev/null
+++ b/botanjs/src/Dandelion/StarticRes.js
@@ -0,0 +1,5 @@
+(function(){
+	var ns = __namespace( "Dandelion.StaticRes" );
+
+	ns[ NS_EXPORT ]( EX_READONLY_GETTER , "BLANK_IMG", function() { return "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="; } );
+})();
diff --git a/k8s/deployments.yaml b/k8s/deployments.yaml
index 0009d15..5b7506d 100644
--- a/k8s/deployments.yaml
+++ b/k8s/deployments.yaml
@@ -26,18 +26,22 @@ spec:
             mountPath: "/app/cache"
       containers:
         - name: web
-          image: registry.k8s.astropenguin.net/astrojs:2022.04.05.06
+          image: registry.k8s.astropenguin.net/astrojs:2022.04.09.03
           securityContext:
             runAsGroup: 1001
             runAsNonRoot: true
             runAsUser: 1001
           env:
+            - name: DEBUG
+              value: "0"
             - name: FLASK_DEBUG
               value: "0"
             - name: FLASK_ENV
               value: "production"
             - name: RUN_MODE
               value: "web"
+            - name: REDIS_CONN
+              value: "redis://:@localhost:6379/9"
           volumeMounts:
           - name: cache
             mountPath: "/app/cache"
@@ -50,7 +54,7 @@ spec:
         - name: redis
           image: redis:6.0.8-alpine
         - name: compiler
-          image: registry.k8s.astropenguin.net/astrojs:2022.04.05.06
+          image: registry.k8s.astropenguin.net/astrojs:2022.04.09.03
           securityContext:
             runAsGroup: 1001
             runAsNonRoot: true
@@ -58,6 +62,10 @@ spec:
           env:
             - name: RUN_MODE
               value: "tasks"
+            - name: DEBUG
+              value: "0"
+            - name: REDIS_CONN
+              value: "redis://:@localhost:6379/9"
           volumeMounts:
           - name: cache
             mountPath: "/app/cache"