Esempio n. 1
0
    def test_with_meta(self):
        output = """
<p><a class="wiki-lnk" href="/local/wikilink">Wikilink</a>    <code>[[wikilink]]</code></p>
<p><a class="wiki-lnk" href="/local/path/to/file_name">File name</a></p>
<p><a class="wiki-lnk" href="/local/path/to/file_name">File name</a></p>
<p><a class="wiki-lnk" href="/local/path/to/file-name">File name</a></p>
<p><a class="wiki-lnk" href="/local/path/to/file_name/?a=b&amp;b=c">File name</a></p>
<p><a class="wiki-lnk" href="/local/path/to/file_name.html">File name</a></p>
<p><a class="wiki-lnk" href="/local/path/to/file_name.html?a=b&amp;b=c">File name</a></p>
<p><a class="wiki-lnk" href="https://www.example.com/">www.example.com</a></p>
<p><a class="wiki-lnk" href="https://www.example.com/?a=b&amp;b=c">www.example.com</a></p>
<p><a class="wiki-lnk" href="https://www.example.com/example-tutorial">Example tutorial</a></p>
<p><a class="wiki-lnk" href="https://www.example.com/example-tutorial">Example Tutorial</a></p>
<p><img class="wiki-img" src="/local/wikilink.png" /></p>
<p><img class="wiki-img" src="/local/path/to/file_name.jpg?a=b&amp;b=c" /></p>
<p><img class="wiki-img" src="https://example.jpeg?a=b&amp;b=c" /></p>
<p><img class="wiki-img" src="https://www.example.com/example-tutorial.jpeg" /></p>
<p><img class="wiki-img" src="https://example.com/example-tutorial.gif" /></p>
<p><img alt="better example" class="wiki-img" src="/local/example_tutorial.jpg" /></p>
        """.strip()
        md2 = markdown.Markdown(
            extensions=[WikiLinkPlusExtension(),
                        MetaExtension()])
        html = md2.convert(meta_text + "\n\n" + text)
        # ~ print(html)
        self.assertEqual(html, output)
Esempio n. 2
0
class PostProcessor(object):

    _markdown_extensions = [MathJaxExtension(), MetaExtension()]

    @staticmethod
    def create_slug(title):
        return "-".join([t.lower() for t in title.split()])

    @classmethod
    def construct_url(cls, post):
        url = url_for("blogging.page_by_id",
                      post_id=post["post_id"],
                      slug=cls.create_slug(post["title"]))
        return url

    @classmethod
    def render_text(cls, post):
        md = markdown.Markdown(extensions=cls.all_extensions())
        post["rendered_text"] = md.convert(post["text"])
        post["meta"] = md.Meta

    @classmethod
    def process(cls, post, render=True):
        """
        This method takes the post data and renders it
        :param post:
        :param render:
        :return:
        """
        post["slug"] = cls.create_slug(post["title"])
        post["editable"] = current_user.get_id() == post["user_id"]
        post["url"] = cls.construct_url(post)
        if render:
            cls.render_text(post)
        cls.custom_process(post)
        return

    @classmethod
    def custom_process(cls, post):
        """
        Override this method to add additional processes. The result is that
        the ``post`` dict is modified or enhanced with newer key value pairs.

        :param post: The post data with values for keys such as title, text,
         tags etc.
        :type post: dict
        """
        pass

    @classmethod
    def all_extensions(cls):
        return cls._markdown_extensions

    @classmethod
    def set_custom_extensions(cls, extensions):
        assert type(extensions) == list
        cls._markdown_extensions.append(cls._custom_extensions)
Esempio n. 3
0
 def render(self, gs):
     md = Markdown(extensions=[
         MetaExtension(),
         TableExtension(),
         WikiLinkExtension(),
         CMS7Extension(gs, baselevel=2),
         TocExtension()
     ],
                   output_format='html5')
     return Markup(md.convert(self.text))
Esempio n. 4
0
 def render(self, gs, *, baselevel=2, hyphenate=False, paragraphs=None):
     md = Markdown(extensions=[
             MetaExtension(),
             TableExtension(),
             WikiLinkExtension(),
             CMS7Extension(gs, path=self.source, baselevel=baselevel, hyphenate=hyphenate, paragraphs=paragraphs),
             TocExtension(anchorlink=True)
         ],
         output_format='html5')
     return Markup(md.convert(self.text))
Esempio n. 5
0
class PostProcessor(object):

    _markdown_extensions = [MathJaxExtension(), MetaExtension()]

    @staticmethod
    def create_slug(title):
        return slugify(title)

    @classmethod
    def construct_url(cls, post):
        url = url_for("blogging.page_by_id",
                      post_id=post["post_id"],
                      slug=cls.create_slug(post["title"]))
        return url

    @classmethod
    def render_text(cls, post):
        md = markdown.Markdown(extensions=cls.all_extensions())
        post["rendered_text"] = md.convert(post["text"])
        post["meta"] = md.Meta

    @classmethod
    def is_author(cls, post, user):
        return user.get_id() == '' + str(post['user_id'])

    @classmethod
    def process(cls, post, render=True):
        """
        This method takes the post data and renders it
        :param post:
        :param render:
        :return:
        """
        post["slug"] = cls.create_slug(post["title"])
        post["editable"] = cls.is_author(post, current_user)
        post["url"] = cls.construct_url(post)
        post["priority"] = 0.8
        if render:
            cls.render_text(post)

    @classmethod
    def all_extensions(cls):
        return cls._markdown_extensions

    @classmethod
    def set_custom_extensions(cls, extensions):
        if type(extensions) == list:
            cls._markdown_extensions.extend(extensions)
Esempio n. 6
0
    def test_with_meta(self):
        output = """
<p><a class="wikilink" href="/static/wikilink">Wikilink</a>    <code>[[wikilink]]</code></p>
<p><a class="wikilink" href="/static/wikilink">Wikilink</a>    <code>[[Wikilink]]</code></p>
<p><a class="wikilink" href="/static/path/to/file_name">File name</a></p>
<p><a class="wikilink" href="/static/path/to/file_name">File name</a></p>
<p><a class="wikilink" href="/static/path/to/file-name">File name</a></p>
<p><a class="wikilink" href="/static/path/to/file_name/?a=b&amp;b=c">File name</a></p>
<p><a class="wikilink" href="/static/path/to/file_name.html">File name</a></p>
<p><a class="wikilink" href="/static/path/to/file_name.html?a=b&amp;b=c">File name</a></p>
<p><a class="wikilink" href="https://www.example.com/">www.example.com</a></p>
<p><a class="wikilink" href="https://www.example.com/?a=b&amp;b=c">www.example.com</a></p>
<p><a class="wikilink" href="https://www.example.com/example-tutorial">Example tutorial</a></p>
<p><a class="wikilink" href="https://www.example.com/example-tutorial">Example Tutorial</a></p>
        """.strip()
        md2 = markdown.Markdown(
            extensions=[WikiLinkPlusExtension(),
                        MetaExtension()])
        html = md2.convert(meta_text + "\n\n" + text)
        # ~ print(html)
        self.assertEqual(html, output)
Esempio n. 7
0

checkclock = ReadOnlyCheckclock(
    Path("~/.config/qtile/checkclock.sqlite").expanduser(), working_days="Mon-Fri"
)


ordinal_pattern = re.compile(r"\b([0-9]{1,2})(st|nd|rd|th)\b")
md = markdown.Markdown(
    output_format="html5",
    extensions=[
        FencedCodeExtension(),
        CodeHiliteExtension(css_class="highlight", guess_lang=False),
        DefListExtension(),
        FootnoteExtension(),
        MetaExtension(),
        Nl2BrExtension(),
        SaneListExtension(),
        TocExtension(),
        StrikethroughExtension(),
        TableExtension(),
        AttrListExtension(),
    ],
)

DOWNLOAD_EXTENSIONS = [".ods", ".odt"]
LEXER_MAP = {"pgsql": "sql"}

THEME_MODE_KEY = "theme-mode"
DEFAULT_THEME_MODE = "light"
SERVER_ROOT = Path(os.path.abspath(os.path.dirname(__file__)))
Esempio n. 8
0
    def handleMatch(self, m):
        node = markdown.util.etree.Element('mathjax')
        node.text = markdown.util.AtomicString(
            m.group(2) + m.group(3) + m.group(2))
        return node


class MathJaxExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        # Needs to come before escape matching because \ is pretty important
        # in LaTeX
        md.inlinePatterns.add('mathjax', MathJaxPattern(), '<escape')


_markdown_extensions = [MathJaxExtension(), MetaExtension()]


def get_locale():
    if 'locale' in session:
        if session['locale'] is not None:
            return session['locale']

    return 'en'


def set_locale():
    sqlalchemy_utils.i18n.get_locale = get_locale


# Get page by id
from flask import redirect, render_template, send_from_directory, url_for

from flask_login import UserMixin, LoginManager, login_user, logout_user
from flask_blogging import BloggingEngine
from flask_blogging.dynamodbstorage import DynamoDBStorage
from flask_fileupload.storage.s3storage import S3Storage
from flask_fileupload import FlaskFileUpload

from markdown.extensions.attr_list import AttrListExtension
from markdown.extensions.extra import ExtraExtension
from markdown.extensions.meta import MetaExtension


extn1 = AttrListExtension()
extn3 = ExtraExtension()
extn4 = MetaExtension()

app = Flask(__name__)

app.config["SECRET_KEY"] = "secret"  # for WTF-forms and login
app.config["BLOGGING_URL_PREFIX"] = "/blog"
# app.config["BLOGGING_DISQUS_SITENAME"] = "test"
app.config["BLOGGING_SITEURL"] = "http://localhost:8000"
app.config["BLOGGING_SITENAME"] = "Jeremy Clewell"
# app.config["BLOGGING_TWITTER_USERNAME"] = "******"
app.config["FILEUPLOAD_S3_BUCKET"]='jeremyclewell-site'
app.config["FILEUPLOAD_PREFIX"] = "/upload"
app.config["FILEUPLOAD_ALLOWED_EXTENSIONS"] = ["png", "jpg", "jpeg", "gif"]
app.config["BLOGGING_ESCAPE_MARKDOWN"] = False
app.config["BLOGGING_GOOGLE_ANALYTICS"] = "UA-15169356-1"
Esempio n. 10
0
    def _build(self, out="", views=None, user_settings_file=""):

        out = out or self.environment_dist
        if os.path.abspath(self.environment_src) in os.path.abspath(out):
            raise OSError("Cannot build site in source directory")

        if not os.path.exists(self.environment_src):
            raise OSError("Cannot find source directory")

        views = views or self.views

        if os.path.exists(out):
            if views == self.views:
                shutil.rmtree(out)
                os.mkdir(out)
        else:
            os.mkdir(out)

        if user_settings_file:
            self.load_user_settings(user_settings_file)
            self.load_db()

        md = markdown.Markdown(
            extensions=[MetaExtension()] +
            self.settings["pages"]["extensions"],
            extension_configs=self.settings["pages"]["extension_options"])

        #copy assets (skip if this is not the top level of the recursive build)
        if views == self.views:
            try:
                assets_folder = os.path.join(
                    self.environment_src,
                    self.settings["environment"]["assets"])
                for f in os.listdir(assets_folder):
                    if os.path.isdir(os.path.join(assets_folder, f)):
                        shutil.copytree(os.path.join(assets_folder, f),
                                        os.path.join(out, f))
                    else:
                        shutil.copy(os.path.join(assets_folder, f), out)
            except OSError:
                print("Could not copy assets")

            #reset g
            self.g = {}

        tmp_fname = os.path.join(self.environment_src, "templates",
                                 "_tmp.html")

        #create the html pages
        for view in views:

            #if there are subviews, we should build those instead
            if view.get("subviews"):
                new_out = os.path.join(out, view["route"])
                self._build(out=new_out, views=view["subviews"])
                continue

            #else, build the page for this view

            # create context dict
            context = dict(
                [(k, globals()["__builtins__"][k])
                 for k in self.settings["templates"]["builtins"]],
                full_route=view["full_route"],
                route=view["route"],
            )
            context.update(**view.get("context", {}))

            # query the database
            context["query"] = self.query_db(view.get("query"))

            #determine the markdown pages to use for this view

            page_fnames = view.get("pages")
            if page_fnames == None:
                page_fnames = [
                    "".join(view["full_route"].lstrip("/").split(".")[:-1]) +
                    ".md"
                ]
            if page_fnames:
                page_fnames = [
                    os.path.join(self.environment_src,
                                 self.settings["environment"]["pages"], fname)
                    for fname in _collection(page_fnames)
                ]
            else:
                page_fnames = []

            #load the context processor
            #syntax: "module.submodule:callable"
            context_processor_name = view.get("context_processor")
            if context_processor_name:
                try:
                    # module_name, variable_name = context_processor_name.split(":")
                    module, context_processor = _eval_module_and_object(
                        context_processor_name)
                except ValueError:
                    raise ValueError(
                        "incorrect syntax for 'context_processor'")

            else:
                context_processor = None

            with codecs.open(os.path.join(out, view["route"]),
                             mode="w",
                             encoding="utf-8") as out_file:
                try:
                    blocks = BlockTable(view["template"])
                    blocks_as_context_vars = {}

                    for page_fname in page_fnames:
                        # with open(page_fname, "r") as page_file:
                        with codecs.open(page_fname,
                                         mode="r",
                                         encoding="utf-8") as page_file:
                            html = md.convert(six.text_type(page_file.read()))
                            html = html.replace("%", "&#37;").replace(
                                "{", "&#123;").replace("}", "&#125;")
                            meta = {}
                            special = {"__store_as__": "block"}

                            for k, v in getattr(md, "Meta", {}).items():
                                # double-underscore vars are special vars used by gansa
                                if k in ("__block__", "__store_as__"):
                                    d = special
                                else:
                                    d = meta

                                # v will always be a list, which is probably not what users want
                                # if only one item is specified
                                if len(v) == 1:
                                    d[k] = v[0]
                                else:
                                    d[k] = v

                            context.update(meta)

                            block_name = special.get(
                                "__block__",
                                self.settings["templates"]["default_block"])
                            if special["__store_as__"] == "var":
                                blocks_as_context_vars[block_name] =\
                                 blocks_as_context_vars.get(block_name, "") + html
                            elif special["__store_as__"] == "block":
                                blocks.add(block_name, html)

                    context.update(blocks_as_context_vars)

                    with codecs.open(tmp_fname, mode="w",
                                     encoding="utf-8") as tmp:
                        tmp.write(blocks.to_template())

                    template = self.templates.get_template("_tmp.html")
                # if no markdown page was found, just write context variables to the template
                except OSError:
                    template = self.templates.get_template(view["template"])

                if context_processor:
                    new_context = context_processor(context, dict(view), self)
                    if new_context != None:
                        context = new_context

                try:
                    stream = template.render(**context)
                except TypeError:
                    raise TypeError(
                        "context processor must return dict or other mapping")

                out_file.write(stream)
        if views == self.views:
            try:
                os.remove(tmp_fname)
            except OSError:
                pass

        if views == self.views and self.settings["callbacks"].get(
                "postrender"):
            try:
                _, callback = _eval_module_and_object(
                    self.settings["callbacks"]["postrender"])
            except ValueError:
                raise ValueError("incorrect syntax for 'postrender'")
            callback(self, {"views": views, "out": out})
Esempio n. 11
0
class Wiki:
    DEFAULT_MD_EXTENSIONS = [
        FootnoteExtension(),
        TocExtension(),
        TableExtension(),
        MetaExtension(),
        AutoTitleExtension(),
        HintedWikiLinkExtension(),
        SizeEnabledImageExtension()
    ]

    @staticmethod
    def link_to(page):
        return getattr(page, 'link_to', None) or '/page/' + page

    def __init__(self, md_extensions=[...]):
        if md_extensions[-1] is ...:
            md_extensions = md_extensions[:-1] + self.DEFAULT_MD_EXTENSIONS
        self.md = markdown.Markdown(extensions=md_extensions)

        self.title = 'UNSET TITLE'
        self.logo = '/static/logo.png'
        self.root_dir_path = None
        self.rsc_dir_path = None

        self.titles: Dict[str, Page] = {}  # page keys are always in lowercase
        self.tags: Dict[str, List[Page]] = defaultdict(list)  # tag names are always lowercase
        self.unique_pages: List[Page] = []

    def set_root_path(self, path: Path):
        self.root_dir_path = path
        self.rsc_dir_path = path / 'rsc'

    def scan_path(self, clear=False):
        if clear:
            self.clear_pages()

        conf_path = self.root_dir_path / 'config.py'
        if conf_path.is_file():
            exec(conf_path.read_text(), {'wiki': self})

        for page_path in self.root_dir_path.glob('[!_]*.md'):
            try:
                with page_path.open() as r:
                    page = Page(r.read(), self)
            except PageLoadError as e:
                raise PageLoadError('error loading page ' + str(page_path)) from e
            self.add_page(page)

    def clear_pages(self):
        self.titles.clear()
        self.tags.clear()
        self.unique_pages.clear()

    def add_page(self, page: Page):
        for title in page.titles:
            p = self.titles.setdefault(title.lower(), page)
            if p is not page:
                raise Exception('multiple pages sharing a title ' + title)
        for t in page.tags:
            self.tags[t].append(page)
        self.unique_pages.append(page)

    def match(self, main, hints):
        main_terms = split_terms(main)
        hint_terms = split_terms(hints)
        for p in self.unique_pages:
            s = p.score(main_terms, hint_terms)
            yield p, s

    def best_match(self, main, hints)->MaxStore:
        store = MaxStore()
        main_terms = split_terms(main)
        hint_terms = split_terms(hints)
        for p in self.unique_pages:
            s = p.score(main_terms, hint_terms, cutoff=store.cutoff)
            store.add(p, s)
        return store

    def __getitem__(self, name):
        name = name.lower()
        return self.titles.get(name), self.tags.get(name)

    def __contains__(self, item):
        return (item in self.titles) or (item in self.tags)

    @classmethod
    def from_dir(cls, dir_path):
        ret = cls()
        dir_path = Path(dir_path).absolute()
        if not dir_path.is_dir():
            raise ValueError('path id not a directory')
        ret.set_root_path(dir_path)
        ret.scan_path()
        return ret