ftml/parsing/rule/impls/block/blocks/
include_elements.rs

1/*
2 * parsing/rule/impls/block/blocks/include_elements.rs
3 *
4 * ftml - Library to parse Wikidot text
5 * Copyright (C) 2019-2025 Wikijump Team
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21use super::prelude::*;
22use crate::data::PageRef;
23use crate::parsing::UnstructuredParseResult;
24
25// TODO: maybe scrap this? we want to move to components anyways
26
27/// Block rule for include (elements).
28///
29/// This takes the resultant `SyntaxTree` from another page and
30/// inserts them into this page being built.
31pub const BLOCK_INCLUDE_ELEMENTS: BlockRule = BlockRule {
32    name: "block-include-elements",
33    accepts_names: &["include-elements"],
34    accepts_star: false,
35    accepts_score: false,
36    accepts_newlines: true,
37    parse_fn,
38};
39
40fn parse_fn<'r, 't>(
41    parser: &mut Parser<'r, 't>,
42    name: &'t str,
43    flag_star: bool,
44    flag_score: bool,
45    in_head: bool,
46) -> ParseResult<'r, 't, Elements<'t>> {
47    debug!("Found invalid include-elements block");
48    parser.check_page_syntax()?;
49    assert!(!flag_star, "Include (elements) doesn't allow star flag");
50    assert!(!flag_score, "Include (elements) doesn't allow score flag");
51    assert_block_name(&BLOCK_INCLUDE_ELEMENTS, name);
52
53    // Parse block
54    let (page_name, variables) =
55        parser.get_head_name_map(&BLOCK_INCLUDE_ELEMENTS, in_head)?;
56
57    let page_ref = match PageRef::parse(page_name) {
58        Ok(page_ref) => page_ref,
59        Err(_) => return Err(parser.make_err(ParseErrorKind::BlockMalformedArguments)),
60    };
61
62    // Get page to be included
63    let UnstructuredParseResult {
64        result,
65        mut html_blocks,
66        mut code_blocks,
67        mut table_of_contents_depths,
68        mut footnotes,
69        has_footnote_block,
70        mut bibliographies,
71    } = include_page(parser, &page_ref)?;
72
73    if has_footnote_block {
74        parser.set_footnote_block();
75    }
76
77    // Extract elements and errors
78    let ParseSuccess {
79        item: elements,
80        errors,
81        paragraph_safe,
82        ..
83    } = result?;
84
85    // Update parser state, build, and return
86    parser.append_shared_items(
87        &mut html_blocks,
88        &mut code_blocks,
89        &mut table_of_contents_depths,
90        &mut footnotes,
91        &mut bibliographies,
92    );
93
94    let variables = variables.to_hash_map();
95    let element = Element::Include {
96        paragraph_safe,
97        variables,
98        location: page_ref,
99        elements,
100    };
101
102    ok!(element, errors)
103}
104
105fn include_page<'r, 't>(
106    parser: &Parser<'r, 't>,
107    _page: &PageRef,
108) -> Result<UnstructuredParseResult<'r, 't>, ParseError> {
109    // TODO stubbed
110
111    if false {
112        return Err(parser.make_err(ParseErrorKind::NoSuchPage));
113    }
114
115    Ok(UnstructuredParseResult {
116        result: Ok(ParseSuccess::new(
117            vec![text!("<INCLUDED PAGE (ELEMENTS)>")],
118            vec![],
119            false,
120        )),
121        html_blocks: vec![],
122        code_blocks: vec![],
123        table_of_contents_depths: vec![],
124        footnotes: vec![],
125        has_footnote_block: false,
126        bibliographies: Default::default(),
127    })
128}