sphinx-contrib / confluencebuilder

Confluence Markup Builder Plugin for Sphinx
BSD 2-Clause "Simplified" License
317 stars 99 forks source link

Ask for help - CSS on raw HTML #1024

Closed lutin-malin closed 3 months ago

lutin-malin commented 3 months ago

I'm exploring actively your plugin and really love it.

My use case is around antsibull-docs and a on-prem confluence. The 1st tool does generates the .rst files, ready to be consumed by your extension.

My issue is about the rendering of raw HTML.

the confluence rendering (lacking the identation in the 2nd and 3rd lines): image which is actually (from the page.conf file):

<tr class="row-even">
  <td><div class="ansible-option-indent"></div><div class="ansible-option-cell">
    <div class="ansibleOptionAnchor" id="return-certificate/Subject"></div>
    <p class="ansible-option-title"><strong>Subject</strong></p>
    <a class="ansibleOptionLink" href="#return-certificate/Subject" title="Permalink to this return value"></a>
    <p class="ansible-option-type-line">
      <span class="ansible-option-type">string</span>
    </p>
  </div></td>
  <td><div class="ansible-option-indent-desc"></div><div class="ansible-option-cell">
    <p>the subject of the cert</p>
    <p class="ansible-option-line"><strong class="ansible-option-returned-bold">Returned:</strong> success</p>
  </div></td>
</tr>

while if rendered to HTML will look like to (what i'm targetting) image

I've nailed down the behaviour to the specific .css file used by the HTML rendering. In the same cell, There is an hidden <div> with CSS style margin-left: 2em before the relevant one, making the fake ident.

Now comes my question : is there an option where i could include some CSS to the raw-generated HTML, to mimic this rendering ?

Note that i have limited acces to the source .rst files since generated by the antisbull...

I already appreciate your support on this.

jdknight commented 3 months ago

Manipulating CSS, let alone non-trivial HTML, is not something stock Confluence supports. There are some tricks on self-hosted solutions, if the instance's system administration has enabled the HTML macro (for others readers, this may work on Confluence Cloud using other marketplace HTML-support macro extension, in theory).

I am under the assumption that you are publishing raw HTML using either the help of the confluence_permit_raw_html configuration or using raw directives. And all that's left is trying to inject styling into a page.

With the html macro, you might be able to achieve what you want by looking at what the following example provides:

.. raw:: confluence_storage

    <div class="my-class">
    test
    </div>

    <ac:structured-macro ac:name="html"><ac:plain-text-body><![CDATA[

    <style type="text/css" scoped>
        .my-class {
            font-size: 2em;
        }
    </style>

    <script>
    var obj = document.createElement("style");
    obj.innerHTML = `
    .my-class {
        color: blue;
    }
    `;
    document.getElementsByTagName("head")[0].appendChild(obj);
    </script>

    ]]></ac:plain-text-body></ac:structured-macro>

Which has a rendering of:

image

This example shows the use of a scoped style tag. This may work on select browsers, but is not recommended (last I recall, this was originally HTML5 only and has now been dropped; so does not work on all browsers). The second method is trying to use Javascript to inject styling into the page. There might be other ways to manipulate CSS inside the body, but I'm not familiar with any other approaches (but feel free to let me know otherwise).

If you can get the HTML macro to work as expected, next would be to find a way to inject HTML in a Sphinx configuration without having to deal with specific content page (since I believe you mainly rely on antsibull-docs to generate content). You should be able to use either rst_epilog or confluence_footer_file to inject an HTML on the bottom of each page. See either example:

rst_epilog (conf.py) ``` rst_epilog = ''' .. raw:: confluence_storage .my-class { font-size: 2em; } ]]> ''' ```
confluence_footer_file (conf.py) ``` confluence_footer_file = 'footer.tpl' ``` (footer.tpl) ``` .my-class { font-size: 2em; } ]]> ```

That all said, if the target instance does not provide the HTML macro, the only other approaches that I can think of is using a marketplace-provided CSS macro type (if supported on the target instance) or trying to replace class attributes with appropriate style attributes (assuming Confluence does not filter out all the desired style types).

lutin-malin commented 3 months ago

I'm very pleased by your answer @jdknight .

Indeed i have the HTML macro enabled on my confluence instance, and my conf.py has it enabled like this confluence_permit_raw_html = 'html'

I followed your recomendataion to rely on a confluence_footer_file and i'm getting the expected result : image

For further reference, i'm just pasting what my conf looks like, if anyone would need to refer to it :

extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx_antsibull_ext','sphinxcontrib.confluencebuilder']

# Add custom style in every rst generated to fake the styles
confluence_footer_file = '../../confluence_footer.tpl'

# confluence settings
confluence_publish = True
confluence_space_key = 'my_space'
confluence_parent_page = 'my_page'
confluence_server_url = 'my_url'
confluence_server_user = 'my_login'
confluence_server_pass = 'my_passw'

confluence_editor = 'v2'
confluence_lang_overrides = {
    'yaml+jinja': 'yaml'
}

confluence_disable_notifications = True
confluence_permit_raw_html = 'html'

and in my confluence_footer.tpl :

<ac:structured-macro ac:name="html"><ac:plain-text-body><![CDATA[
<script>
var antisbullStyle= document.createElement("style");
antisbullStyle.innerHTML = `
/* below is the entire content of the antsibull-minimal.css, shrinked for simplicity */
.ansible-option-indent{
  margin-left:2em
}
`;
document.getElementsByTagName("head")[0].appendChild(antisbullStyle);
</script>

]]></ac:plain-text-body></ac:structured-macro>

Thanks again !