diff --git a/independent-publisher-connectors/Markdown Converter/Markdown Converter.zip b/independent-publisher-connectors/Markdown Converter/Markdown Converter.zip new file mode 100644 index 0000000000..ca282d92e0 Binary files /dev/null and b/independent-publisher-connectors/Markdown Converter/Markdown Converter.zip differ diff --git a/independent-publisher-connectors/Markdown Converter/apiDefinition.swagger.json b/independent-publisher-connectors/Markdown Converter/apiDefinition.swagger.json new file mode 100644 index 0000000000..a5d79994fe --- /dev/null +++ b/independent-publisher-connectors/Markdown Converter/apiDefinition.swagger.json @@ -0,0 +1,2193 @@ +{ + "swagger": "2.0", + "info": { + "title": "Markdown Converter (Independent Publisher)", + "description": "A comprehensive markdown converter that supports transformations to various formats including HTML, JSON, XML, and many more.", + "version": "1.0", + "contact": { + "name": "Troy Taylor", + "url": "https://www.troystaylor.com", + "email": "troy@troystaylor.com" + } + }, + "host": "troystaylor.com", + "basePath": "/markdown", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/convert/toHtml": { + "post": { + "summary": "Convert Markdown to HTML", + "description": "Converts Markdown content to HTML format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support).", + "operationId": "MarkdownToHtml", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to HTML", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "html": { + "type": "string", + "description": "The HTML output.", + "x-ms-summary": "HTML Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toJson": { + "post": { + "summary": "Convert Markdown to JSON", + "description": "Converts Markdown content to a structured JSON format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support).", + "operationId": "MarkdownToJson", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to JSON", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "structuredData": { + "type": "object", + "description": "The structured JSON output.", + "x-ms-summary": "JSON Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toXml": { + "post": { + "summary": "Convert Markdown to XML", + "description": "Converts Markdown content to XML format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support).", + "operationId": "MarkdownToXml", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to XML", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "xml": { + "type": "string", + "description": "The XML output.", + "x-ms-summary": "XML Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toPlainText": { + "post": { + "summary": "Convert Markdown to plain text", + "description": "Converts Markdown content to plain text format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support).", + "operationId": "MarkdownToPlainText", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to plain text", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "plainText": { + "type": "string", + "description": "The plain text output.", + "x-ms-summary": "Plain Text Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toCsv": { + "post": { + "summary": "Convert Markdown to CSV", + "description": "Converts Markdown tables to CSV format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support).", + "operationId": "MarkdownToCsv", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to CSV", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "csv": { + "type": "string", + "description": "The CSV output.", + "x-ms-summary": "CSV Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toLaTeX": { + "post": { + "summary": "Convert Markdown to LaTeX", + "description": "Converts Markdown content to LaTeX format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support).", + "operationId": "MarkdownToLaTeX", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to LaTeX", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "latex": { + "type": "string", + "description": "The LaTeX output.", + "x-ms-summary": "LaTeX Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toAdaptiveCard": { + "post": { + "summary": "Convert Markdown to Adaptive Card", + "description": "Converts Markdown content to Microsoft Adaptive Card JSON format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support).", + "operationId": "MarkdownToAdaptiveCard", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to Adaptive Card", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "adaptiveCard": { + "type": "object", + "description": "The Adaptive Card output as JSON.", + "x-ms-summary": "Adaptive Card Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toYaml": { + "post": { + "summary": "Convert Markdown to YAML", + "description": "Converts Markdown content to YAML format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support).", + "operationId": "MarkdownToYaml", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to YAML", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "yaml": { + "type": "string", + "description": "The YAML output.", + "x-ms-summary": "YAML Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toEmail": { + "post": { + "summary": "Convert Markdown to email HTML", + "description": "Converts Markdown content to email-friendly HTML format.", + "operationId": "MarkdownToEmail", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to email HTML", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "emailHtml": { + "type": "string", + "description": "The email HTML output.", + "x-ms-summary": "Email HTML Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toSvg": { + "post": { + "summary": "Convert Markdown to SVG", + "description": "Converts Markdown content to SVG format.", + "operationId": "MarkdownToSvg", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to SVG", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "svg": { + "type": "string", + "description": "The SVG output.", + "x-ms-summary": "SVG Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toRss": { + "post": { + "summary": "Convert Markdown to RSS", + "description": "Converts Markdown content to RSS format.", + "operationId": "MarkdownToRss", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to RSS", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "rss": { + "type": "string", + "description": "The RSS output.", + "x-ms-summary": "RSS Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toWiki": { + "post": { + "summary": "Convert Markdown to Wiki Markup", + "description": "Converts Markdown content to wiki markup format.", + "operationId": "MarkdownToWiki", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to Wiki Markup", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "wikiMarkup": { + "type": "string", + "description": "The Wiki markup output.", + "x-ms-summary": "Wiki Markup Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toPng": { + "post": { + "summary": "Convert Markdown to PNG image", + "description": "Converts Markdown content to PNG image format.", + "operationId": "MarkdownToPng", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to PNG image", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "pngBase64": { + "type": "string", + "description": "The PNG image in Base64 encoding.", + "x-ms-summary": "PNG Base64" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the output.", + "x-ms-summary": "MIME Type" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toChart": { + "post": { + "summary": "Convert Markdown to chart", + "description": "Converts Markdown content to a chart image.", + "operationId": "MarkdownToChart", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to chart", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "chartBase64": { + "type": "string", + "description": "The chart image in Base64 encoding.", + "x-ms-summary": "Chart Base64" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the output.", + "x-ms-summary": "MIME Type" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toDiagram": { + "post": { + "summary": "Convert Markdown to diagram", + "description": "Converts Markdown content to a diagram image.", + "operationId": "MarkdownToDiagram", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to diagram", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "diagramBase64": { + "type": "string", + "description": "The diagram image in Base64 encoding.", + "x-ms-summary": "Diagram Base64" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the output.", + "x-ms-summary": "MIME Type" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/statistics": { + "post": { + "summary": "Get Markdown statistics", + "description": "Analyzes Markdown content and returns statistics about it.", + "operationId": "MarkdownStats", + "x-ms-visibility": "important", + "x-ms-summary": "Get Markdown statistics", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to analyze.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to analyze.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Statistics generated successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "statistics": { + "type": "object", + "description": "Statistics about the markdown content.", + "x-ms-summary": "Statistics", + "properties": { + "characterCount": { + "type": "integer", + "description": "Total character count.", + "x-ms-summary": "Character Count" + }, + "wordCount": { + "type": "integer", + "description": "Total word count.", + "x-ms-summary": "Word Count" + }, + "lineCount": { + "type": "integer", + "description": "Total line count.", + "x-ms-summary": "Line Count" + }, + "paragraphCount": { + "type": "integer", + "description": "Total paragraph count.", + "x-ms-summary": "Paragraph Count" + }, + "headingCount": { + "type": "integer", + "description": "Total heading count.", + "x-ms-summary": "Heading Count" + }, + "linkCount": { + "type": "integer", + "description": "Total link count.", + "x-ms-summary": "Link Count" + }, + "imageCount": { + "type": "integer", + "description": "Total image count.", + "x-ms-summary": "Image Count" + }, + "tableCount": { + "type": "integer", + "description": "Total table count.", + "x-ms-summary": "Table Count" + }, + "codeBlockCount": { + "type": "integer", + "description": "Total code block count.", + "x-ms-summary": "Code Block Count" + } + } + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of analysis.", + "x-ms-summary": "Analysis Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toQr": { + "post": { + "summary": "Convert Markdown to QR code", + "description": "Converts Markdown content to a QR code image.", + "operationId": "MarkdownToQr", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to QR code", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "qrBase64": { + "type": "string", + "description": "The QR code image in Base64 encoding.", + "x-ms-summary": "QR Base64" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the output.", + "x-ms-summary": "MIME Type" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toJpeg": { + "post": { + "summary": "Convert Markdown to JPEG image", + "description": "Converts Markdown content to JPEG image format.", + "operationId": "MarkdownToJpeg", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to JPEG image", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "jpegBase64": { + "type": "string", + "description": "The JPEG image in Base64 encoding.", + "x-ms-summary": "JPEG Base64" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the output.", + "x-ms-summary": "MIME Type" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toBadge": { + "post": { + "summary": "Convert Markdown to badge", + "description": "Converts Markdown content to a badge image.", + "operationId": "MarkdownToBadge", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to badge", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "badgeBase64": { + "type": "string", + "description": "The badge image in Base64 encoding.", + "x-ms-summary": "Badge Base64" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the output.", + "x-ms-summary": "MIME Type" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toInfographic": { + "post": { + "summary": "Convert Markdown to infographic", + "description": "Converts Markdown content to an infographic image.", + "operationId": "MarkdownToInfographic", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to infographic", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "infographicBase64": { + "type": "string", + "description": "The infographic image in Base64 encoding.", + "x-ms-summary": "Infographic Base64" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the output.", + "x-ms-summary": "MIME Type" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toLog": { + "post": { + "summary": "Convert Markdown to log format", + "description": "Converts Markdown content to log format.", + "operationId": "MarkdownToLog", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to log format", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "logOutput": { + "type": "string", + "description": "The log format output.", + "x-ms-summary": "Log Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toMetrics": { + "post": { + "summary": "Convert Markdown to metrics format", + "description": "Converts Markdown content to metrics format.", + "operationId": "MarkdownToMetrics", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to metrics format", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "metricsOutput": { + "type": "string", + "description": "The metrics format output.", + "x-ms-summary": "Metrics Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toSyslog": { + "post": { + "summary": "Convert Markdown to syslog format", + "description": "Converts Markdown content to syslog format.", + "operationId": "MarkdownToSyslog", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to syslog format", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "syslogOutput": { + "type": "string", + "description": "The syslog format output.", + "x-ms-summary": "Syslog Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toJsDoc": { + "post": { + "summary": "Convert Markdown to JSDoc", + "description": "Converts Markdown content to JSDoc format.", + "operationId": "MarkdownToJsDoc", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to JSDoc", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "jsDoc": { + "type": "string", + "description": "The JSDoc output.", + "x-ms-summary": "JSDoc Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toXmlDoc": { + "post": { + "summary": "Convert Markdown to XML documentation", + "description": "Converts Markdown content to XML documentation format.", + "operationId": "MarkdownToXmlDoc", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to XML documentation", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "xmlDoc": { + "type": "string", + "description": "The XML documentation output.", + "x-ms-summary": "XML Documentation Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toReadme": { + "post": { + "summary": "Convert Markdown to README format", + "description": "Converts and formats Markdown content to a README style format.", + "operationId": "MarkdownToReadme", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to README format", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "readme": { + "type": "string", + "description": "The README-formatted output.", + "x-ms-summary": "README Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toChangelog": { + "post": { + "summary": "Convert Markdown to changelog format", + "description": "Converts and formats Markdown content to a changelog format.", + "operationId": "MarkdownToChangelog", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to changelog format", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "changelog": { + "type": "string", + "description": "The changelog-formatted output.", + "x-ms-summary": "Changelog Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toTableOfContents": { + "post": { + "summary": "Convert Markdown to Table of Contents", + "description": "Extracts headings from Markdown content and generates a table of contents.", + "operationId": "MarkdownToTableOfContents", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to Table of Contents", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to process.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to process.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Table of contents generated successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "tableOfContents": { + "type": "string", + "description": "The table of contents output.", + "x-ms-summary": "Table of Contents" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of generation.", + "x-ms-summary": "Generation Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/convert/toStyledHtml": { + "post": { + "summary": "Convert Markdown to styled HTML", + "description": "Converts Markdown content to HTML with custom CSS styling.", + "operationId": "MarkdownToStyledHtml", + "x-ms-visibility": "important", + "x-ms-summary": "Convert to styled HTML", + "parameters": [ + { + "name": "body", + "in": "body", + "description": "Markdown content to convert.", + "required": true, + "schema": { + "type": "object", + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "title": "Markdown Content", + "x-ms-visibility": "important", + "x-ms-summary": "Markdown Content" + }, + "theme": { + "type": "string", + "description": "Optional theme name for styling.", + "title": "Theme", + "x-ms-visibility": "advanced", + "x-ms-summary": "Theme" + } + }, + "required": [ + "markdown" + ] + } + } + ], + "responses": { + "200": { + "description": "Conversion completed successfully.", + "schema": { + "type": "object", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "styledHtml": { + "type": "string", + "description": "The styled HTML output.", + "x-ms-summary": "Styled HTML Output" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "400": { + "description": "Bad request - invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/info": { + "get": { + "summary": "Get Markdown Converter information", + "description": "Returns information about the Markdown converter capabilities and supported formats.", + "operationId": "MarkdownInfo", + "x-ms-visibility": "advanced", + "x-ms-summary": "Get converter information", + "parameters": [], + "responses": { + "200": { + "description": "Information retrieved successfully.", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the converter.", + "x-ms-summary": "Converter Name" + }, + "version": { + "type": "string", + "description": "The version of the converter.", + "x-ms-summary": "Version" + }, + "supportedFormats": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of supported output formats.", + "x-ms-summary": "Supported Formats" + }, + "capabilities": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of special capabilities.", + "x-ms-summary": "Capabilities" + }, + "timestamp": { + "type": "string", + "description": "Time of the request.", + "x-ms-summary": "Request Time" + } + } + } + }, + "500": { + "description": "Internal server error." + } + } + } + } + }, + "definitions": { + "MarkdownRequest": { + "type": "object", + "description": "A request containing Markdown content to convert.", + "required": [ + "markdown" + ], + "properties": { + "markdown": { + "type": "string", + "description": "Markdown content to convert.", + "x-ms-summary": "Markdown Content" + } + } + }, + "MarkdownResponse": { + "type": "object", + "description": "Generic response format for markdown conversions.", + "properties": { + "originalMarkdown": { + "type": "string", + "description": "The original markdown content.", + "x-ms-summary": "Original Markdown" + }, + "format": { + "type": "string", + "description": "The output format.", + "x-ms-summary": "Output Format" + }, + "timestamp": { + "type": "string", + "description": "Time of conversion.", + "x-ms-summary": "Conversion Time" + } + } + } + }, + "x-ms-connector-metadata": [ + { + "propertyName": "Website", + "propertyValue": "https://www.troystaylor.com" + }, + { + "propertyName": "Privacy policy", + "propertyValue": "https://www.troystaylor.com" + }, + { + "propertyName": "Categories", + "propertyValue": "Content and Files" + } + ], + "security": [] +} \ No newline at end of file diff --git a/independent-publisher-connectors/Markdown Converter/apiProperties.json b/independent-publisher-connectors/Markdown Converter/apiProperties.json new file mode 100644 index 0000000000..b1fcaecbce --- /dev/null +++ b/independent-publisher-connectors/Markdown Converter/apiProperties.json @@ -0,0 +1,10 @@ +{ + "properties": { + "connectionParameters": {}, + "iconBrandColor": "#da3b01", + "scriptOperations": [], + "capabilities": [], + "policyTemplateInstances": [], + "publisher": "Troy Taylor" + } +} \ No newline at end of file diff --git a/independent-publisher-connectors/Markdown Converter/readme.md b/independent-publisher-connectors/Markdown Converter/readme.md new file mode 100644 index 0000000000..5fb8376ded --- /dev/null +++ b/independent-publisher-connectors/Markdown Converter/readme.md @@ -0,0 +1,75 @@ +# Markdown Converter (Independent Publisher) +A comprehensive markdown converter that supports transformations to various formats including HTML, JSON, XML, and many more. + +## Publisher: Troy Taylor + +## Prerequisites +There are no prerequisites to use this connector. + +## Obtaining Credentials +There are no credentials needed to use this connector. + +## Supported Operations +### Convert Markdown to HTML +Converts Markdown content to HTML format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support). +### Convert Markdown to JSON +Converts Markdown content to a structured JSON format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support). +### Convert Markdown to XML +Converts Markdown content to XML format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support). +### Convert Markdown to plain text +Converts Markdown content to plain text format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support). +### Convert Markdown to CSV +Converts Markdown tables to CSV format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support). +### Convert Markdown to LaTeX +Converts Markdown content to LaTeX format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support). +### Convert Markdown to Adaptive Card +Converts Markdown content to Microsoft Adaptive Card JSON format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support). +### Convert Markdown to YAML +Converts Markdown content to YAML format with enhanced features (including math/TeX support, task lists, footnotes, embedded content, reference links, fenced divs, strikethrough, highlighting, subscript, superscript, and emoji support). +### Convert Markdown to email HTML +Converts Markdown content to email-friendly HTML format. +### Convert Markdown to SVG +Converts Markdown content to SVG format. +### Convert Markdown to RSS +Converts Markdown content to RSS format. +### Convert Markdown to Wiki Markup +Converts Markdown content to wiki markup format. +### Convert Markdown to PNG image +Converts Markdown content to PNG image format. +### Convert Markdown to chart +Converts Markdown content to a chart image. +### Convert Markdown to diagram +Converts Markdown content to a diagram image. +### Convert Markdown to QR code +Converts Markdown content to a QR code image. +### Convert Markdown to JPEG image +Converts Markdown content to JPEG image format. +### Convert Markdown to badge +Converts Markdown content to a badge image. +### Convert Markdown to infographic +Converts Markdown content to an infographic image. +### Convert Markdown to log format +Converts Markdown content to log format. +### Convert Markdown to metrics format +Converts Markdown content to metrics format. +### Convert Markdown to syslog format +Converts Markdown content to syslog format. +### Convert Markdown to JSDoc +Converts Markdown content to JSDoc format. +### Convert Markdown to XML documentation +Converts Markdown content to XML documentation format. +### Convert Markdown to README format +Converts and formats Markdown content to a README style format. +### Convert Markdown to changelog format +Converts and formats Markdown content to a changelog format. +### Convert Markdown to Table of Contents +Extracts headings from Markdown content and generates a table of contents. +### Convert Markdown to styled HTML +Converts Markdown content to HTML with custom CSS styling. +### Get Markdown Converter information +Returns information about the Markdown converter capabilities and supported formats. +### Get Markdown statistics +Analyzes Markdown content and returns statistics about it. + +## Known Issues and Limitations +There are no known issues at this time. diff --git a/independent-publisher-connectors/Markdown Converter/script.csx b/independent-publisher-connectors/Markdown Converter/script.csx new file mode 100644 index 0000000000..a90d9d91d6 --- /dev/null +++ b/independent-publisher-connectors/Markdown Converter/script.csx @@ -0,0 +1,2849 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +public class Script : ScriptBase +{ + public override async Task ExecuteAsync() + { + // Get the real operation ID (handle base64 encoding as per Microsoft docs) + string realOperationId = this.Context.OperationId; + string originalOperationId = realOperationId; + + // First, check if it's already a known operation ID + if (!IsKnownOperationId(realOperationId)) + { + // Only attempt base64 decoding if the string could be base64 and doesn't look like a normal operation ID + if (IsLikelyBase64(realOperationId) && !IsValidOperationId(realOperationId)) + { + try + { + byte[] data = Convert.FromBase64String(realOperationId); + string decoded = System.Text.Encoding.UTF8.GetString(data); + + // Only use decoded value if it produces a valid operation ID + if (IsValidOperationId(decoded) && IsKnownOperationId(decoded)) + { + realOperationId = decoded; + } + } + catch (Exception) + { + // Any exception means we should use the original value + realOperationId = originalOperationId; + } + } + } + + // Check operation ID and route to appropriate handler + if (realOperationId == "MarkdownToHtml") + { + return await this.HandleMarkdownToHtml().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToAdaptiveCard") + { + return await this.HandleMarkdownToAdaptiveCard().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToChart") + { + return await this.HandleMarkdownToChart().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToQr") + { + return await this.HandleMarkdownToQR().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToJson") + { + return await this.HandleMarkdownToJson().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToXml") + { + return await this.HandleMarkdownToXml().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToPlainText") + { + return await this.HandleMarkdownToPlainText().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToCsv") + { + return await this.HandleMarkdownToCsv().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToLaTeX") + { + return await this.HandleMarkdownToLaTeX().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToYaml") + { + return await this.HandleMarkdownToEmail().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToEmail") + { + return await this.HandleMarkdownToEmail().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToSvg") + { + return await this.HandleMarkdownToSvg().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToRss") + { + return await this.HandleMarkdownToRss().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToWiki") + { + return await this.HandleMarkdownToWiki().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToPng") + { + return await this.HandleMarkdownToPng().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToDiagram") + { + return await this.HandleMarkdownToDiagram().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownStats") + { + return await this.HandleMarkdownStats().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToJpeg") + { + return await this.HandleMarkdownToJpeg().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToBadge") + { + return await this.HandleMarkdownToBadge().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToInfographic") + { + return await this.HandleMarkdownToInfographic().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToLog") + { + return await this.HandleMarkdownToLog().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToMetrics") + { + return await this.HandleMarkdownToMetrics().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToSyslog") + { + return await this.HandleMarkdownToSyslog().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToJsDoc") + { + return await this.HandleMarkdownToJsDoc().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToXmlDoc") + { + return await this.HandleMarkdownToXmlDoc().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToReadme") + { + return await this.HandleMarkdownToReadme().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToChangelog") + { + return await this.HandleMarkdownToChangelog().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToTableOfContents") + { + return await this.HandleMarkdownToTableOfContents().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownToStyledHtml") + { + return await this.HandleMarkdownToStyledHtml().ConfigureAwait(false); + } + else if (realOperationId == "MarkdownInfo") + { + return await this.HandleMarkdownInfo().ConfigureAwait(false); + } + // Handle unknown operation ID + HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest); + response.Content = CreateJsonContent(new JObject + { + ["error"] = $"Unknown operation ID '{realOperationId}'", + ["receivedOperationId"] = realOperationId, + ["originalOperationId"] = originalOperationId, + ["operationIdLength"] = realOperationId?.Length ?? 0, + ["originalOperationIdLength"] = originalOperationId?.Length ?? 0, + ["isValidFormat"] = IsValidOperationId(realOperationId ?? ""), + ["availableOperations"] = new JArray("MarkdownToHtml", "MarkdownToAdaptiveCard", "MarkdownToChart", "MarkdownToQr", "MarkdownToJson", "MarkdownToXml", "MarkdownToPlainText", "MarkdownToCsv", "MarkdownToLaTeX", "MarkdownToYaml", "MarkdownToEmail", "MarkdownToSvg", "MarkdownToRss", "MarkdownToWiki", "MarkdownToPng", "MarkdownToDiagram", "MarkdownStats", "MarkdownToJpeg", "MarkdownToBadge", "MarkdownToInfographic", "MarkdownToLog", "MarkdownToMetrics", "MarkdownToSyslog", "MarkdownToJsDoc", "MarkdownToXmlDoc", "MarkdownToReadme", "MarkdownToChangelog", "MarkdownToTableOfContents", "MarkdownToStyledHtml", "MarkdownInfo"), + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return response; + } + + private async Task HandleMarkdownToHtml() + { + try + { + // Read request content + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided. Please include 'markdown' or 'text' field in request body.", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + // Convert markdown to HTML + var html = ConvertToHtml(markdown); + + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["html"] = html, + ["format"] = "html", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToAdaptiveCard() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + // Convert to Adaptive Card + var adaptiveCard = ConvertMarkdownToAdaptiveCardJson(markdown); + + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["adaptiveCard"] = adaptiveCard, + ["format"] = "adaptiveCard", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToChart() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + // Generate chart + var chartBase64 = ConvertToChart(markdown); + + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["chartBase64"] = chartBase64, + ["format"] = "chart", + ["mimeType"] = "image/png", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToQR() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + // Generate QR code + var qrBase64 = ConvertToQRCode(markdown); + + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["qrBase64"] = qrBase64, + ["format"] = "qr", + ["mimeType"] = "image/png", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToJson() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + // Convert to JSON structure + var jsonStructure = ConvertToJsonStructure(markdown); + + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["jsonStructure"] = jsonStructure, + ["format"] = "json", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToXml() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + // Convert to XML + var xml = ConvertToXml(markdown); + + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["xml"] = xml, + ["format"] = "xml", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToPlainText() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + // Convert to plain text + var plainText = ConvertToPlainText(markdown); + + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["plainText"] = plainText, + ["format"] = "plainText", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + // Additional format handlers + private async Task HandleMarkdownToCsv() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + var csv = ConvertToCsv(markdown); + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["csv"] = csv, + ["format"] = "csv", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToLaTeX() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + var latex = ConvertToLaTeX(markdown); + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["latex"] = latex, + ["format"] = "latex", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToYaml() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + var yaml = ConvertToYaml(markdown); + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["yaml"] = yaml, + ["format"] = "yaml", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownToEmail() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + var email = ConvertToEmail(markdown); + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["emailHtml"] = email, + ["format"] = "email", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownStats() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + var stats = GetMarkdownStats(markdown); + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["stats"] = stats, + ["format"] = "stats", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + private async Task HandleMarkdownInfo() + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + var info = GetMarkdownInfo(markdown); + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + ["info"] = info, + ["format"] = "info", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } + + // Basic HTML conversion + private string ConvertToHtml(string markdown) + { + if (string.IsNullOrWhiteSpace(markdown)) + return ""; + + var html = new StringBuilder(); + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + bool inCodeBlock = false; + bool inList = false; + bool inOrderedList = false; + bool inBlockquote = false; + string codeBlockLanguage = ""; + + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + var originalLine = line; + + // Handle code blocks + if (trimmedLine.StartsWith("```")) + { + if (inCodeBlock) + { + html.AppendLine(""); + inCodeBlock = false; + codeBlockLanguage = ""; + } + else + { + codeBlockLanguage = trimmedLine.Substring(3).Trim(); + html.AppendLine($"
");
+                    inCodeBlock = true;
+                }
+                continue;
+            }
+
+            if (inCodeBlock)
+            {
+                html.AppendLine(System.Web.HttpUtility.HtmlEncode(originalLine));
+                continue;
+            }
+
+            // Handle empty lines
+            if (string.IsNullOrWhiteSpace(trimmedLine))
+            {
+                if (inList)
+                {
+                    html.AppendLine(inOrderedList ? "" : "");
+                    inList = false;
+                    inOrderedList = false;
+                }
+                if (inBlockquote)
+                {
+                    html.AppendLine("");
+                    inBlockquote = false;
+                }
+                continue;
+            }
+
+            // Handle headings
+            if (trimmedLine.StartsWith("#"))
+            {
+                if (inList)
+                {
+                    html.AppendLine(inOrderedList ? "" : "");
+                    inList = false;
+                    inOrderedList = false;
+                }
+                if (inBlockquote)
+                {
+                    html.AppendLine("");
+                    inBlockquote = false;
+                }
+
+                var level = 0;
+                while (level < trimmedLine.Length && trimmedLine[level] == '#')
+                    level++;
+
+                if (level <= 6)
+                {
+                    var text = trimmedLine.Substring(level).Trim();
+                    // Generate heading ID for anchor links
+                    var headingId = text.ToLower().Replace(" ", "-").Replace("[^a-z0-9-]", "");
+                    html.AppendLine($"{ProcessInlineMarkdown(text)}");
+                    continue;
+                }
+            }
+
+            // Handle blockquotes
+            if (trimmedLine.StartsWith(">"))
+            {
+                if (!inBlockquote)
+                {
+                    html.AppendLine("
"); + inBlockquote = true; + } + var text = trimmedLine.Substring(1).Trim(); + html.AppendLine($"

{ProcessInlineMarkdown(text)}

"); + continue; + } + else if (inBlockquote) + { + html.AppendLine("
"); + inBlockquote = false; + } + + // Handle ordered lists + if (Regex.IsMatch(trimmedLine, @"^\d+\.\s")) + { + if (!inList) + { + html.AppendLine("
    "); + inList = true; + inOrderedList = true; + } + else if (!inOrderedList) + { + html.AppendLine(""); + html.AppendLine("
      "); + inOrderedList = true; + } + var match = Regex.Match(trimmedLine, @"^\d+\.\s(.*)"); + var text = match.Groups[1].Value; + html.AppendLine($"
    1. {ProcessInlineMarkdown(text)}
    2. "); + continue; + } + + // Handle unordered lists + if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* ") || trimmedLine.StartsWith("+ ")) + { + if (!inList) + { + html.AppendLine("
        "); + inList = true; + inOrderedList = false; + } + else if (inOrderedList) + { + html.AppendLine("
    "); + html.AppendLine("
      "); + inOrderedList = false; + } + var text = trimmedLine.Substring(2).Trim(); + html.AppendLine($"
    • {ProcessInlineMarkdown(text)}
    • "); + continue; + } // Handle horizontal rules + if (trimmedLine == "---" || trimmedLine == "***" || trimmedLine == "___") + { + if (inList) + { + html.AppendLine(inOrderedList ? "
" : ""); + inList = false; + inOrderedList = false; + } + html.AppendLine("
"); + continue; + } + + // Handle tables + if (trimmedLine.Contains("|") && !inCodeBlock) + { + if (inList) + { + html.AppendLine(inOrderedList ? "" : ""); + inList = false; + inOrderedList = false; + } + + var tableLines = new List { originalLine }; + + // Look ahead to find the complete table + for (int i = Array.IndexOf(lines, originalLine) + 1; i < lines.Length; i++) + { + if (lines[i].Contains("|")) + { + tableLines.Add(lines[i]); + } + else + { + break; + } + } + + // Process the table + if (tableLines.Count >= 2) + { + html.AppendLine(""); + + // Header row + var headerCells = tableLines[0].Split('|').Select(cell => cell.Trim()).Where(cell => !string.IsNullOrEmpty(cell)).ToArray(); + if (headerCells.Length > 0) + { + html.AppendLine(""); + foreach (var cell in headerCells) + { + html.AppendLine($""); + } + html.AppendLine(""); + } + + // Skip separator row (if it exists) + int dataRowStart = tableLines.Count > 1 && tableLines[1].Contains("-") ? 2 : 1; + + // Data rows + if (dataRowStart < tableLines.Count) + { + html.AppendLine(""); + for (int i = dataRowStart; i < tableLines.Count; i++) + { + var dataCells = tableLines[i].Split('|').Select(cell => cell.Trim()).Where(cell => !string.IsNullOrEmpty(cell)).ToArray(); + if (dataCells.Length > 0) + { + html.AppendLine(""); + foreach (var cell in dataCells) + { + html.AppendLine($""); + } + html.AppendLine(""); + } + } + html.AppendLine(""); + } + + html.AppendLine("
{ProcessInlineMarkdown(cell)}
{ProcessInlineMarkdown(cell)}
"); + + // Skip the lines we've already processed + for (int skip = 1; skip < tableLines.Count; skip++) + { + // This is a bit tricky since we can't modify the foreach iterator + // We'll handle this by checking if the line was already processed + } + } + continue; + } + + // Close lists if we're not in one anymore + if (inList) + { + html.AppendLine(inOrderedList ? "" : ""); + inList = false; + inOrderedList = false; + } + + // Handle paragraphs + if (!string.IsNullOrWhiteSpace(trimmedLine)) + { + html.AppendLine($"

{ProcessInlineMarkdown(trimmedLine)}

"); + } + } + + // Close any remaining open tags + if (inList) + { + html.AppendLine(inOrderedList ? "" : ""); + } + if (inBlockquote) + { + html.AppendLine(""); + } + if (inCodeBlock) + { + html.AppendLine("
"); + } + + return html.ToString(); + } + private string ProcessInlineMarkdown(string text) + { + // Handle HTML entities first to prevent double encoding + text = System.Web.HttpUtility.HtmlEncode(text); + + // Links [text](url) and [text](url "title") + text = Regex.Replace(text, @"\[([^\]]+)\]\(([^)]+?)(?:\s"([^"]+)")?\)", + match => + { + var linkText = match.Groups[1].Value; + var url = match.Groups[2].Value; + var title = match.Groups[3].Success ? $" title=\"{match.Groups[3].Value}\"" : ""; + return $"{linkText}"; + }); + + // Reference links [text][ref] - simplified version + text = Regex.Replace(text, @"\[([^\]]+)\]\[([^\]]+)\]", "$1"); + + // Auto links + text = Regex.Replace(text, @"<(https?://[^>]+)>", "$1"); + text = Regex.Replace(text, @"<([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})>", "$1"); + + // Images ![alt](url) and ![alt](url "title") + text = Regex.Replace(text, @"!\[([^\]]*)\]\(([^)]+?)(?:\s"([^"]+)")?\)", + match => + { + var alt = match.Groups[1].Value; + var url = match.Groups[2].Value; + var title = match.Groups[3].Success ? $" title=\"{match.Groups[3].Value}\"" : ""; + return $"\"{alt}\"{title}"; + }); + + // Bold **text** or __text__ (non-greedy) + text = Regex.Replace(text, @"\*\*(.*?)\*\*", "$1"); + text = Regex.Replace(text, @"__(.*?)__", "$1"); + + // Italic *text* or _text_ (with negative lookbehind/lookahead to avoid conflicts) + text = Regex.Replace(text, @"(?$1"); + text = Regex.Replace(text, @"(?$1"); + + // Strikethrough ~~text~~ + text = Regex.Replace(text, @"~~(.*?)~~", "$1"); + + // Superscript x^2^ and subscript H~2~O + text = Regex.Replace(text, @"\^([^^]+?)\^", "$1"); + text = Regex.Replace(text, @"~([^~]+?)~", "$1"); + + // Inline code `text` (preserve encoded content) + text = Regex.Replace(text, @"`([^`]+?)`", match => + { + var code = match.Groups[1].Value; + // Decode for code content since it should be literal + code = System.Web.HttpUtility.HtmlDecode(code); + code = System.Web.HttpUtility.HtmlEncode(code); + return $"{code}"; + }); + + // Keyboard keys [[Ctrl+C]] + text = Regex.Replace(text, @"\[\[([^\]]+?)\]\]", "$1"); + + // Highlight ==text== + text = Regex.Replace(text, @"==(.*?)==", "$1"); + + // Task lists - [ ] and [x] + text = Regex.Replace(text, @"- \[ \]", " "); + text = Regex.Replace(text, @"- \[x\]", " "); + + // Footnote references [^1] + text = Regex.Replace(text, @"\[\^([^\]]+?)\]", "$1"); + + // Line breaks (two spaces at end of line) + text = Regex.Replace(text, @" $", "
", RegexOptions.Multiline); + + return text; + } + + // Basic Adaptive Card conversion + private JObject ConvertMarkdownToAdaptiveCardJson(string markdown) + { + var cardElements = new JArray(); + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + + if (string.IsNullOrWhiteSpace(trimmedLine)) + continue; + + // Handle headings + if (trimmedLine.StartsWith("#")) + { + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') + level++; + + var text = trimmedLine.Substring(level).Trim(); + var size = level == 1 ? "Large" : level == 2 ? "Medium" : "Default"; + var weight = level <= 2 ? "Bolder" : "Default"; + + cardElements.Add(new JObject + { + ["type"] = "TextBlock", + ["text"] = text, + ["size"] = size, + ["weight"] = weight + }); + } + else + { + // Regular text + cardElements.Add(new JObject + { + ["type"] = "TextBlock", + ["text"] = trimmedLine, + ["wrap"] = true + }); + } + } + + return new JObject + { + ["type"] = "AdaptiveCard", + ["$schema"] = "http://adaptivecards.io/schemas/adaptive-card.json", + ["version"] = "1.3", + ["body"] = cardElements + }; + } + + // Basic chart generation + private string ConvertToChart(string markdown) + { + var lines = markdown.Split('\n'); + var headingCount = lines.Count(line => line.TrimStart().StartsWith("#")); + var listCount = lines.Count(line => line.TrimStart().StartsWith("- ") || line.TrimStart().StartsWith("* ")); + + var svg = $@" + + Markdown Content Chart + + + Headings: {headingCount} + + + Lists: {listCount} + "; + + var svgBytes = Encoding.UTF8.GetBytes(svg); + return "data:image/svg+xml;base64," + Convert.ToBase64String(svgBytes); + } + + // Basic QR code generation + private string ConvertToQRCode(string markdown) + { + var plainText = Regex.Replace(markdown, @"[#*`~_\[\]()>-]", ""); + var hash = Math.Abs(plainText.GetHashCode()) % 1000; + + var svg = $@" + + QR-Style Code + + + + + + + + Hash: {hash} + "; + + var svgBytes = Encoding.UTF8.GetBytes(svg); + return "data:image/svg+xml;base64," + Convert.ToBase64String(svgBytes); + } + + // Basic JSON conversion + private string ConvertToJson(string markdown) + { + var document = ConvertToJsonStructure(markdown); + return JsonConvert.SerializeObject(document, Newtonsoft.Json.Formatting.Indented); + } + + // JSON structure conversion + private JObject ConvertToJsonStructure(string markdown) + { + var elements = new JArray(); + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + bool inCodeBlock = false; + var codeBlockContent = new StringBuilder(); + string codeBlockLanguage = ""; + + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + + // Handle code blocks + if (trimmedLine.StartsWith("```")) + { + if (inCodeBlock) + { + elements.Add(new JObject + { + ["type"] = "codeBlock", + ["language"] = codeBlockLanguage, + ["content"] = codeBlockContent.ToString().Trim() + }); + codeBlockContent.Clear(); + inCodeBlock = false; + } + else + { + codeBlockLanguage = trimmedLine.Substring(3).Trim(); + inCodeBlock = true; + } + continue; + } + + if (inCodeBlock) + { + codeBlockContent.AppendLine(line); + continue; + } + + if (string.IsNullOrWhiteSpace(trimmedLine)) + continue; + + // Handle headings + if (trimmedLine.StartsWith("#")) + { + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') + level++; + + var text = trimmedLine.Substring(level).Trim(); + elements.Add(new JObject + { + ["type"] = "heading", + ["level"] = level, + ["text"] = text + }); + } + // Handle lists + else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* ")) + { + var text = trimmedLine.Substring(2).Trim(); + elements.Add(new JObject + { + ["type"] = "listItem", + ["text"] = text + }); + } + // Handle paragraphs + else + { + elements.Add(new JObject + { + ["type"] = "paragraph", + ["text"] = trimmedLine + }); + } + } + + return new JObject + { + ["document"] = new JObject + { + ["type"] = "markdown", + ["elements"] = elements + } + }; + } + + // Basic XML conversion + private string ConvertToXml(string markdown) + { + var xml = new StringBuilder(); + xml.AppendLine(""); + xml.AppendLine(""); + + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + bool inCodeBlock = false; + + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + + // Handle code blocks + if (trimmedLine.StartsWith("```")) + { + if (inCodeBlock) + { + xml.AppendLine(" "); + inCodeBlock = false; + } + else + { + var language = trimmedLine.Substring(3).Trim(); + xml.AppendLine($" "); + inCodeBlock = true; + } + continue; + } + + if (inCodeBlock) + { + xml.AppendLine($" {System.Web.HttpUtility.HtmlEncode(line)}"); + continue; + } + + if (string.IsNullOrWhiteSpace(trimmedLine)) + continue; + + // Handle headings + if (trimmedLine.StartsWith("#")) + { + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') + level++; + + var text = trimmedLine.Substring(level).Trim(); + xml.AppendLine($" {System.Web.HttpUtility.HtmlEncode(text)}"); + } + // Handle lists + else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* ")) + { + var text = trimmedLine.Substring(2).Trim(); + xml.AppendLine($" {System.Web.HttpUtility.HtmlEncode(text)}"); + } + // Handle paragraphs + else + { + xml.AppendLine($" {System.Web.HttpUtility.HtmlEncode(trimmedLine)}"); + } + } + + xml.AppendLine(""); + return xml.ToString(); + } + + // Basic Plain Text conversion + private string ConvertToPlainText(string markdown) + { + var text = new StringBuilder(); + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + bool inCodeBlock = false; + + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + + // Handle code blocks + if (trimmedLine.StartsWith("```")) + { + if (inCodeBlock) + { + text.AppendLine(); + inCodeBlock = false; + } + else + { + inCodeBlock = true; + } + continue; + } + + if (inCodeBlock) + { + text.AppendLine(line); + continue; + } + + if (string.IsNullOrWhiteSpace(trimmedLine)) + { + text.AppendLine(); + continue; + } + + // Handle headings - just remove the # symbols + if (trimmedLine.StartsWith("#")) + { + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') + level++; + + var headingText = trimmedLine.Substring(level).Trim(); + text.AppendLine(headingText); + text.AppendLine(new string('=', headingText.Length)); // Add underline for headings + } + // Handle lists - just remove the bullet points + else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* ")) + { + var listText = trimmedLine.Substring(2).Trim(); + text.AppendLine($"• {listText}"); + } + // Handle paragraphs - remove markdown formatting + else + { + var plainText = RemoveMarkdownFormatting(trimmedLine); + text.AppendLine(plainText); + } + } + + return text.ToString(); + } + + private string RemoveMarkdownFormatting(string text) + { + // Remove bold + text = Regex.Replace(text, @"\*\*(.*?)\*\*", "$1"); + // Remove italic + text = Regex.Replace(text, @"\*(.*?)\*", "$1"); + // Remove strikethrough + text = Regex.Replace(text, @"~~(.*?)~~", "$1"); + // Remove code + text = Regex.Replace(text, @"`(.*?)`", "$1"); + // Remove links but keep the text + text = Regex.Replace(text, @"\[([^\]]+)\]\([^\)]+\)", "$1"); + + return text; + } + + // Generic handler for remaining operations + private async Task HandleMarkdownToSvg() => await HandleGenericConversion("svg", ConvertToSvg); + private async Task HandleMarkdownToRss() => await HandleGenericConversion("rss", ConvertToRss); + private async Task HandleMarkdownToWiki() => await HandleGenericConversion("wiki", ConvertToWiki); + private async Task HandleMarkdownToPng() => await HandleGenericConversion("png", ConvertToPng); + private async Task HandleMarkdownToDiagram() => await HandleGenericConversion("diagram", ConvertToDiagram); + private async Task HandleMarkdownToJpeg() => await HandleGenericConversion("jpeg", ConvertToJpeg); + private async Task HandleMarkdownToBadge() => await HandleGenericConversion("badge", ConvertToBadge); + private async Task HandleMarkdownToInfographic() => await HandleGenericConversion("infographic", ConvertToInfographic); + private async Task HandleMarkdownToLog() => await HandleGenericConversion("log", ConvertToLog); + private async Task HandleMarkdownToMetrics() => await HandleGenericConversion("metrics", ConvertToMetrics); + private async Task HandleMarkdownToSyslog() => await HandleGenericConversion("syslog", ConvertToSyslog); + private async Task HandleMarkdownToJsDoc() => await HandleGenericConversion("jsdoc", ConvertToJsDoc); + private async Task HandleMarkdownToXmlDoc() => await HandleGenericConversion("xmldoc", ConvertToXmlDoc); + private async Task HandleMarkdownToReadme() => await HandleGenericConversion("readme", ConvertToReadme); + private async Task HandleMarkdownToChangelog() => await HandleGenericConversion("changelog", ConvertToChangelog); + private async Task HandleMarkdownToTableOfContents() => await HandleGenericConversion("toc", ConvertToTableOfContents); + private async Task HandleMarkdownToStyledHtml() => await HandleGenericConversion("styledHtml", ConvertToStyledHtml); + + private async Task HandleGenericConversion(string format, Func converter) + { + try + { + var contentAsString = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var contentAsJson = JObject.Parse(contentAsString); + var markdown = (string)contentAsJson["markdown"] ?? (string)contentAsJson["text"] ?? ""; + + if (string.IsNullOrEmpty(markdown)) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.BadRequest); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = "No markdown content provided", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + + var result = converter(markdown); + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(new JObject + { + ["originalMarkdown"] = markdown, + [format] = result, + ["format"] = format, + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return response; + } + catch (Exception ex) + { + var errorResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError); + errorResponse.Content = CreateJsonContent(new JObject + { + ["error"] = $"Error processing request: {ex.Message}", + ["timestamp"] = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") + }.ToString()); + return errorResponse; + } + } // Additional conversion methods + private string ConvertToCsv(string markdown) + { + var csv = new StringBuilder(); + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + bool foundTable = false; + + // First, check if there are any tables in the markdown + for (int i = 0; i < lines.Length; i++) + { + if (lines[i].Contains("|")) + { + // Found a table, extract it + var tableLines = new List(); + for (int j = i; j < lines.Length && lines[j].Contains("|"); j++) + { + tableLines.Add(lines[j]); + i = j; // Update outer loop index + } + + if (tableLines.Count >= 2) + { + foundTable = true; + + // Process table headers + var headerCells = tableLines[0].Split('|').Select(cell => cell.Trim()).Where(cell => !string.IsNullOrEmpty(cell)).ToArray(); + if (headerCells.Length > 0) + { + csv.AppendLine(string.Join(",", headerCells.Select(cell => $"\"{EscapeCsvField(RemoveMarkdownFormatting(cell))}\""))); + } + + // Skip separator row if it exists + int dataRowStart = tableLines.Count > 1 && tableLines[1].Contains("-") ? 2 : 1; + + // Process data rows + for (int rowIndex = dataRowStart; rowIndex < tableLines.Count; rowIndex++) + { + var dataCells = tableLines[rowIndex].Split('|').Select(cell => cell.Trim()).Where(cell => !string.IsNullOrEmpty(cell)).ToArray(); + if (dataCells.Length > 0) + { + csv.AppendLine(string.Join(",", dataCells.Select(cell => $"\"{EscapeCsvField(RemoveMarkdownFormatting(cell))}\""))); + } + } + + csv.AppendLine(); // Add empty line between tables + } + } + } + + // If no tables found, create a structured CSV of the document content + if (!foundTable) + { + csv.AppendLine("Type,Content,Level,LineNumber"); + + for (int i = 0; i < lines.Length; i++) + { + var trimmedLine = lines[i].Trim(); + if (string.IsNullOrWhiteSpace(trimmedLine)) continue; + + if (trimmedLine.StartsWith("#")) + { + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') level++; + var text = RemoveMarkdownFormatting(trimmedLine.Substring(level).Trim()); + csv.AppendLine($"Heading,\"{EscapeCsvField(text)}\",{level},{i + 1}"); + } + else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* ") || trimmedLine.StartsWith("+ ")) + { + var text = RemoveMarkdownFormatting(trimmedLine.Substring(2).Trim()); + csv.AppendLine($"ListItem,\"{EscapeCsvField(text)}\",0,{i + 1}"); + } + else if (Regex.IsMatch(trimmedLine, @"^\d+\.\s")) + { + var match = Regex.Match(trimmedLine, @"^\d+\.\s(.*)"); + var text = RemoveMarkdownFormatting(match.Groups[1].Value); + csv.AppendLine($"OrderedListItem,\"{EscapeCsvField(text)}\",0,{i + 1}"); + } + else if (trimmedLine.StartsWith(">")) + { + var text = RemoveMarkdownFormatting(trimmedLine.Substring(1).Trim()); + csv.AppendLine($"Blockquote,\"{EscapeCsvField(text)}\",0,{i + 1}"); + } + else if (trimmedLine.StartsWith("```")) + { + var language = trimmedLine.Substring(3).Trim(); + csv.AppendLine($"CodeBlock,\"{EscapeCsvField(language)}\",0,{i + 1}"); + } + else if (trimmedLine == "---" || trimmedLine == "***" || trimmedLine == "___") + { + csv.AppendLine($"HorizontalRule,\"\",0,{i + 1}"); + } + else + { + var text = RemoveMarkdownFormatting(trimmedLine); + csv.AppendLine($"Paragraph,\"{EscapeCsvField(text)}\",0,{i + 1}"); + } + } + } + + return csv.ToString(); + } + + private string EscapeCsvField(string field) + { + if (field == null) return ""; + return field.Replace("\"", "\"\""); + } + + private string ConvertToLaTeX(string markdown) + { + var latex = new StringBuilder(); + latex.AppendLine("\\documentclass{article}"); + latex.AppendLine("\\begin{document}"); + + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + if (string.IsNullOrWhiteSpace(trimmedLine)) continue; + + if (trimmedLine.StartsWith("#")) + { + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') level++; + var text = trimmedLine.Substring(level).Trim(); + var command = level == 1 ? "section" : level == 2 ? "subsection" : "subsubsection"; + latex.AppendLine($"\\{command}{{{text}}}"); + } + else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* ")) + { + latex.AppendLine("\\begin{itemize}"); + latex.AppendLine($"\\item {trimmedLine.Substring(2).Trim()}"); + latex.AppendLine("\\end{itemize}"); + } + else + { + latex.AppendLine(trimmedLine); + latex.AppendLine(); + } + } + + latex.AppendLine("\\end{document}"); + return latex.ToString(); + } + + private string ConvertToYaml(string markdown) + { + var yaml = new StringBuilder(); + yaml.AppendLine("document:"); + yaml.AppendLine(" type: markdown"); + yaml.AppendLine(" elements:"); + + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + if (string.IsNullOrWhiteSpace(trimmedLine)) continue; + + if (trimmedLine.StartsWith("#")) + { + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') level++; + var text = trimmedLine.Substring(level).Trim(); + yaml.AppendLine($" - type: heading"); + yaml.AppendLine($" level: {level}"); + yaml.AppendLine($" text: \"{text}\""); + } + else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* ")) + { + var text = trimmedLine.Substring(2).Trim(); + yaml.AppendLine($" - type: listItem"); + yaml.AppendLine($" text: \"{text}\""); + } + else + { + yaml.AppendLine($" - type: paragraph"); + yaml.AppendLine($" text: \"{trimmedLine}\""); + } + } + return yaml.ToString(); + } + + private string ConvertToEmail(string markdown) + { + var html = ConvertToHtml(markdown); + var emailHtml = $@" + + + + + + + +{html} + +"; + return emailHtml; + } + + private JObject GetMarkdownStats(string markdown) + { + var lines = markdown.Split('\n'); + var headingCount = lines.Count(line => line.TrimStart().StartsWith("#")); + var listCount = lines.Count(line => line.TrimStart().StartsWith("- ") || line.TrimStart().StartsWith("* ")); + var codeBlockCount = lines.Count(line => line.TrimStart().StartsWith("```")); + var wordCount = markdown.Split(new[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).Length; + var characterCount = markdown.Length; + + return new JObject + { + ["headings"] = headingCount, + ["lists"] = listCount, + ["codeBlocks"] = codeBlockCount / 2, // Divide by 2 since each block has start and end + ["words"] = wordCount, + ["characters"] = characterCount, + ["lines"] = lines.Length + }; + } + + private JObject GetMarkdownInfo(string markdown) + { + var stats = GetMarkdownStats(markdown); + return new JObject + { + ["stats"] = stats, + ["hasHeadings"] = (int)stats["headings"] > 0, + ["hasLists"] = (int)stats["lists"] > 0, + ["hasCodeBlocks"] = (int)stats["codeBlocks"] > 0, + ["estimatedReadingTime"] = Math.Ceiling((int)stats["words"] / 200.0) // 200 words per minute + }; + } + + // Proper implementations for remaining formats + private string ConvertToSvg(string markdown) + { + var stats = GetMarkdownStats(markdown); + var svg = new StringBuilder(); + + // Dynamic height based on content + var estimatedHeight = Math.Max(400, (int)stats["lines"] * 25 + 200); + + svg.AppendLine($""); + + // Background with gradient + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + svg.AppendLine(" "); + + // Background + svg.AppendLine($" "); + + // Header section + svg.AppendLine(" "); + svg.AppendLine(" Markdown Document Visualization"); + + // Stats section + svg.AppendLine($" Lines: {stats["lines"]} | Words: {stats["words"]} | Characters: {stats["characters"]}"); + svg.AppendLine($" Headings: {stats["headings"]} | Lists: {stats["lists"]} | Code Blocks: {stats["codeBlocks"]}"); + + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + int y = 120; + int sectionNumber = 1; + bool inCodeBlock = false; + + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + + // Skip empty lines + if (string.IsNullOrWhiteSpace(trimmedLine)) + { + y += 10; + continue; + } + + // Handle code blocks + if (trimmedLine.StartsWith("```")) + { + if (!inCodeBlock) + { + svg.AppendLine($" "); + svg.AppendLine($" Code Block Start"); + inCodeBlock = true; + } + else + { + svg.AppendLine($" "); + svg.AppendLine($" Code Block End"); + inCodeBlock = false; + } + y += 30; + continue; + } + + if (inCodeBlock) + { + var codeText = line.Length > 90 ? line.Substring(0, 87) + "..." : line; + svg.AppendLine($" "); + svg.AppendLine($" {System.Web.HttpUtility.HtmlEncode(codeText)}"); + y += 25; + continue; + } + + var displayText = trimmedLine.Length > 80 ? trimmedLine.Substring(0, 77) + "..." : trimmedLine; + var escapedText = System.Web.HttpUtility.HtmlEncode(displayText); + + // Headings + if (trimmedLine.StartsWith("#")) + { + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') level++; + var fontSize = Math.Max(10, 18 - (level - 1) * 2); + var headingText = trimmedLine.Substring(level).Trim(); + if (headingText.Length > 60) headingText = headingText.Substring(0, 57) + "..."; + + // Section divider for main headings + if (level <= 2) + { + svg.AppendLine($" "); + svg.AppendLine($" "); + svg.AppendLine($" {sectionNumber}"); + sectionNumber++; + y += 10; + } + + svg.AppendLine($" {System.Web.HttpUtility.HtmlEncode(headingText)}"); + y += fontSize + 10; + } + // Lists + else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* ") || trimmedLine.StartsWith("+ ")) + { + svg.AppendLine($" "); + var listText = trimmedLine.Substring(2).Trim(); + if (listText.Length > 70) listText = listText.Substring(0, 67) + "..."; + svg.AppendLine($" {System.Web.HttpUtility.HtmlEncode(listText)}"); + y += 20; + } + // Ordered lists + else if (System.Text.RegularExpressions.Regex.IsMatch(trimmedLine, @"^\d+\.\s")) + { + var match = System.Text.RegularExpressions.Regex.Match(trimmedLine, @"^(\d+)\.\s(.*)"); + var number = match.Groups[1].Value; + var listText = match.Groups[2].Value; + + svg.AppendLine($" "); + svg.AppendLine($" {number}"); + + if (listText.Length > 70) listText = listText.Substring(0, 67) + "..."; + svg.AppendLine($" {System.Web.HttpUtility.HtmlEncode(listText)}"); + y += 20; + } + // Blockquotes + else if (trimmedLine.StartsWith(">")) + { + var quoteText = trimmedLine.Substring(1).Trim(); + if (quoteText.Length > 70) quoteText = quoteText.Substring(0, 67) + "..."; + svg.AppendLine($" "); + svg.AppendLine($" {System.Web.HttpUtility.HtmlEncode(quoteText)}"); + y += 25; + } + // Tables + else if (trimmedLine.Contains("|")) + { + svg.AppendLine($" "); + svg.AppendLine($" Table Row: {escapedText}"); + y += 30; + } + // Regular paragraphs + else + { + svg.AppendLine($" {escapedText}"); + y += 18; + } + + // Prevent overflow + if (y > estimatedHeight - 50) break; + } + + // Footer + svg.AppendLine($" Generated on {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC"); + + svg.AppendLine(""); + return svg.ToString(); + } + + private string ConvertToRss(string markdown) + { + var rss = new StringBuilder(); + rss.AppendLine(""); + rss.AppendLine(""); + rss.AppendLine(" "); + rss.AppendLine(" Markdown Content"); + rss.AppendLine(" RSS feed generated from Markdown content"); + rss.AppendLine($" {DateTime.UtcNow:ddd, dd MMM yyyy HH:mm:ss} GMT"); + + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + var currentItem = new StringBuilder(); + string currentTitle = "Markdown Content"; + + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + if (string.IsNullOrWhiteSpace(trimmedLine)) continue; + + if (trimmedLine.StartsWith("#")) + { + // If we have accumulated content, create an item + if (currentItem.Length > 0) + { + rss.AppendLine(" "); + rss.AppendLine($" {System.Web.HttpUtility.HtmlEncode(currentTitle)}"); + rss.AppendLine($" {System.Web.HttpUtility.HtmlEncode(currentItem.ToString().Trim())}"); + rss.AppendLine($" {DateTime.UtcNow:ddd, dd MMM yyyy HH:mm:ss} GMT"); + rss.AppendLine(" "); + currentItem.Clear(); + } + + // Start new item with heading as title + var level = 0; + while (level < trimmedLine.Length && trimmedLine[level] == '#') level++; + currentTitle = trimmedLine.Substring(level).Trim(); + } + else + { + currentItem.AppendLine(trimmedLine); + } + } + + // Add final item if there's content + if (currentItem.Length > 0) + { + rss.AppendLine(" "); + rss.AppendLine($" {System.Web.HttpUtility.HtmlEncode(currentTitle)}"); + rss.AppendLine($" {System.Web.HttpUtility.HtmlEncode(currentItem.ToString().Trim())}"); + rss.AppendLine($" {DateTime.UtcNow:ddd, dd MMM yyyy HH:mm:ss} GMT"); + rss.AppendLine(" "); + } + + rss.AppendLine(" "); + rss.AppendLine(""); + return rss.ToString(); + } + + private string ConvertToWiki(string markdown) + { + var wiki = new StringBuilder(); + var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None); + bool inCodeBlock = false; + + foreach (var line in lines) + { + var trimmedLine = line.Trim(); + + // Handle code blocks + if (trimmedLine.StartsWith("```")) + { + if (inCodeBlock) + { + wiki.AppendLine(""); + inCodeBlock = false; + } + else + { + wiki.AppendLine("
");
+                    inCodeBlock = true;
+                }
+                continue;
+            }
+
+            if (inCodeBlock)
+            {
+                wiki.AppendLine(line);
+                continue;
+            }
+
+            if (string.IsNullOrWhiteSpace(trimmedLine))
+            {
+                wiki.AppendLine();
+                continue;
+            }
+
+            // Handle headings - convert # to = wiki syntax
+            if (trimmedLine.StartsWith("#"))
+            {
+                var level = 0;
+                while (level < trimmedLine.Length && trimmedLine[level] == '#') level++;
+                var text = trimmedLine.Substring(level).Trim();
+                var wikiEquals = new string('=', level);
+                wiki.AppendLine($"{wikiEquals} {text} {wikiEquals}");
+            }
+            // Handle lists - convert to wiki bullet syntax
+            else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* "))
+            {
+                var text = trimmedLine.Substring(2).Trim();
+                wiki.AppendLine($"* {text}");
+            }
+            // Handle bold/italic
+            else
+            {
+                var wikiLine = trimmedLine;
+                // Convert **bold** to '''bold'''
+                wikiLine = Regex.Replace(wikiLine, @"\*\*(.*?)\*\*", "'''$1'''");
+                // Convert *italic* to ''italic''
+                wikiLine = Regex.Replace(wikiLine, @"\*(.*?)\*", "''$1''");
+                // Convert `code` to code
+                wikiLine = Regex.Replace(wikiLine, @"`(.*?)`", "$1");
+
+                wiki.AppendLine(wikiLine);
+            }
+        }
+        return wiki.ToString();
+    }
+
+    private string ConvertToPng(string markdown)
+    {
+        // Generate a simple PNG representation as base64
+        var svg = ConvertToSvg(markdown);
+        // For a real implementation, you'd convert SVG to PNG
+        // For now, return a data URL with the SVG content
+        var svgBytes = Encoding.UTF8.GetBytes(svg);
+        return "data:image/svg+xml;base64," + Convert.ToBase64String(svgBytes);
+    }
+
+    private string ConvertToDiagram(string markdown)
+    {
+        var svg = new StringBuilder();
+        svg.AppendLine("");
+        svg.AppendLine("  ");
+        svg.AppendLine("    ");
+        svg.AppendLine("  ");
+        svg.AppendLine("  ");
+        svg.AppendLine("  Markdown Flow Diagram");
+
+        var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
+        var headings = lines.Where(l => l.Trim().StartsWith("#")).Take(5).ToList();
+
+        int y = 60;
+        int boxHeight = 40;
+        int boxWidth = 200;
+
+        for (int i = 0; i < headings.Count; i++)
+        {
+            var heading = headings[i].Trim();
+            var level = 0;
+            while (level < heading.Length && heading[level] == '#') level++;
+            var text = heading.Substring(level).Trim();
+
+            if (text.Length > 25) text = text.Substring(0, 22) + "...";
+
+            var x = 150 + (level - 1) * 50;
+            var color = level == 1 ? "#3498db" : level == 2 ? "#2ecc71" : "#e74c3c";
+
+            // Draw box
+            svg.AppendLine($"  ");
+            svg.AppendLine($"  {System.Web.HttpUtility.HtmlEncode(text)}");
+
+            // Draw arrow to next box
+            if (i < headings.Count - 1)
+            {
+                svg.AppendLine($"  ");
+            }
+
+            y += boxHeight + 30;
+        }
+
+        // Add arrowhead marker
+        svg.AppendLine("  ");
+        svg.AppendLine("    ");
+        svg.AppendLine("      ");
+        svg.AppendLine("    ");
+        svg.AppendLine("  ");
+
+        svg.AppendLine("");
+        return svg.ToString();
+    }
+
+    private string ConvertToJpeg(string markdown)
+    {
+        // Similar to PNG, generate SVG and return as data URL
+        var svg = ConvertToSvg(markdown);
+        var svgBytes = Encoding.UTF8.GetBytes(svg); return "data:image/svg+xml;base64," + Convert.ToBase64String(svgBytes);
+    }
+
+    private string ConvertToBadge(string markdown)
+    {
+        var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
+        var stats = GetMarkdownStats(markdown);
+
+        var svg = new StringBuilder();
+        svg.AppendLine("");
+
+        // Background
+        svg.AppendLine("  ");
+
+        // Badge title
+        svg.AppendLine("  Markdown Stats");
+
+        // Stats
+        svg.AppendLine($"  Words: {stats["words"]}");
+        svg.AppendLine($"  Lines: {stats["lines"]}");
+        svg.AppendLine($"  Headings: {stats["headings"]}");
+
+        // Status indicator
+        var color = (int)stats["words"] > 100 ? "#27ae60" : (int)stats["words"] > 50 ? "#f39c12" : "#e74c3c";
+        svg.AppendLine($"  ");
+        svg.AppendLine($"  ");
+
+        svg.AppendLine("");
+        return svg.ToString();
+    }
+
+    private string ConvertToInfographic(string markdown)
+    {
+        var stats = GetMarkdownStats(markdown);
+        var svg = new StringBuilder();
+        svg.AppendLine("");
+
+        // Background
+        svg.AppendLine("  ");
+
+        // Header
+        svg.AppendLine("  ");
+        svg.AppendLine("  Markdown Analysis");
+        svg.AppendLine("  Content Overview");
+
+        // Word count section
+        var wordBarWidth = Math.Min(300, (int)stats["words"] / 10);
+        svg.AppendLine("  Word Count");
+        svg.AppendLine("  ");
+        svg.AppendLine($"  ");
+        svg.AppendLine($"  {stats["words"]} words");
+
+        // Heading count
+        var headingBarWidth = Math.Min(300, (int)stats["headings"] * 30);
+        svg.AppendLine("  Headings");
+        svg.AppendLine("  ");
+        svg.AppendLine($"  ");
+        svg.AppendLine($"  {stats["headings"]} headings");
+
+        // List items
+        var listBarWidth = Math.Min(300, (int)stats["lists"] * 20);
+        svg.AppendLine("  Lists");
+        svg.AppendLine("  ");
+        svg.AppendLine($"  ");
+        svg.AppendLine($"  {stats["lists"]} items");
+
+        // Code blocks
+        var codeBarWidth = Math.Min(300, (int)stats["codeBlocks"] * 50);
+        svg.AppendLine("  Code Blocks");
+        svg.AppendLine("  ");
+        svg.AppendLine($"  ");
+        svg.AppendLine($"  {stats["codeBlocks"]} blocks");
+
+        // Reading time estimate
+        var readingTime = Math.Ceiling((int)stats["words"] / 200.0);
+        svg.AppendLine("  ");
+        svg.AppendLine("  Estimated Reading Time");
+        svg.AppendLine($"  {readingTime} min");
+
+        // Footer
+        svg.AppendLine($"  Generated on {DateTime.UtcNow:yyyy-MM-dd}");
+        svg.AppendLine("");
+        return svg.ToString();
+    }
+
+    private string ConvertToLog(string markdown)
+    {
+        var log = new StringBuilder();
+        var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
+        var timestamp = DateTime.UtcNow;
+
+        foreach (var line in lines)
+        {
+            var trimmedLine = line.Trim();
+            if (string.IsNullOrWhiteSpace(trimmedLine)) continue;
+
+            var logLevel = "INFO";
+            var message = trimmedLine;
+
+            // Determine log level based on content
+            if (trimmedLine.Contains("error") || trimmedLine.Contains("Error"))
+                logLevel = "ERROR";
+            else if (trimmedLine.Contains("warn") || trimmedLine.Contains("Warn"))
+                logLevel = "WARN";
+            else if (trimmedLine.Contains("debug") || trimmedLine.Contains("Debug"))
+                logLevel = "DEBUG";
+            else if (trimmedLine.StartsWith("#"))
+            {
+                logLevel = "INFO";
+                var level = 0;
+                while (level < trimmedLine.Length && trimmedLine[level] == '#') level++;
+                message = $"Section: {trimmedLine.Substring(level).Trim()}";
+            }
+            else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* "))
+            {
+                logLevel = "INFO";
+                message = $"Item: {trimmedLine.Substring(2).Trim()}";
+            }
+
+            log.AppendLine($"[{timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{logLevel}] {message}");
+            timestamp = timestamp.AddMilliseconds(100); // Increment time slightly for each line
+        }
+
+        return log.ToString();
+    }
+
+    private string ConvertToMetrics(string markdown)
+    {
+        var stats = GetMarkdownStats(markdown);
+        var metrics = new StringBuilder();
+        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+
+        metrics.AppendLine("# HELP markdown_words_total Total number of words in markdown content");
+        metrics.AppendLine("# TYPE markdown_words_total counter");
+        metrics.AppendLine($"markdown_words_total {stats["words"]} {timestamp}");
+        metrics.AppendLine();
+
+        metrics.AppendLine("# HELP markdown_characters_total Total number of characters in markdown content");
+        metrics.AppendLine("# TYPE markdown_characters_total counter");
+        metrics.AppendLine($"markdown_characters_total {stats["characters"]} {timestamp}");
+        metrics.AppendLine();
+
+        metrics.AppendLine("# HELP markdown_lines_total Total number of lines in markdown content");
+        metrics.AppendLine("# TYPE markdown_lines_total counter");
+        metrics.AppendLine($"markdown_lines_total {stats["lines"]} {timestamp}");
+        metrics.AppendLine();
+
+        metrics.AppendLine("# HELP markdown_headings_total Total number of headings in markdown content");
+        metrics.AppendLine("# TYPE markdown_headings_total counter");
+        metrics.AppendLine($"markdown_headings_total {stats["headings"]} {timestamp}");
+        metrics.AppendLine();
+
+        metrics.AppendLine("# HELP markdown_lists_total Total number of list items in markdown content");
+        metrics.AppendLine("# TYPE markdown_lists_total counter");
+        metrics.AppendLine($"markdown_lists_total {stats["lists"]} {timestamp}");
+        metrics.AppendLine();
+
+        metrics.AppendLine("# HELP markdown_code_blocks_total Total number of code blocks in markdown content");
+        metrics.AppendLine("# TYPE markdown_code_blocks_total counter");
+        metrics.AppendLine($"markdown_code_blocks_total {stats["codeBlocks"]} {timestamp}");
+        metrics.AppendLine();
+
+        metrics.AppendLine("# HELP markdown_reading_time_minutes Estimated reading time in minutes");
+        metrics.AppendLine("# TYPE markdown_reading_time_minutes gauge");
+        var readingTime = Math.Ceiling((int)stats["words"] / 200.0);
+        metrics.AppendLine($"markdown_reading_time_minutes {readingTime} {timestamp}");
+
+        return metrics.ToString();
+    }
+
+    private string ConvertToSyslog(string markdown)
+    {
+        var syslog = new StringBuilder();
+        var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
+        var timestamp = DateTime.UtcNow;
+
+        foreach (var line in lines)
+        {
+            var trimmedLine = line.Trim();
+            if (string.IsNullOrWhiteSpace(trimmedLine)) continue;
+
+            // Syslog format: version timestamp hostname app-name procid msgid structured-data msg
+            var priority = 14; // user.info
+            var version = 1;
+            var hostname = "markdown-converter";
+            var appName = "md2syslog";
+            var procId = "-";
+            var msgId = "-";
+            var structuredData = "-";
+
+            // Adjust priority based on content
+            if (trimmedLine.Contains("error") || trimmedLine.Contains("Error"))
+                priority = 11; // user.err
+            else if (trimmedLine.Contains("warn") || trimmedLine.Contains("Warn"))
+                priority = 12; // user.warning
+            else if (trimmedLine.StartsWith("#"))
+                priority = 13; // user.notice
+
+            var syslogTimestamp = timestamp.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
+            var message = trimmedLine.Replace("\t", " ").Replace("  ", " ");
+
+            syslog.AppendLine($"<{priority}>{version} {syslogTimestamp} {hostname} {appName} {procId} {msgId} {structuredData} {message}");
+            timestamp = timestamp.AddSeconds(1);
+        }
+
+        return syslog.ToString();
+    }
+    private string ConvertToJsDoc(string markdown)
+    {
+        var jsDoc = new StringBuilder();
+        var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
+
+        jsDoc.AppendLine("/**");
+
+        foreach (var line in lines)
+        {
+            var trimmedLine = line.Trim();
+            if (string.IsNullOrWhiteSpace(trimmedLine))
+            {
+                jsDoc.AppendLine(" *");
+                continue;
+            }
+
+            if (trimmedLine.StartsWith("#"))
+            {
+                var level = 0;
+                while (level < trimmedLine.Length && trimmedLine[level] == '#') level++;
+                var text = trimmedLine.Substring(level).Trim();
+
+                if (level == 1)
+                {
+                    jsDoc.AppendLine($" * @description {text}");
+                }
+                else
+                {
+                    jsDoc.AppendLine($" * @section {text}");
+                }
+            }
+            else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* "))
+            {
+                var text = trimmedLine.Substring(2).Trim();
+                if (text.Contains(":"))
+                {
+                    var parts = text.Split(new[] { ':' }, 2);
+                    if (parts.Length == 2)
+                    {
+                        var paramName = parts[0].Trim();
+                        var paramDesc = parts[1].Trim();
+                        jsDoc.AppendLine($" * @param {{{paramName}}} {paramDesc}");
+                    }
+                }
+                else
+                {
+                    jsDoc.AppendLine($" * @note {text}");
+                }
+            }
+            else if (trimmedLine.StartsWith("```"))
+            {
+                if (trimmedLine.Length > 3)
+                {
+                    var language = trimmedLine.Substring(3).Trim();
+                    jsDoc.AppendLine($" * @example");
+                }
+            }
+            else
+            {
+                jsDoc.AppendLine($" * {trimmedLine}");
+            }
+        }
+
+        jsDoc.AppendLine(" */");
+        return jsDoc.ToString();
+    }
+
+    private string ConvertToXmlDoc(string markdown)
+    {
+        var xmlDoc = new StringBuilder();
+        var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
+
+        xmlDoc.AppendLine("/// ");
+
+        bool inSummary = true;
+        bool inExample = false;
+
+        foreach (var line in lines)
+        {
+            var trimmedLine = line.Trim();
+            if (string.IsNullOrWhiteSpace(trimmedLine))
+            {
+                if (inSummary)
+                {
+                    xmlDoc.AppendLine("/// ");
+                    inSummary = false;
+                }
+                continue;
+            }
+
+            if (trimmedLine.StartsWith("#"))
+            {
+                if (inSummary)
+                {
+                    xmlDoc.AppendLine("/// ");
+                    inSummary = false;
+                }
+
+                var level = 0;
+                while (level < trimmedLine.Length && trimmedLine[level] == '#') level++;
+                var text = trimmedLine.Substring(level).Trim();
+                xmlDoc.AppendLine($"/// {System.Web.HttpUtility.HtmlEncode(text)}");
+            }
+            else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* "))
+            {
+                var text = trimmedLine.Substring(2).Trim();
+                if (text.Contains(":"))
+                {
+                    var parts = text.Split(new[] { ':' }, 2);
+                    if (parts.Length == 2)
+                    {
+                        var paramName = parts[0].Trim();
+                        var paramDesc = parts[1].Trim();
+                        xmlDoc.AppendLine($"/// {System.Web.HttpUtility.HtmlEncode(paramDesc)}");
+                    }
+                }
+                else
+                {
+                    xmlDoc.AppendLine($"/// {System.Web.HttpUtility.HtmlEncode(text)}");
+                }
+            }
+            else if (trimmedLine.StartsWith("```"))
+            {
+                if (!inExample)
+                {
+                    xmlDoc.AppendLine("/// ");
+                    xmlDoc.AppendLine("/// ");
+                    inExample = true;
+                }
+                else
+                {
+                    xmlDoc.AppendLine("/// ");
+                    xmlDoc.AppendLine("/// ");
+                    inExample = false;
+                }
+            }
+            else
+            {
+                if (inSummary)
+                {
+                    xmlDoc.AppendLine($"/// {System.Web.HttpUtility.HtmlEncode(trimmedLine)}");
+                }
+                else if (inExample)
+                {
+                    xmlDoc.AppendLine($"/// {System.Web.HttpUtility.HtmlEncode(trimmedLine)}");
+                }
+                else
+                {
+                    xmlDoc.AppendLine($"/// {System.Web.HttpUtility.HtmlEncode(trimmedLine)}");
+                }
+            }
+        }
+
+        if (inSummary)
+        {
+            xmlDoc.AppendLine("/// ");
+        }
+
+        if (inExample)
+        {
+            xmlDoc.AppendLine("/// ");
+            xmlDoc.AppendLine("/// ");
+        }
+        return xmlDoc.ToString();
+    }
+    private string ConvertToReadme(string markdown)
+    {
+        var readme = new StringBuilder();
+        var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
+        var stats = GetMarkdownStats(markdown);
+
+        // Extract project name from first heading or use default
+        var projectName = "Project";
+        var description = "";
+        var features = new List();
+        var installation = new List();
+        var usage = new List();
+        bool hasFoundTitle = false;
+
+        // Parse content for structure
+        for (int i = 0; i < lines.Length; i++)
+        {
+            var trimmedLine = lines[i].Trim();
+
+            if (!hasFoundTitle && trimmedLine.StartsWith("#"))
+            {
+                var level = 0;
+                while (level < trimmedLine.Length && trimmedLine[level] == '#') level++;
+                if (level == 1)
+                {
+                    projectName = trimmedLine.Substring(level).Trim();
+                    hasFoundTitle = true;
+
+                    // Look for description in next few lines
+                    for (int j = i + 1; j < Math.Min(i + 5, lines.Length); j++)
+                    {
+                        var nextLine = lines[j].Trim();
+                        if (!string.IsNullOrWhiteSpace(nextLine) && !nextLine.StartsWith("#"))
+                        {
+                            description = nextLine;
+                            break;
+                        }
+                    }
+                    continue;
+                }
+            }
+
+            // Look for section indicators
+            if (trimmedLine.StartsWith("#"))
+            {
+                var level = 0;
+                while (level < trimmedLine.Length && trimmedLine[level] == '#') level++;
+                var heading = trimmedLine.Substring(level).Trim().ToLower();
+
+                if (heading.Contains("feature") || heading.Contains("what") || heading.Contains("benefit"))
+                {
+                    // Collect features from following content
+                    for (int j = i + 1; j < lines.Length; j++)
+                    {
+                        var featureLine = lines[j].Trim();
+                        if (featureLine.StartsWith("#")) break;
+                        if (featureLine.StartsWith("- ") || featureLine.StartsWith("* "))
+                        {
+                            features.Add(featureLine.Substring(2).Trim());
+                        }
+                    }
+                }
+                else if (heading.Contains("install") || heading.Contains("setup") || heading.Contains("getting started"))
+                {
+                    // Collect installation steps
+                    for (int j = i + 1; j < lines.Length; j++)
+                    {
+                        var installLine = lines[j].Trim();
+                        if (installLine.StartsWith("#")) break;
+                        if (!string.IsNullOrWhiteSpace(installLine))
+                        {
+                            installation.Add(installLine);
+                        }
+                    }
+                }
+                else if (heading.Contains("usage") || heading.Contains("example") || heading.Contains("how to"))
+                {
+                    // Collect usage examples
+                    for (int j = i + 1; j < lines.Length; j++)
+                    {
+                        var usageLine = lines[j].Trim();
+                        if (usageLine.StartsWith("#")) break;
+                        if (!string.IsNullOrWhiteSpace(usageLine))
+                        {
+                            usage.Add(usageLine);
+                        }
+                    }
+                }
+            }
+        }
+
+        // Build professional README structure
+        readme.AppendLine($"# {projectName}");
+        readme.AppendLine();
+
+        if (!string.IsNullOrEmpty(description))
+        {
+            readme.AppendLine(description);
+            readme.AppendLine();
+        }
+
+        // Add badges
+        readme.AppendLine("![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)");
+        readme.AppendLine($"![Lines of Code](https://img.shields.io/badge/Lines%20of%20Code-{stats["lines"]}-blue)");
+        readme.AppendLine($"![Word Count](https://img.shields.io/badge/Words-{stats["words"]}-green)");
+        readme.AppendLine();
+
+        // Table of Contents
+        readme.AppendLine("## Table of Contents");
+        readme.AppendLine();
+        readme.AppendLine("- [Description](#description)");
+        if (features.Count > 0) readme.AppendLine("- [Features](#features)");
+        if (installation.Count > 0) readme.AppendLine("- [Installation](#installation)");
+        if (usage.Count > 0) readme.AppendLine("- [Usage](#usage)");
+        readme.AppendLine("- [Contributing](#contributing)");
+        readme.AppendLine("- [License](#license)");
+        readme.AppendLine();
+
+        // Description
+        readme.AppendLine("## Description");
+        readme.AppendLine();
+        readme.AppendLine($"This project contains {stats["words"]} words across {stats["lines"]} lines, ");
+        readme.AppendLine($"with {stats["headings"]} headings and {stats["lists"]} list items.");
+        if ((int)stats["codeBlocks"] > 0)
+        {
+            readme.AppendLine($"It includes {stats["codeBlocks"]} code blocks demonstrating various concepts.");
+        }
+        readme.AppendLine();
+
+        // Features
+        if (features.Count > 0)
+        {
+            readme.AppendLine("## Features");
+            readme.AppendLine();
+            foreach (var feature in features)
+            {
+                readme.AppendLine($"- {feature}");
+            }
+            readme.AppendLine();
+        }
+        else
+        {
+            readme.AppendLine("## Features");
+            readme.AppendLine();
+            readme.AppendLine("- Comprehensive documentation");
+            readme.AppendLine("- Well-structured content");
+            readme.AppendLine("- Easy to understand format");
+            readme.AppendLine();
+        }
+
+        // Installation
+        readme.AppendLine("## Installation");
+        readme.AppendLine();
+        if (installation.Count > 0)
+        {
+            foreach (var installStep in installation.Take(10)) // Limit to prevent overflow
+            {
+                readme.AppendLine(installStep);
+            }
+        }
+        else
+        {
+            readme.AppendLine("```bash");
+            readme.AppendLine("git clone ");
+            readme.AppendLine("cd " + projectName.ToLower().Replace(" ", "-"));
+            readme.AppendLine("# Follow setup instructions");
+            readme.AppendLine("```");
+        }
+        readme.AppendLine();
+
+        // Usage
+        readme.AppendLine("## Usage");
+        readme.AppendLine();
+        if (usage.Count > 0)
+        {
+            foreach (var usageItem in usage.Take(15)) // Limit to prevent overflow
+            {
+                readme.AppendLine(usageItem);
+            }
+        }
+        else
+        {
+            readme.AppendLine("Detailed usage instructions will be provided here.");
+            readme.AppendLine();
+            readme.AppendLine("```bash");
+            readme.AppendLine("# Example usage");
+            readme.AppendLine("./run.sh");
+            readme.AppendLine("```");
+        }
+        readme.AppendLine();
+
+        // Contributing
+        readme.AppendLine("## Contributing");
+        readme.AppendLine();
+        readme.AppendLine("1. Fork the repository");
+        readme.AppendLine("2. Create your feature branch (`git checkout -b feature/AmazingFeature`)");
+        readme.AppendLine("3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)");
+        readme.AppendLine("4. Push to the branch (`git push origin feature/AmazingFeature`)");
+        readme.AppendLine("5. Open a Pull Request");
+        readme.AppendLine();
+
+        // License
+        readme.AppendLine("## License");
+        readme.AppendLine();
+        readme.AppendLine("This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.");
+        readme.AppendLine();
+
+        // Footer
+        readme.AppendLine("---");
+        readme.AppendLine($"*Generated on {DateTime.UtcNow:yyyy-MM-dd} from Markdown content*");
+        return readme.ToString();
+    }
+
+    private string ConvertToChangelog(string markdown)
+    {
+        var changelog = new StringBuilder();
+        var lines = markdown.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
+
+        changelog.AppendLine("# Changelog");
+        changelog.AppendLine();
+        changelog.AppendLine("All notable changes to this project will be documented in this file.");
+        changelog.AppendLine();
+        changelog.AppendLine("The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),");
+        changelog.AppendLine("and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).");
+        changelog.AppendLine();
+
+        var currentDate = DateTime.UtcNow.ToString("yyyy-MM-dd");
+        changelog.AppendLine($"## [Unreleased] - {currentDate}");
+        changelog.AppendLine();
+
+        var addedItems = new List();
+        var changedItems = new List();
+        var fixedItems = new List();
+
+        foreach (var line in lines)
+        {
+            var trimmedLine = line.Trim();
+            if (string.IsNullOrWhiteSpace(trimmedLine)) continue;
+
+            if (trimmedLine.StartsWith("#"))
+            {
+                var level = 0;
+                while (level < trimmedLine.Length && trimmedLine[level] == '#') level++;
+                var text = trimmedLine.Substring(level).Trim();
+                addedItems.Add(text);
+            }
+            else if (trimmedLine.StartsWith("- ") || trimmedLine.StartsWith("* "))
+            {
+                var text = trimmedLine.Substring(2).Trim();
+                if (text.ToLower().Contains("fix") || text.ToLower().Contains("bug"))
+                {
+                    fixedItems.Add(text);
+                }
+                else if (text.ToLower().Contains("change") || text.ToLower().Contains("update"))
+                {
+                    changedItems.Add(text);
+                }
+                else
+                {
+                    addedItems.Add(text);
+                }
+            }
+            else
+            {
+                addedItems.Add(trimmedLine);
+            }
+        }
+
+        if (addedItems.Count > 0)
+        {
+            changelog.AppendLine("### Added");
+            foreach (var item in addedItems)
+            {
+                changelog.AppendLine($"- {item}");
+            }
+            changelog.AppendLine();
+        }
+
+        if (changedItems.Count > 0)
+        {
+            changelog.AppendLine("### Changed");
+            foreach (var item in changedItems)
+            {
+                changelog.AppendLine($"- {item}");
+            }
+            changelog.AppendLine();
+        }
+
+        if (fixedItems.Count > 0)
+        {
+            changelog.AppendLine("### Fixed");
+            foreach (var item in fixedItems)
+            {
+                changelog.AppendLine($"- {item}");
+            }
+            changelog.AppendLine();
+        }
+
+        changelog.AppendLine("## [1.0.0] - 2023-01-01");
+        changelog.AppendLine();
+        changelog.AppendLine("### Added");
+        changelog.AppendLine("- Initial release");
+
+        return changelog.ToString();
+    }
+    private string ConvertToTableOfContents(string markdown)
+    {
+        var toc = new StringBuilder("# Table of Contents\n\n");
+        var lines = markdown.Split('\n');
+        foreach (var line in lines)
+        {
+            if (line.TrimStart().StartsWith("#"))
+            {
+                var level = 0;
+                var trimmed = line.Trim();
+                while (level < trimmed.Length && trimmed[level] == '#') level++;
+                var text = trimmed.Substring(level).Trim();
+                var indent = new string(' ', (level - 1) * 2);
+                toc.AppendLine($"{indent}- {text}");
+            }
+        }
+        return toc.ToString();
+    }
+    private string ConvertToStyledHtml(string markdown)
+    {
+        var html = ConvertToHtml(markdown);
+        return $@"
+            
+            
+                
+            
+            {html}
+            ";
+    }
+
+    // Helper methods for operation ID validation
+    private bool IsKnownOperationId(string operationId)
+    {
+        var knownOperations = new[]
+        {
+            "MarkdownToHtml", "MarkdownToAdaptiveCard", "MarkdownToChart", "MarkdownToQr",
+            "MarkdownToJson", "MarkdownToXml", "MarkdownToPlainText", "MarkdownToCsv",
+            "MarkdownToLaTeX", "MarkdownToYaml", "MarkdownToEmail", "MarkdownToSvg",
+            "MarkdownToRss", "MarkdownToWiki", "MarkdownToPng", "MarkdownToDiagram",
+            "MarkdownStats", "MarkdownToJpeg", "MarkdownToBadge", "MarkdownToInfographic",
+            "MarkdownToLog", "MarkdownToMetrics", "MarkdownToSyslog", "MarkdownToJsDoc",
+            "MarkdownToXmlDoc", "MarkdownToReadme", "MarkdownToChangelog",
+            "MarkdownToTableOfContents", "MarkdownToStyledHtml", "MarkdownInfo"
+        };
+        return knownOperations.Contains(operationId);
+    }
+    private bool IsLikelyBase64(string input)
+    {
+        if (string.IsNullOrEmpty(input)) return false;
+
+        // If it's a known operation ID format, it's not base64
+        if (IsValidOperationId(input)) return false;
+
+        // Must be at least 4 characters and divisible by 4 when padding is considered
+        if (input.Length < 4 || input.Length % 4 != 0) return false;
+
+        // Should only contain base64 characters
+        if (!System.Text.RegularExpressions.Regex.IsMatch(input, @"^[A-Za-z0-9+/]*={0,2}$")) return false;
+
+        // Should not be too short (most real base64 encoded operation IDs would be longer)
+        if (input.Length < 8) return false;
+
+        return true;
+    }
+
+    private bool IsValidOperationId(string operationId)
+    {
+        if (string.IsNullOrEmpty(operationId)) return false;
+
+        // Check if it contains only printable ASCII characters
+        if (!operationId.All(c => c >= 32 && c <= 126)) return false;
+
+        // Check if it looks like a valid operation ID pattern
+        return System.Text.RegularExpressions.Regex.IsMatch(operationId, @"^[A-Za-z][A-Za-z0-9]*$");
+    }
+}