Advertisement
Guest User

generate_img.html 0.0.99.20211018 (2021-10-18) by cleemy desu wayo

a guest
Oct 18th, 2021
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 21.63 KB | None | 0 0
  1. <!doctype html>
  2. <html><head>
  3. <meta charset="utf-8">
  4. <title>generate img</title>
  5. <script>
  6. //
  7. // generate_img.html version 0.0.99.20211018 (2021-10-18) written by cleemy desu wayo
  8. //
  9. // this is a personal work and is a PDS (Public Domain Software)
  10. //
  11. // see https://twitter.com/cleemy4545/status/1450188684045787142 and the thread
  12. //
  13. // old version of generate_img.html : https://pastebin.com/wEG4s4Eu
  14. //
  15. // another edition:
  16. //   generate_img.py (Python + Pillow)       : https://pastebin.com/geUDPrWT
  17. //   generate_img.rb (Ruby + RMagick)        : https://pastebin.com/2pEVnM8Q
  18. //   generate_img.js (Node.js + node-canvas) : https://pastebin.com/wgfaHUKh
  19. //
  20.  
  21. 'use strict';
  22. let dirImg                 = './';
  23. let dirTextimg             = './';
  24. let isDirTextimgOverridden = false;
  25. let mainCanvasElem    = null;      // after loading the page, this always points to either of the two canvas elements
  26. let mainCanvas        = null;      // will be set to null every time the redrawing starts
  27. let mainCanvasContext = null;
  28. let newImgPiece       = new Image;
  29. let textimgParams     = new Map([['body', ''], ['x', 0], ['y', 0], ['charPos', 0]]);
  30. let pos               = new Map([['x', 0], ['y', 0]]);
  31. let margin            = new Map([['x', 0], ['y', 0]]);
  32. let step              = new Map([['x', 1], ['y', 0]]);
  33. let textSize          = 16;
  34. let textColor         = [];
  35. let textFont          = 'unifont';
  36. let textStep          = 1;
  37.  
  38. let generateCount     = 0;
  39.  
  40. let lines        = [];
  41. let lineNum      = -1;
  42. let loopCount   = 0;
  43. let isImgLoading = false;
  44.  
  45. const waitMillisec  = 0;
  46.  
  47. //
  48. // parseArgs(sourceStr): parse sourceStr and return an Array
  49. //
  50. // '(100,100,20,#ffffff)'      --> return ['100', '100', '20', '#ffffff']
  51. // '(100)'                     --> return ['100']
  52. // '   (100)   '               --> return ['100']
  53. // '(   100  ,   100   )'      --> return ['100', '100']
  54. // '(   100  ,   10 0  )'      --> return ['100', '10 0']
  55. // '(,,20)'                    --> return ['', '', '20']
  56. // '(20,,)'                    --> return ['20', '', '']
  57. // '(,,,)'                     --> return ['', '', '', '']
  58. // '( , , , )'                 --> return ['', '', '', '']
  59. // '()'                        --> return ['']
  60. // '( )'                       --> return ['']
  61. // ''                          --> return []
  62. // '(())'                      --> return ['()']
  63. // '(100,100' (invalid string) --> return []
  64. // [100, 100] (not string)     --> return []
  65. //
  66. const parseArgs = function(sourceStr) {
  67.   if (Object.prototype.toString.call(sourceStr) !== '[object String]') {
  68.     return [];
  69.   }
  70.  
  71.   const args_str = sourceStr.trim().replace(/^\((.*)\)$/, '$1');  // ' (100,100) ' --> '100,100'
  72.   if (args_str === sourceStr) {
  73.     return [];
  74.   }
  75.  
  76.   return args_str.split(',').map(s => s.trim());
  77. }
  78.  
  79. //
  80. // properFilePath(filePath, baseFilePath): return a proper file path
  81. //
  82. // this ignores base_file_path_src if file_path starts with '/', 'file:///',
  83. // 'https://', 'ftp://' or some such
  84. //
  85. const properFilePath = function(filePath, baseFilePathSrc = '') {
  86.  
  87.   // has a control code?
  88.   if (`${filePath}${baseFilePathSrc}`.match(/[\x00-\x1f\x7f-\x9f]/)) { return '' }
  89.  
  90.   let resultStr = '';
  91.  
  92.   if (filePath.startsWith('/') || filePath.startsWith('file:///')) {
  93.     resultStr = filePath.replace(/^(file:)?\/+/, 'file:///');
  94.   } else if (filePath.match(/^[a-zA-Z]+:\/\//)) {
  95.     resultStr = filePath.replace(/^([a-zA-Z]+):\/\/+/, '$1://');
  96.   } else {
  97.  
  98.     let baseFilePath = baseFilePathSrc;
  99.  
  100.     if (baseFilePath === null || baseFilePath === undefined || baseFilePath === '') {
  101.       baseFilePath = '.';
  102.     } else if (baseFilePath.startsWith('/') || baseFilePath.startsWith('file:///')) {
  103.       baseFilePath = baseFilePath.replace(/^(file:)?\/+/, 'file:///');
  104.     } else if (baseFilePath.match(/^[a-zA-Z]+:\/\//)) {
  105.       baseFilePath = baseFilePath.replace(/^([a-zA-Z]+):\/\/+/, '$1://');
  106.     } else {
  107.       baseFilePath = './' + baseFilePath.replace(/^(\.\/+)+/, '');
  108.     }
  109.  
  110.     resultStr = baseFilePath.replace(/\/+$/, '') + '/' + filePath.replace(/^(\.\/+)+/, '');
  111.   }
  112.  
  113.   if (!configFilePrefixAllowlist.some(str => resultStr.startsWith(str))) {
  114.     resultStr = '';
  115.   }
  116.  
  117.   return resultStr;
  118. }
  119.  
  120. //
  121. // pasteImg(params): draw new image
  122. //
  123. const pasteImg = function(params) {
  124.   mainCanvasContext.drawImage(newImgPiece, params.get('x'), params.get('y'));
  125.  
  126.   return [newImgPiece.width, newImgPiece.height];
  127. }
  128.  
  129. //
  130. // drawTextimg(): draw textimg
  131. //
  132. const drawTextimg = function() {
  133.   const d = document;
  134.   const c = Array.from(textimgParams.get('body'))[textimgParams.get('charPos')]
  135.  
  136.   // reached the end
  137.   if (c === undefined) {
  138.     isImgLoading = false;
  139.     return false;
  140.   }
  141.  
  142.   const filePath = properFilePath('textimg_' + c.codePointAt(0).toString(16) + '.png', dirTextimg);
  143.  
  144.   d.getElementById('debug_text').value += '      **** load start: ' + filePath + "\n";
  145.  
  146.   newImgPiece.onload = () => {
  147.     let newImgPieceSize = { x: 0, y: 0 };
  148.     [newImgPieceSize['x'], newImgPieceSize['y']] = pasteImg(textimgParams);
  149.  
  150.     textimgParams.set('charPos', textimgParams.get('charPos') + 1);
  151.     textimgParams.set('x', textimgParams.get('x') + newImgPieceSize['x']);    // "textimg:" does not change pos
  152.     setTimeout(() => {drawTextimg()}, d.getElementById('wait_millisec').value);
  153.   }
  154.   newImgPiece.onerror = () => {
  155.     textimgParams.set('charPos', textimgParams.get('charPos') + 1);
  156.     setTimeout(() => {drawTextimg()}, d.getElementById('wait_millisec').value);
  157.   }
  158.   newImgPiece.src = filePath;
  159. }
  160.  
  161. const drawStart = function() {
  162.   const d = document;
  163.   const generateCountBuffer = generateCount + 1;
  164.   d.getElementById('debug_text').value = "draw start... (" + (new Date().toISOString()) + ")\n";
  165.  
  166.   if (mainCanvasContext) { mainCanvasContext.clearRect(0, 0, mainCanvas.width, mainCanvas.height); }
  167.   dirImg            = './';
  168.   dirTextimg        = './';
  169.   mainCanvas        = null;
  170.   mainCanvasContext = null;
  171.   pos               = new Map([['x', 0], ['y', 0]]);
  172.   margin            = new Map([['x', 0], ['y', 0]]);
  173.   step              = new Map([['x', 1], ['y', 0]]);
  174.   textSize          = 16;
  175.   textColor         = [];
  176.   textFont          = 'unifont';
  177.   textStep          = 1;
  178.   generateCount     = generateCountBuffer;
  179.  
  180.   lines        = d.getElementById('main_text').value.split('\n');
  181.   lineNum      = -1;
  182.   loopCount    = 0;
  183.   isImgLoading = false;
  184.  
  185.   setTimeout(() => {parseAndExec(generateCountBuffer)}, d.getElementById('wait_millisec').value);
  186. }
  187.  
  188. const parseAndExec = function(count) {
  189.   const d = document;
  190.   const generateCountBuffer = generateCount;
  191.   const isImgLoadingBuffer  = isImgLoading;
  192.   const imgLodingStatusStr  = ' ... isImgLoading = ' + ((isImgLoadingBuffer) ? 'true (waiting...)' : 'false');
  193.  
  194.   if (count < generateCountBuffer) {
  195.    return false;   // newer redrawing has already started
  196.  }
  197.  
  198.  loopCount += 1;
  199.  if (! isImgLoadingBuffer) {
  200.    lineNum += + 1;
  201.  }
  202.  const line = lines[lineNum];
  203.  
  204.  // reached the end
  205.  if (line === null || line === undefined) {
  206.    const exitMessage = (mainCanvas === null) ? "error: no background image\n" : "done.\n";
  207.    d.getElementById('debug_text').value += exitMessage;
  208.    return false;
  209.  }
  210.  
  211.  d.getElementById('debug_text').value += '(loop count: ' + loopCount + ') ' +
  212.                                          ' at line [' + (lineNum + 1) + '] ' +
  213.                                          imgLodingStatusStr + "\n";
  214.  
  215.  // now waiting
  216.  if (isImgLoadingBuffer) {
  217.    setTimeout(() => {parseAndExec(generateCountBuffer)}, d.getElementById('wait_millisec').value);
  218.     return false;
  219.   }
  220.  
  221.   let m = null;
  222.  
  223.   if (m = line.match(/^dir *: *([-_a-zA-Z0-9./%:]+) *$/)) {
  224.     dirImg = properFilePath(m[1]);
  225.     if (!isDirTextimgOverridden) { dirTextimg = dirImg }
  226.  
  227.   } else if (m = line.match(/^dir *\( *textimg *\) *: *([-_a-zA-Z0-9./%:]+) *$/)) {
  228.     dirTextimg = properFilePath(m[1]);
  229.     isDirTextimgOverridden = true;
  230.  
  231.   } else if (m = line.match(/^bg *: *([-_a-zA-Z0-9./%:]+) *$/)) {
  232.     const bgSrc = properFilePath(m[1], dirImg);
  233.  
  234.     d.getElementById('debug_text').value += '      **** load bg start: ' + bgSrc + "\n";
  235.  
  236.     newImgPiece.src = bgSrc;
  237.     isImgLoading = true;
  238.     newImgPiece.onload = () => {
  239.       mainCanvas = mainCanvasElem;
  240.       mainCanvas.setAttribute('width',  newImgPiece.width);
  241.       mainCanvas.setAttribute('height', newImgPiece.height);
  242.  
  243.       mainCanvasContext = mainCanvas.getContext('2d');
  244.       mainCanvasContext.drawImage(newImgPiece, 0, 0);
  245.       isImgLoading = false;
  246.     }
  247.     newImgPiece.onerror = () => {
  248.       isImgLoading = false;
  249.     }
  250.  
  251.   } else if ((m = line.match(/^paste *(\(.*?\))? *: *([-_a-zA-Z0-9./%:]+) *$/)) && mainCanvas) {
  252.    const filePath = properFilePath(m[2], dirImg);
  253.  
  254.     let pasteParams = new Map([['src', filePath    ],
  255.                                ['x',   pos.get('x')],
  256.                                ['y',   pos.get('y')]]);
  257.  
  258.     const pasteArgs  = parseArgs(m[1]);
  259.     const argsLength = pasteArgs.length;
  260.     if (argsLength >= 1) {
  261.       if (pasteArgs[0].match(/^-?[0-9]+(\.[0-9]+)?$/)) {
  262.         pasteParams.set('x', pos.get('x') + parseFloat(pasteArgs[0]));
  263.       }
  264.       if ((argsLength >= 2) && pasteArgs[1].match(/^-?[0-9]+(\.[0-9]+)?$/)) {
  265.        pasteParams.set('y', pos.get('y') + parseFloat(pasteArgs[1]));
  266.       }
  267.     }
  268.  
  269.     d.getElementById('debug_text').value += '      **** load start: ' + pasteParams.get('src') + "\n";
  270.  
  271.     isImgLoading = true;
  272.     newImgPiece.onload = () => {
  273.       let newImgPieceSize = { x: 0, y: 0 };
  274.       [newImgPieceSize['x'], newImgPieceSize['y']] = pasteImg(pasteParams);
  275.  
  276.       ['x', 'y'].forEach(axis => {
  277.         pos.set(axis, pos.get(axis) + newImgPieceSize[axis] * step.get(axis) + margin.get(axis));
  278.       });
  279.       isImgLoading = false;
  280.     }
  281.     newImgPiece.onerror = () => {
  282.       isImgLoading = false;
  283.     }
  284.     newImgPiece.src = pasteParams.get('src');
  285.  
  286.   } else if ((m = line.match(/^textimg *(\(.*?\))? *: *(.+)$/)) && mainCanvas) {
  287.  
  288.    textimgParams.set('body',    m[2]);
  289.     textimgParams.set('x',       pos.get('x'));    // "textimg:" does not change pos
  290.     textimgParams.set('y',       pos.get('y'));    // "textimg:" does not change pos
  291.     textimgParams.set('charPos', 0);
  292.  
  293.     const textimgArgs = parseArgs(m[1]);
  294.     const argsLength = textimgArgs.length;
  295.     if (argsLength >= 1) {
  296.       if (textimgArgs[0].match(/^-?[0-9]+(\.[0-9]+)?$/)) {
  297.         textimgParams.set('x', pos.get('x') + parseFloat(textimgArgs[0]));
  298.       }
  299.       if ((argsLength >= 2) && textimgArgs[1].match(/^-?[0-9]+(\.[0-9]+)?$/)) {
  300.        textimgParams.set('y', pos.get('y') + parseFloat(textimgArgs[1]));
  301.       }
  302.     }
  303.     isImgLoading = true;
  304.     drawTextimg();
  305.  
  306.   } else if ((m = line.match(/^text *(\(.*?\))? *: *(.+)$/)) && mainCanvas) {
  307.    let textParams = new Map([['body',  m[2]                ],
  308.                              ['x',     pos.get('x')        ],
  309.                              ['y',     pos.get('y')        ],
  310.                              ['size',  parseFloat(textSize)],
  311.                              ['color', textColor           ]]);
  312.  
  313.     const textArgs   = parseArgs(m[1]);
  314.     const argsLength = textArgs.length;
  315.     if (argsLength >= 1) {
  316.       if (textArgs[0].match(/^-?[0-9]+(\.[0-9]+)?$/)) {
  317.         textParams.set('x', pos.get('x') + parseFloat(textArgs[0]));
  318.       }
  319.       if ((argsLength >= 2) && textArgs[1].match(/^-?[0-9]+(\.[0-9]+)?$/)) {
  320.        textParams.set('y', pos.get('y') + parseFloat(textArgs[1]));
  321.       }
  322.       if ((argsLength >= 3) && textArgs[2].match(/^[0-9]+(\.[0-9]+)?$/)) {
  323.        textParams.set('size', parseFloat(textArgs[2]));
  324.       }
  325.       if ((argsLength >= 4) && textArgs[3].startsWith('#')) {
  326.        const matched_rgb = textArgs[3].match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/)
  327.        if (matched_rgb !== null) {
  328.          const matched_rgb_array = matched_rgb.slice(1, 4).map(s => parseInt(s, 16));
  329.           textParams.set('color', matched_rgb_array);
  330.         }
  331.       }
  332.     }
  333.  
  334.     mainCanvasContext.font = textParams.get('size').toString() + 'px ' + textFont;
  335.     mainCanvasContext.fillStyle = 'rgb(' + textParams.get('color').join(',') + ')';
  336.     mainCanvasContext.fillText(textParams.get('body'),
  337.                                textParams.get('x'),
  338.                                textParams.get('y') + textParams.get('size'));
  339.     pos.set('y', pos.get('y') + parseFloat(textSize) * parseFloat(textStep) + margin.get('y'));
  340.  
  341.   } else if (m = line.match(/^text_([a-z]+) *: *(.+?) *$/)) {
  342.     if (m[1] === 'font') {
  343.       textFont = m[2];
  344.     } else if (m[1] === 'size') {
  345.       textSize = parseFloat(m[2]);
  346.     } else if (m[1] === 'color') {
  347.       let regex;
  348.       let radix;
  349.       if (m[2].startsWith('#')) {
  350.         regex = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2}) *$/;
  351.         radix = 16;
  352.       } else {
  353.         regex = /^([0-9]+) *, *([0-9]+) *, *([0-9]+) *$/;
  354.         radix = 10;
  355.       }
  356.       const matched_rgb = m[2].match(regex);
  357.       if (matched_rgb !== null) {
  358.         textColor = matched_rgb.slice(1, 4).map(s => parseInt(s, radix));
  359.       }
  360.     } else if (m[1] === 'step') {
  361.       textStep = parseFloat(m[2]);
  362.     }
  363.  
  364.   } else if (m = line.match(/^(blank|margin|pos|step) *(\(.*?\))? *: *([-0-9.]+?) *$/)) {
  365.     const args = parseArgs(m[2]);
  366.     if ((args.length !== 0) && (['x', 'y', ''].indexOf(args[0]) < 0)) {
  367.      return false;
  368.     }
  369.  
  370.     let axes = ['x', 'y'];
  371.     if (['x', 'y'].indexOf(args[0]) >= 0) {
  372.       axes = [args[0]];
  373.     }
  374.  
  375.     axes.forEach(axis => {
  376.       switch (m[1]) {
  377.         case 'blank'  : pos.set    (axis, pos.get(axis) + parseFloat(m[3])); break;
  378.         case 'margin' : margin.set (axis, parseFloat(m[3])); break;
  379.         case 'pos'    : pos.set    (axis, parseFloat(m[3])); break;
  380.         case 'step'   : step.set   (axis, parseFloat(m[3])); break;
  381.       }
  382.     });
  383.   }
  384.   setTimeout(() => {parseAndExec(generateCountBuffer)}, d.getElementById('wait_millisec').value);
  385. }
  386.  
  387. let watchCount = 0;
  388. let keepAfterChangeCount = 0;
  389. let lastMainText = '';
  390. const textareaWatch = function() {
  391.   const d = document;
  392.   watchCount += 1;
  393.   if (keepAfterChangeCount >= 1) {
  394.     keepAfterChangeCount += 1;
  395.   }
  396.  
  397.   d.getElementById('change_count_label').textContent = watchCount +
  398.                                                        ' (' + keepAfterChangeCount + ')' +
  399.                                                        ' (' + generateCount + ')';
  400.  
  401.   if (lastMainText !== d.getElementById('main_text').value) {
  402.     keepAfterChangeCount = 1;
  403.   } else if (keepAfterChangeCount > 9) {
  404.     keepAfterChangeCount = 0;
  405.     drawStart();
  406.   }
  407.  
  408.   lastMainText = d.getElementById('main_text').value;
  409.  
  410.   setTimeout(() => {textareaWatch()}, 100);
  411. }
  412.  
  413. window.addEventListener('load', () => {
  414.   mainCanvasElem = document.getElementById('main_canvas');
  415.   document.getElementById('debug_text').value = '';
  416.   lastMainText = document.getElementById('main_text').value;
  417.   textareaWatch();
  418.   configChange();
  419.   drawStart();
  420.   toolsTextimgFilenameGenerate();
  421. });
  422.  
  423. let subWindow;
  424. const createNewWindow = function() {
  425.   document.getElementById('btn_new_window').disabled   = true;
  426.   document.getElementById('main_canvas').style.display = 'none';
  427.  
  428.   const newWindowHtml =
  429.         '<html><head><title>generate_img.html canvas</title>' +
  430.         '<style>' +
  431.         '*      { margin: 0 0 0 0; }' +
  432.         'button { display: inline-block; font-size: 0.9rem; white-space: normal; ' +
  433.         '  padding: 0 0 0 0; max-width: 16rem; min-width: 3rem; width: 50%; min-height: 2.4rem; }' +
  434.         '</style>' +
  435.         '<script>' +
  436.         'window.onkeydown = (e) => { if (e.keyCode === 27) { window.close(); }};' +
  437.         'const toFullScreen = () => { document.getElementById(\'main_canvas_on_sub_window\').requestFullscreen(); };' +
  438.         '</' + 'script' + '>' +
  439.         '</head><body>' +
  440.         '<header style="position: fixed; max-width: 45rem; width: 100%;">' +
  441.         '<button onclick="toFullScreen();">full screen</button>' +
  442.         '<button onclick="window.close();" style="float: right;">close this window</button>' +
  443.         '</header>' +
  444.         '<main id="main_application_on_sub_window">' +
  445.         '<canvas id="main_canvas_on_sub_window" style="margin-top: 2.4rem;"' +
  446.        '  onclick="document.exitFullscreen();"' +
  447.        '  ondblclick="toFullScreen();"' +
  448.        '></canvas>' +
  449.         '</main>' +
  450.         '</body></html>';
  451.  
  452.   subWindow = window.open('', '_blank', 'resizable');
  453.   subWindow.document.open();
  454.   subWindow.document.write(newWindowHtml);
  455.   subWindow.document.close();
  456.  
  457.   watchSubWindowAndRedraw();
  458. }
  459.  
  460. const watchSubWindowAndRedraw = function() {
  461.   const subCanvas = subWindow.document.getElementById('main_canvas_on_sub_window');
  462.   const d = document;
  463.   if (subCanvas !== null) {
  464.     mainCanvasElem = subCanvas;
  465.     drawStart();
  466.     subWindow.addEventListener('unload', () => {
  467.       mainCanvasElem = d.getElementById('main_canvas');
  468.       d.getElementById('main_canvas').style.display = 'block';
  469.       drawStart();
  470.       d.getElementById('btn_new_window').disabled = false;
  471.     });
  472.   } else {
  473.     setTimeout(() => { watchSubWindowAndRedraw() }, 200);
  474.   }
  475. }
  476.  
  477. let configFilePrefixAllowlist = ['./', 'file:///'];
  478. const configChange = function() {
  479.   const d = document;
  480.  
  481.   configFilePrefixAllowlist = ['./', 'file:///'];
  482.   if (d.getElementById('config_allow_external_http').checked)  { configFilePrefixAllowlist.push('http://'); }
  483.   if (d.getElementById('config_allow_external_https').checked) { configFilePrefixAllowlist.push('https://'); }
  484.   drawStart();
  485. }
  486.  
  487.  
  488. let lastToolsTextimgFilename = '';
  489. const toolsTextimgFilenameGenerate = function() {
  490.   const d = document;
  491.   const tmpStr = d.getElementById('tools_textimg_filename_text').value;
  492.  
  493.   if (lastToolsTextimgFilename !== tmpStr) {
  494.     lastToolsTextimgFilename = tmpStr;
  495.  
  496.     let result_html = '';
  497.     let result_text = '';
  498.     Array.from(tmpStr).forEach(c => {
  499.       const codePointStr = c.codePointAt(0);
  500.       const codePointStrHex = codePointStr.toString(16);
  501.       result_html += '"&#x' + codePointStrHex + ';" (' + codePointStr + ', 0x' + codePointStrHex + ')';
  502.       result_html += ' ---- textimg_' + codePointStrHex + '.png';
  503.       result_html += '<br>';
  504.  
  505.       result_text += '"' + c + '" (' + codePointStr + ', 0x' + codePointStrHex + ')';
  506.       result_text += ' ---- textimg_' + codePointStrHex + '.png';
  507.       result_text += "\n";
  508.     });
  509.     //d.getElementById('tools_textimg_filename_result').innerHTML = result_html;
  510.     d.getElementById('tools_textimg_filename_result').innerText = result_text;
  511.  
  512.     let styleStr = 'none';
  513.     if (result_html !== '') { styleStr = 'block'; }
  514.     d.getElementById('tools_textimg_filename_result').style.display = styleStr;
  515.   }
  516.  
  517.   setTimeout(() => { toolsTextimgFilenameGenerate() }, 800);
  518. }
  519. </script>
  520.  
  521. <style>
  522. *               { margin: 0 0 0 0; }
  523. main            { display: block; white-space: nowrap; }
  524. textarea, input { background-color: #001319; color: #aabbcc; }
  525. body, p, aside  { background-color: #112636; }
  526. body            { padding: 0 1rem 0 1rem; }
  527. p, aside        { color: #aabbcc; }
  528. button          { height: 2.2rem; font-size: 1.2rem; }
  529.  
  530. aside.footer_aside {
  531.   background-color: #33384a;
  532.   margin: 2rem 1rem 1.5rem 1rem;
  533.   padding: 0 1.2rem 1.2rem 1.2rem;
  534.   border-radius: 0.8rem;
  535. }
  536. aside.footer_aside p:first-child {
  537.   padding: 0.6rem 0 0.6rem 0;
  538. }
  539. aside.footer_aside p {
  540.   background-color: #33384a;
  541. }
  542. aside.footer_aside p.tools_result {
  543.   display: none;
  544.   background-color: #001319;
  545.   background-color: #232738;
  546.   margin: 0.8rem 0.8rem 0.8rem 0.8rem;
  547.   padding: 0.8rem 0.8rem 0.8rem 0.8rem;
  548.   border-radius: 0.8rem;
  549.   width: 30rem;
  550.   font-size: 0.9rem;
  551. }
  552. aside.footer_aside p label {
  553.   margin: 0 0.6rem 0 0.2rem;
  554. }
  555. aside#config p.config {
  556.   padding: 0.2rem 1rem 0.6rem 0.6rem;
  557. }
  558.  
  559. canvas#main_canvas       { display: inline; vertical-align: top; margin-top: 2px;}
  560. button#btn_new_window    { display: inline; font-size: 0.9rem; }
  561. textarea#main_text       { display: inline; vertical-align: top; font-size: 1.1rem; }
  562. textarea#debug_text      { width: 90%; font-size: 0.75rem; }
  563. aside#debug_info p label { margin: 0 0.6rem 0 2rem; }
  564. aside#debug_info input   { font-size:0.9rem; padding:0 0 0 0; }
  565. </style>
  566.  
  567. </head>
  568. <body>
  569. <aside id="version_info"><p>Hi! I'm cleemy desu wayo. This is generate_img.html version 0.0.99.20211018 (2021-10-18)</p></aside>
  570.  
  571. <main id="main_application">
  572. <textarea id="main_text" rows="20" cols="40"></textarea>
  573.  
  574. <div style="display: inline-block; vertical-align: top;">
  575. <p><button id="btn_new_window" onclick="createNewWindow();">open new window</button></p>
  576. <canvas id="main_canvas" ondblclick="createNewWindow();"></canvas>
  577. </div>
  578. <div style="display:none;"><button id="btn_exec" onclick="drawStart();">Exec</button></div>
  579. </main>
  580.  
  581. <aside id="config" class="footer_aside">
  582. <p>config:</p>
  583. <p class="config">
  584.   <label>allow external resources:</label>
  585.   <input type="checkbox" size="40" id="config_allow_external_https" onchange="configChange();"><label>https</label>
  586.   <input type="checkbox" size="40" id="config_allow_external_http" onchange="configChange();"><label>http</label>
  587. </p>
  588. <p class="config">
  589.   <label>main loop wait:</label>
  590.   <input type="text" size="4" id="wait_millisec" value="0">
  591. </p>
  592. </aside>
  593.  
  594.  
  595. <aside id="debug_info" class="footer_aside">
  596. <p>debug info:</p>
  597. <textarea readonly rows="5" id="debug_text"></textarea>
  598. <p>
  599.   <span id="change_count_label">--</span>
  600. </p>
  601. </aside>
  602.  
  603. <aside id="tools" class="footer_aside">
  604. <p>tools:</p>
  605. <p>
  606. <label>textimg filename check:</label><input type="text" size="40" id="tools_textimg_filename_text">
  607. </p>
  608. <p id="tools_textimg_filename_result" class="tools_result"></p>
  609. </aside>
  610.  
  611. </body></html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement