def sanitize_image(link):
    """
    Patched function to resolve the url using Lektor.
    """
    if get_ctx() and get_ctx().record is not None:
        url = url_parse(link)
        if not url.scheme:
            return get_ctx().record.url_to(link, alt=PRIMARY_ALT, base_url=get_ctx().base_url)
    return link
Exemplo n.º 2
0
 def __render(self):
     # When the markdown instance is attached to a cached object we can
     # end up in the situation where the context changed from the time
     # we were put into the cache to the time where we got referenced
     # by something elsewhere.  In that case we need to re-process our
     # markdown.  For instance this affects relative links.
     if self.__html is None or self.__cached_for_ctx != get_ctx():
         self.__html, self.__meta = markdown_to_html(self.source, self.__record())
         self.__cached_for_ctx = get_ctx()
Exemplo n.º 3
0
def get_item_body(item, field, body_template):
    if field not in item:
        raise RuntimeError('Body field %r not found in %r' % (field, item))

    if body_template:
        rv = get_ctx().env.render_template(body_template, get_ctx().pad, this=item, values={'body': item[field]})
        return text_type(rv)
    else:
        with get_ctx().changed_base_url(item.url_path):
            return text_type(escape(item[field]))
Exemplo n.º 4
0
 def __render(self):
     # When the markdown instance is attached to a cached object we can
     # end up in the situation where the context changed from the time
     # we were put into the cache to the time where we got referenced
     # by something elsewhere.  In that case we need to re-process our
     # markdown.  For instance this affects relative links.
     if self.__html is None or \
        self.__cached_for_ctx != get_ctx():
         self.__html, self.__meta = markdown_to_html(
             self.source, self.__record())
         self.__cached_for_ctx = get_ctx()
    def build_artifact(self, artifact):

        data = {'pages': []}
        for page in self.get_all_children():
            data['pages'].append({
                'title': self.join_fields(page, self.source.title),
                'text': self.join_fields(page, self.source.text),
                'tags': self.join_fields(page, self.source.tags),
                'url': page.url_path
            })

        get_ctx().record_dependency(artifact.artifact_name)

        with artifact.open('wb') as f:
            f.write(dumps(data).encode('utf-8'))
Exemplo n.º 6
0
 def __render(self):
     # When the markdown instance is attached to a cached object we can
     # end up in the situation where the context changed from the time
     # we were put into the cache to the time where we got referenced
     # by something elsewhere.  In that case we need to re-process our
     # markdown.  For instance this affects relative links.
     if self.__html is None or \
        self.__cached_for_ctx != get_ctx():
         self.__html, __resources = notebook_to_html(
             self.source, self.__record())
         self.__cached_for_ctx = get_ctx()
         if 'inlining' in __resources:
             css_strs = __resources['inlining'].get('css')
             if css_strs:
                 self.__meta = '\n'.join(css_strs)
Exemplo n.º 7
0
def rst_to_html(text, extra_params, record):
    ctx = get_ctx()
    if ctx is None:
        raise RuntimeError('Context is required for markdown rendering')

    pub = docutils.core.Publisher(
        destination_class=docutils.io.StringOutput)
    pub.set_components('standalone', 'restructuredtext', 'html')
    pub.process_programmatic_settings(None, extra_params, None)
    pub.set_source(
        source=StringIO(text),
        source_path=record.source_filename if record is not None else None)
    pub.publish()

    metadata = {}
    for docinfo in pub.document.traverse(docutils.nodes.docinfo):
        for element in docinfo.children:
            if element.tagname == 'field':
                name_elem, body_elem = element.children
                name = name_elem.astext()
                value = body_elem.astext()
            else:
                name = element.tagname
                value = element.astext()
            name = name.lower()
            if name == 'date':
                value = datetime.datetime.strptime(value, "%Y-%m-%d %H:%M")
            metadata[name] = value

    parts = pub.writer.parts
    body = parts['html_title'] + parts['html_subtitle'] + parts['fragment']

    return body, metadata
Exemplo n.º 8
0
def render_template_into(self, template_name, this, **extra):
    """Render a template into the artifact and an amp subartifact."""
    values = extra.get('values', {})
    values['canonical'] = self.artifact_name
    values['amp_path'] = ''
    extra['values'] = values

    if self.dst_filename.endswith('.html'):
        amp_path = '/amp/{}'.format(self.artifact_name)
        values['amp_path'] = amp_path
        rv2 = self.build_state.env.render_template(
            'amp-{}'.format(template_name), self.build_state.pad,
            this=this, **extra)

        ctx = get_ctx()

        @ctx.sub_artifact(amp_path)
        def build_ampsite(artifact):
            artifact.sources = self.sources
            with artifact.open('w') as f:
                f.write(rv2.encode('utf-8') + b'\n')

    rv = self.build_state.env.render_template(
        template_name, self.build_state.pad,
        this=this, **extra)
    with self.open('wb') as f:
        f.write(rv.encode('utf-8') + b'\n')
Exemplo n.º 9
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        source_out = self.build_state.make_named_temporary("less")
        map_out = self.build_state.make_named_temporary("less-sourcemap")
        here = os.path.dirname(self.source.source_filename)

        cmdline = [
            "lessc",
            "--no-js",
            "--include-path=%s" % here,
            "--source-map=%s" % map_out,
            self.source.source_filename,
            source_out,
        ]

        reporter.report_debug_info("lessc cmd line", cmdline)

        proc = portable_popen(cmdline)
        if proc.wait() != 0:
            raise RuntimeError("lessc failed")

        with open(map_out) as f:
            dep_base = os.path.dirname(map_out)
            for dep in json.load(f).get("sources") or ():
                ctx.record_dependency(os.path.join(dep_base, dep))

        artifact.replace_with_file(source_out)
Exemplo n.º 10
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        source_out = self.build_state.make_named_temporary('less')
        map_out = self.build_state.make_named_temporary('less-sourcemap')
        here = os.path.dirname(self.source.source_filename)

        exe = self.build_state.config['LESSC_EXECUTABLE']
        if exe is None:
            exe = 'lessc'

        cmdline = [exe, '--no-js', '--include-path=%s' % here,
                   '--source-map=%s' % map_out,
                   self.source.source_filename,
                   source_out]

        reporter.report_debug_info('lessc cmd line', cmdline)

        proc = portable_popen(cmdline)
        if proc.wait() != 0:
            raise RuntimeError('lessc failed')

        with open(map_out) as f:
            for dep in json.load(f).get('sources') or ():
                ctx.record_dependency(os.path.join(here, dep))

        artifact.replace_with_file(source_out)

        @ctx.sub_artifact(artifact_name=artifact.artifact_name + '.map',
                          sources=[self.source.source_filename])
        def build_less_sourcemap_artifact(artifact):
            artifact.replace_with_file(map_out)
Exemplo n.º 11
0
    def get_disqus_config(self,
                          identifier=None,
                          url=None,
                          title=None,
                          category_id=None):
        configs = []
        ctx = get_ctx()
        if identifier is None:
            if ctx.source is not None and ctx.source.path is not None:
                identifier = ctx.source.path
        if identifier is not None:
            configs.append('this.page.identifier = %s;' %
                           htmlsafe_json_dump(identifier))

        if url is None and ctx.source is not None:
            try:
                url = url_to(ctx.source, external=True)
            except RuntimeError:
                url = None
        if url is not None:
            configs.append('this.page.url = %s;' % htmlsafe_json_dump(url))
        if title is not None:
            configs.append('this.page.title = %s;' % htmlsafe_json_dump(title))
        if category_id is not None:
            configs.append('this.page.category_id = %s;' %
                           htmlsafe_json_dump(category_id))
        return ' '.join(configs)
Exemplo n.º 12
0
 def __getitem__(self, name):
     # If any data of a flowblock is accessed, we record that we need
     # this dependency.
     ctx = get_ctx()
     if ctx is not None:
         ctx.record_dependency(self.flowblockmodel.filename)
     return self._data[name]
Exemplo n.º 13
0
def limit_dependencies(jinja_env, query):
    if not isinstance(query, Query):
        return jinja_env.undefined(
            "limit_dependencies expected a Query instance, not {!r}".format(
                query))

    # XXX: We cache the query results in the pad's record cache, so
    # any changes in the query results will not be noticed for the
    # lifetime of the pad.
    #
    # ``Lektor.devserver.BackgroundBuilder`` appears to create
    # a new pad for every rebuild attempt, and so any changes
    # in query results should get notice at the next rebuild
    # when running under ``lektor server``.
    id_ = serialize_query(query)

    def creator():
        return QueryResults(query, id_)

    with disable_dependency_recording():
        root = query.pad.root
    virtual_path = f'{VIRTUAL_PATH_PREFIX}/{id_}'
    results = get_or_create_virtual(root, virtual_path, creator)

    ctx = get_ctx()
    if ctx is not None:
        ctx.record_virtual_dependency(results)

    return PrecomputedQuery(query.path,
                            query.pad,
                            results.query_result_ids,
                            alt=query.alt)
Exemplo n.º 14
0
    def __html__(self):
        ctx = get_ctx()

        # If we're in a nested render, we disable the rendering here or we
        # risk a recursion error.
        if ctx is None or self in ctx.flow_block_render_stack:
            return Markup.escape(repr(self))

        ctx.flow_block_render_stack.append(self)
        try:
            try:
                return self.pad.db.env.render_template(
                    [
                        "blocks/%s.html" % self._data["_flowblock"],
                        "blocks/default.html",
                    ],
                    pad=self.pad,
                    this=self,
                    alt=self.record.alt,
                    values={"record": self.record},
                )
            except TemplateNotFound:
                return Markup("[could not find snippet template]")
        finally:
            ctx.flow_block_render_stack.pop()
Exemplo n.º 15
0
Arquivo: db.py Projeto: jab/lektor
    def _iterate(self):
        """Low level record iteration."""
        # If we iterate over children we also need to track those
        # dependencies.  There are two ways in which we track them.  The
        # first is through the start record of the query.  If that does
        # not work for whatever reason (because it does not exist for
        # instance).
        self_record = self.pad.get(self.path)
        if self_record is not None:
            self.pad.db.track_record_dependency(self_record)

        # We also always want to record the path itself as dependency.
        ctx = get_ctx()
        if ctx is not None:
            ctx.record_dependency(self.pad.db.to_fs_path(self.path))

        for name, is_attachment in self.pad.db.iter_items(self.path):
            if not ((is_attachment == self._include_attachments) or
                    (not is_attachment == self._include_pages)):
                continue

            record = self._get(name, persist=False)
            if self._visible_only and not record.is_visible:
                continue
            for filter in self._filters or ():
                if not save_eval(filter, record):
                    break
            else:
                yield record
Exemplo n.º 16
0
    def __html__(self):
        ctx = get_ctx()

        # Parse config
        config = get_plugin(u"graphviz").get_config()
        img_format = config.get("format", "png")
        substitutions = {
            k.replace("substitutions.", ""): v for (k, v) in config.items() if k.startswith("substitutions.")
        }

        # Add default styles
        additional_options = []
        if u"style.graph" in config:
            additional_options.append("-G{}".format(config.get("style.graph")))
        if u"style.node" in config:
            additional_options.append("-N{}".format(config.get("style.node")))
        if u"style.edge" in config:
            additional_options.append("-E{}".format(config.get("style.edge")))

        # Get artifact image filename
        image_filename = self.get_image_filename(ctx.source.url_path, img_format)

        @ctx.sub_artifact(artifact_name=image_filename, sources=[ctx.source.source_filename])
        def generate_image(artifact):
            with artifact.open("w") as f:
                substituted_source = Template(self.source).safe_substitute(substitutions)
                f.write(render_diagram(substituted_source, img_format, additional_options))

        return image_filename
Exemplo n.º 17
0
 def image(self, src, title, text):
     if self.record is not None:
         url = url_parse(src)
         if not url.scheme:
             src = self.record.url_to('!' + src,
                                      base_url=get_ctx().base_url)
     return mistune.Renderer.image(self, src, title, text)
Exemplo n.º 18
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        source_out = self.build_state.make_named_temporary('less')
        map_out = self.build_state.make_named_temporary('less-sourcemap')
        here = os.path.dirname(self.source.source_filename)

        exe = self.build_state.config['LESSC_EXECUTABLE']
        if exe is None:
            exe = 'lessc'

        cmdline = [
            exe, '--no-js',
            '--include-path=%s' % here,
            '--source-map=%s' % map_out, self.source.source_filename,
            source_out
        ]

        reporter.report_debug_info('lessc cmd line', cmdline)

        proc = portable_popen(cmdline)
        if proc.wait() != 0:
            raise RuntimeError('lessc failed')

        with open(map_out) as f:
            for dep in json.load(f).get('sources') or ():
                ctx.record_dependency(os.path.join(here, dep))

        artifact.replace_with_file(source_out)

        @ctx.sub_artifact(artifact_name=artifact.artifact_name + '.map',
                          sources=[self.source.source_filename])
        def build_less_sourcemap_artifact(artifact):
            artifact.replace_with_file(map_out)
Exemplo n.º 19
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        page = feed_source.parent

        feed = AtomFeed(title=page.record_label + u' — Pallets Project',
                        feed_url=url_to(feed_source, external=True),
                        url=url_to('/blog', external=True),
                        id=get_id(ctx.env.project.id))

        for item in page.children.order_by('-pub_date').limit(10):
            item_author = item['author']

            feed.add(
                item['title'],
                text_type(item['body']),
                xml_base=url_to(item, external=True),
                url=url_to(item, external=True),
                content_type='html',
                id=get_id(u'%s/%s' %
                          (ctx.env.project.id, item['_path'].encode('utf-8'))),
                author=item_author,
                updated=datetime(*item['pub_date'].timetuple()[:3]))

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8'))
Exemplo n.º 20
0
 def link(self, link, title, text):
     if self.record is not None:
         url = url_parse(link)
         if not url.scheme:
             link = self.record.url_to('!' + link,
                                       base_url=get_ctx().base_url)
     return mistune.Renderer.link(self, link, title, text)
def gen_js(record):
    if not record or not hasattr(record, "_js"):
        return ""

    ctx = get_ctx()

    def js_template(name):
        t = """<script>{%% include "%s" %%}</script>""" % name
        return ctx.env.jinja_env.from_string(t).render()

    js = record._js
    ret = []
    for src in js["css"]:
        js["templates"]["shortcodes/add_css.js"] = True
        js["embed"][f'API.add_css("{escape(src)}")'] = True
        # FIXME place this in head
        # s = f'<link rel="stylesheet" href="{escape(src)}"/>'
        # ret.append(s)

    for src, async_ in js["links"].items():
        s = f'<script src="{escape(src)}"{" async" if async_ else ""}></script>'
        ret.append(s)
    for src in js["templates"]:
        try:
            s = js_template(src)
        except TemplateNotFound:
            s = f"[shortcode template {src} not found]"
        ret.append(s)

    for src in js["embed"]:
        s = f"<script>{src}</script>"
        ret.append(s)

    return Markup("\n".join(ret))
Exemplo n.º 22
0
    def make_default_tmpl_values(self,
                                 pad=None,
                                 this=None,
                                 values=None,
                                 alt=None,
                                 template=None):
        values = dict(values or ())

        # If not provided, pick the alt from the provided "this" object.
        # As there is no mandatory format for it, we make sure that we can
        # deal with a bad attribute there.
        if alt is None:
            if this is not None:
                alt = getattr(this, 'alt', None)
                if not isinstance(alt, string_types):
                    alt = None
            if alt is None:
                alt = PRIMARY_ALT

        # This is already a global variable but we can inject it as a
        # local override if available.
        if pad is None:
            ctx = get_ctx()
            if ctx is not None:
                pad = ctx.pad
        if pad is not None:
            values['site'] = pad
        if this is not None:
            values['this'] = this
        if alt is not None:
            values['alt'] = alt
        self.plugin_controller.emit('process-template-context',
                                    context=values,
                                    template=template)
        return values
Exemplo n.º 23
0
def mode_link(mode):
    try:
        ctx = get_ctx()
        if not ctx:
            return 'DEVMODE?'

        pad = ctx.pad

        record = pad.get('/mode/' + mode)
        if record:
            title = record['title']
            if title.endswith(')'):
                title = title[:title.rindex('(')]
            title = title.lower()
            if not title:
                if mode.startswith('p'):
                    title = '?' + mode[1:]
                else:
                    title = mode
        else:
            title = "mode not found: " + mode
        title = title.strip()
        return '<a href="{url}">{title}</a>'.format(title=title,
                                                    url='/mode/' + mode)
    except Exception as ex:
        print('failed:', ex)
        raise
Exemplo n.º 24
0
    def get_og_items(self, record):
        plugin_config = self.get_config()
        model_config = IniFile(record.datamodel.filename)
        root = get_ctx().pad.root
        items = {
            'site_name':
            plugin_config.get('global.site_name', self.env.project.name),
            'url':
            url_to(record, external=True),
            'title':
            get_og_title(record, model_config, root),
            'type':
            'website',
        }
        image = get_og_image(record, root)

        if image is not None:
            items.update({
                'image': url_to(image, external=True),
                'image:width': image.width,
                'image:height': image.height,
                'image:type': 'image/' + image.format,
            })

            if image.parent is root:
                items['image:alt'] = 'logo'

        return items
Exemplo n.º 25
0
Arquivo: flow.py Projeto: jab/lektor
 def __getitem__(self, name):
     # If any data of a flowblock is accessed, we record that we need
     # this dependency.
     ctx = get_ctx()
     if ctx is not None:
         ctx.record_dependency(self.flowblockmodel.filename)
     return self._data[name]
Exemplo n.º 26
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        page = feed_source.parent

        fg = FeedGenerator()
        fg.id(get_id(ctx.env.project.id))
        fg.title(page.record_label + u" — Pallets Project")
        fg.link(href=url_to("/blog", external=True))
        fg.link(href=url_to(feed_source, external=True), rel="self")

        for item in page.children.order_by('-pub_date', '-pub_order',
                                           'title').limit(10):
            fe = fg.add_entry()
            fe.title(item["title"])
            fe.content(text_type(item["body"]), type="html")
            fe.link(href=url_to(item, external=True))
            fe.id(
                get_id(u"{}/{}".format(ctx.env.project.id,
                                       item["_path"].encode("utf-8"))))
            fe.author(name=item["author"])
            updated = datetime(*item["pub_date"].timetuple()[:3])
            updated = updated.isoformat() + "Z" if not updated.tzinfo else ""
            fe.updated(updated)

        with artifact.open('wb') as f:
            f.write(fg.atom_str(pretty=True))
Exemplo n.º 27
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        page = feed_source.parent

        feed = AtomFeed(
            title=page.record_label + u' — Pallets Project',
            feed_url=url_to(feed_source, external=True),
            url=url_to('/blog', external=True),
            id=get_id(ctx.env.project.id)
        )

        for item in page.children.order_by(
            '-pub_date', '-pub_order', 'title'
        ).limit(10):
            item_author = item['author']

            feed.add(
                item['title'],
                text_type(item['body']),
                xml_base=url_to(item, external=True),
                url=url_to(item, external=True),
                content_type='html',
                id=get_id(u'%s/%s' % (
                    ctx.env.project.id,
                    item['_path'].encode('utf-8'))),
                author=item_author,
                updated=datetime(*item['pub_date'].timetuple()[:3]))

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8'))
Exemplo n.º 28
0
    def make_default_tmpl_values(self, pad=None, this=None, values=None, alt=None,
                                 template=None):
        values = dict(values or ())

        # If not provided, pick the alt from the provided "this" object.
        # As there is no mandatory format for it, we make sure that we can
        # deal with a bad attribute there.
        if alt is None:
            if this is not None:
                alt = getattr(this, 'alt', None)
                if not isinstance(alt, string_types):
                    alt = None
            if alt is None:
                alt = PRIMARY_ALT

        # This is already a global variable but we can inject it as a
        # local override if available.
        if pad is None:
            ctx = get_ctx()
            if ctx is not None:
                pad = ctx.pad
        if pad is not None:
            values['site'] = pad
        if this is not None:
            values['this'] = this
        if alt is not None:
            values['alt'] = alt
        self.plugin_controller.emit('process-template-context',
                                    context=values, template=template)
        return values
Exemplo n.º 29
0
 def image(self, src, title, text):
     if self.record is not None:
         url = url_parse(src)
         if not url.scheme:
             src = self.record.url_to('!' + src,
                                      base_url=get_ctx().base_url)
     return mistune.Renderer.image(self, src, title, text)
Exemplo n.º 30
0
def importPy(fileName):
    ctx = get_ctx()
    filePath = os.getcwd(
    ) + '/content' + ctx.source.path + '/' + fileName  # ­ЪциРђЇРЎѓ№ИЈ
    with codecs.open(filePath, 'r', 'utf-8') as pyFile:
        pyStr = pyFile.read()
    return HTML(u'<code class="language-python">{}</code>'.format(pyStr))
Exemplo n.º 31
0
 def link(self, link, title, text):
     if self.record is not None:
         url = url_parse(link)
         if not url.scheme:
             link = self.record.url_to('!' + link,
                                       base_url=get_ctx().base_url)
     return mistune.Renderer.link(self, link, title, text)
Exemplo n.º 32
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        project_id = ctx.env.project.id

        feed = make_feed(self.source, project_id)
        for item in get_items(ctx, feed_source):
            try:
                _id = get_id('{0}/{1}'.format(
                    project_id, item['_path'].encode('utf-8'))),

                with ctx.changed_base_url(item.url_path):
                    feed_item = FeedItem(item, feed_source)

                feed.add(
                    feed_item.title,
                    feed_item.body,
                    xml_base=feed_item.url,
                    url=feed_item.url,
                    content_type='html',
                    id=_id,
                    author=feed_item.author,
                    updated=feed_item.updated,
                )
            except Exception as exc:
                reporter.report_generic(exc)

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8'))
Exemplo n.º 33
0
    def _load_template(self, name, globals):
        ctx = get_ctx()

        try:
            rv = jinja2.Environment._load_template(self, name, globals)
            if ctx is not None:
                filename = rv.filename
                if PY2 and is_windows:
                    try:
                        filename = filename.decode('utf-8')
                    except UnicodeDecodeError:
                        pass
                ctx.record_dependency(filename)
            return rv
        except jinja2.TemplateSyntaxError as e:
            if ctx is not None:
                ctx.record_dependency(e.filename)
            raise
        except jinja2.TemplateNotFound as e:
            if ctx is not None:
                # If we can't find the template we want to record at what
                # possible locations the template could exist.  This will help
                # out watcher to pick up templates that will appear in the
                # future.  This assumes the loader is a file system loader.
                for template_name in e.templates:
                    pieces = split_template_path(template_name)
                    for base in self.loader.searchpath:
                        ctx.record_dependency(os.path.join(base, *pieces))
            raise
Exemplo n.º 34
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        blog = feed_source.parent

        summary = get(blog, feed_source.blog_summary_field) or ""
        if hasattr(summary, "__html__"):
            subtitle_type = "html"
            summary = text_type(summary.__html__())
        else:
            subtitle_type = "text"
        blog_author = text_type(get(blog, feed_source.blog_author_field) or "")

        feed = Atom1Feed(
            title=feed_source.feed_name,
            subtitle=summary,
            author_name=blog_author,
            feed_url=url_to(feed_source, external=True),
            link=url_to(blog, external=True),
            feed_guid=get_id(ctx.env.project.id),
            description=None,
        )

        if feed_source.items:
            # "feed_source.items" is a string like "site.query('/blog')".
            expr = Expression(ctx.env, feed_source.items)
            items = expr.evaluate(ctx.pad)
        else:
            items = blog.children

        if feed_source.item_model:
            items = items.filter(F._model == feed_source.item_model)

        order_by = "-" + feed_source.item_date_field
        items = items.order_by(order_by).limit(int(feed_source.limit))

        for item in items:
            try:
                item_author_field = feed_source.item_author_field
                item_author = get(item, item_author_field) or blog_author

                feed.add_item(
                    title=get_item_title(item, feed_source.item_title_field),
                    description=None,
                    content=get_item_body(item, feed_source.item_body_field),
                    link=url_to(item, external=True),
                    unique_id=get_id(
                        u"%s/%s" %
                        (ctx.env.project.id, item["_path"].encode("utf-8"))),
                    author_name=item_author,
                    updateddate=get_item_updated(item,
                                                 feed_source.item_date_field),
                )

            except Exception as exc:
                msg = "%s: %s" % (item["_id"], exc)
                click.echo(click.style("E", fg="red") + " " + msg)

        with artifact.open("wb") as f:
            feed.write(f, "utf-8")
Exemplo n.º 35
0
    def _iterate(self):
        """Low level record iteration."""
        # If we iterate over children we also need to track those
        # dependencies.  There are two ways in which we track them.  The
        # first is through the start record of the query.  If that does
        # not work for whatever reason (because it does not exist for
        # instance).
        self_record = self.pad.get(self.path, alt=self.alt)
        if self_record is not None:
            self.pad.db.track_record_dependency(self_record)

        # We also always want to record the path itself as dependency.
        ctx = get_ctx()
        if ctx is not None:
            ctx.record_dependency(self.pad.db.to_fs_path(self.path))

        for name, _, is_attachment in self.pad.db.iter_items(
                self.path, alt=self.alt):
            if not ((is_attachment == self._include_attachments) or
                    (not is_attachment == self._include_pages)):
                continue

            record = self._get(name, persist=False)
            if self._matches(record):
                yield record
    def build_artifact(self, artifact):
        ctx = get_ctx()
        plugin = ctx.env.plugins["thumbnail-generator"]
        config = plugin.config

        artifact.ensure_dir()
        AttachmentBuildProgram.build_artifact(self, artifact)

        if not config:
            return

        source_img = artifact.source_obj.attachment_filename

        with open(source_img, "rb") as f:
            _, w, h = get_image_info(f)

        # For every section in the config, we need to generate one image.
        for item, conf in config.items():
            width = int(conf["max_width"])
            height = int(conf.get("max_height", "0"))

            if not height:
                _, height = compute_dimensions(width, None, w, h)

            df = artifact.source_obj.url_path
            ext_pos = df.rfind(".")
            dst_filename = "%s-%s.%s" % (df[:ext_pos], item, df[ext_pos + 1:])

            def closure(dst_filename,
                        source_img,
                        width,
                        height,
                        resize_image=True):
                # We need this closure, otherwise variables get updated and this
                # doesn't work at all.
                @ctx.sub_artifact(artifact_name=dst_filename,
                                  sources=[source_img])
                def build_thumbnail_artifact(artifact):
                    artifact.ensure_dir()
                    if not resize_image:
                        shutil.copy2(source_img, artifact.dst_filename)
                    else:
                        process_image(
                            ctx,
                            source_img,
                            artifact.dst_filename,
                            width,
                            height,
                            quality=85,
                            extra_params=[
                                "-strip",
                                "-interlace",
                                "Plane",
                            ],
                        )

            # If the image is larger than the max_width, resize it, otherwise
            # just copy it.
            resize_image = w > width or h > height
            closure(dst_filename, source_img, width, height, resize_image)
Exemplo n.º 37
0
    def _load_template(self, name, globals):
        ctx = get_ctx()

        try:
            rv = jinja2.Environment._load_template(self, name, globals)
            if ctx is not None:
                filename = rv.filename
                if PY2 and is_windows:
                    try:
                        filename = filename.decode('utf-8')
                    except UnicodeDecodeError:
                        pass
                ctx.record_dependency(filename)
            return rv
        except jinja2.TemplateSyntaxError as e:
            if ctx is not None:
                ctx.record_dependency(e.filename)
            raise
        except jinja2.TemplateNotFound as e:
            if ctx is not None:
                # If we can't find the template we want to record at what
                # possible locations the template could exist.  This will help
                # out watcher to pick up templates that will appear in the
                # future.  This assumes the loader is a file system loader.
                for template_name in e.templates:
                    pieces = split_template_path(template_name)
                    for base in self.loader.searchpath:
                        ctx.record_dependency(os.path.join(base, *pieces))
            raise
Exemplo n.º 38
0
def drender(match, record):
    content = match.group('content')
    align = ''
    other = ''
    items = content.split(',')
    words = items[0].split(' ')
    name = words[0]
    if len(words) > 1:
        align = words[1].strip()
    if len(items) > 1:
        other = items[1].strip()

    # sort out the align
    style = ''
    if align in ('left', 'right'):
        style = 'float: %s;' % align
    elif align == 'top':
        style = 'vertial-align: top;'
    elif align == 'middle':
        style = 'vertical-align: middle;'  # this is not exactly right, but is the best there is
    elif align == 'bottom':
        style = 'vertical-align: initial;'

    # sort out the other
    params = ''
    if '=' in other:
        params = other
    elif ':' in other:
        style += ' %s' % other

    # put it all together
    if style.strip() != '':
        params = ('style="%s" %s' % (style.strip(), params.strip())).strip()

    # sort out the href
    if '.' not in name:
        name = '%s.gif' % name
    href = '/Diagrams/%s' % name

    # get the alt text
    try:
        pad = get_ctx().pad
        diagram = pad.get(href)
        alttext = diagram['alttext']
        alttext = html.escape(alttext, quote=True)
    except:
        print('Error getting alt text for diagram "%s"' % href)
        traceback.print_exc()
        alttext = False

    if alttext:
        alttag = ' alt="%s"' % alttext
    else:
        alttag = ''

    if params != '':
        return '<img class="diagram"%s src="%s" %s />' % (alttag, href, params)
    else:
        return '<img class="diagram"%s src="%s" />' % (alttag, href)
Exemplo n.º 39
0
 def get_lektor_config(self):
     """Returns the global config."""
     ctx = get_ctx()
     if ctx is not None:
         cfg = ctx.pad.db.config
     else:
         cfg = self.env.load_config()
     return cfg
 def get_pygments_stylesheet(artifact_name='/static/pygments.css'):
     ctx = get_ctx()
     @ctx.sub_artifact(artifact_name=artifact_name, sources=[
         self.config_filename])
     def build_stylesheet(artifact):
         with artifact.open('w') as f:
             f.write(self.get_formatter().get_style_defs())
     return artifact_name
Exemplo n.º 41
0
 def __init__(self, image, config=None, ctx=None):
     if config is None:
         config = self.DEFAULT_CONFIG.copy()
     if ctx is None:
         ctx = get_ctx()
     self.config = config
     self.image = image
     self.ctx = ctx
Exemplo n.º 42
0
 def get_lektor_config(self):
     """Returns the global config."""
     ctx = get_ctx()
     if ctx is not None:
         cfg = ctx.pad.db.config
     else:
         cfg = self.env.load_config()
     return cfg
def pythonmarkdown_to_html(text, record=None):
    """
    Convert python-markdown into html.
    """
    ctx = get_ctx()
    if ctx is None:
        raise RuntimeError('Context is required for python-markdown rendering')
    
    env = get_ctx().env
    plugin = env.plugins.get('pythonmarkdown', None)
    if not plugin:
        raise RuntimeError('PythonMarkdownPLugin is required for python-markdown rendering')    
    cfg = PythonMarkdownConfig(plugin.get_config())
    # TODO May need to emit event to let other plugin hook into this one.
    try:
        return markdown.markdown(text, **cfg.options)
    except:
        return "pythonmarkdown error: " + traceback.format_exc()
Exemplo n.º 44
0
Arquivo: db.py Projeto: jab/lektor
def _require_ctx(record):
    ctx = get_ctx()
    if ctx is None:
        raise RuntimeError('This operation requires a context but none was '
                           'on the stack.')
    if ctx.pad is not record.pad:
        raise RuntimeError('The context on the stack does not match the '
                           'pad of the record.')
    return ctx
Exemplo n.º 45
0
def _require_ctx(record):
    ctx = get_ctx()
    if ctx is None:
        raise RuntimeError('This operation requires a context but none was '
                           'on the stack.')
    if ctx.pad is not record.pad:
        raise RuntimeError('The context on the stack does not match the '
                           'pad of the record.')
    return ctx
Exemplo n.º 46
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        blog = feed_source.parent

        summary = get(blog, feed_source.blog_summary_field) or ''
        subtitle_type = ('html' if hasattr(summary, '__html__') else 'text')
        blog_author = unicode(get(blog, feed_source.blog_author_field) or '')
        generator = ('Lektor Atom Plugin',
                     'https://github.com/ajdavis/lektor-atom',
                     pkg_resources.get_distribution('lektor-atom').version)

        project_id = ctx.env.load_config().base_url
        if not project_id:
            project_id = ctx.env.project.id
        feed = AtomFeed(
            title=feed_source.feed_name,
            subtitle=unicode(summary),
            subtitle_type=subtitle_type,
            author=blog_author,
            feed_url=url_to(feed_source, external=True),
            url=url_to(blog, external=True),
            id=get_id(project_id),
            generator=generator)

        if feed_source.items:
            # "feed_source.items" is a string like "site.query('/blog')".
            expr = Expression(ctx.env, feed_source.items)
            items = expr.evaluate(ctx.pad)
        else:
            items = blog.children

        if feed_source.item_model:
            items = items.filter(F._model == feed_source.item_model)

        order_by = '-' + feed_source.item_date_field
        items = items.order_by(order_by).limit(int(feed_source.limit))

        for item in items:
            item_author_field = feed_source.item_author_field
            item_author = get(item, item_author_field) or blog_author

            feed.add(
                get_item_title(item, feed_source.item_title_field),
                get_item_body(item, feed_source.item_body_field),
                xml_base=url_to(item, external=True),
                url=url_to(item, external=True),
                content_type='html',
                id=get_id(u'%s/%s' % (
                    project_id,
                    item['_path'].encode('utf-8'))),
                author=item_author,
                updated=get_item_updated(item, feed_source.item_date_field))

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8'))
Exemplo n.º 47
0
 def init_translator(self):
     ctx = get_ctx()
     if not ctx:
         self.translator = gettext.GNUTranslations()
         return super().__init__()
     if not self.__lastlang == ctx.locale:
         self.__lastlang = ctx.locale
         self.translator = gettext.translation("contents",
                 join(self.i18npath, '_compiled'),
                 languages=[ctx.locale], fallback=True)
Exemplo n.º 48
0
 def track_record_dependency(self, record):
     ctx = get_ctx()
     if ctx is not None:
         for filename in record.iter_source_filenames():
             ctx.record_dependency(filename)
         if record.datamodel.filename:
             ctx.record_dependency(record.datamodel.filename)
             for dep_model in self.iter_dependent_models(record.datamodel):
                 if dep_model.filename:
                     ctx.record_dependency(dep_model.filename)
     return record
Exemplo n.º 49
0
 def link(self, link, title, text):
     if self.record is not None:
         url = url_parse(link)
         if not url.scheme:
             link = self.record.url_to('!' + link,
                                       base_url=get_ctx().base_url)
     link = escape(link)
     if not title:
         return '<a href="%s">%s</a>' % (link, text)
     title = escape(title)
     return '<a href="%s" title="%s">%s</a>' % (link, title, text)
Exemplo n.º 50
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        source = self.source

        appcast = AppCast(
            title=source.cast_name,
            link=url_to(source, external=True),
        )

        try:
            expr = Expression(ctx.env, source.items)
        except AttributeError:
            items = source.parent.children
        else:
            items = expr.evaluate(ctx.pad)

        if source.item_model:
            items = items.filter(F._model == source.item_model)
        items = items.order_by('-build_number')

        for item in items:
            with ctx.changed_base_url(item.url_path):
                description = six.text_type(markupsafe.escape(item['note']))

            try:
                offset = int(source.timezone)
            except ValueError:
                tzinfo = pytz.timezone(source.timezone)
            else:
                tzinfo = pytz.FixedOffset(offset)
            pub_date = item['pub_datetime'].replace(tzinfo=tzinfo)

            try:
                build_number = str(item['build_number'])
                if '.' in build_number:
                    build_number = build_number.rstrip('0').rstrip('.')
                appcast.add(
                    title='Version {}'.format(item['version']),
                    description=description,
                    pub_date=pub_date,
                    url=item['download_url'],
                    build=build_number,
                    version=item['version'],
                    length=item['length'],
                    dsasign=item['dsa_signature'],
                    minsysver=item['min_sysver'],
                )
            except Exception as e:
                msg = '{}: {}'.format(item.id, e)
                click.echo(click.style('E', fg='red') + ' ' + msg)

        with artifact.open('wb') as f:
            f.write(appcast.to_string().encode('utf-8'))
Exemplo n.º 51
0
 def image(self, src, title, text):
     if self.record is not None:
         url = url_parse(src)
         if not url.scheme:
             src = self.record.url_to('!' + src,
                                      base_url=get_ctx().base_url)
     src = escape(src)
     text = escape(text)
     if title:
         title = escape(title)
         return '<img src="%s" alt="%s" title="%s">' % (src, text, title)
     return '<img src="%s" alt="%s">' % (src, text)
Exemplo n.º 52
0
def get_plugin(plugin_id_or_class, env=None):
    """Looks up the plugin instance by id or class."""
    if env is None:
        ctx = get_ctx()
        if ctx is None:
            raise RuntimeError('Context is unavailable and no enviroment '
                               'was passed to the function.')
        env = ctx.env
    plugin_id = env.plugin_ids_by_class.get(plugin_id_or_class,
                                            plugin_id_or_class)
    try:
        return env.plugins[plugin_id]
    except KeyError:
        raise LookupError('Plugin %r not found' % plugin_id)
Exemplo n.º 53
0
    def __getitem__(self, name):
        # If any data of a flowblock is accessed, we record that we need
        # this dependency.
        ctx = get_ctx()
        if ctx is not None:
            ctx.record_dependency(self.flowblockmodel.filename)

        rv = self._bound_data.get(name, Ellipsis)
        if rv is not Ellipsis:
            return rv
        rv = self._data[name]
        if hasattr(rv, '__get__'):
            rv = rv.__get__(self.record)
            self._bound_data[name] = rv
        return rv
Exemplo n.º 54
0
 def get_config(self, fresh=False):
     """Returns the config specific for this plugin.  By default this
     will be cached for the current build context but this can be
     disabled by passing ``fresh=True``.
     """
     ctx = get_ctx()
     if ctx is not None and not fresh:
         cache = ctx.cache.setdefault(__name__ + ':configs', {})
         cfg = cache.get(self.id)
         if cfg is None:
             cfg = IniFile(self.config_filename)
             cache[self.id] = cfg
     else:
         cfg = IniFile(self.config_filename)
     return cfg
Exemplo n.º 55
0
    def icon_path(self, license):
        icon_target_path = (
            '/static/lektor-creative-commons/{type}/{version}/{size}.png'
        ).format(**license)
        icon_source_path = os.path.join(
            os.path.dirname(__file__), 'assets', license['type'],
            license['version'], license['size'] + '.png'
        )
        ctx = get_ctx()

        @ctx.sub_artifact(
            icon_target_path,
            sources=[ctx.source.source_filename],
            source_obj=icon_source_path
        )
        def copy_icon(artifact):
            artifact.replace_with_file(artifact.source_obj, copy=True)

        return icon_target_path
Exemplo n.º 56
0
def markdown_to_html(text):
    ctx = get_ctx()
    if ctx is None:
        raise RuntimeError("Context is required for markdown rendering")

    # These markdown parsers are all terrible.  Not one of them does not
    # modify internal state.  So since we only do one of those per thread
    # we can at least cache them on a thread local.
    md = getattr(_markdown_cache, "md", None)
    if md is None:
        md = make_markdown(ctx.env)
        _markdown_cache.md = md

    meta = {}
    ctx.env.plugin_controller.emit("markdown-meta-init", meta=meta)
    md.renderer.meta = meta
    rv = md(text)
    ctx.env.plugin_controller.emit("markdown-meta-postprocess", meta=meta)
    return rv, meta
Exemplo n.º 57
0
    def image(self, src, title, text):
        if self.record is not None:
            url = url_parse(src)
            if not url.scheme:
                context = get_ctx()

                attachment = self.record.attachments.get(src)

                # image is attached to the current record
                if context.base_url == self.record.url_path and attachment:
                    # this handle situations where the last path contains
                    # a "." and therefor will be build in a image instead of
                    # a directory and the path to the image will be
                    # _last_path.something/image.jpg instead of
                    # last_path/image.jpg
                    src = self.record.url_to(attachment.url_path)

                else:
                    src = self.record.url_to('!' + src,
                                             base_url=context.base_url)
        return mistune.Renderer.image(self, src, title, text)
Exemplo n.º 58
0
    def get_bag(self, name):
        sources = self._known_bags.get(name)
        if not sources:
            return None
        rv = self._bags.get(name)
        if rv is None:
            filenames = []
            rv = OrderedDict()
            for filename in sources:
                filename = os.path.join(self.root_path, filename)
                rv = merge(rv, load_databag(filename))
                filenames.append(filename)
            self._bags[name] = (rv, filenames)
        else:
            rv, filenames = rv

        ctx = get_ctx()
        if ctx is not None:
            for filename in filenames:
                ctx.record_dependency(filename)

        return rv
Exemplo n.º 59
0
Arquivo: flow.py Projeto: jab/lektor
def find_record_for_flowblock(blck):
    """The record that contains this flow block.  This might be unavailable
    in certain situations, it is however very useful when using the generic
    block template rendering.
    """
    ctx = get_ctx()
    if ctx is None:
        raise RuntimeError('Context unavailable')
    record = ctx.record
    if record is None:
        raise RuntimeError('Context does not point to a record')

    # It's only the correct record, if we are contained as a field in it.
    # This could be improved by making a better mapping for this on the
    # datamodel probably but it's good enough for the moment.
    for key, value in record.iter_fields():
        if isinstance(value, Flow):
            for other_blck in value.blocks:
                if other_blck is blck:
                    return record

    return Undefined('Associated record unavailable.', name='record')