1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WebページでJavaScriptを編集・実行できるページを作る

Last updated at Posted at 2024-01-31

はじめに

自作のJavaScript数値計算ライブラリの確認用デモページのために作る。
同様なサービスなどは大量にあると思うがよりシンプルに...というか個人開発で賄える範囲のものに留める(ようにする)。

こんな感じで
image.png

使ったライブラリ

Ace

ブラウザ上でリアルタイムに編集できてシンタックスハイライトが付けられるコードエディタ。
HTMLで<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js"></script>のように読み込む
私は以下のようにユーティリティ化している

aceUtil.js
let editor=null;

export default {
    set: (id, lang=void 0, theme=void 0)=>{
        if( typeof(id)==='object' ){
            if( id.lang !=null ) lang=id.lang;
            if( id.theme!=null ) theme=id.theme;
        }
        editor=ace.edit(id);
        editor.setTheme(theme);
        editor.session.setMode(lang);
        console.log(editor);
    },

    setValue: (text, point=-1)=>{ editor.setValue(text, point); },
    getValue: ()=>{ return editor.getValue(); },

    loadText: async (url)=>{ return fetch(url, { cache: "no-store" } ).then(res=> res.text()).then(text=> editor.setValue(text, -1)); }
}

HTMLのID(多分、エレメント自体でもOK)でエレメントを指定するとその下に<texterea>と色々作られる。
(textareaが本体だがそれにラッパーで色付けとか付けられた透過するdivが作られる)

編集エリアからの入出力はsetValuegetValueで行われる。
setValueのpositionは位置を表すが負の値を与えると0になるようである。

コードの実行

index.js
function run(){
//    const { code }=Babel.transform(aceUtil.getValue(), { presets: ['env'], plugins: ['operator_overload'] });
//    const f=Function(code);
    const f=Function(aceUtil.getValue());

    if( document.getElementById('auto-clear').checked ) clearResult();
    f();
}

これだけす。Functionを作って実行するだけです。
後々は少しトランスパイルを通しますがその場合は上のようなコードになります。
これには別途、色々設定が必要です。

モジュールのロード

ただ上のコードではグローバルにあるものしか使えません。
そこで以下のようなloadMdule関数を使って自作ライブラリをロードしています。

loadModule.js
export default async (filepath)=>{
    return await import(filepath).then(module=>{
        for( const [key, val] of Object.entries(module) ){
            if( window[key]==null ){
                window[key]=val;
                console.log('Set Global Property '+key);                   
            }
            else{
                console.error('! Global.'+key+' already defined');
            }
        }
    });
}

exportされたオブジェクトのプロパティをブラウザのグローバルであるwindowにセットしているだけです。
もちろん、名前がかぶると衝突してエラーメッセージを吐きます。

export側はこんな感じになってます。

modules/calc.js
...

export {add, sub, mul, div, // 四則演算 
        sqrt, pow, factorial, exp, sin, cos, tan, sinh, cosh, tanh, // 初等関数 
        specialFunc,
        diff, integral, // 微分、積分
        Complex, // 複素数クラス
        Vector, Matrix, // ベクトルクラス、行列クラス 
        linearAlgebra,
        solver,
       };

...の部分で本体を定義importする形になっています。
JS標準のようにMathクラスのような、MyMathとかでラップしても良かったですがユーザーが編集するにはめんどくさいと思ったので裸でexportしました。

アウトプット

アウトプットはconsoleのようにoutput.log(...)とすると下のid="result"に出るようにしてあります。
下のようにdiv要素を作ってそこに入れているだけです。

また、output.math(...)を使うとMathjaxを使った、形式で出してくれるようにしてあります。

function resetMathJax(...)の部分は追加があった場合の再描写です。

output.js
const output={
    log: (...args)=>{
        const elem=document.getElementById('result');
        const div=document.createElement('div');
        const text=args.reverse().reduce((a, sum)=> sum+' '+a, '');

        div.innerHTML=text;
        elem.appendChild(div);
    },

    math: (...args)=>{
        const elem=document.getElementById('result');
        const div=document.createElement('div');
        div.innerHTML+='\\[ ';
        args.forEach(a=>{ div.innerHTML+=typeof a.toTex ==='function' ? a.toTex(): a });
        div.innerHTML+=' \\]';
        elem.appendChild(div);
        restartMathJax();
    }
};
export { output };

function restartMathJax(){ MathJax.Hub.Queue(["Typeset", MathJax.Hub, "dynamicElement"]); }

成果物

gitpubリポジトリ、色々付け加えてしかも途中ですが...orz
githubページ

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?