Compare commits
	
		
			2 Commits
		
	
	
		
			0b31e97492
			...
			4a2ea1bce9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4a2ea1bce9 | |||
| fe82b19c91 | 
| @@ -144,6 +144,12 @@ Running this command should do: | ||||
| uwsgi --http :9090 --plugin python --wsgi-file main.py | ||||
| ``` | ||||
|  | ||||
| #### Using Gunicorn | ||||
|  | ||||
| ```shell | ||||
| gunicorn morss:cgi_standalone_app | ||||
| ``` | ||||
|  | ||||
| #### Using morss' internal HTTP server | ||||
|  | ||||
| Morss can run its own HTTP server. The later should start when you run morss | ||||
|   | ||||
| @@ -94,7 +94,7 @@ path = | ||||
|   http://localhost/ | ||||
|  | ||||
| title = //div[@id='header']/h1 | ||||
| desc = //div[@id='header']/h2 | ||||
| desc = //div[@id='header']/p | ||||
| items = //div[@id='content']/div | ||||
|  | ||||
| item_title = ./a | ||||
| @@ -102,7 +102,7 @@ item_link = ./a/@href | ||||
| item_desc = ./div[class=desc] | ||||
| item_content = ./div[class=content] | ||||
|  | ||||
| base = file:reader.html.template | ||||
| base = file:www/sheet.xsl | ||||
|  | ||||
| [twitter] | ||||
| mode = html | ||||
|   | ||||
| @@ -46,10 +46,23 @@ def parse_rules(filename=None): | ||||
|     rules = dict([(x, dict(config.items(x))) for x in config.sections()]) | ||||
|  | ||||
|     for section in rules.keys(): | ||||
|         # for each ruleset | ||||
|  | ||||
|         for arg in rules[section].keys(): | ||||
|             # for each rule | ||||
|  | ||||
|             if rules[section][arg].startswith('file:'): | ||||
|                 import_file = os.path.join(os.path.dirname(__file__), rules[section][arg][5:]) | ||||
|                 rules[section][arg] = open(import_file).read() | ||||
|                 paths = [os.path.join(sys.prefix, 'share/morss', rules[section][arg][5:]), | ||||
|                     os.path.join(os.path.dirname(__file__), '..', rules[section][arg][5:])] | ||||
|  | ||||
|                 for path in paths: | ||||
|                     try: | ||||
|                         file_raw = open(path).read() | ||||
|                         file_clean = re.sub('<[/?]?(xsl|xml)[^>]+?>', '', file_raw) | ||||
|                         rules[section][arg] = file_clean | ||||
|  | ||||
|                     except IOError: | ||||
|                         pass | ||||
|  | ||||
|             elif '\n' in rules[section][arg]: | ||||
|                 rules[section][arg] = rules[section][arg].split('\n')[1:] | ||||
| @@ -293,10 +306,7 @@ class ParserXML(ParserBase): | ||||
|  | ||||
|     NSMAP = {'atom': 'http://www.w3.org/2005/Atom', | ||||
|         'atom03': 'http://purl.org/atom/ns#', | ||||
|         'media': 'http://search.yahoo.com/mrss/', | ||||
|         'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', | ||||
|         'slash': 'http://purl.org/rss/1.0/modules/slash/', | ||||
|         'dc': 'http://purl.org/dc/elements/1.1/', | ||||
|         'content': 'http://purl.org/rss/1.0/modules/content/', | ||||
|         'rssfake': 'http://purl.org/rss/1.0/'} | ||||
|  | ||||
|   | ||||
| @@ -1,196 +0,0 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| 	<head> | ||||
| 		<title>Feed reader by morss</title> | ||||
| 		<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" /> | ||||
| 		<meta name="robots" content="noindex" /> | ||||
|  | ||||
| 		<style type="text/css"> | ||||
| 			/* columns - from https://thisisdallas.github.io/Simple-Grid/simpleGrid.css */ | ||||
|  | ||||
| 			* { | ||||
| 				box-sizing: border-box; | ||||
| 			} | ||||
|  | ||||
| 			#content { | ||||
| 				width: 100%; | ||||
| 				max-width: 1140px; | ||||
| 				min-width: 755px; | ||||
| 				margin: 0 auto; | ||||
| 				overflow: hidden; | ||||
|  | ||||
| 				padding-top: 20px; | ||||
| 				padding-left: 20px; /* grid-space to left */ | ||||
| 				padding-right: 0px; /* grid-space to right: (grid-space-left - column-space) e.g. 20px-20px=0 */ | ||||
| 			} | ||||
|  | ||||
| 			.item { | ||||
| 				width: 33.33%; | ||||
| 				float: left; | ||||
| 				padding-right: 20px; /* column-space */ | ||||
| 			} | ||||
|  | ||||
| 			@media handheld, only screen and (max-width: 767px) { | ||||
| 				#content { | ||||
| 					width: 100%; | ||||
| 					min-width: 0; | ||||
| 					margin-left: 0px; | ||||
| 					margin-right: 0px; | ||||
| 					padding-left: 20px; /* grid-space to left */ | ||||
| 					padding-right: 10px; /* grid-space to right: (grid-space-left - column-space) e.g. 20px-10px=10px */ | ||||
| 				} | ||||
|  | ||||
| 				.item { | ||||
| 					width: auto; | ||||
| 					float: none; | ||||
| 					margin-left: 0px; | ||||
| 					margin-right: 0px; | ||||
| 					margin-top: 10px; | ||||
| 					margin-bottom: 10px; | ||||
| 					padding-left: 0px; | ||||
| 					padding-right: 10px; /* column-space */ | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			/* design */ | ||||
|  | ||||
| 			#header h1, #header h2, #header p { | ||||
| 				font-family: sans; | ||||
| 				text-align: center; | ||||
| 				margin: 0; | ||||
| 				padding: 0; | ||||
| 			} | ||||
|  | ||||
| 			#header h1 { | ||||
| 				font-size: 2.5em; | ||||
| 				font-weight: bold; | ||||
| 				padding: 1em 0 0.25em; | ||||
| 			} | ||||
|  | ||||
| 			#header h2 { | ||||
| 				font-size: 1em; | ||||
| 				font-weight: normal; | ||||
| 			} | ||||
|  | ||||
| 			#header p { | ||||
| 				color: gray; | ||||
| 				font-style: italic; | ||||
| 				font-size: 0.75em; | ||||
| 			} | ||||
|  | ||||
| 			#content { | ||||
| 				text-align: justify; | ||||
| 				line-height: 1.5em; | ||||
| 			} | ||||
|  | ||||
| 				.item .title { | ||||
| 					font-weight: bold; | ||||
| 					display: block; | ||||
| 					text-align: center; | ||||
| 				} | ||||
|  | ||||
| 				.item .link { | ||||
| 					color: inherit; | ||||
| 					text-decoration: none; | ||||
| 				} | ||||
|  | ||||
| 				.item:not(.active) { | ||||
| 					cursor: pointer; | ||||
|  | ||||
| 					height: 20em; | ||||
| 					margin-bottom: 20px; | ||||
| 					overflow: hidden; | ||||
| 					text-overflow: ellpisps; | ||||
|  | ||||
| 					padding: 0.25em; | ||||
| 					position: relative; | ||||
| 				} | ||||
|  | ||||
| 					.item:not(.active) .title { | ||||
| 						padding-bottom: 0.1em; | ||||
| 						margin-bottom: 0.1em; | ||||
| 						border-bottom: 1px solid silver; | ||||
| 					} | ||||
|  | ||||
| 					.item:not(.active):before { | ||||
| 						content: " "; | ||||
| 						display: block; | ||||
| 						width: 100%; | ||||
| 						position: absolute; | ||||
| 						top: 18.5em; | ||||
| 						height: 1.5em; | ||||
| 						background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%); | ||||
| 					} | ||||
|  | ||||
| 					.item:not(.active) .article * { | ||||
| 						max-width: 100%; | ||||
| 						font-size: 1em !important; | ||||
| 						font-weight: normal; | ||||
| 						display: inline; | ||||
| 						margin: 0; | ||||
| 					} | ||||
|  | ||||
| 				.item.active { | ||||
| 					background: white; | ||||
| 					position: fixed; | ||||
| 					overflow: auto; | ||||
| 					top: 0; | ||||
| 					left: 0; | ||||
| 					height: 100%; | ||||
| 					width: 100%; | ||||
| 					z-index: 1; | ||||
| 				} | ||||
|  | ||||
| 					body.noscroll { | ||||
| 						overflow: hidden; | ||||
| 					} | ||||
|  | ||||
| 					.item.active > * { | ||||
| 						max-width: 700px; | ||||
| 						margin: auto; | ||||
| 					} | ||||
|  | ||||
| 					.item.active .title { | ||||
| 						font-size: 2em; | ||||
| 						padding: 0.5em 0; | ||||
| 					} | ||||
|  | ||||
| 					.item.active .article object, | ||||
| 					.item.active .article video, | ||||
| 					.item.active .article audio { | ||||
| 						display: none; | ||||
| 					} | ||||
|  | ||||
| 					.item.active .article img { | ||||
| 						max-height: 20em; | ||||
| 						max-width: 100%; | ||||
| 					} | ||||
| 		</style> | ||||
| 	</head> | ||||
|  | ||||
| 	<body> | ||||
| 		<div id="header"> | ||||
| 			<h1>RSS feed</h1> | ||||
| 			<h2>with full text articles</h2> | ||||
| 			<p>- via morss</p> | ||||
| 		</div> | ||||
|  | ||||
| 		<div id="content"> | ||||
| 				<div class="item"> | ||||
| 					<a class="title link" href="@item.link" target="_blank"></a> | ||||
| 					<div class="desc"></div> | ||||
| 					<div class="content"></div> | ||||
| 				</div> | ||||
| 		</div> | ||||
|  | ||||
| 	<script> | ||||
| 		var items = document.getElementsByClassName('item') | ||||
| 		for (var i in items) | ||||
| 			items[i].onclick = function() | ||||
| 			{ | ||||
| 				this.classList.toggle('active') | ||||
| 				document.body.classList.toggle('noscroll') | ||||
| 			} | ||||
| 	</script> | ||||
| 	</body> | ||||
| </html> | ||||
							
								
								
									
										2
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.py
									
									
									
									
									
								
							| @@ -13,7 +13,7 @@ setup( | ||||
|     license = 'AGPL v3', | ||||
|     packages = [package_name], | ||||
|     install_requires = ['lxml', 'bs4', 'python-dateutil', 'chardet', 'pymysql'], | ||||
|     package_data = {package_name: ['feedify.ini', 'reader.html.template']}, | ||||
|     package_data = {package_name: ['feedify.ini']}, | ||||
|     data_files = [ | ||||
|         ('share/' + package_name, ['README.md', 'LICENSE']), | ||||
|         ('share/' + package_name + '/www', glob('www/*.*')), | ||||
|   | ||||
							
								
								
									
										124
									
								
								www/sheet.xsl
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								www/sheet.xsl
									
									
									
									
									
								
							| @@ -1,13 +1,22 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | ||||
| <xsl:stylesheet version="1.1" | ||||
| 	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | ||||
| 	xmlns:atom="http://www.w3.org/2005/Atom" | ||||
| 	xmlns:atom03="http://purl.org/atom/ns#" | ||||
| 	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
| 	xmlns:content="http://purl.org/rss/1.0/modules/content/" | ||||
| 	xmlns:rssfake="http://purl.org/rss/1.0/" | ||||
| 	> | ||||
|  | ||||
| 	<xsl:output method="html"/> | ||||
|  | ||||
| 	<xsl:template match="/"> | ||||
| 		<!DOCTYPE html> | ||||
| 		<html> | ||||
| 		<head> | ||||
| 			<title>RSS feed by morss</title> | ||||
| 			<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" /> | ||||
| 			<meta name="robots" content="noindex" /> | ||||
|  | ||||
| 			<style type="text/css"> | ||||
| 				body { | ||||
| @@ -23,36 +32,16 @@ | ||||
| 					max-width: 100%; | ||||
| 				} | ||||
|  | ||||
| 				body > ul { | ||||
| 				.item { | ||||
| 					background-color: #FFFAF4; | ||||
| 					border: 1px solid silver; | ||||
| 					padding: 1%; | ||||
| 					margin: 1%; | ||||
| 					max-width: 100%; | ||||
| 				} | ||||
|  | ||||
| 				ul { | ||||
| 					list-style-type: none; | ||||
| 				} | ||||
|  | ||||
| 				.tag { | ||||
| 					color: darkred; | ||||
| 				} | ||||
|  | ||||
| 				.attr { | ||||
| 					color: darksalmon; | ||||
| 				} | ||||
|  | ||||
| 				.value { | ||||
| 					color: darkblue; | ||||
| 				} | ||||
|  | ||||
| 				.comment { | ||||
| 					color: lightgrey; | ||||
| 				} | ||||
|  | ||||
| 				pre { | ||||
| 					margin: 0; | ||||
| 					max-width: 100%; | ||||
| 					white-space: normal; | ||||
| 				.item > a { | ||||
| 					border-bottom: 1px solid silver; | ||||
| 				} | ||||
| 			</style> | ||||
| 		</head> | ||||
| @@ -65,59 +54,44 @@ | ||||
|  | ||||
| 			<div id="url"></div> | ||||
|  | ||||
| 			<ul> | ||||
| 				<xsl:apply-templates/> | ||||
| 			</ul> | ||||
| 			<hr/> | ||||
|  | ||||
| 			<div id="header"> | ||||
| 				<h1> | ||||
| 					<xsl:value-of select="rdf:RDF/rssfake:channel/rssfake:title|rss/channel/title|atom:feed/atom:title|atom03:feed/atom03:title"/> | ||||
| 				</h1> | ||||
|  | ||||
| 				<p> | ||||
| 					<xsl:value-of select="rdf:RDF/rssfake:channel/rssfake:description|rss/channel/description|atom:feed/atom:subtitle|atom03:feed/atom03:subtitle"/> | ||||
| 				</p> | ||||
| 			</div> | ||||
|  | ||||
| 			<div id="content"> | ||||
| 				<xsl:for-each select="rdf:RDF/rssfake:channel/rssfake:item|rss/channel/item|atom:feed/atom:entry|atom03:feed/atom03:entry"> | ||||
| 					<div class="item"> | ||||
| 						<a href="/" target="_blank"><xsl:attribute name="href"><xsl:value-of select="rssfake:link|link|atom:link/@href|atom03:link/@href"/></xsl:attribute> | ||||
| 								<xsl:value-of select="rssfake:title|title|atom:title|atom03:title"/> | ||||
| 						</a> | ||||
|  | ||||
| 						<div class="desc"> | ||||
| 							<xsl:value-of select="rssfake:description|description|atom:summary|atom03:summary"/> | ||||
| 						</div> | ||||
|  | ||||
| 						<div class="content"> | ||||
| 							<xsl:value-of select="content:encoded|atom:content|atom03:content"/> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</xsl:for-each> | ||||
| 			</div> | ||||
|  | ||||
| 			<script> | ||||
| 				document.getElementById("url").innerHTML = window.location.href; | ||||
| 				document.getElementById("url").innerHTML = window.location.href.replace(':html/', '') | ||||
|  | ||||
| 				if (!/:html/.test(window.location.href)) | ||||
| 					for (var content of document.getElementsByClassName("content")) | ||||
| 						content.innerHTML = content.innerText | ||||
| 			</script> | ||||
| 		</body> | ||||
| 		</html> | ||||
| 	</xsl:template> | ||||
|  | ||||
| 	<xsl:template match="*"> | ||||
| 		<li> | ||||
| 			<span class="element"> | ||||
| 				< | ||||
| 					<span class="tag"><xsl:value-of select="name()"/></span> | ||||
|  | ||||
| 					<xsl:for-each select="@*"> | ||||
| 						<span class="attr"> <xsl:value-of select="name()"/></span> | ||||
| 						= | ||||
| 						"<span class="value"><xsl:value-of select="."/></span>" | ||||
| 					</xsl:for-each> | ||||
| 				> | ||||
| 			</span> | ||||
|  | ||||
| 			<xsl:if test="node()"> | ||||
| 				<ul> | ||||
| 					<xsl:apply-templates/> | ||||
| 				</ul> | ||||
| 			</xsl:if> | ||||
|  | ||||
| 			<span class="element"> | ||||
| 				</ | ||||
| 					<span class="tag"><xsl:value-of select="name()"/></span> | ||||
| 				> | ||||
| 			</span> | ||||
| 		</li> | ||||
| 	</xsl:template> | ||||
|  | ||||
| 	<xsl:template match="comment()"> | ||||
| 		<li> | ||||
| 			<pre class="comment"><![CDATA[<!--]]><xsl:value-of select="."/><![CDATA[-->]]></pre> | ||||
| 		</li> | ||||
| 	</xsl:template> | ||||
|  | ||||
| 	<xsl:template match="text()"> | ||||
| 		<li> | ||||
| 			<pre> | ||||
| 				<xsl:value-of select="normalize-space(.)"/> | ||||
| 			</pre> | ||||
| 		</li> | ||||
| 	</xsl:template> | ||||
|  | ||||
| 	<xsl:template match="text()[not(normalize-space())]"/> | ||||
|  | ||||
| </xsl:stylesheet> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user