示例#1
0
 def make_tag_list(self, tag_id, number):
     tag_id = Path.urldecode(tag_id)
     conf = self.blog.default_conf
     list_size = conf('local.list_size')
     bundle = self.blog.post_bundle.bundle_list
     tagged = [
         post for post in bundle.values()
         if not post.hidden and tag_id in post.tags
     ]
     list_count = int(math.ceil(float(len(tagged)) / float(list_size)))
     if not 0 < number <= list_count:
         abort(404)
     if tagged is None or list_count < 1:
         abort(404)
     post_list = tagged[
         list_size * (number - 1):list_size * number
     ]
     for post in post_list:
         post = self.blog.plugin_manager.do_filter('dx_post', post)
     prev_page = next_page = True
     if number == 1:
         prev_page = False
     if number == list_count:
         next_page = False
     list_url = Path.format_url(self.tags_url, tag_id)
     url = list_url if list_url.endswith('/') else list_url + '/'
     web_title = self.i18n.get('{0} - Page {1}', tag_id, number)
     return self.blog.get_render(
         'list.html', posts=post_list,
         list_id=number, list_url=url,
         prev_page=prev_page, next_page=next_page,
         web_title=web_title)
示例#2
0
 def init_runtime(self):
     '''Initialize runtime environments of DelogX.'''
     conf = self.default_conf
     runtime = self.runtime
     app_path = runtime.get('path.app')
     module_path = runtime.get('path.module')
     init_path_list = [
         'directory.post',
         'directory.page',
         'directory.static',
         'directory.themes',
         'directory.plugins'
     ]
     init_url_list = [
         'url_prefix.post',
         'url_prefix.page',
         'url_prefix.static',
         'url_prefix.post_list'
     ]
     for key in init_path_list:
         runtime.let(key, Path.abs_path(app_path, conf(key)))
     for key in init_url_list:
         runtime.let(key, Path.format_url(conf(key)))
     themes_dir = runtime.get('directory.themes')
     theme = conf('local.theme')
     theme = 'default' if not theme else theme
     theme_path = os.path.join(themes_dir, theme)
     self.framework.template_folder = theme_path
     self.i18n = I18n(
         Path.format_url(module_path, 'locale'), conf('local.locale'))
示例#3
0
 def load_meta(self):
     '''Load the meta of this item, include `hidden`, `url` and `title`.'''
     if not self.valid():
         return
     self.hidden = self.filename.startswith('.')
     self.url = os.path.splitext(self.filename)[0]
     if self.hidden:
         self.url = self.url[1:]
     atx_re = re.compile(r'^\s*#\s*([^#]+)\s*#*\s*$')
     setext_re = re.compile(r'^\s*=+\s*$')
     lines = Path.read_file(self.path)
     first_line = Path.get_first_line(lines)
     line1 = lines[first_line] if first_line < len(lines) else ''
     line2 = lines[first_line + 1] if first_line + 1 < len(lines) else ''
     line1 = line1.strip('\n').strip('\r')
     line2 = line2.strip('\n').strip('\r')
     atx_match = atx_re.match(line1)
     setext_match = setext_re.match(line2)
     if atx_match and atx_match.group(1):
         self.title = atx_match.group(1)
         self.title_line = first_line + 1
     elif setext_match and line1.strip():
         self.title = line1
         self.title_line = first_line + 2
     else:
         self.title = self.url
         self.title_line = 0
示例#4
0
 def run(self):
     conf = self.blog.default_conf
     self.config = Config(os.path.join(self.workspace, 'config.json'))
     self.i18n = I18n(
         Path.format_url(self.workspace, 'locale'), conf('local.locale'))
     self.tags_url = self.config.get('delog_tags.url')
     if not self.tags_url:
         self.tags_url = '/tag'
     self.tags_url = Path.format_url(self.tags_url)
     tag_rule = Path.format_url(self.tags_url, '<tag_id>/')
     tag_list_rule = Path.format_url(tag_rule, '<int:number>/')
     self.blog.add_url_rule(tag_rule, 'delog_tag', self.make_tag)
     self.blog.add_url_rule(
         tag_list_rule, 'delog_tag_list', self.make_tag_list)
     self.manager.add_action('dx_post_update', self.load_tags)
示例#5
0
    def route_list(self, number):
        '''Response a list of posts.

        Hidden posts will be ignored.

        Args:

            number (int): Page number of the list.

        Returns:

            str: Rendered HTML of the posts list.

        Abort:

            404: No such page of posts list.
        '''
        runtime = self.runtime.get
        post_count = self.post_bundle.get_list_count()
        post_list = self.post_bundle.get_list(number)
        if post_list is None:
            abort(404)
        for post in post_list:
            post = self.plugin_manager.do_filter('dx_post', post)
        prev_page = next_page = True
        if number == 1:
            prev_page = False
        if number == post_count:
            next_page = False
        list_url = Path.format_url(runtime('url_prefix.post_list'))
        url = list_url if list_url.endswith('/') else list_url + '/'
        return self.get_render(
            'list.html', posts=post_list,
            list_id=number, list_url=url,
            prev_page=prev_page, next_page=next_page)
示例#6
0
    def __init__(self, app_path, framework, config='config.json'):
        '''Initialize DelogX object.

        Args:

            app_path (str): Absolute path of the blog application.
            framework (Flask): Flask application object.
            config (str): Config file of DelogX, defaults `config.json`.
        '''
        self.framework = framework
        app_path = os.path.realpath(app_path)
        config = Path.abs_path(app_path, config)
        config = Config(config)
        runtime = Config()
        module_path = os.path.dirname(os.path.realpath(__file__))
        runtime.let('path.app', app_path)
        runtime.let('path.module', module_path)
        ver_file = os.path.join(module_path, 'VERSION')
        with codecs.open(ver_file, encoding='utf-8') as f:
            version = ''.join(f.readlines()).strip()
        runtime.let('blog.version', version)
        self.config = config
        self.runtime = runtime
        self.markdown_ext = list()
        self.init_runtime()
        self.init_plugins()
        self.init_bundles()
        self.init_route()
        self.update_header()
示例#7
0
    def __init__(self, blog, directory):
        '''Initialize a DelogX bundle.

        Args:

            blog (DelogX): DelogX object.
            directory (str): Name of items directory.
        '''
        self.blog = blog
        self.bundle_list = OrderedDict()
        app_path = blog.runtime.get('path.app')
        self.directory = Path.abs_path(app_path, directory)
        if not os.path.exists(self.directory):
            try:
                os.makedirs(self.directory)
            except OSError as exception:
                if (exception.errno != errno.EEXIST
                        or not os.path.isdir(self.directory)):
                    raise exception
        for filename in os.listdir(self.directory):
            real_path = os.path.join(self.directory, filename)
            if (os.path.isfile(real_path)
                    and os.path.splitext(filename)[1] == '.md'):
                self.update(filename)
        self.sort()
示例#8
0
 def load_content(self):
     '''Load and parse the content of this item.'''
     lines = Path.read_file(self.path)
     if lines is None:
         lines = list()
     lines = lines[self.title_line:]
     self.markdown = ''.join(lines)
     self.content = Markdown.markdown(self.markdown, self.blog.markdown_ext)
示例#9
0
 def load_tags(self, *args, **kwargs):
     post = kwargs.get('post')
     if not post:
         return
     post.tags = list()
     title = post.title
     title_split = list(filter(None, title.split('::', 1)))
     if title_split:
         post.title = title_split[0].strip()
         tags = ''.join(title_split[1:]).split(',')
         post.tags = list(filter(None, list(map(str.strip, tags))))
         tags_link = list()
         tags_html = '<div class="post-tags">{0}</div>'
         for tag in post.tags:
             tags_link.append('<a href="{0}">{1}</a>'.format(
                 Path.format_url(self.tags_url, Path.urlencode(tag)), tag))
         if tags_link:
             tags_html = tags_html.format(' '.join(tags_link))
             post.content = tags_html + post.content
示例#10
0
    def cook_page(self, page):
        '''Cook a Page.

        Add prefix to the URL of the Page.

        Args:

            page (Page): Page needs to cook.

        Returns:

            Page: Cooked Page.
        '''
        runtime = self.runtime.get
        if not page:
            return None
        page_url = runtime('url_prefix.page')
        page.cooked_url = Path.format_url(page_url, Path.urlencode(page.url))
        return page
示例#11
0
 def init_route(self):
     '''Initialize URL routes of DelogX.'''
     runtime = self.runtime
     static_rule = Path.format_url(
         runtime.get('url_prefix.static'), '<static_file>')
     list_rule = Path.format_url(
         runtime.get('url_prefix.post_list'), '<int:number>/')
     item_rule = Path.format_url(
         runtime.get('url_prefix.page'), '<item_id>/')
     page_rule = Path.format_url(
         runtime.get('url_prefix.page'), '<page_id>/')
     post_rule = Path.format_url(
         runtime.get('url_prefix.post'), '<post_id>/')
     icon_rule = Path.format_url(
         runtime.get('url_prefix.static'), 'favicon.ico')
     self.add_url_rule('/', 'delogx_index', self.route_index)
     self.add_url_rule(static_rule, 'delogx_static', self.route_static)
     self.add_url_rule(list_rule, 'delogx_list', self.route_list)
     if runtime.get('url_prefix.post') == runtime.get('url_prefix.page'):
         self.add_url_rule(item_rule, 'delogx_page', self.route_item)
     else:
         self.add_url_rule(page_rule, 'delogx_page', self.route_page)
         self.add_url_rule(post_rule, 'delogx_post', self.route_post)
     self.framework.add_url_rule(
         '/favicon.ico', 'delogx_favicon', redirect_to=icon_rule)
     self.framework.errorhandler(404)(self.route_not_found)
示例#12
0
 def parse_readmore(self, post):
     if not post:
         return
     content_split = re.split(r'<[Hh][Rr](?:\s+\/)?>', post.content, 1)
     if len(content_split) == 2:
         summary, more = content_split
     else:
         summary = content_split[0]
         more = ''
     post_url = self.blog.runtime.get('url_prefix.post')
     post_url = Path.format_url(post_url, Path.urlencode(post.url))
     content = '''{0}
     <div class="{1}"><a href="{2}">{3}</a></div>
     <div class="post-more">{4}</div>
     '''
     more_class = ['read-more']
     if not more:
         more_class.append('no-more-content')
     more_class = ' '.join(more_class)
     content = content.format(
         summary, more_class, post_url, self.i18n.get('Read More'), more)
     post.content = content
示例#13
0
 def run(self):
     self.config = Config(os.path.join(self.workspace, 'config.json'))
     self.feed_url = self.config.get('delog_feed.url')
     self.feed_limit = self.config.get('delog_feed.limit')
     if not self.feed_url:
         self.feed_url = '/feed'
     if not self.feed_limit:
         self.feed_limit = 10
     self.feed_url = Path.format_url(self.feed_url)
     if not self.feed_url.endswith('/'):
         self.feed_url += '/'
     self.blog.add_url_rule(self.feed_url, 'delog_feed', self.make_feed)
     self.manager.add_filter('dx_render', self.add_link)
示例#14
0
    def cook_post(self, post):
        '''Cook a Post.

        Add prefix to the URL of the Post and convert timestamp to string.

        Args:

            post (Post): Post needs to cook.

        Returns:

            Post: Cooked Post.
        '''
        conf = self.config.get
        runtime = self.runtime.get
        if not post:
            return None
        post_url = runtime('url_prefix.post')
        time_format = conf('local.time_format')
        post.cooked_url = Path.format_url(post_url, Path.urlencode(post.url))
        post.cooked_time = time.strftime(
            time_format, time.localtime(post.time))
        post.cooked_time = post.cooked_time
        return post
示例#15
0
    def get_post(self, post_id):
        '''Return cooked Post object by id.

        Args:

            post_id (str): Request ID of the post.

        Returns:

            Post: Cooked Post object.
        '''
        post_id = Path.urldecode(post_id)
        post = self.post_bundle.get(post_id)
        self.plugin_manager.do_action('dx_post')
        return self.plugin_manager.do_filter('dx_post', post)
示例#16
0
    def get_page(self, page_id):
        '''Return cooked Page object by id.

        Args:

            page_id (str): Request ID of the page.

        Returns:

            Page: Cooked Page object.
        '''
        page_id = Path.urldecode(page_id)
        page = self.page_bundle.get(page_id)
        self.plugin_manager.do_action('dx_page')
        page = self.plugin_manager.do_filter('dx_page', page)
        return page
示例#17
0
    def cook_static(self, statics):
        '''Cook a list of static files.

        Convert all relative links to absolute.

        Args:

            statics (list of str): Static files.

        Returns:

            list: Cooked list of static files.
        '''
        runtime = self.runtime.get
        static_url = runtime('url_prefix.static')
        if not statics:
            statics = list()
        for i, link in enumerate(statics):
            if not link.startswith(('/', 'http://', 'https://')):
                statics[i] = Path.format_url(static_url, link)
        return statics
示例#18
0
 def run(self):
     conf = self.blog.default_conf
     self.i18n = I18n(
         Path.format_url(self.workspace, 'locale'), conf('local.locale'))
     self.manager.add_action('dx_post_update', self.parse_readmore)