237 lines
7.7 KiB
C#
Executable File
237 lines
7.7 KiB
C#
Executable File
using Markdig;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using Markdig.Extensions.JiraLinks;
|
|
|
|
namespace WeChatWASM.MDV
|
|
{
|
|
public class MarkdownViewer
|
|
{
|
|
private GUISkin mSkin = null;
|
|
private string mText = string.Empty;
|
|
private string mCurrentPath = string.Empty;
|
|
private HandlerImages mHandlerImages = new HandlerImages();
|
|
private HandlerNavigate mHandlerNavigate = new HandlerNavigate();
|
|
|
|
private Vector2 mScrollPos = Vector2.zero;
|
|
private Layout mLayout = null;
|
|
private bool mRaw = false;
|
|
|
|
private static History mHistory = new History();
|
|
|
|
public MarkdownViewer( GUISkin skin, string path, string content )
|
|
{
|
|
mSkin = skin;
|
|
mCurrentPath = path;
|
|
mText = content;
|
|
|
|
mHistory.OnOpen( mCurrentPath );
|
|
mLayout = ParseDocument();
|
|
|
|
mHandlerImages.CurrentPath = mCurrentPath;
|
|
|
|
mHandlerNavigate.CurrentPath = mCurrentPath;
|
|
mHandlerNavigate.History = mHistory;
|
|
mHandlerNavigate.FindBlock = ( id ) => mLayout.Find( id );
|
|
mHandlerNavigate.ScrollTo = ( pos ) => mScrollPos.y = pos;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
public bool Update()
|
|
{
|
|
return mHandlerImages.Update();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
Layout ParseDocument()
|
|
{
|
|
var context = new Context( mSkin, mHandlerImages, mHandlerNavigate );
|
|
var builder = new LayoutBuilder( context );
|
|
var renderer = new RendererMarkdown( builder );
|
|
|
|
var pipelineBuilder = new MarkdownPipelineBuilder()
|
|
.UseAutoLinks()
|
|
;
|
|
|
|
if( !string.IsNullOrEmpty( Preferences.JIRA ) )
|
|
{
|
|
pipelineBuilder.UseJiraLinks( new JiraLinkOptions( Preferences.JIRA ) );
|
|
}
|
|
|
|
var pipeline = pipelineBuilder.Build();
|
|
pipeline.Setup( renderer );
|
|
|
|
var doc = Markdown.Parse( mText, pipeline );
|
|
renderer.Render( doc );
|
|
|
|
return builder.GetLayout();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
#if !UNITY_2018
|
|
private float mHeight = 1.0f;
|
|
#endif
|
|
|
|
protected Rect GetEditorRect()
|
|
{
|
|
#if !UNITY_2018
|
|
|
|
// fix for Screen.height
|
|
var offset = 450.0f;
|
|
var scale = 2.0f;
|
|
|
|
// calculate working space
|
|
if( Event.current.type == EventType.Layout )
|
|
{
|
|
mHeight = ( Screen.height - offset ) / scale;
|
|
}
|
|
|
|
// reserve space (we are going to paint on it directly)
|
|
GUILayout.Space( mHeight );
|
|
|
|
// return working rect
|
|
return new Rect( 0.0f, 10.0f, EditorGUIUtility.currentViewWidth, mHeight );
|
|
#else
|
|
GUILayout.FlexibleSpace();
|
|
var rectContainer = GUILayoutUtility.GetLastRect();
|
|
rectContainer.width = EditorGUIUtility.currentViewWidth;
|
|
return rectContainer;
|
|
|
|
#endif
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
public void Draw()
|
|
{
|
|
GUI.skin = mSkin;
|
|
GUI.enabled = true;
|
|
|
|
// content rect
|
|
|
|
var rectContainer = GetEditorRect();
|
|
|
|
|
|
// clear background
|
|
|
|
var rectFullScreen = new Rect( 0.0f, rectContainer.yMin - 4.0f, Screen.width, Screen.height );
|
|
GUI.DrawTexture( rectFullScreen, GUI.skin.window.normal.background, ScaleMode.StretchToFill, false );
|
|
|
|
// scroll window
|
|
|
|
var padLeft = 8.0f;
|
|
var padRight = 4.0f;
|
|
var padHoriz = padLeft + padRight;
|
|
var scrollWidth = GUI.skin.verticalScrollbar.fixedWidth;
|
|
var minWidth = rectContainer.width - scrollWidth - padHoriz;
|
|
var maxHeight = ContentHeight( minWidth );
|
|
|
|
var hasScrollbar = maxHeight >= rectContainer.height;
|
|
var contentWidth = hasScrollbar ? minWidth : rectContainer.width - padHoriz;
|
|
var rectContent = new Rect( -padLeft, 0.0f, contentWidth, maxHeight );
|
|
|
|
// draw content
|
|
|
|
using( var scroll = new GUI.ScrollViewScope( rectContainer, mScrollPos, rectContent ) )
|
|
{
|
|
mScrollPos = scroll.scrollPosition;
|
|
|
|
if( mRaw )
|
|
{
|
|
rectContent.width = minWidth - GUI.skin.button.fixedWidth;
|
|
DrawRaw( rectContent );
|
|
}
|
|
else
|
|
{
|
|
DrawMarkdown( rectContent );
|
|
}
|
|
}
|
|
|
|
DrawToolbar( rectContainer, hasScrollbar ? scrollWidth + padRight : padRight );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
float ContentHeight( float width )
|
|
{
|
|
return mRaw ? GUI.skin.GetStyle( "raw" ).CalcHeight( new GUIContent( mText ), width ) : mLayout.Height;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void DrawToolbar( Rect rect, float marginRight )
|
|
{
|
|
var style = GUI.skin.button;
|
|
var size = style.fixedHeight;
|
|
var btn = new Rect( rect.xMax - size - marginRight, rect.yMin, size, size );
|
|
|
|
if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( mRaw ? "btnRaw" : "btnFile" ) ) )
|
|
{
|
|
mRaw = !mRaw;
|
|
}
|
|
|
|
if( mRaw == false )
|
|
{
|
|
if( mHistory.CanForward )
|
|
{
|
|
btn.x -= size;
|
|
|
|
if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( "btnForward" ) ) )
|
|
{
|
|
Selection.activeObject = AssetDatabase.LoadAssetAtPath<TextAsset>( mHistory.Forward() );
|
|
}
|
|
}
|
|
|
|
if( mHistory.CanBack )
|
|
{
|
|
btn.x -= size;
|
|
|
|
if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( "btnBack" ) ) )
|
|
{
|
|
Selection.activeObject = AssetDatabase.LoadAssetAtPath<TextAsset>( mHistory.Back() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void DrawRaw( Rect rect )
|
|
{
|
|
EditorGUI.SelectableLabel( rect, mText, GUI.skin.GetStyle( "raw" ) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void DrawMarkdown( Rect rect )
|
|
{
|
|
switch( Event.current.type )
|
|
{
|
|
case EventType.Ignore:
|
|
break;
|
|
|
|
case EventType.ContextClick:
|
|
var menu = new GenericMenu();
|
|
menu.AddItem( new GUIContent( "View Source" ), false, () => mRaw = !mRaw );
|
|
menu.ShowAsContext();
|
|
|
|
break;
|
|
|
|
case EventType.Layout:
|
|
mLayout.Arrange( rect.width );
|
|
break;
|
|
|
|
default:
|
|
mLayout.Draw();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|