def install_theme(argv): if len(argv) < 1: print_themes() return blog_configuration = get_blog_configuration() if blog_configuration == None: notify(messages.no_blog_configuration) return new_folder_name = "theme "+str(datetime.datetime.now()).replace(':','-') try: shutil.move("theme", new_folder_name) except: pass try: shutil.copytree(os.path.expanduser("~")+"/.local/share/VenC/themes/"+argv[0], "theme") notify(messages.theme_installed) except FileNotFoundError as e: notify(messages.theme_doesnt_exists.format("'"+argv[0]+"'"),color='RED') ''' Restore previous states ''' try: shutil.move(new_folder_name, "theme") except Exception as e: die(str(e))
def highlight(self, cpu_thread_id, argv, included_file=False): try: name = "venc_source_"+argv[0].replace('+','Plus') lexer = pygments.lexers.get_lexer_by_name(argv[0], stripall=False) formatter = pygments.formatters.HtmlFormatter(linenos=(True if argv[1]=="True" else False), cssclass=name) if not included_file: code = "::".join(argv[2:]) else: code = argv[2] result = "<div class=\"__VENC_PYGMENTIZE_WRAPPER__\">"+pygments.highlight(code.replace("\:",":"), lexer, formatter).replace(".:",".:").replace(":.",":.")+"</div>" css = formatter.get_style_defs() if not name+".css" in self._includes.keys(): self._includes[name+".css"] = css return result except pygments.util.ClassNotFound: die(messages.unknown_language.format(argv[0])) except Exception as e: print(e)
def yield_entries_content(): try: for filename in os.listdir(os.getcwd()+"/entries"): exploded_filename = filename.split("__") try: date = exploded_filename[1].split('-') entry_id = int(exploded_filename[0]) datetime.datetime( year=int(date[2]), month=int(date[0]), day=int(date[1]), hour=int(date[3]), minute=int(date[4]) ) if entry_id >= 0: yield filename else: raise ValueError except ValueError: notify(messages.invalid_entry_filename.format(filename), "YELLOW") except IndexError: notify(messages.invalid_entry_filename.format(filename), "YELLOW") except FileNotFoundError: die(messages.file_not_found.format(os.getcwd()+"/entries"))
def highlight(self, argv): try: name = "venc_source_"+argv[0].replace('+','Plus') lexer = pygments.lexers.get_lexer_by_name(argv[0], stripall=True) formatter = pygments.formatters.HtmlFormatter(linenos=("table" if argv[1]=="True" else False), cssclass=name) code = argv[2] result = pygments.highlight(code.replace("\:",":"), lexer, formatter).replace(".:",".:") css = formatter.get_style_defs() css += "\n."+name+"table {width: 100%; display: block;}" css += "\n."+name+"table tr {width: 100%; display: block;}" css += "\n."+name+"table tbody {width: 100%; display: block;}" css += "\n."+name+"table .linenos {width: 4%; display: inline-block;vertical-align: top;}" css += "\n."+name+"table .code {width: 95%; display: inline-block;vertical-align: top;}" css += "\n."+name+"table td pre {vertical-align: top; overflow: hidden; overflow-x: scroll;}" css += "\n."+name+" pre {overflow: hidden; overflow-x: scroll;}" if not name+".css" in self._includes.keys(): self._includes[name+".css"] = css return result except pygments.util.ClassNotFound: die(messages.unknown_language.format(argv[0])) except Exception as e: print(e)
def format_filename(self, value): try: if value == 0: return self.filename.format(**{'page_number': ''}) else: return self.filename.format(**{'page_number': value}) except KeyError as e: die(messages.variable_error_in_filename.format(str(e)))
def handle_error(self, exception, error, default_output, error_origin = list()): if self.debug: raise exception err = get_formatted_message(error, "RED")+"\n" if self.ressource != str(): err = messages.in_ressource.format(self.ressource)+'\n'+err if error_origin != list(): err+=(''.join(self.current_input_string).strip()) for origin in error_origin: err = highlight_value(err, origin) die(err, "RED")
def format_filename(self, value): try: if value == 0: return self.path_encode( self.filename.format(**{'page_number': ''})) else: return self.path_encode( self.filename.format(**{'page_number': value})) except KeyError as e: from venc2.prompt import die die(messages.variable_error_in_filename.format(str(e)))
def handle_error(self, error): extra = "" err = get_formatted_message(error, "RED") + "\n" if self.ressource[cpu_thread_id] != str(): err = messages.in_ressource.format( self.ressource[cpu_thread_id]) + '\n' + err extra += (''.join(self.current_input_string[cpu_thread_id])) extra = highlight_value( extra, self.current_input_string[cpu_thread_id][self.vop:self.vcp + 2]) die(err, "RED", extra)
def new_entry(argv): blog_configuration = get_blog_configuration() if len(argv) < 1: die(messages.missing_params.format("--new-entry")) content = {"authors": "", "tags": "", "categories": "", "title":argv[0]} try: wd = os.listdir(os.getcwd()) except OSError: die(messages.cannot_read_in.format(os.getcwd())) date = datetime.datetime.now() entry = dict() raw_entry_date = datetime.datetime.now() try: entry["ID"] = max([ int(filename.split("__")[0]) for filename in yield_entries_content()]) + 1 except ValueError: entry["ID"] = 1 entry["title"] = argv[0] entry["month"] = raw_entry_date.month entry["year"] = raw_entry_date.year entry["day"] = raw_entry_date.day entry["hour"] = raw_entry_date.hour entry["minute"] = raw_entry_date.minute entry["date"] = raw_entry_date entry_date = str(date.month)+'-'+str(date.day)+'-'+str(date.year)+'-'+str(date.hour)+'-'+str(date.minute) output_filename = os.getcwd()+'/entries/'+str(entry["ID"])+"__"+entry_date+"__"+entry["title"].replace(' ','_') stream = codecs.open(output_filename, 'w', encoding="utf-8") if len(argv) == 1: output = yaml.dump(content, default_flow_style=False, allow_unicode=True) + "---VENC-BEGIN-PREVIEW---\n---VENC-END-PREVIEW---\n" else: try: output = open(os.getcwd()+'/templates/'+argv[1], 'r').read().replace(".:GetEntryTitle:.", argv[0]) except FileNotFoundError as e: die(messages.file_not_found.format(os.getcwd()+"/templates/"+argv[1])) stream.write(output) stream.close() try: command = [arg for arg in blog_configuration["text_editor"].split(' ') if arg != ''] command.append(output_filename) subprocess.call(command) except FileNotFoundError: die(messages.unknown_command.format(blog_configuration["text_editor"])) notify(messages.entry_written)
def new_entry(argv): if len(argv) < 1: die(messages.missing_params.format("--new-entry")) blog_configuration = get_blog_configuration() content = {"authors": "", "tags": "", "categories": "", "title":argv[0]} try: wd = os.listdir(os.getcwd()) except OSError: die(messages.cannot_read_in.format(os.getcwd())) date = datetime.datetime.now() entry = dict() raw_entry_date = datetime.datetime.now() try: entry["ID"] = max([ int(filename.split("__")[0]) for filename in yield_entries_content()]) + 1 except ValueError: entry["ID"] = 1 entry["title"] = argv[0] entry["month"] = raw_entry_date.month entry["year"] = raw_entry_date.year entry["day"] = raw_entry_date.day entry["hour"] = raw_entry_date.hour entry["minute"] = raw_entry_date.minute entry["date"] = raw_entry_date entry_date = str(date.month)+'-'+str(date.day)+'-'+str(date.year)+'-'+str(date.hour)+'-'+str(date.minute) output_filename = os.getcwd()+'/entries/'+str(entry["ID"])+"__"+entry_date+"__"+entry["title"].replace(' ','_') stream = codecs.open(output_filename, 'w', encoding="utf-8") if len(argv) == 1: output = yaml.dump(content, default_flow_style=False, allow_unicode=True) + "---VENC-BEGIN-PREVIEW---\n---VENC-END-PREVIEW---\n" else: try: output = open(os.getcwd()+'/templates/'+argv[1], 'r').read().replace(".:GetEntryTitle:.", argv[0]) except FileNotFoundError as e: die(messages.file_not_found.format(os.getcwd()+"/templates/"+argv[1])) stream.write(output) stream.close() try: command = [arg for arg in blog_configuration["text_editor"].split(' ') if arg != ''] command.append(output_filename) subprocess.call(command) except FileNotFoundError: die(messages.unknown_command.format(blog_configuration["text_editor"])) notify(messages.entry_written)
def format_filename(self, value): try: if value == 0: return self.filename.format(**{ 'page_number':'' }) else: return self.filename.format(**{ 'page_number':value }) except KeyError as e: die(messages.variable_error_in_filename.format(str(e)))
def handle_malformed_patterns(e): if e.escape: if e.too_many_openings_symbols: die(messages.malformed_escape_patterns_missing_closing_symbols.format(e.ressource)) die(messages.malformed_escape_patterns_missing_opening_symbols.format(e.ressource)) if e.too_many_opening_symbols: die(messages.malformed_patterns_missing_closing_symbols.format(e.ressource)) die(messages.malformed_patterns_missing_opening_symbols.format(e.ressource))
def serv_blog(argv=list()): try: os.chdir("blog/") PORT = int(blog_configuration["server_port"]) server_address = ("", PORT) notify(messages.serving_blog.format(PORT)) httpd = http.server.HTTPServer(server_address, VenCServer) httpd.serve_forever() except ValueError: die(messages.server_port_is_invalid.format(blog_configuration["server_port"])) except KeyboardInterrupt: httpd.server_close() except FileNotFoundError: httpd.server_close()
def __init__(self, theme_folder): try: self.header = ProcessedString(open(theme_folder+"chunks/header.html",'r').read(), "header.html") self.footer = ProcessedString(open(theme_folder+"chunks/footer.html",'r').read(), "footer.html") self.rss_header = ProcessedString(open(theme_folder+"chunks/rssHeader.xml",'r').read(), "rssHeader.html") self.rss_footer = ProcessedString(open(theme_folder+"chunks/rssFooter.xml",'r').read(), "rssFooter.html") self.atom_header = ProcessedString(open(theme_folder+"chunks/atomHeader.xml",'r').read(), "atomHeader.html") self.atom_footer = ProcessedString(open(theme_folder+"chunks/atomFooter.xml",'r').read(), "atomFooter.html") self.entry = EntryWrapper(open(theme_folder+"chunks/entry.html",'r').read(), "entry.html") self.rss_entry = EntryWrapper(open(theme_folder+"chunks/rssEntry.xml",'r').read(),"rssEntry.xxml") self.atom_entry = EntryWrapper(open(theme_folder+"chunks/atomEntry.xml",'r').read(),"atomEntry.xml") self.audio = open(theme_folder+"chunks/audio.html",'r').read() self.video = open(theme_folder+"chunks/video.html",'r').read() except FileNotFoundError as e: die(messages.file_not_found.format(str(e.filename)))
def serv_blog(argv=list()): try: os.chdir("blog/") PORT = int(blog_configuration["server_port"]) server_address = ("", PORT) notify(messages.serving_blog.format(PORT)) httpd = http.server.HTTPServer(server_address, VenCServer) httpd.serve_forever() except ValueError: die( messages.server_port_is_invalid.format( blog_configuration["server_port"])) except KeyboardInterrupt: httpd.server_close() except FileNotFoundError: httpd.server_close()
def remote_copy(argv=list()): blog_configuration = get_blog_configuration() try: ftp = ftplib.FTP(blog_configuration["ftp_host"]) ftp.encoding='latin-1' except socket.gaierror as e: die(str(e)) username = input("VenC: "+messages.username) user_passwd = getpass.getpass(prompt="VenC: "+messages.user_passwd) try: ftp.login(user=username,passwd=user_passwd) ftp.cwd(blog_configuration["path"]["ftp"]) notify(messages.clean_ftp_directory) ftp_clean_destination(ftp) notify(messages.copy_to_ftp_directory) ftp_export_recursively(os.getcwd()+"/blog", ftp) except TimeoutError as e: die(str(e)) except ftplib.error_perm as e: die(str(e), color="YELLOW")
def remote_copy(argv=list()): blog_configuration = get_blog_configuration() try: ftp = ftplib.FTP(blog_configuration["ftp_host"]) ftp.encoding = 'latin-1' except socket.gaierror as e: die(str(e)) username = input("VenC: " + messages.username) user_passwd = getpass.getpass(prompt="VenC: " + messages.user_passwd) try: ftp.login(user=username, passwd=user_passwd) ftp.cwd(blog_configuration["path"]["ftp"]) notify(messages.clean_ftp_directory) ftp_clean_destination(ftp) notify(messages.copy_to_ftp_directory) ftp_export_recursively(os.getcwd() + "/blog", ftp) except TimeoutError as e: die(str(e)) except ftplib.error_perm as e: die(str(e), color="YELLOW")
def __init__(self, wrapper, filename): pattern_replacement = { ".:GetEntryContent:." : "---VENC-GET-ENTRY-CONTENT---", ".:GetEntryPreview:." : "---VENC-GET-ENTRY-PREVIEW---", ".:PreviewIfInThreadElseContent:." : "---VENC-PREVIEW-IF-IN-THREAD-ELSE-CONTENT---" } self.content_type_flag = 0 wrapper_len = len(wrapper) self.process_get_entry_content = 1 if ".:GetEntryContent:." in wrapper else 0 self.process_get_entry_preview = 1 if ".:GetEntryPreview:." in wrapper else 0 if ".:PreviewIfInThreadElseContent:." in wrapper: self.process_get_entry_content = 1 self.process_get_entry_preview = 1 for content_pattern in pattern_replacement.keys(): wrapper = wrapper.replace(content_pattern, pattern_replacement[content_pattern]) if len(wrapper) == wrapper_len: die(messages.missing_entry_content_inclusion.format(filename)) self.processed_string = ProcessedString(wrapper, filename, True)
def highlight(self, argv): try: name = "venc_source_" + argv[0].replace('+', 'Plus') lexer = pygments.lexers.get_lexer_by_name(argv[0], stripall=True) formatter = pygments.formatters.HtmlFormatter( linenos=("table" if argv[1] == "True" else False), cssclass=name) code = argv[2] result = pygments.highlight(code.replace("\:", ":"), lexer, formatter).replace(".:", ".:") css = formatter.get_style_defs() if not name + ".css" in self._includes.keys(): self._includes[name + ".css"] = css return result except pygments.util.ClassNotFound: die(messages.unknown_language.format(argv[0])) except Exception as e: print(e)
def __init__(self, wrapper, filename): self.patterns = [".:GetEntryContent:.", ".:GetEntryPreview:.", ".:PreviewIfInThreadElseContent:."] for pattern in self.patterns: try: w = wrapper.split(pattern) if len(w) > 2: die(messages.too_much_call_of_content.format(filename)) for p in self.patterns: if p in w[0] or p in w[1]: die(messages.too_much_call_of_content.format(filename)) self.above = ProcessedString(w[0], filename) self.below = ProcessedString(w[1], filename) self.required_content_pattern = pattern return except IndexError: pass die(messages.missing_entry_content_inclusion)
def __init__(self, wrapper, filename): self.patterns = [ ".:GetEntryContent:.", ".:GetEntryPreview:.", ".:PreviewIfInThreadElseContent:." ] for pattern in self.patterns: try: w = wrapper.split(pattern) if len(w) > 2: die(messages.too_much_call_of_content.format(filename)) for p in self.patterns: if p in w[0] or p in w[1]: die(messages.too_much_call_of_content.format(filename)) self.above = ProcessedString(w[0], filename) self.below = ProcessedString(w[1], filename) self.required_content_pattern = pattern return except IndexError: pass die(messages.missing_entry_content_inclusion)
def __init__(self, filename, paths, jsonld_callback, date_format, encoding="utf-8", ): self.previous_entry = None self.next_entry = None self.schemadotorg = {} # Loading raw_data = open(os.getcwd()+"/entries/"+filename,'r').read() entry_parted = raw_data.split("---VENC-BEGIN-PREVIEW---\n") if len(entry_parted) == 2: entry_parted = [entry_parted[0]] + entry_parted[1].split("---VENC-END-PREVIEW---\n") if len(entry_parted) == 3: self.preview = ProcessedString(entry_parted[1], filename) self.content = ProcessedString(entry_parted[2], filename) try: metadata = yaml.load(entry_parted[0]) except yaml.scanner.ScannerError as e: die(messages.possible_malformed_entry.format(filename, ''), extra=str(e)) else: cause = messages.missing_separator_in_entry.format("---VENC-END-PREVIEW---") die(messages.possible_malformed_entry.format(filename, cause)) else: cause = messages.missing_separator_in_entry.format("---VENC-BEGIN-PREVIEW---") die(messages.possible_malformed_entry.format(filename, cause)) # Setting up optional metadata for key in metadata.keys(): if not key in ["authors", "tags", "categories", "title"]: if metadata[key] != None: setattr(self, key, metadata[key]) elif key == "https://schema.org" and metadata[key] != None: self.schemadotorg = metadata[key] else: notify(messages.invalid_or_missing_metadata.format(key, filename), color="YELLOW") setattr(self, key, '') # Fix missing or incorrect metadata for key in ["authors", "tags", "categories", "title"]: if key not in metadata.keys() or metadata[key] == None: notify(messages.invalid_or_missing_metadata.format(key, filename), color="YELLOW") metadata[key] = '' self.raw_metadata = metadata self.filename = filename self.id = int(filename.split('__')[0]) raw_date = filename.split('__')[1].split('-') self.date = datetime.datetime( year=int(raw_date[2]), month=int(raw_date[0]), day=int(raw_date[1]), hour=int(raw_date[3]), minute=int(raw_date[4]) ) self.formatted_date = self.date.strftime(date_format) try: self.title = metadata["title"].replace(".:GetEntryTitle:.",'') except KeyError: die(messages.missing_mandatory_field_in_entry.format("title", self.id)) try: self.authors = [ {"value":e} for e in list(metadata["authors"].split(",") if metadata["authors"] != str() else list()) ] except KeyError: die(messages.missing_mandatory_field_in_entry.format("authors", self.id)) try: self.tags = [ {"value":e} for e in list(metadata["tags"].split(",") if metadata["tags"] != str() else list())] except KeyError: die(messages.missing_mandatory_field_in_entry.format("tags", self.id)) params = { "entry_id": self.id, "entry_title": self.title } sf = paths["entries_sub_folders"].format(**params).replace(' ','-') self.sub_folder = urllib.parse.quote(sf, encoding=encoding)+'/' if sf != '' else '' try: self.url = ".:GetRelativeOrigin:."+self.sub_folder+urllib.parse.quote(paths["entry_file_name"].format(**params), encoding=encoding) except UnicodeEncodeError as e: self.url = ".:GetRelativeOrigin:."+self.sub_folder+paths["entry_file_name"].format(**params) notify("\"{0}\": ".format(sf+paths["entry_file_name"].format(**params))+str(e), color="YELLOW") self.categories_leaves = list() self.raw_categories = [ c.strip() for c in metadata["categories"].split(',')] try: for category in self.raw_categories: category_leaf = category.split(' > ')[-1].strip() if len(category_leaf) != 0: category_leaf_path = ".:GetRelativeOrigin:." for sub_category in category.split(' > '): category_leaf_path +=sub_category.strip()+'/' self.categories_leaves.append({ "value": category_leaf, "path": category_leaf_path, "raw" : category }) except IndexError : # when list is empty pass self.categories_tree = [] build_categories_tree(-1, self.raw_categories, self.categories_tree, None, -1, encoding=encoding, sub_folders=paths["categories_sub_folders"]) self.html_categories_tree = {} self.html_tags = {} self.html_authors = {} self.html_categories_leaves = {} if jsonld_callback != None: jsonld_callback(self)
def new_blog(argv): if len(argv) < 1: die(Messages.missingParams.format("--new-blog")) default_configuration = { "blog_name": messages.blog_name, "disable_threads": "", "disable_archives": False, "disable_categories": False, "disable_single_entries": False, "disable_main_thread": False, "disable_rss_feed": False, "disable_atom_feed": False, "text_editor": "nano", "date_format": "%A %d. %B %Y", "author_name": messages.your_name, "blog_description": messages.blog_description, "blog_keywords": messages.blog_keywords, "author_description": messages.about_you, "license": messages.license, "blog_url": messages.blog_url, "ftp_host": messages.ftp_host, "blog_language": messages.blog_language, "author_email": messages.your_email, "code_highlight_css_override": False, "path": { "ftp": messages.ftp_path, "entries_sub_folders": "", "categories_sub_folders": "", "dates_sub_folders": "", "index_file_name": "index{page_number}.html", "category_directory_name": "{category}", "dates_directory_name": "%Y-%m", "entry_file_name": "entry{entry_id}.html", "rss_file_name": "rss.xml", "atom_file_name": "atom.xml" }, "entries_per_pages": 10, "columns": 1, "feed_lenght": 5, "reverse_thread_order": True, "markup_language": "Markdown", "path_encoding": "utf-8", "server_port": 8888, "sort_by": "id", "enable_jsonld": False, "enable_jsonp": False } for folder_name in argv: try: os.mkdir(folder_name) except OSError: die(messages.file_already_exists.format("--new-blog",os.getcwd()+'/'+folder_name)) os.mkdir(folder_name+'/'+"blog") os.mkdir(folder_name+'/'+"entries") os.mkdir(folder_name+'/'+"theme") os.mkdir(folder_name+'/'+"includes") os.mkdir(folder_name+'/'+"extra") os.mkdir(folder_name+'/'+"templates") stream = codecs.open(folder_name+'/'+'blog_configuration.yaml', 'w',encoding="utf-8") yaml.dump(default_configuration, stream, default_flow_style=False, allow_unicode=True) notify(messages.blog_created)
def get_blog_configuration(): try: blog_configuration = yaml.load(open(os.getcwd()+"/blog_configuration.yaml",'r').read()) mandatory_fields = [ "blog_name", "text_editor", "date_format", "author_name", "blog_description", "blog_keywords", "author_description", "license", "blog_url", "ftp_host", "blog_language", "author_email", "entries_per_pages", "columns", "feed_lenght", "reverse_thread_order", "markup_language", "disable_threads", "disable_main_thread", "disable_archives", "disable_categories", "disable_single_entries", "path_encoding", "code_highlight_css_override", "server_port", "disable_rss_feed", "disable_atom_feed", "sort_by", "enable_jsonld", "enable_jsonp" ] everything_is_okay = True for field in mandatory_fields: if not field in blog_configuration.keys(): everything_is_okay = False notify(messages.missing_mandatory_field_in_blog_conf.format(field),"RED") mandatory_fields = [ "index_file_name", "category_directory_name", "dates_directory_name", "entry_file_name", "rss_file_name", "atom_file_name", "ftp", "entries_sub_folders", "categories_sub_folders", "dates_sub_folders" ] for field in mandatory_fields: if not field in blog_configuration["path"].keys(): everything_is_okay = False notify(messages.missing_mandatory_field_in_blog_conf.format(field),"RED") if not "https://schema.org" in blog_configuration.keys(): blog_configuration["https://schema.org"] = {} if not blog_configuration["markup_language"] in ["none", "Markdown", "reStructuredText"]: everything_is_okay = False notify(messages.unknown_markup_language.format(blog_configuration["markup_language"], "blog_configuration.yaml"),"RED") if (not "sort_by" in blog_configuration.keys() ) or blog_configuration["sort_by"] in ['', None]: blog_configuration["sort_by"] = "id" if blog_configuration["blog_url"][-1:] == '/': blog_configuration["blog_url"] = blog_configuration["blog_url"][:-1] if not everything_is_okay: exit() return blog_configuration except FileNotFoundError: die(messages.no_blog_configuration) except PermissionError: die(messages.no_blog_configuration) except yaml.scanner.ScannerError: die(messages.possible_malformed_blogC_configuration)
def new_blog(argv): if len(argv) < 1: die(Messages.missingParams.format("--new-blog")) default_configuration = { "blog_name": messages.blog_name, "disable_threads": "", "disable_archives": False, "disable_categories": False, "disable_single_entries": False, "disable_main_thread": False, "disable_rss_feed": False, "disable_atom_feed": False, "text_editor": "nano", "date_format": "%A %d. %B %Y", "author_name": messages.your_name, "blog_description": messages.blog_description, "blog_keywords": messages.blog_keywords, "author_description": messages.about_you, "license": messages.license, "blog_url": messages.blog_url, "ftp_host": messages.ftp_host, "blog_language": messages.blog_language, "author_email": messages.your_email, "code_highlight_css_override": False, "path": { "ftp": messages.ftp_path, "entries_sub_folders": "", "categories_sub_folders": "", "dates_sub_folders": "", "index_file_name": "index{page_number}.html", "category_directory_name": "{category}", "dates_directory_name": "%Y-%m", "entry_file_name": "entry{entry_id}.html", "rss_file_name": "rss.xml", "atom_file_name": "atom.xml" }, "entries_per_pages": 10, "columns": 1, "feed_lenght": 5, "reverse_thread_order": True, "markup_language": "Markdown", "path_encoding": "utf-8", "server_port": 8888, "sort_by": "id", "enable_jsonld": True, "enable_jsonp": True } for folder_name in argv: try: os.mkdir(folder_name) except OSError: die(messages.file_already_exists.format("--new-blog",os.getcwd()+'/'+folder_name)) os.mkdir(folder_name+'/'+"blog") os.mkdir(folder_name+'/'+"entries") os.mkdir(folder_name+'/'+"theme") os.mkdir(folder_name+'/'+"includes") os.mkdir(folder_name+'/'+"extra") os.mkdir(folder_name+'/'+"templates") stream = codecs.open(folder_name+'/'+'blog_configuration.yaml', 'w',encoding="utf-8") yaml.dump(default_configuration, stream, default_flow_style=False, allow_unicode=True) notify(messages.blog_created)
def __init__(self, filename, paths, jsonld_callback, date_format, encoding="utf-8", ): self.previous_entry = None self.next_entry = None self.chapter = None self.schemadotorg = {} # Loading raw_data = open(os.getcwd()+"/entries/"+filename,'r').read() entry_parted = raw_data.split("---VENC-BEGIN-PREVIEW---\n") if len(entry_parted) == 2: entry_parted = [entry_parted[0]] + entry_parted[1].split("---VENC-END-PREVIEW---\n") if len(entry_parted) == 3: try: self.preview = ProcessedString(entry_parted[1], filename) self.content = ProcessedString(entry_parted[2], filename) except IllegalUseOfEscape: die(messages.illegal_use_of_escape.format(filename)) try: metadata = yaml.load(entry_parted[0], Loader=yaml.FullLoader) except yaml.scanner.ScannerError as e: die(messages.possible_malformed_entry.format(filename, ''), extra=str(e)) else: cause = messages.missing_separator_in_entry.format("---VENC-END-PREVIEW---") die(messages.possible_malformed_entry.format(filename, cause)) else: cause = messages.missing_separator_in_entry.format("---VENC-BEGIN-PREVIEW---") die(messages.possible_malformed_entry.format(filename, cause)) # Setting up optional metadata for key in metadata.keys(): if not key in ["authors", "tags", "categories", "title"]: if metadata[key] != None: if key == "https://schema.org": self.schemadotorg = metadata[key] else: setattr(self, key, metadata[key]) else: notify(messages.invalid_or_missing_metadata.format(key, filename), color="YELLOW") setattr(self, key, '') # Fix missing or incorrect metadata for key in ["authors", "tags", "categories", "title"]: if key not in metadata.keys() or metadata[key] == None: notify(messages.invalid_or_missing_metadata.format(key, filename), color="YELLOW") metadata[key] = '' self.raw_metadata = metadata self.filename = filename self.id = int(filename.split('__')[0]) raw_date = filename.split('__')[1].split('-') self.date = datetime.datetime( year=int(raw_date[2]), month=int(raw_date[0]), day=int(raw_date[1]), hour=int(raw_date[3]), minute=int(raw_date[4]) ) self.formatted_date = self.date.strftime(date_format) try: self.title = metadata["title"].replace(".:GetEntryTitle:.",'') except KeyError: die(messages.missing_mandatory_field_in_entry.format("title", self.id)) try: self.authors = [ e.strip() for e in metadata["authors"].split(",")] if type(metadata["authors"]) == str else metadata["authors"] if type(self.authors) != list: raise GenericMessage(messages.entry_metadata_is_not_a_list.format("authors", self.id)) except KeyError: die(messages.missing_mandatory_field_in_entry.format("authors", self.id)) try: self.tags = [ e.strip() for e in metadata["tags"].split(",")] if type(metadata["tags"]) == str else metadata["tags"] if type(self.tags) != list: raise GenericMessage(messages.entry_metadata_is_not_a_list.format("tags", self.id)) except KeyError: die(messages.missing_mandatory_field_in_entry.format("tags", self.id)) params = { "entry_id": self.id, "entry_title": self.title } # TODO MAY BE OPTIMIZED sf = paths["entries_sub_folders"].format(**params) if encoding == '': self.sub_folder = quirk_encoding(unidecode.unidecode(sf))+'/' if sf != '' else '' self.url = "\x1a"+self.sub_folder if self.sub_folder == '' or paths["entry_file_name"] != "index.html": self.url += quirk_encoding( unidecode.unidecode( paths["entry_file_name"].format(**params) ) ) else: try: self.sub_folder = urllib.parse.quote(sf, encoding=encoding)+'/' if sf != '' else '' self.url = "\x1a"+self.sub_folder if self.sub_folder == '' or paths["entry_file_name"] != "index.html": self.url += urllib.parse.quote(paths["entry_file_name"].format(**params), encoding=encoding) except UnicodeEncodeError as e: self.url = "\x1a"+self.sub_folder+paths["entry_file_name"].format(**params) notify("\"{0}\": ".format(sf+paths["entry_file_name"].format(**params))+str(e), color="YELLOW") self.categories_leaves = list() self.raw_categories = [ c.strip() for c in metadata["categories"].split(',')] try: for category in self.raw_categories: category_leaf = category.split(' > ')[-1].strip() if len(category_leaf) != 0: category_leaf_path = "\x1a" for sub_category in category.split(' > '): category_leaf_path +=sub_category.strip()+'/' self.categories_leaves.append({ "value": category_leaf, "path": category_leaf_path, "branch" : category }) except IndexError : # when list is empty pass self.categories_tree = [] build_categories_tree(-1, self.raw_categories, self.categories_tree, None, -1, encoding=encoding, sub_folders=paths["categories_sub_folders"]) self.html_categories_tree = {} self.html_tags = {} self.html_authors = {} self.html_categories_leaves = {} self.html_for_metadata = {} if jsonld_callback != None: jsonld_callback(self)
def get_blog_configuration(): try: blog_configuration = yaml.load( open(os.getcwd() + "/blog_configuration.yaml", 'r').read()) mandatory_fields = [ "blog_name", "text_editor", "date_format", "author_name", "blog_description", "blog_keywords", "author_description", "license", "blog_url", "ftp_host", "blog_language", "author_email", "entries_per_pages", "columns", "feed_lenght", "reverse_thread_order", "markup_language", "disable_threads", "disable_main_thread", "disable_archives", "disable_categories", "disable_single_entries", "path_encoding", "code_highlight_css_override", "server_port", "disable_rss_feed", "disable_atom_feed", "sort_by", "enable_jsonld", "enable_jsonp" ] everything_is_okay = True for field in mandatory_fields: if not field in blog_configuration.keys(): everything_is_okay = False notify( messages.missing_mandatory_field_in_blog_conf.format( field), "RED") mandatory_fields = [ "index_file_name", "category_directory_name", "dates_directory_name", "entry_file_name", "rss_file_name", "atom_file_name", "ftp", "entries_sub_folders", "categories_sub_folders", "dates_sub_folders" ] for field in mandatory_fields: if not field in blog_configuration["path"].keys(): everything_is_okay = False notify( messages.missing_mandatory_field_in_blog_conf.format( field), "RED") if not "https://schema.org" in blog_configuration.keys(): blog_configuration["https://schema.org"] = {} if not blog_configuration["markup_language"] in [ "none", "Markdown", "reStructuredText" ]: everything_is_okay = False notify( messages.unknown_markup_language.format( blog_configuration["markup_language"], "blog_configuration.yaml"), "RED") if (not "sort_by" in blog_configuration.keys() ) or blog_configuration["sort_by"] in ['', None]: blog_configuration["sort_by"] = "id" if blog_configuration["blog_url"][-1:] == '/': blog_configuration["blog_url"] = blog_configuration[ "blog_url"][:-1] if not everything_is_okay: exit() return blog_configuration except FileNotFoundError: die(messages.no_blog_configuration) except PermissionError: die(messages.no_blog_configuration) except yaml.scanner.ScannerError: die(messages.possible_malformed_blogC_configuration)
def undefined_variable(match): from venc2.prompt import die die(messages.undefined_variable.format(match, current_source.ressource), extra=current_source.string.replace( match[1:-1], '\033[91m' + match[1:-1] + '\033[0m'))