miso_soup3 Blog

主に ASP.NET 関連について書いています。

Web ページに MathJax を使って MathML を表示する

 Reference

使い方 MathML

ここでは、MathJax を使った MathML を記述する方法について書きます。LaTex, Tex 等の情報はありません。

load

head 内に、下記のように script を記述します。 ?configのクエリ文字列については?config の設定についてを参照してください。

<script 
    type="text/javascript"
    src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
inline & block
  • インライン表示:<math display="inline">
  • ブロック表示:<math display="block">
  • デフォルトはインライン表示
    • <math> はインライン表示
tag
namespace

必須ではないが、<math xmlns="http://www.w3.org/1998/Math/MathML"> といったように名前空間をつけることが望ましいです。

参照:MathML input

self-closing tag

自己終了タグ(例:<mspace width="5pt" />)は使用しないで下さい。

参照:MathML input

設定オプション Core

参照:The Core Configuration Options

mml2jax

MathJax の ページ内に記述された MathML を認識するコンポーネントはmml2jaxと呼ばれます。mml2jaxはいくつかの設定オプションがあります。

詳細についてはmml2jax configuration optionsを参照してください。MathJax の MathML のサポートの詳細についてはMathMLのページを参照してください。

ここでは、mml2jaxの設定オプションについて記述します。

◇init

mml2jax の設定オプションを追加するには、以下のようにMathJax.Hub.config()mml2jaxセクションを追加します。

MathJax.Hub.Config({
    mml2jax: {
        preview: "mathml"
    }
});

以下は、MathJax の設定を含めた script の記述例です。

<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
        mml2jax: {
            preview: "mathml"
        }
    });
</script>
<script type="text/javascript"
        src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

◇preview: "mathml"

preview: "mathml" という設定により MathJax が MathML のレンダリング完了までに Html ページに挿入するものを指定できます。

"mathml","alttext","altimg","none" デフォルト値はmathmlです。

  • "mathml"
    • レンダリング中にmathタグをそのまま保持します。
  • "alttext"
    • レンダリング中に<math>要素のalttext属性の値が表示されます。例:<math alttext="表示中"> 表示中というテキストが表示されるます。
  • "altimg"
    • レンダリング中に<math>要素のaltimg*属性の値で指定された URL の画像が表示されます。例:<math alttext="../image/hoge.jpg">
  • "none"
    • プレビューが挿入されるのを防ぎます。

この他、 HTML スニペットを使用することもできます。詳細は description of HTML snippetsを参照してください。

Examples:

preview: ["[math]"]

レンダリング完了まで "[math]" というテキストが表示されます。

preview: [["img",{src: "/images/mypic.jpg"}]], 

レンダリング完了まで指定した URL の画像が表示されます。

Word からコピペする場合

Word から数式をコピーして貼り付ける場合、html タグを以下の様にする。

<html lang="ja" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math">

Word から数式をコピーした場合、以下の様な MathML がコピーできる

<mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"><mml:mfrac><mml:mrow><mml:mo>-</mml:mo><mml:mi mathvariant="normal">b</mml:mi><mml:mo>±</mml:mo><mml:msqrt><mml:msup><mml:mrow><mml:mi mathvariant="normal">b</mml:mi></mml:mrow><mml:mrow><mml:mn>2</mml:mn></mml:mrow></mml:msup><mml:mo>-</mml:mo><mml:mn>4</mml:mn><mml:mi mathvariant="normal">a</mml:mi><mml:mi mathvariant="normal">c</mml:mi></mml:msqrt></mml:mrow><mml:mrow><mml:mn>2</mml:mn><mml:mi mathvariant="normal">a</mml:mi></mml:mrow></mml:mfrac></mml:math>

Umbraco で Macro を使う

概要

Macro は Razor, XSLT, usercontrol で書くことができる。(Umbraco 7 では、usercontrol はあまり使われないと思われる。)

Parameter も設定可能。

Macro の入力用ヘルパーあり(Rich Text Editor にも付属)。

用途

ユーザーが任意の場所に、動的な要素を埋め込みたい時に使用する。

例えば、本文中にとある手順について書くとする。この手順は、あちこちの記事で表示する可能性があり、機能がリリースされるたびに更新が必要となる。

例:Azure Websites と ASP.NET を使用する の "このチュートリアルを完了するには、Azure アカウントが必要です。" の部分。

Macro を使用しない場合は、リリースの度に複数の記事を修正しなければいけない。Razor で @Html.Partial("hoge") と書きたいところだが、ユーザーが管理画面の入力欄で任意の場所に配置できるようにしたい。そこで Macro を使う。

手順

  • Partial View Macro Files を作成する。
    • Back Office > Developer > Partial View Macro Files

このとき、 .cshtml は @inherits Umbraco.Web.Macros.PartialViewMacroPage と、継承する。

  • Macro を作成する。
    • Back Office > Deceloper > Macros
  • Macro を配置する。方法は 2 つ。

◇方法1

ユーザーが Macro を配置したい場所にて以下のコードを書く。パラメータがある場合は、属性とその値も追加する。

<div><?UMBRACO_MACRO macroAlias="{ Macro の 名前}}" /></div>

開発者は、.cshtml 側で以下のコードを記述し、Macro をレンダリングさせる。

string afterRender = umbraco.library.RenderMacroContent(string Text, int PageId(Model.Content.Id)等);

◇方法2

入力フィールドがリッチテキストの場合は、ユーザーが 入力用ヘルパーから配置する。

Bug

  • Partial View Macro Files が文字化けする場合がある。
    • 改行文字の混合が原因?
    • Visual Studio から、ファイル>名前を付けて ... を保存>エンコード付きで保存>改行文字 でファイルを保存し直すと直る。
    • Back Office から編集して保存すると文字化けする可能性大。

Umbraco 7 Note 1

Umbraco についてです。メモとして描いていたので内容は部分的です。

Umbraco で登場する用語

  • Dashboards
    • http://hoge/umbraco でアクセスできる管理画面
  • Umbraco API
    • Version 6 から登場した Umbarco のデータを操作できる API
  • Back Office
    • Umbraco の構成要素

Back Office

C# で例えると、Document Type : クラス、Content : クラスから作成したインスタンス、Properies : クラスがもつ Property、Data Type : Property の型、Property Editors : Property の型の構造(string, int, Custom Class の中身の実装)。Umbraco でサイトを作成するには、Document Type を定義し、Properties を定義し、Content を作成してページを作る。

  • Document Type
    • ページの構造。
    • 例: Blog という Document Type は、 Title, BodyText, PublishDate, という Properties を持つ。
  • Content
    • ページ。
    • 例: Document Type の "Blog" から 2011/11/10 の記事 を作成する。(= Content を 1 つ作成した)
    • 例: Document Type の "Blog" から 2011/11/30 の記事 を作成する。(= Content を 1 つ作成した)
  • Properties
  • Data Type
  • Property Editors
  • Media Type
  • Media
  • Member Type
  • Member
  • Node
  • User
  • Macros
  • Macro Parameter Editor
  • Templates/Layouts/Masterpages
  • Packages

参照

未分類

Document Type

Document Type は継承することができる。この Document Type の継承は、"Property" や "Tab" を継承したい(同じ構造を持たせたい) 、という目的の時に使用する。とあるページがとあるページの下に配置されるからといって、Document Type を継承しなければいけない、ということではない。 (http://hoge/blog の下に http://hoge/blog/entry というページを配置する場合、必ずしも entry の Document Type は blog の Document Type を継承しなければいけない、ということではない。)

Document Type Compositions

Umbraco 7.2 から追加された機能。Document Type を複数継承することができるようになった。

今までは、継承する Document Type は一つしか選択できず、また継承元を変更することもできなかった。Document Type Compositions により複数の Document Type を継承元として選択できるようになり、変更も可能になった。

例えば、複数の Document Type に "Meta Keyword" という Property を持たせたい場合は、"SEO" という Document Type を作成して "Meta Keyword" という Property を持たせる。そして、例えばページという Document Type にて Document Type Compositions で "SEO" にチェックを入れる。そうすると、ページの Document Type に "Meta Keyword" という Property を持たせることができる。そして、ページは、他の Document Type も継承することができるので、気軽に Document Type を小さくまとめて定義できる。

なお、Dashboards の Document Type では、今まで通りのツリー構造で表示される。

Umbraco 7.2 Compositions

Alt Template

実際に選択している Template とは別のテンプレートを適用して表示することができる機能。URL に ?alttemplate=hoge ( hoge に Template の Alias) を付けて表示することができる。

注意として、意図しないページを表示させたり、余計なエラーを発生することになる。

この機能を禁止する場合は、 config/umbracoSettings.config の disableAlternativeTemplates に false を設定する。

<web.routing
    trySkipIisCustomErrors="false"
    internalRedirectPreservesTemplate="false" disableAlternativeTemplates="true">
</web.routing>
Custom Error Page

Custom Error ページの Content を用意する config/umbracoSettings.config にて、Content Id を設定

<errors>
  <error404>1732</error404>
</errors>

Web.config の system.webserver に

<httpErrors existingResponse="PassThrough"/>

ASP.NET の通常のエラー設定も必要に応じて。

<customErrors mode="RemoteOnly" defaultRedirect="~/Error.aspx"/>

Umbraco 7 公開日の設定

Umbraco の Document Type には、作成日・編集日 は予め用意されているが、公開日は用意されていない。

そこで、公開日を設定したい場合は、Document Event を拡張し、コンテンツが公開された時のイベントを拡張し、 ”あるドキュメントが公開されたらその時の日付を Property にセットする”という実装をかく。

以下はその例のコード。 (このコードには、MarkdownでかかれたテキストをHtmlに変換する処理も混ざっている。)

プロジェクト配下に「Umbraco.Core.ApplicationEventHandler」を継承したクラスを配置する。

参照:

application-startup - Events - Reference - Documentation - our.umbraco.org

Document Events https://our.umbraco.org/documentation/reference/events/Document-Events (ちょっと古い)

using HogeProject.Umbraco.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;

namespace HogeProject.Umbraco.Extensions
{
    /// <summary>
    /// Umbraco の アプリケーション イベントをカスタマイズします
    /// </summary>
    /// <remarks>
    /// https://our.umbraco.org/documentation/Reference/Events/application-startup
    /// 
    /// Document Events https://our.umbraco.org/documentation/reference/events/Document-Events (ちょっと古い)
    /// </remarks>
    public class HogeProjectApplicationEventHandler : ApplicationEventHandler
    {
        protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            ContentService.Publishing += ContentService_Publishing;
            ContentService.Saving += ContentService_Saving;
        }

        /// <summary>
        /// Content Saving
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ContentService_Saving(IContentService sender, SaveEventArgs<IContent> e)
        {
            foreach(IContent node in e.SavedEntities)
            {
                if (node.ContentType.Alias == "Article" || node.ContentType.Alias == "BlogEntry")
                {
                    //markdown で書かれた文章を変換しプロパティに格納します。
                    SetMarkdownParsed(node);
                }
            }
        }

        /// <summary>
        /// Content が Publish されようとするときに呼び出されます。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void ContentService_Publishing(IPublishingStrategy sender, PublishEventArgs<IContent> e)
        {
            foreach (IContent node in e.PublishedEntities)
            {
                if (node.ContentType.Alias == "Article" || node.ContentType.Alias == "Subject")
                {
                    // 最初の公開日をプロパティに設定します。
                    SetFirstPublishedDate(node, "sinceSet");
                }
                else if (node.ContentType.Alias == "BlogEntry")
                {
                    // 最初の公開日をプロパティに設定します。
                    SetFirstPublishedDate(node, "firstPublishedDate");
                }
            }
        }

        /// <summary>
        /// プロパティに最初の公開日を設定します
        /// </summary>
        /// <param name="content"></param>
        private void SetFirstPublishedDate(IContent content, string propertyAlias)
        {
            //指定した値が null の場合のみ設定します

            if (content.HasProperty(propertyAlias) == false)
                return;

            //既に設定してある場合は設定しない
            if (content.GetValue(propertyAlias) != null)
                return;

            //初期データの場合は設定しない
            if (content.HasProperty("isInitialData") && content.GetValue<bool>("isInitialData"))
                return;

            content.SetValue(propertyAlias, DateTime.Now);
        }

        /// <summary>
        /// Markdown でかかれた本文を Html に変換し、プロパティに設定します。
        /// </summary>
        /// <param name="content"></param>
        private void SetMarkdownParsed(IContent content)
        {
            if (!content.HasProperty("bodyText") || !content.HasProperty("bodyTextParsed"))
                return;

            string bodyTextMarkdown = content.GetValue<string>("bodyText");
            string bodyTextHtml = MarkdownHelper.Transform(bodyTextMarkdown);

            content.SetValue("bodyTextParsed", bodyTextHtml);
        }
    }
}