From cbf305dd05ba4183c1666c8a4d0f149f97c7e0a0 Mon Sep 17 00:00:00 2001 From: Justin Georgi Date: Sun, 17 May 2026 08:47:57 -0700 Subject: [PATCH 1/5] Add Annotation namespaces Signed-off-by: Justin Georgi --- extension.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/extension.json b/extension.json index b051000..6505292 100644 --- a/extension.json +++ b/extension.json @@ -7,6 +7,19 @@ "license-name": "MIT", "type": "media", "manifest_version": 1, + "namespaces": [ + { + "id": 2218, + "constant": "NS_AV_ANNOT", + "name": "Annotation", + "protection": "annotations-edit" + }, + { + "id": 2219, + "constant": "NS_AV_ANNOT_TALK", + "name": "Annotation_talk" + } + ], "AutoloadNamespaces": { "MediaWiki\\Extension\\AnatImageViewer\\": "includes/" }, -- 2.49.1 From d39458d53bf34d938a1c2236e592fb95ebd8e315 Mon Sep 17 00:00:00 2001 From: Justin Georgi Date: Sun, 17 May 2026 11:16:19 -0700 Subject: [PATCH 2/5] Create basic content function Signed-off-by: Justin Georgi --- extension.json | 26 ++++--- includes/AnatImageHandler.php | 63 --------------- includes/AnatImageHooks.php | 77 ------------------- includes/AnnotationContent.php | 32 ++++++++ ...nsformOutput.php => AnnotationHandler.php} | 76 +++++++++--------- includes/AnnotationHooks.php | 33 ++++++++ 6 files changed, 115 insertions(+), 192 deletions(-) delete mode 100644 includes/AnatImageHandler.php delete mode 100644 includes/AnatImageHooks.php create mode 100644 includes/AnnotationContent.php rename includes/{AnatImageTransformOutput.php => AnnotationHandler.php} (63%) create mode 100644 includes/AnnotationHooks.php diff --git a/extension.json b/extension.json index 6505292..5dda34f 100644 --- a/extension.json +++ b/extension.json @@ -1,8 +1,8 @@ { - "name": "AnatImageViewer", + "name": "AnnotatedImages", "author": "Justin Georgi", "url": "https://gitea.azgeorgis.net/jgeorgi/AnatImageViewer", - "description": "This extension allows the creation of .an pages in the Files namespace which will be annotated images.", + "description": "This extension allows the creation of pages in the Annotation namespace which will create annotated images.", "version": "0.0.1", "license-name": "MIT", "type": "media", @@ -12,23 +12,27 @@ "id": 2218, "constant": "NS_AV_ANNOT", "name": "Annotation", - "protection": "annotations-edit" - }, + "protection": "annotations-edit", + "subpages": false, + "content": true, + "defaultcontentmodel": "annotation" + }, { "id": 2219, "constant": "NS_AV_ANNOT_TALK", - "name": "Annotation_talk" - } + "name": "Annotation_talk", + "subpages": true, + "content": false, + "defaultcontentmodel": "wikitext" + } ], + "callback": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHooks::registrationCallback", "AutoloadNamespaces": { "MediaWiki\\Extension\\AnatImageViewer\\": "includes/" }, - "MediaHandlers": { - "image/annotation": "MediaWiki\\Extension\\AnatImageViewer\\AnatImageHandler" + "ContentHandlers": { + "annotation": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHandler" }, "Hooks": { - "MimeMagicInit": "MediaWiki\\Extension\\AnatImageViewer\\AnatImageHooks::onMimeMagicInit", - "MimeMagicImproveFromExtension": "MediaWiki\\Extension\\AnatImageViewer\\AnatImageHooks::onMimeMagicImproveFromExtension", - "ParserFirstCallInit": "MediaWiki\\Extension\\AnatImageViewer\\AnatImageHooks::onParserFirstCallInit" } } \ No newline at end of file diff --git a/includes/AnatImageHandler.php b/includes/AnatImageHandler.php deleted file mode 100644 index 6c9eb32..0000000 --- a/includes/AnatImageHandler.php +++ /dev/null @@ -1,63 +0,0 @@ -validateParam() - * @param int $flags A bitfield, may contain self::TRANSFORM_LATER - * @return MediaTransformOutput - */ - public function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0) { - return new AnatImageTransformOutput($image, $params); - } - - /** - * Small helper function to display information on the browser console - * - * Usage: - * echo ''; - * - * @param $data information to display - * @param bool $add_script_tags true to put information is inside complete script tag - */ - public static function console_log($data, $add_script_tags = false) { - $command = 'console.log('. json_encode($data, JSON_HEX_TAG).');'; - if ($add_script_tags) { - $command = ''; - } - echo $command; - } -} \ No newline at end of file diff --git a/includes/AnatImageHooks.php b/includes/AnatImageHooks.php deleted file mode 100644 index 58a5197..0000000 --- a/includes/AnatImageHooks.php +++ /dev/null @@ -1,77 +0,0 @@ -addExtraTypes('image/annotation an'); - $mime->addExtraInfo('image/annotation [METAIMAGE]'); - } - - /** - * MWHook: Make sure that an files (fake) get the proper mime assignement on upload - * - * @see https://www.mediawiki.org/wiki/Manual:Hooks/MimeMagicImproveFromExtension - * - * @param MimeAnalyzer $mimeAnalyzer Instance of MW MimeAnalyzer object - * @param string $ext extention of upload file - * @param string &$mime current assigned mime type - */ - public static function onMimeMagicImproveFromExtension( $mimeAnalyzer, $ext, &$mime ) { - if ( $mime !== 'image/annotation' && in_array( $ext, ['an'] ) ) { - $mime = 'image/annotation'; - } - } - - /** - * MWHook: Called when the parser initializes for the first time - * - * @param Parser $parser: Parser object being initialized - */ - static function onParserFirstCallInit( $parser ) { - $parser->setHook('anconfig', array( __CLASS__, 'renderConfigTag')); - } - - /** - * Render the config toml in a
 tag
-     * 
-     * @param $input The text inside the custom tag
-     * @param array $args Any attributes given in the tag
-     * @param Parser $parser The parser object
-     * @param PPFrame $frame The parent frame calling the parser
-     * @return string HTML string of output
-     */
-    static function renderConfigTag( $input, array $args, $parser, $frame ) {
-		return '
' . $input . '
'; - } - - /** - * Small helper function to display information on the browser console - * - * Usage: - * echo ''; - * - * @param $data information to display - * @param bool $add_script_tags true to put information is inside complete script tag - */ - public static function console_log($data, $add_script_tags = false) { - $command = 'console.log('. json_encode($data, JSON_HEX_TAG).');'; - if ($add_script_tags) { - $command = ''; - } - echo $command; - } -} \ No newline at end of file diff --git a/includes/AnnotationContent.php b/includes/AnnotationContent.php new file mode 100644 index 0000000..ae8f492 --- /dev/null +++ b/includes/AnnotationContent.php @@ -0,0 +1,32 @@ +file = $file; - $this->parameters = $parameters; - self::console_log($parameters, true); +class AnnotationHandler extends TextContentHandler { + private const ANNOT_VERSION = '0.1'; + + public function __construct( $modelId = 'annotation' ) { + parent::__construct( $modelId, [ CONTENT_FORMAT_TEXT ] ); } - /** - * Fetch HTML for this transform output - * - * @access public - * @param array $options Associative array of options. Boolean options - * should be indicated with a value of true for true, and false or - * absent for false. - * alt Alternate text or caption - * desc-link Boolean, show a description link - * file-link Boolean, show a file download link - * custom-url-link Custom URL to link to - * custom-title-link Custom Title object to link to - * valign vertical-align property, if the output is an inline element - * img-class Class applied to the "" tag, if there is such a tag - * preview Boolean, render is being called from a preview page - * - * @return string HTML - */ - public function toHtml($options = []) { - $descriptText = $this->file->getDescriptionText(); - preg_match('/
([\S\s]*?)<\/pre>/',$descriptText,$annotDescript);
-        $metadata = toml_decode($annotDescript[1], true);
+    /*
+	public function serializeContent( Content $content, $format = null ) {
+	}
+
+	public function unserializeContent( $blob, $format = null ) {
+	}
+    */
+    
+	public function makeEmptyContent() {
+		return new AnnotationContent();
+	}
+
+	public function supportsDirectEditing() {
+		return true;
+	}
+
+    protected function fillParserOutput( Content $content, ContentParseParams $cpoParams, ParserOutput &$output	) {
+		// define $html somewhere
+		// e.g. $output->setText( $html );
+
+        self::console_log($content, true);
+
+        $metadata = toml_decode($content->getNativeData(), true);
 
         if (isset($metadata['baseImage'])) {
-            $baseImage = MediaWikiServices::getInstance()->getRepoGroup()->findFile(`File:` . $metadata['baseImage']);
+            $baseImage = MediaWikiServices::getInstance()->getRepoGroup()->findFile('File:' . $metadata['baseImage']);
         } else {
             $baseImage = false;
         }
 
-        return self::buildSvg($metadata,$baseImage);
-	}
+        $output->setText( self::buildSvg($metadata,$baseImage) );
+    }
 
     /**
      * Build annotated SVG from TOML metadata
diff --git a/includes/AnnotationHooks.php b/includes/AnnotationHooks.php
new file mode 100644
index 0000000..bbb1e8a
--- /dev/null
+++ b/includes/AnnotationHooks.php
@@ -0,0 +1,33 @@
+';
+     * self::console_log('logged string');
+     * echo '';
+     * 
+     * @param $data information to display
+     * @param bool $add_script_tags true to put information is inside complete script tag
+     */
+    public static function console_log($data, $add_script_tags = false) {
+        $command = 'console.log('. json_encode($data, JSON_HEX_TAG).');';
+        if ($add_script_tags) {
+            $command = '';
+        }
+        echo $command;
+    }
+}
\ No newline at end of file
-- 
2.49.1


From c4e783dd9d94ffb774729de3fce48d97338bac54 Mon Sep 17 00:00:00 2001
From: Justin Georgi 
Date: Mon, 18 May 2026 08:56:56 -0700
Subject: [PATCH 3/5] Stuck point

Signed-off-by: Justin Georgi 
---
 extension.json                 | 11 ++++------
 includes/AnnotationContent.php |  2 +-
 includes/AnnotationHandler.php | 37 +++++++++++++++++++++++++---------
 includes/AnnotationHooks.php   | 20 ++++++++++++------
 4 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/extension.json b/extension.json
index 5dda34f..8559803 100644
--- a/extension.json
+++ b/extension.json
@@ -13,17 +13,13 @@
             "constant": "NS_AV_ANNOT",
             "name": "Annotation",
             "protection": "annotations-edit",
-            "subpages": false,
-            "content": true,
-            "defaultcontentmodel": "annotation"
+            "subpages": false
             },
         {
             "id": 2219,
             "constant": "NS_AV_ANNOT_TALK",
             "name": "Annotation_talk",
-            "subpages": true,
-            "content": false,
-            "defaultcontentmodel": "wikitext"
+            "subpages": true
             }
     ],
     "callback": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHooks::registrationCallback",
@@ -31,8 +27,9 @@
 		"MediaWiki\\Extension\\AnatImageViewer\\": "includes/"
     },
     "ContentHandlers": {
-        "annotation": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHandler"
+        "annotation": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHandler::class"
     },
     "Hooks": {
+        "ContentHandlerDefaultModelFor": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHooks::onContentHandlerDefaultModelFor"
     }
 }
\ No newline at end of file
diff --git a/includes/AnnotationContent.php b/includes/AnnotationContent.php
index ae8f492..b61c2c2 100644
--- a/includes/AnnotationContent.php
+++ b/includes/AnnotationContent.php
@@ -8,7 +8,7 @@ class AnnotationContent extends TextContent {
 	public function __construct( $modelId = 'annotation' ) {
 		parent::__construct( $modelId );
 	}
-    
+
     /*
 	public function getTextForSearchIndex() {
 	}
diff --git a/includes/AnnotationHandler.php b/includes/AnnotationHandler.php
index cb630ec..3d55a8e 100644
--- a/includes/AnnotationHandler.php
+++ b/includes/AnnotationHandler.php
@@ -4,20 +4,41 @@ namespace MediaWiki\Extension\AnatImageViewer;
 use Devium\Toml\Toml;
 use MediaWiki\MediaWikiServices;
 use Content;
-use TextContentHandler;
+use Title;
+use CodeContentHandler;
 use MediaWiki\Content\Renderer\ContentParseParams;
 use ParserOutput;
-use ConfigFactory;
-use RequestContext;
 use Html;
 
-class AnnotationHandler extends TextContentHandler {
+class AnnotationHandler extends CodeContentHandler {
     private const ANNOT_VERSION = '0.1';
 
 	public function __construct( $modelId = 'annotation' ) {
 		parent::__construct( $modelId, [ CONTENT_FORMAT_TEXT ] );
 	}
 
+	protected function getContentClass() {
+		return AnnotationContent::class;
+	}
+    
+	/**
+	 * Only allow this content handler to be used in the Module namespace
+	 * @param Title $title
+	 * @return bool
+	 */
+	public function canBeUsedOn( Title $title ) {
+		if ( $title->getNamespace() !== NS_AV_ANNOT ) {
+			return false;
+		}
+
+		return parent::canBeUsedOn( $title );
+	}
+
+	/** @inheritDoc */
+	public function supportsPreloadContent(): bool {
+		return true;
+	}
+
     /*
 	public function serializeContent( Content $content, $format = null ) {
 	}
@@ -25,7 +46,7 @@ class AnnotationHandler extends TextContentHandler {
 	public function unserializeContent( $blob, $format = null ) {
 	}
     */
-    
+
 	public function makeEmptyContent() {
 		return new AnnotationContent();
 	}
@@ -35,9 +56,7 @@ class AnnotationHandler extends TextContentHandler {
 	}
 
     protected function fillParserOutput( Content $content, ContentParseParams $cpoParams, ParserOutput &$output	) {
-		// define $html somewhere
-		// e.g. $output->setText( $html );
-
+        self::console_log('Parsing the fucking thing', true);
         self::console_log($content, true);
 
         $metadata = toml_decode($content->getNativeData(), true);
@@ -83,8 +102,6 @@ class AnnotationHandler extends TextContentHandler {
             );
             $elBaseImg = Html::rawElement('image', $attrBase);
             }
-        $mainConfig = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
-        $context = RequestContext::getMain();
 
         //Render and return svg
         $attrSvg = array(
diff --git a/includes/AnnotationHooks.php b/includes/AnnotationHooks.php
index bbb1e8a..22d081d 100644
--- a/includes/AnnotationHooks.php
+++ b/includes/AnnotationHooks.php
@@ -1,17 +1,25 @@
 getNamespace() === NS_AV_ANNOT ) {
+            self::console_log('Found fucking thing!',true);
+            $model = CONTENT_MODEL_ANNOTATION;
+		}
+	}
+
     /**
      * Small helper function to display information on the browser console
      * 
-- 
2.49.1


From aad84ac0fc0fbd33c4cd3440303225f775faa677 Mon Sep 17 00:00:00 2001
From: Justin Georgi 
Date: Mon, 18 May 2026 18:13:20 -0700
Subject: [PATCH 4/5] Basic svg rendering

Signed-off-by: Justin Georgi 
---
 extension.json                 | 17 +++++----
 includes/AnnotationContent.php | 64 ++++++++++++++++++++++++----------
 includes/AnnotationHandler.php | 33 ++++++++++--------
 3 files changed, 75 insertions(+), 39 deletions(-)

diff --git a/extension.json b/extension.json
index 8559803..2497bc2 100644
--- a/extension.json
+++ b/extension.json
@@ -7,29 +7,32 @@
 	"license-name": "MIT",
 	"type": "media",
 	"manifest_version": 1,
+	"requires": {
+		"MediaWiki": ">= 1.39.0"
+	},
     "namespaces": [
         {
             "id": 2218,
             "constant": "NS_AV_ANNOT",
             "name": "Annotation",
             "protection": "annotations-edit",
-            "subpages": false
+            "subpages": false,
+			"content": false,
+			"defaultcontentmodel": "annotation"
             },
         {
             "id": 2219,
             "constant": "NS_AV_ANNOT_TALK",
             "name": "Annotation_talk",
-            "subpages": true
+            "subpages": true,
+            "content": false,
+			"defaultcontentmodel": "wikitext"
             }
     ],
-    "callback": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHooks::registrationCallback",
 	"AutoloadNamespaces": {
 		"MediaWiki\\Extension\\AnatImageViewer\\": "includes/"
     },
     "ContentHandlers": {
-        "annotation": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHandler::class"
-    },
-    "Hooks": {
-        "ContentHandlerDefaultModelFor": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHooks::onContentHandlerDefaultModelFor"
+        "annotation": "MediaWiki\\Extension\\AnatImageViewer\\AnnotationHandler"
     }
 }
\ No newline at end of file
diff --git a/includes/AnnotationContent.php b/includes/AnnotationContent.php
index b61c2c2..7a396d5 100644
--- a/includes/AnnotationContent.php
+++ b/includes/AnnotationContent.php
@@ -1,32 +1,60 @@
 getText() ) );
+		return $text === '';
 	}
 
-	public function getWikitextForTransclusion() {
-	}
-
-	public function getTextForSummary( $maxLength = 250 ) {
-	}
-
-	public function getSize() {
-	}
-
-	public function copy() {
-	}
-    */
-
+	/**
+	 * Determines whether this content should be counted as a "page" for the wiki's statistics.
+	 *
+	 * @param bool|null $hasLinks
+	 *
+	 * @return bool
+	 */
 	public function isCountable( $hasLinks = null ) {
-        return false;
+		return false;
+	}
+
+	public function isValid() {
+		return parent::isValid();
+	}
+
+	/**
+	 * Should return text relevant to the wiki's search index.
+	 *
+	 * @return string
+	 */
+	public function getTextForSearchIndex() {
+		return strip_tags( $this->getText() );
+	}
+
+	public function convert( $toModel, $lossy = '' ) {
+		return parent::convert( $toModel, $lossy );
+	}
+
+	public function getSection( $sectionId ) {
+		return parent::getSection( $sectionId );
+	}
+
+	public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) {
+		return parent::replaceSection( $sectionId, $with, $sectionTitle );
 	}
 }
\ No newline at end of file
diff --git a/includes/AnnotationHandler.php b/includes/AnnotationHandler.php
index 3d55a8e..66a3b0a 100644
--- a/includes/AnnotationHandler.php
+++ b/includes/AnnotationHandler.php
@@ -1,6 +1,8 @@
 getNativeData(), true);
+        self::console_log(var_dump($metadata), true);
 
         if (isset($metadata['baseImage'])) {
             $baseImage = MediaWikiServices::getInstance()->getRepoGroup()->findFile('File:' . $metadata['baseImage']);
@@ -77,11 +82,11 @@ class AnnotationHandler extends CodeContentHandler {
      * and produces the html string for the svg with base image and annotations.
      * 
      * @param string $metadata The metadata object parsed from the text
-     * @param string $baseImageUrl The full url pointing to the base image to annotate
-     * @param array $frameParams The additional user defined parameters for the viewer such as hotspot and view classes
-     * @return string Html string of the complete model-viewer element inside a div container
+     * @param string $baseImage The full url pointing to the base image to annotate
+     * @return string Html string of the complete svg
      */
     private function buildSvg($metadata, $baseImage) {
+        self::console_log(var_dump($baseImage), true);
         //Gather basic data
         $elBaseImg = '';
         $vbHeight = 100;
-- 
2.49.1


From 15f77d45ba3889d996fdf6b5c5c548ac5d56877c Mon Sep 17 00:00:00 2001
From: Justin Georgi 
Date: Tue, 19 May 2026 15:24:27 -0700
Subject: [PATCH 5/5] Generate SVG with base image

Signed-off-by: Justin Georgi 
---
 includes/AnnotationHandler.php | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/includes/AnnotationHandler.php b/includes/AnnotationHandler.php
index 66a3b0a..ea52a62 100644
--- a/includes/AnnotationHandler.php
+++ b/includes/AnnotationHandler.php
@@ -61,13 +61,16 @@ class AnnotationHandler extends CodeContentHandler {
 	}
 
     protected function fillParserOutput( Content $content, ContentParseParams $cpoParams, ParserOutput &$output	) {
+        parent::fillParserOutput( $content, $cpoParams, $output );
         self::console_log('Parsing the fucking thing', true);
 
-        $metadata = toml_decode($content->getNativeData(), true);
-        self::console_log(var_dump($metadata), true);
+        $metadata = toml_decode($content->getText(), true);
+        self::console_log(print_r($metadata, true), true);
 
         if (isset($metadata['baseImage'])) {
-            $baseImage = MediaWikiServices::getInstance()->getRepoGroup()->findFile('File:' . $metadata['baseImage']);
+            $imageTitle = Title::makeTitleSafe( NS_FILE, $metadata['baseImage'] );
+            $baseImage = MediaWikiServices::getInstance()->getRepoGroup()->findFile($imageTitle);
+            self::console_log($baseImage->getFullUrl(), true);
         } else {
             $baseImage = false;
         }
@@ -82,11 +85,10 @@ class AnnotationHandler extends CodeContentHandler {
      * and produces the html string for the svg with base image and annotations.
      * 
      * @param string $metadata The metadata object parsed from the text
-     * @param string $baseImage The full url pointing to the base image to annotate
+     * @param File $baseImage The full url pointing to the base image to annotate
      * @return string Html string of the complete svg
      */
     private function buildSvg($metadata, $baseImage) {
-        self::console_log(var_dump($baseImage), true);
         //Gather basic data
         $elBaseImg = '';
         $vbHeight = 100;
-- 
2.49.1