Aller au contenu

Construire des pages à partir d'informations globales sur tous les appels de macros du thème#



Utilisation très avancée

Le contenu de cette page ne sera utile qu'à des personnes étant un minimum familières avec les évènements utilisées pour les plugins mkdocs, ou les "fichiers de crochets".



Le thème stocke des informations détaillées sur les appels de macros effectués dans les différentes pages de la documentation. Ces informations peuvent être ensuite utilisées pour construire des pages avec des données plus génériques concernant tout ou partie des pages de la documentation ou des exercices, comme par exemple la page de recherche de CodEx, ou gérer les boutons de suivi des IDEs présents dans la page de recherche et celle des parcours (toujours sur CodEx).

Vue d'ensemble#

  • Le thème stocke les informations pour tous les appels des macros du thème, effectuĂ©s durant les Ă©vènements on_page_markdown, dans des objets MacroData stockĂ©s dans une liste.

  • L'intĂ©gralitĂ© de ces donnĂ©es est donc accessible Ă  partir du crochet on_env, une fois que toutes les pages markdown ont Ă©tĂ© traitĂ©es.

  • Il est possible d'accĂ©der Ă  cette liste d'objets en l'extrayant du plugin pyodide_macros, via l'argument config de l'un des crochets mkdocs en utilisant le code config.plugins['pyodide_macros'].all_macros_data (un exemple est disponible plus bas dans cette page).

  • Il est conseillĂ© de formatter les donnĂ©es Ă  votre convenance depuis le crochet on_env, en stockant les donnĂ©es dans une variable globale.

  • Le crochet on_page_context peut ensuite ĂŞtre utilisĂ© pour modifier le contenu html des pages souhaitĂ©es, en mutant page.content Ă  partir des donnĂ©es extraites depuis le crochet on_env.

    Utilisable uniquement pour créer du contenu html !

    Les contenus générés à cette étape ne doivent effectivement être que des contenus html, et non des contenus markdown : la conversion de markdown vers html a en effet déjà été effectuée par mkdocs.



Mise en place#

  1. Définir un fichier de crochets dans le projet (en dehors du docs_dir). Typiquement, hooks.py, à la racine du projet.

  2. Référencer ce fichier dans le mkdocs.yml :

    hooks:
        - hooks.py
    


  3. Coller dans le fichier de crochets le code ci-dessous, qui peut servir d'architecture de base :

    from typing import Any
    from jinja2 import Environment
    from mkdocs.config.defaults import MkDocsConfig
    from mkdocs.structure.nav import Navigation
    from mkdocs.structure.files import Files
    from mkdocs.structure.pages import Page
    from pyodide_mkdocs_theme.pyodide_macros import *
    
    
    MY_DATA: Any = {}
    
    def on_env(env:Environment, config:MkDocsConfig, files:Files):
        """
        Fonction exécutée une seule fois durant le build.
    
        ATTENTION:
            * L'argument `env` n'a rien à voir avec l'argument utilisé pour définir les macros.
            * La variable `plugin` ci-dessous, elle, correspond bien Ă  l'argument `env` des
              fonctions `define_env` utilisées pour déclarer les macros.
            * Les signatures des fonctions crochets mkdocs sont très contraintes et ne permettent
              généralement pas de renommer les arguments...
        """
        plugin: PyodideMacroPlugin = config.plugins['pyodide_macros'])
        lst: List[MacroData] = plugin.all_macros_data
        # Extraire/formatter ensuite les données nécessaires à votre convenance et les rendre
        # disponibles dans une variable globale (ex: MY_DATA).
        # Il est recommander de typer les objets autant que possible, de manière à profiter
        # ensuite de l'auto-complétion.
    
    
    def on_page_context(ctx, page:Page, *, config:MkDocsConfig, nav:Navigation):
        """
        Fonction exécutée une fois par page de la documentation.
        Muter `page.content:str`, en y ajoutant le code html voulu.
        """
        # Utiliser MY_DATA pour construire le code html voulu, lorsque la page passée en argument
        # est celle désirée.
        if page.url == 'custom/generic_pages/':
            page.content += '<a href="here">Whatever you want</a>'
    


  4. Modifier ensuite le code pour customiser les pages voulues.


Un exemple d'utilisation de cette fonctionnalité est disponible sur le dépôt de CodEx (codex_hooks.py).

Données disponibles#

Interface MacroData#

La classe MacroData regroupe l'interface commune des données fournies dans la liste plugin.all_macros_data.
Ces objets comportent une interface générique, et une partie spécifique à la macro utilisée.




Interface générique

MacroDataGeneric #

Generic interface, common to all MacroData objects.

Absolute url of the element in the built page (defaults to full_page_url).

args: ObjectWithDataGetters instance-attribute #

All values of arguments, as passed in the macro call (overridden by child class with the needed class).

full_page_url: str instance-attribute #

Absolute url of the built page holding this element.

macro: str instance-attribute #

Name of the macro that created this object. Notes:

  • "IDEv" calls are seen has "IDE".
  • "IDE_tester" calls are not gathered.

meta: Dict[str, Any] instance-attribute #

Metadata of the source page (allows to store extra informations there, to add logic later when building the content).

page_url: str instance-attribute #

As provided by page.url (aka, relative to the site_dir and taking in consideration the value of use_directory_urls).

src_uri: str instance-attribute #

Uri of the source file, relative to cwd.




Interface spécifique

MacroDataSpecific #

Properties of MacroData objects that are defined only when appropriated (generally, for macros involving python files, like IDE, IDEv, terminal, py_btn).

content: Optional[Content] = None class-attribute instance-attribute #

Object showing the "content" associated with sections or buttons for the generated object.
See the detailed interface of the Content objects. Support autocompletion when defined.

has: Optional[HasContent] = None class-attribute instance-attribute #

Object indicating what sections, files or buttons are present on the generated object.
See the detailed interface of the HasContent objects. Support autocompletion when defined.

has_check_btn: Optional[bool] = None class-attribute instance-attribute #

True if the related element will have a visible validation button in the GUI.
Alternative way to access the information in self.has.check_btn or self.content.check_btn

load_py_name: Optional[str] = None class-attribute instance-attribute #

Python file name used for the download/export machinery of the IDEs (Will generally differ from the macro py_name argument).

storage_id: Optional[str] = None class-attribute instance-attribute #

Id used as key in the localStorage, if the related entry exists, None otherwise.

Sous classes de MacroData#

Afin de profiter de l'auto-complétion, le thème met à disposition les variantes des classes MacroData correspondant à chaque type de macros.

Il est donc fortement conseillé de réarranger à votre convenance les objets de plugin.all_macros_data depuis le crochet on_env, en créant d'autres structures de données qui utiliseront un et un seul type de sous-classe. Ainsi, l'IDE proposera les suggestions d'auto-complétion.

Exemple d'utilisation d'une sous classe de MacroData
from typing import Dict
from jinja2 import Environment
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import Files

from pyodide_mkdocs_theme.pyodide_macros import PyodideMacroPlugin, MacroDataIDE


# Déclaration avec typage, pour profiter de l'auto-complétion dans `on_page_context`:
IDES: Dict[str,MacroDataIDE] = {}


def on_env(env:Environment, config:MkDocsConfig, files:Files):

    plugin: PyodideMacroPlugin = config.plugins['pyodide_macros'])
    for macro_data in plugin.all_macros_data:
        if macro_data.macro == 'IDE':
            IDES[ macro_data.page_url ] = macro_data



MacroDataIDE
class MacroDataIDE(MacroData):
    """ Runtime data object for the MacroDataIDE macro. """

    args: MacroArgsDataIDE


class MacroArgsDataIDE(ObjectWithDataGetters):
    """ Runtime arguments object for the MacroDataIDE macro. """

    py_name: str
    ID: int
    SANS: str
    WHITE: str
    REC_LIMIT: int
    SHOW: str
    MERMAID: bool
    AUTO_RUN: bool
    MAX: int
    LOGS: bool
    MODE: str
    MIN_SIZE: int
    MAX_SIZE: int
    TERM_H: int
    TEST: str
    TWO_COLS: bool
    STD_KEY: str
    EXPORT: bool
MacroDataTerminal
class MacroDataTerminal(MacroData):
    """ Runtime data object for the MacroDataTerminal macro. """

    args: MacroArgsDataTerminal


class MacroArgsDataTerminal(ObjectWithDataGetters):
    """ Runtime arguments object for the MacroDataTerminal macro. """

    py_name: str
    ID: int
    SANS: str
    WHITE: str
    REC_LIMIT: int
    SHOW: str
    MERMAID: bool
    AUTO_RUN: bool
    TERM_H: int
    FILL: str
MacroDataPy_btn
class MacroDataPy_btn(MacroData):
    """ Runtime data object for the MacroDataPy_btn macro. """

    args: MacroArgsDataPy_btn


class MacroArgsDataPy_btn(ObjectWithDataGetters):
    """ Runtime arguments object for the MacroDataPy_btn macro. """

    py_name: str
    ID: int
    SANS: str
    WHITE: str
    REC_LIMIT: int
    SHOW: str
    ICON: str
    HEIGHT: int
    WIDTH: int
    SIZE: int
    TIP: str
    TIP_SHIFT: int
    TIP_WIDTH: float
    WRAPPER: str
    MERMAID: bool
    AUTO_RUN: bool
MacroDataRun
class MacroDataRun(MacroData):
    """ Runtime data object for the MacroDataRun macro. """

    args: MacroArgsDataRun


class MacroArgsDataRun(ObjectWithDataGetters):
    """ Runtime arguments object for the MacroDataRun macro. """

    py_name: str
    ID: int
    SANS: str
    WHITE: str
    REC_LIMIT: int
    SHOW: str
    MERMAID: bool
MacroDataSection
class MacroDataSection(MacroData):
    """ Runtime data object for the MacroDataSection macro. """

    args: MacroArgsDataSection


class MacroArgsDataSection(ObjectWithDataGetters):
    """ Runtime arguments object for the MacroDataSection macro. """

    py_name: str
    section: str
MacroDataMulti_qcm
class MacroDataMulti_qcm(MacroData):
    """ Runtime data object for the MacroDataMulti_qcm macro. """

    args: MacroArgsDataMulti_qcm


class MacroArgsDataMulti_qcm(ObjectWithDataGetters):
    """ Runtime arguments object for the MacroDataMulti_qcm macro. """

    questions: Any
    description: str
    hide: bool
    multi: bool
    shuffle: bool
    shuffle_questions: bool
    shuffle_items: bool
    admo_kind: str
    admo_class: str
    qcm_title: str
    tag_list_of_qs: str
    DEBUG: bool
    SHOW: str
MacroDataPy
class MacroDataPy(MacroData):
    """ Runtime data object for the MacroDataPy macro. """

    args: MacroArgsDataPy


class MacroArgsDataPy(ObjectWithDataGetters):
    """ Runtime arguments object for the MacroDataPy macro. """

    py_name: str
MacroDataFigure
class MacroDataFigure(MacroData):
    """ Runtime data object for the MacroDataFigure macro. """

    args: MacroArgsDataFigure


class MacroArgsDataFigure(ObjectWithDataGetters):
    """ Runtime arguments object for the MacroDataFigure macro. """

    div_id: str
    div_class: str
    inner_text: str
    admo_kind: str
    admo_class: str
    admo_title: str
    p5_buttons: str
    SHOW: str

Content et HasContent#

Si définies, les propriétés content et has des objets MacroData offrent les interfaces suivantes :

Content

class Content:
    """ Content of each section (or absolute Path on the disk for REMs files). """

    env: str = ""
    env_term: str = ""
    code: str = ""
    corr: str = ""
    tests: str = ""
    secrets: str = ""
    post_term: str = ""
    post: str = ""
    REM: Optional[Path] = None
    VIS_REM: Optional[Path] = None
    check_btn: bool = False

HasContent

class HasContent:
    """ Flags to know what sections/elements are defined or not. """

    env: bool = False
    env_term: bool = False
    code: bool = False
    corr: bool = False
    tests: bool = False
    secrets: bool = False
    post_term: bool = False
    post: bool = False
    REM: bool = False
    VIS_REM: bool = False
    check_btn: bool = False