Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
VueContentHandler
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 5
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getContentClass
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 makeEmptyContent
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 fillParserOutput
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
12
 validateSave
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\Content;
8
9use InvalidArgumentException;
10use MediaWiki\Config\Config;
11use MediaWiki\Content\Renderer\ContentParseParams;
12use MediaWiki\Html\Html;
13use MediaWiki\MainConfigNames;
14use MediaWiki\Parser\ParserFactory;
15use MediaWiki\Parser\ParserOutput;
16use MediaWiki\Parser\ParserOutputFlags;
17use MediaWiki\ResourceLoader\VueComponentParser;
18use StatusValue;
19use WikiPage;
20
21/**
22 * Content handler for Vue pages.
23 *
24 * @since 1.45
25 * @ingroup Content
26 */
27class VueContentHandler extends CodeContentHandler {
28
29    private array $textModelsToParse;
30
31    private ?VueComponentParser $vueComponentParser = null;
32
33    public function __construct(
34        string $modelId,
35        Config $config,
36        private readonly ParserFactory $parserFactory,
37    ) {
38        parent::__construct( $modelId, [ CONTENT_FORMAT_VUE ] );
39        $this->textModelsToParse = $config->get( MainConfigNames::TextModelsToParse ) ?? [];
40    }
41
42    /**
43     * @return class-string<VueContent>
44     */
45    protected function getContentClass() {
46        return VueContent::class;
47    }
48
49    /** @inheritDoc */
50    public function makeEmptyContent() {
51        $class = $this->getContentClass();
52        return new $class( "<template>\n</template>\n\n<script>\n</script>\n\n<style>\n</style>\n" );
53    }
54
55    /**
56     * Fills the provided ParserOutput object with information derived from the content.
57     * Unless $cpo->getGenerateHtml was false, this includes an HTML representation of the content.
58     *
59     * For content models listed in $wgTextModelsToParse, this method will call the MediaWiki
60     * wikitext parser on the text to extract any (wikitext) links, magic words, etc.
61     *
62     * Subclasses may override this to provide custom content processing..
63     *
64     * @stable to override
65     *
66     * @param Content $content
67     * @param ContentParseParams $cpoParams
68     * @param ParserOutput &$output The output object to fill (reference).
69     */
70    protected function fillParserOutput(
71        Content $content,
72        ContentParseParams $cpoParams,
73        ParserOutput &$output
74    ) {
75        '@phan-var VueContent $content';
76        if ( in_array( $content->getModel(), $this->textModelsToParse ) ) {
77            // parse just to get links etc into the database, HTML is replaced below.
78            $output = $this->parserFactory->getInstance()->parse(
79                $content->getText(),
80                $cpoParams->getPage(),
81                WikiPage::makeParserOptionsFromTitleAndModel(
82                    $cpoParams->getPage(),
83                    $content->getModel(),
84                    'canonical'
85                ),
86                true,
87                true,
88                $cpoParams->getRevId()
89            );
90        }
91
92        if ( $cpoParams->getGenerateHtml() ) {
93            // Return Vue code wrapped in a <pre> tag.
94            $html = Html::element(
95                'pre',
96                [ 'class' => 'mw-code mw-vue', 'dir' => 'ltr' ],
97                "\n" . $content->getText() . "\n"
98            ) . "\n";
99        } else {
100            $html = null;
101        }
102
103        $output->clearWrapperDivClass();
104        $output->setRawText( $html );
105        // Suppress the TOC (T307691)
106        $output->setOutputFlag( ParserOutputFlags::NO_TOC );
107        $output->setSections( [] );
108    }
109
110    /**
111     * @param Content $content
112     * @param ValidationParams $validationParams
113     * @return StatusValue
114     */
115    public function validateSave( Content $content, ValidationParams $validationParams ): StatusValue {
116        $this->vueComponentParser ??= new VueComponentParser;
117        try {
118            $parsedComponent = $this->vueComponentParser->parse( $content->serialize() );
119        } catch ( InvalidArgumentException $e ) {
120            // TODO: i18n for error messages
121            return StatusValue::newFatal( 'vue-invalid-content', $e->getMessage() );
122        }
123        if ( $parsedComponent['styleLang'] === 'less' ) {
124            return StatusValue::newFatal( 'vue-less-notsupported' );
125        }
126        return StatusValue::newGood();
127    }
128}