Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
427 lines (322 sloc) 15.4 KB
#
# This file is part of m.css.
#
# Copyright © 2017, 2018 Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
from docutils.parsers import rst
from docutils.parsers.rst import directives
from docutils.parsers.rst.roles import set_classes
from docutils import nodes
class Transition(rst.Directive):
final_argument_whitespace = True
has_content = False
required_arguments = 1
def run(self):
text = ' '.join(self.arguments)
title_nodes, _ = self.state.inline_text(text, self.lineno)
transition_node = nodes.paragraph('', '', *title_nodes)
transition_node['classes'] += ['m-transition']
return [transition_node]
class Note(rst.Directive):
final_argument_whitespace = True
has_content = True
optional_arguments = 1
option_spec = {'class': directives.class_option}
style_class = ''
def run(self):
set_classes(self.options)
if len(self.arguments) == 1:
title_text = self.arguments[0]
title_nodes, _ = self.state.inline_text(title_text, self.lineno)
title_node = nodes.title('', '', *title_nodes)
text = '\n'.join(self.content)
topic_node = nodes.topic(text, **self.options)
topic_node['classes'] += ['m-note', self.style_class]
if len(self.arguments) == 1:
topic_node.append(title_node)
self.state.nested_parse(self.content, self.content_offset,
topic_node)
return [topic_node]
class DefaultNote(Note):
style_class = 'm-default'
class PrimaryNote(Note):
style_class = 'm-primary'
class SuccessNote(Note):
style_class = 'm-success'
class WarningNote(Note):
style_class = 'm-warning'
class DangerNote(Note):
style_class = 'm-danger'
class InfoNote(Note):
style_class = 'm-info'
class DimNote(Note):
style_class = 'm-dim'
class Block(rst.Directive):
final_argument_whitespace = True
has_content = True
required_arguments = 1
option_spec = {'class': directives.class_option}
style_class = ''
def run(self):
set_classes(self.options)
title_text = self.arguments[0]
title_elements, _ = self.state.inline_text(title_text, self.lineno)
title_node = nodes.title('', '', *title_elements)
text = '\n'.join(self.content)
topic_node = nodes.topic(text, **self.options)
topic_node['classes'] += ['m-block', self.style_class]
topic_node.append(title_node)
self.state.nested_parse(self.content, self.content_offset,
topic_node)
return [topic_node]
class DefaultBlock(Block):
style_class = 'm-default'
class PrimaryBlock(Block):
style_class = 'm-primary'
class SuccessBlock(Block):
style_class = 'm-success'
class WarningBlock(Block):
style_class = 'm-warning'
class DangerBlock(Block):
style_class = 'm-danger'
class InfoBlock(Block):
style_class = 'm-info'
class DimBlock(Block):
style_class = 'm-dim'
class FlatBlock(Block):
style_class = 'm-flat'
class Frame(rst.Directive):
final_argument_whitespace = True
has_content = True
optional_arguments = 1
option_spec = {'class': directives.class_option}
style_class = ''
def run(self):
set_classes(self.options)
if len(self.arguments) == 1:
title_text = self.arguments[0]
title_nodes, _ = self.state.inline_text(title_text, self.lineno)
title_node = nodes.title('', '', *title_nodes)
text = '\n'.join(self.content)
topic_node = nodes.topic(text, **self.options)
topic_node['classes'] += ['m-frame', self.style_class]
if len(self.arguments) == 1:
topic_node.append(title_node)
self.state.nested_parse(self.content, self.content_offset,
topic_node)
return [topic_node]
class _Figure(rst.Directive):
final_argument_whitespace = True
has_content = True
optional_arguments = 1
option_spec = {'class': directives.class_option}
style_classes = []
def run(self):
set_classes(self.options)
text = '\n'.join(self.content)
figure_node = nodes.figure(text, **self.options)
figure_node['classes'] += self.style_classes
self.state.nested_parse(self.content, self.content_offset,
figure_node)
# Insert the title node, if any, right after the code / math / graph.
# There could be things like the class directive before, so be sure to
# find the right node.
if len(self.arguments) == 1:
title_text = self.arguments[0]
title_nodes, _ = self.state.inline_text(title_text, self.lineno)
title_node = nodes.caption('', '', *title_nodes)
for i, child in enumerate(figure_node):
if isinstance(child, nodes.raw) or isinstance(child, nodes.literal_block):
figure_node.insert(i + 1, title_node)
break
else: assert False # pragma: no cover
return [figure_node]
class CodeFigure(_Figure):
style_classes = ['m-code-figure']
class ConsoleFigure(CodeFigure):
style_classes = ['m-console-figure']
class MathFigure(_Figure):
style_classes = ['m-figure']
class GraphFigure(_Figure):
style_classes = ['m-figure']
class Text(rst.Directive):
has_content = True
option_spec = {'class': directives.class_option}
style_class = ''
def run(self):
set_classes(self.options)
text = '\n'.join(self.content)
container_node = nodes.container(text, **self.options)
container_node['classes'] += ['m-text', self.style_class]
self.state.nested_parse(self.content, self.content_offset,
container_node)
return [container_node]
class DefaultText(Text):
style_class = 'm-default'
class PrimaryText(Text):
style_class = 'm-primary'
class SuccessText(Text):
style_class = 'm-success'
class WarningText(Text):
style_class = 'm-warning'
class DangerText(Text):
style_class = 'm-danger'
class InfoText(Text):
style_class = 'm-info'
class DimText(Text):
style_class = 'm-dim'
class Button(rst.Directive):
has_content = True
final_argument_whitespace = True
required_arguments = 1
option_spec = {'class': directives.class_option}
style_class = ''
def run(self):
set_classes(self.options)
text = '\n'.join(self.content)
ref_node = nodes.reference(text, '', refuri=self.arguments[0])
if self.content:
node = nodes.Element() # anonymous container for parsing
self.state.nested_parse(self.content, self.content_offset, node)
first_node = node[0]
if not isinstance(first_node, nodes.paragraph):
error = self.state_machine.reporter.error(
'Button must contain directly a caption and optional description',
nodes.literal_block(self.block_text, self.block_text),
line=self.lineno)
return [ref_node, error]
if len(node) == 1:
caption = nodes.inline(first_node.rawsource, '',
*first_node.children)
else:
caption = nodes.container(first_node.rawsource,
*first_node.children)
caption['classes'] += ['m-big']
caption.source = first_node.source
caption.line = first_node.line
ref_node += caption
if len(node) > 1:
second_node = node[1]
description = nodes.container(second_node.rawsource,
*second_node.children)
description['classes'] += ['m-small']
ref_node += description
wrapper_node = nodes.container(**self.options)
wrapper_node['classes'] += ['m-button', self.style_class]
wrapper_node += ref_node
return [wrapper_node]
class DefaultButton(Button):
style_class = 'm-default'
class PrimaryButton(Button):
style_class = 'm-primary'
class SuccessButton(Button):
style_class = 'm-success'
class WarningButton(Button):
style_class = 'm-warning'
class DangerButton(Button):
style_class = 'm-danger'
class InfoButton(Button):
style_class = 'm-info'
class DimButton(Button):
style_class = 'm-dim'
class FlatButton(Button):
style_class = 'm-flat'
def label(style_classes, name, rawtext, text, lineno, inliner, options, content):
return [nodes.inline(rawtext, text, classes=['m-label'] + style_classes)], []
def label_default(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-default'], name, rawtext, text, lineno, inliner, options, content)
def label_primary(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-primary'], name, rawtext, text, lineno, inliner, options, content)
def label_success(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-success'], name, rawtext, text, lineno, inliner, options, content)
def label_warning(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-warning'], name, rawtext, text, lineno, inliner, options, content)
def label_danger(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-danger'], name, rawtext, text, lineno, inliner, options, content)
def label_info(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-info'], name, rawtext, text, lineno, inliner, options, content)
def label_dim(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-dim'], name, rawtext, text, lineno, inliner, options, content)
def label_flat_default(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-flat', 'm-default'], name, rawtext, text, lineno, inliner, options, content)
def label_flat_primary(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-flat', 'm-primary'], name, rawtext, text, lineno, inliner, options, content)
def label_flat_success(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-flat', 'm-success'], name, rawtext, text, lineno, inliner, options, content)
def label_flat_warning(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-flat', 'm-warning'], name, rawtext, text, lineno, inliner, options, content)
def label_flat_danger(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label('m-flat', ['m-danger'], name, rawtext, text, lineno, inliner, options, content)
def label_flat_info(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-flat', 'm-info'], name, rawtext, text, lineno, inliner, options, content)
def label_flat_dim(name, rawtext, text, lineno, inliner, options={}, content=[]):
return label(['m-flat', 'm-dim'], name, rawtext, text, lineno, inliner, options, content)
def register():
rst.directives.register_directive('transition', Transition)
rst.directives.register_directive('note-default', DefaultNote)
rst.directives.register_directive('note-primary', PrimaryNote)
rst.directives.register_directive('note-success', SuccessNote)
rst.directives.register_directive('note-warning', WarningNote)
rst.directives.register_directive('note-danger', DangerNote)
rst.directives.register_directive('note-info', InfoNote)
rst.directives.register_directive('note-dim', DimNote)
rst.directives.register_directive('block-default', DefaultBlock)
rst.directives.register_directive('block-primary', PrimaryBlock)
rst.directives.register_directive('block-success', SuccessBlock)
rst.directives.register_directive('block-warning', WarningBlock)
rst.directives.register_directive('block-danger', DangerBlock)
rst.directives.register_directive('block-info', InfoBlock)
rst.directives.register_directive('block-dim', DimBlock)
rst.directives.register_directive('block-flat', FlatBlock)
rst.directives.register_directive('frame', Frame)
rst.directives.register_directive('code-figure', CodeFigure)
rst.directives.register_directive('console-figure', ConsoleFigure)
rst.directives.register_directive('math-figure', MathFigure)
rst.directives.register_directive('graph-figure', GraphFigure)
rst.directives.register_directive('text-default', DefaultText)
rst.directives.register_directive('text-primary', PrimaryText)
rst.directives.register_directive('text-success', SuccessText)
rst.directives.register_directive('text-warning', WarningText)
rst.directives.register_directive('text-danger', DangerText)
rst.directives.register_directive('text-info', InfoText)
rst.directives.register_directive('text-dim', DimText)
rst.directives.register_directive('button-default', DefaultButton)
rst.directives.register_directive('button-primary', PrimaryButton)
rst.directives.register_directive('button-success', SuccessButton)
rst.directives.register_directive('button-warning', WarningButton)
rst.directives.register_directive('button-danger', DangerButton)
rst.directives.register_directive('button-info', InfoButton)
rst.directives.register_directive('button-dim', DimButton)
rst.directives.register_directive('button-flat', FlatButton)
rst.roles.register_canonical_role('label-default', label_default)
rst.roles.register_canonical_role('label-primary', label_primary)
rst.roles.register_canonical_role('label-success', label_success)
rst.roles.register_canonical_role('label-warning', label_warning)
rst.roles.register_canonical_role('label-danger', label_danger)
rst.roles.register_canonical_role('label-info', label_info)
rst.roles.register_canonical_role('label-dim', label_dim)
rst.roles.register_canonical_role('label-flat-default', label_flat_default)
rst.roles.register_canonical_role('label-flat-primary', label_flat_primary)
rst.roles.register_canonical_role('label-flat-success', label_flat_success)
rst.roles.register_canonical_role('label-flat-warning', label_flat_warning)
rst.roles.register_canonical_role('label-flat-danger', label_flat_danger)
rst.roles.register_canonical_role('label-flat-info', label_flat_info)
rst.roles.register_canonical_role('label-flat-dim', label_flat_dim)