def make_margin_boxes(context, page, state):
    """Yield laid-out margin boxes for this page.

    ``state`` is the actual, up-to-date page-state from
    ``context.page_maker[context.current_page]``.

    """
    # This is a closure only to make calls shorter
    def make_box(at_keyword, containing_block):
        """Return a margin box with resolved percentages.

        The margin box may still have 'auto' values.

        Return ``None`` if this margin box should not be generated.

        :param at_keyword:
            Which margin box to return, e.g. '@top-left'
        :param containing_block:
            As expected by :func:`resolve_percentages`.

        """
        style = context.style_for(page.page_type, at_keyword)
        if style is None:
            # doesn't affect counters
            style = computed_from_cascaded(
                element=None, cascaded={}, parent_style=page.style)
        _standardize_page_based_counters(style, at_keyword)
        box = boxes.MarginBox(at_keyword, style)
        # Empty boxes should not be generated, but they may be needed for
        # the layout of their neighbors.
        # TODO: should be the computed value.
        box.is_generated = style['content'] not in (
            'normal', 'inhibit', 'none')
        # TODO: get actual counter values at the time of the last page break
        if box.is_generated:
            # @margins mustn't manipulate page-context counters
            margin_state = copy.deepcopy(state)
            quote_depth, counter_values, counter_scopes = margin_state
            # TODO: check this, probably useless
            counter_scopes.append(set())
            build.update_counters(margin_state, box.style)
            box.children = build.content_to_boxes(
                box.style, box, quote_depth, counter_values,
                context.get_image_from_uri, context.target_collector,
                context.counter_style, context, page)
            build.process_whitespace(box)
            build.process_text_transform(box)
            box = build.create_anonymous_boxes(box)
        resolve_percentages(box, containing_block)
        if not box.is_generated:
            box.width = box.height = 0
            for side in ('top', 'right', 'bottom', 'left'):
                box._reset_spacing(side)
        return box

    margin_top = page.margin_top
    margin_bottom = page.margin_bottom
    margin_left = page.margin_left
    margin_right = page.margin_right
    max_box_width = page.border_width()
    max_box_height = page.border_height()

    # bottom right corner of the border box
    page_end_x = margin_left + max_box_width
    page_end_y = margin_top + max_box_height

    # Margin box dimensions, described in
    # https://drafts.csswg.org/css-page-3/#margin-box-dimensions
    generated_boxes = []

    for prefix, vertical, containing_block, position_x, position_y in (
        ('top', False, (max_box_width, margin_top),
            margin_left, 0),
        ('bottom', False, (max_box_width, margin_bottom),
            margin_left, page_end_y),
        ('left', True, (margin_left, max_box_height),
            0, margin_top),
        ('right', True, (margin_right, max_box_height),
            page_end_x, margin_top),
    ):
        if vertical:
            suffixes = ['top', 'middle', 'bottom']
            fixed_outer, variable_outer = containing_block
        else:
            suffixes = ['left', 'center', 'right']
            variable_outer, fixed_outer = containing_block
        side_boxes = [
            make_box(f'@{prefix}-{suffix}', containing_block)
            for suffix in suffixes]
        if not any(box.is_generated for box in side_boxes):
            continue
        # We need the three boxes together for the variable dimension:
        compute_variable_dimension(
            context, side_boxes, vertical, variable_outer)
        for box, offset in zip(side_boxes, [0, 0.5, 1]):
            if not box.is_generated:
                continue
            box.position_x = position_x
            box.position_y = position_y
            if vertical:
                box.position_y += offset * (
                    variable_outer - box.margin_height())
            else:
                box.position_x += offset * (
                    variable_outer - box.margin_width())
            compute_fixed_dimension(
                context, box, fixed_outer, not vertical,
                prefix in ('top', 'left'))
            generated_boxes.append(box)

    # Corner boxes

    for at_keyword, cb_width, cb_height, position_x, position_y in (
        ('@top-left-corner', margin_left, margin_top, 0, 0),
        ('@top-right-corner', margin_right, margin_top, page_end_x, 0),
        ('@bottom-left-corner', margin_left, margin_bottom, 0, page_end_y),
        ('@bottom-right-corner', margin_right, margin_bottom,
            page_end_x, page_end_y),
    ):
        box = make_box(at_keyword, (cb_width, cb_height))
        if not box.is_generated:
            continue
        box.position_x = position_x
        box.position_y = position_y
        compute_fixed_dimension(
            context, box, cb_height, True, 'top' in at_keyword)
        compute_fixed_dimension(
            context, box, cb_width, False, 'left' in at_keyword)
        generated_boxes.append(box)

    for box in generated_boxes:
        yield margin_box_content_layout(context, page, box)
Yield laid-out margin boxes for this page.

``state`` is the actual, up-to-date page-state from
``context.page_maker[context.current_page]``.
weasyprint/layout/page.py