49

Is it possible to strike text through in Restructured Text?

Something that for example renders as a <strike> tag when converted to HTML, like: ReSTructuredText

gozzilli
  • 6,931
  • 6
  • 49
  • 80

8 Answers8

45

I checked the docs better, as suggested by Ville Säävuori, and I decided to add the strikethrough like this:

.. role:: strike
    :class: strike

In the document, this can be applied as follows:

:strike:`This text is crossed out`

Then in my css file I have an entry:

.strike {
  text-decoration: line-through;
}
tshepang
  • 10,772
  • 21
  • 84
  • 127
gozzilli
  • 6,931
  • 6
  • 49
  • 80
  • The problem with this approach is that you have to repeat this definition in each reST file that you want to use strike-throughs in, and it doesn't produce meaningful markup on the HTML side (it would be much better to produce a `` or `` tag). I've posted the code for that below (https://stackoverflow.com/a/62493316/695591) – Clément Jun 21 '20 at 00:51
15

There is at least three ways of doing it:

.. role:: strike

An example of :strike:`strike through text`.

.. container:: strike

   Here the full block of test is striked through.

An undecorated paragraph.

.. class:: strike

This paragraph too is is striked through.

.. admonition:: cancelled
   :class: strike

I strike through cancelled text.

After applying rst2html you get:

<p>An example of <span class="strike">strike through text</span>.</p>
<div class="strike container">
Here the full block of test is striked through.</div>
<p>An undecorated paragraph.</p>
<p class="strike">This paragraph too is is striked through.</p>
<div class="strike admonition">
<p class="first admonition-title">cancelled</p>
<p class="last">I strike through cancelled text.</p>

You use them with a style

.strike {
  text-decoration: line-through;
}

Here I have taken the admonition directive as example but any directive that allow the :class: option would do.

As it generates a span the role directive is the only one that allow to apply your style to a part of a paragraph.

It is redundant to add a class strike to a directive also named strike, as suggest Gozzilli, because the directive name is the default class for the html output.

I have checked these syntax both with rest2html and Sphinx. But while everything works as expected with rest2html the class directive fail with Sphinx. You have to replace it with

.. rst-class:: strike

This paragraph too is is striked through.

This is only stated in a small footnote of Sphinx reSt Primer.

marcz
  • 938
  • 10
  • 12
  • You sure about that link. I doesn't look like it goes where you intended. – tshepang Mar 08 '13 at 09:28
  • 2
    @Tshepang, I checked, the link end up on a footnote that state: _When the default domain contains a class directive, this directive will be shadowed. Therefore, Sphinx re-exports it as rst-class._ – marcz Mar 17 '13 at 09:02
13

According to the official spec there is no directive for strikethrough markup in ReST.

However, if the environment allows for :raw: role or you are able to write your own roles, then you can write a custom plugin for it.

Chris Frederick
  • 5,112
  • 3
  • 34
  • 40
3

I found the other answers very helpful. I am not very familiar with Sphinx but I am using it for a project. I too wanted the strike-through ability and have got it working based on the previous answers. To be clear, I added my strikethrough role as gozzilli mentioned but I saved it inside my conf.py using the rst_prolog variable as discussed in the stack overflow thread here. This means that this role is available to all of your rest files.

I then extended the base html template as described above by creating layout.htmlwithin _templatesinside my source directory. The contents of this file are:

{% extends "!layout.html" %}
{% set css_files = css_files + ["_static/myStyle.css"] %}

This basically includes a custom css file to all your built default html docs.

Finally, in my _static directory within my source directory I included the file myStyle.css which contains:

.strike {
  text-decoration: line-through;
}

Which the other answers have already provided.

I am merely writing this answer as it wasn't obvious to me with my limited Sphinx experience which files to edit.

Community
  • 1
  • 1
Gregory Kuhn
  • 1,371
  • 1
  • 15
  • 26
3

Here's a Python definition of a del role, which works better than the accepted answer if you want to use the role in multiple pages of a Pelican blog or a Sphinx documentation project:

from docutils import nodes
from docutils.parsers.rst import roles

def deleted_role(_role, rawtext, text, _lineno, _inliner, options={}, _content=[]):
    roles.set_classes(options)
    options.setdefault('classes', []).append("del")
    return [nodes.inline(rawtext, text, **options)], []

roles.register_canonical_role('del', deleted_role)

Even better would be to extend the HTML writer to produce a proper <del> tag, like this:

from docutils import nodes
from docutils.parsers.rst import roles
from docutils.writers._html_base import HTMLTranslator

class delnode(nodes.inline):
    pass

def visit_delnode(self, node):
    self.body.append(self.starttag(node, 'del', ''))
def depart_delnode(self, node):
    self.body.append('</del>')

HTMLTranslator.visit_delnode = visit_delnode
HTMLTranslator.depart_delnode = depart_delnode

def deleted_role(_role, rawtext, text, _lineno, _inliner, options={}, _content=[]):
    roles.set_classes(options)
    return [delnode(rawtext, text, **options)], []

roles.register_canonical_role('del', deleted_role)

You can trivially adjust it to produce an <s>, of course.

Clément
  • 10,212
  • 13
  • 62
  • 104
2

Consider the user may have a different background, so here is no one solution that can be suitable for everyone.

1.Only one file

If you only use it only on one file. For example, you published a simple project to PyPI, and you may probably just only one README.rst file. The following may you want.

.. |ss| raw:: html

    <strike>

.. |se| raw:: html

    </strike>

single line
=============

|ss| abc\ |se|\defg

multiple line
=============

|ss|  
line 1

line 2
|se|

789

you can copy and paste it on this website: https://livesphinx.herokuapp.com/

and will see the picture as the following:

enter image description here

It's simple, and you can on directly see the preview on some IDE, for example, PyCharm.


bellow is writing for the users of Sphinx

2.beginner of Sphinx

If you are a beginner of Sphinx. ( I mean maybe you want to use Sphinx to create a document, but Python is not familiar for you ) then try as following:

# conf.py

from pathlib import Path
html_static_path = ['_static', ]
html_css_files = ['css/user.define.css']  # If you want to control which HTML should contain it, you can put it on the HTML, which is very like the answer by @Gregory Kuhn.

with open(Path(__file__).parent / Path('_static/css/user.define.rst'), 'r') as f:
    user_define_role = f.read()

rst_prolog = '\n'.join([ user_define_role + '\n',])  # will be included at the beginning of every source file that is read.
# rst_epilog = '\n'.join([ user_define_role + '\n',])  # it's ok if you put it on the end.

user.define.rst

.. role:: strike

user.define.css

.strike {text-decoration: line-through;}

With the rst_prolog, It can auto-add the role on each rst files, but if you change the content( that file, it contains a format that you define), then you must rebuild to make the render is correct.

3.Create roles

You can create an extension to achieve it.

# conf.py

extensions = ['_ext.rst_roles', ]
html_static_path = ['_static', ]
html_css_files = ['css/user.define.css']
# rst_roles.py
from sphinx.application import Sphinx
from docutils.parsers.rst import roles
from docutils import nodes
from docutils.parsers.rst.states import Inliner


def strike_role(role, rawtext, text, lineno, inliner: Inliner, options={}, content=[]):
    your_css_strike_name = 'strike'
    return nodes.inline(rawtext, text, **dict(classes=[your_css_strike_name])), []

def setup(app: Sphinx):
    roles.register_canonical_role('my-strike', strike_role)  # usage:  :my-strike:`content ...`

The full architecture:

  • conf.py
  • _ext/
    • rst_roles.py
  • _static/
    • css/
      • user.define.css

about the rules, you can reference this link rst-roles

And I vary recommended you to see the docutils.parsers.rst.roles.py .

Carson
  • 1,762
  • 1
  • 10
  • 23
  • I don't know why my answer makes someone unhappy then give me a vote down and I hope you can tell me why, anyway, I update my solution hope you will understand. – Carson Jun 22 '20 at 10:59
  • **This is the optimum answer,** currently. The first "Only one file." solution is *really* optimal. It's the only solution that actually works for the common case of a reST file hosted on a third-party site *not* under your direct control (e.g., GitHub- or GitLab-hosted `README.rst`). Haters gonna hate, @Carson. I wouldn't take the downvotes personally. They just jelly. – Cecil Curry Jan 19 '21 at 06:00
1

I wrote an extension for this.
Just pip install sphinxnotes-strike and use:

:strike:`text` 

to show strike text.

For more info: https://sphinx-notes.github.io/strike/

סטנלי גרונן
  • 2,740
  • 21
  • 43
  • 62
0

The repository version 0.17dev of the HTML5-writer uses if a matching class value is found in inline, literal, or container elements:

.. role:: del

:del:`This text has been deleted`, here is the rest of the paragraph.

.. container:: del

  This paragraph has been deleted.
G. Milde
  • 36
  • 1