* Add support for resources

This commit is contained in:
michael 2019-10-27 13:14:34 +00:00
parent 116614c42c
commit 2b0c7ffa88
22 changed files with 1012 additions and 0 deletions

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
<Runnable Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="consoledemo"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
<Modes Count="0"/>
</RunParams>
<Units>
<Unit>
<Filename Value="consoledemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target FileExt=".js">
<Filename Value="consoledemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="js"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
<AllowLabel Value="False"/>
<CPPInline Value="False"/>
<UseAnsiStrings Value="False"/>
</SyntaxOptions>
</Parsing>
<CodeGeneration>
<TargetOS Value="nodejs"/>
</CodeGeneration>
<Linking>
<Debugging>
<GenerateDebugInfo Value="False"/>
<UseLineInfoUnit Value="False"/>
</Debugging>
</Linking>
<Other>
<CustomOptions Value="-Jeutf-8 -Jminclude -Jirtl.js -JRjs"/>
<CompilerPath Value="$(pas2js)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,42 @@
program consoledemo;
{$mode objfpc}
{$R help.txt}
uses
types, p2jsres, nodejs;
Var
RL : TStringDynArray;
S : String;
aInfo : TResourceInfo;
begin
Writeln('Javascript source:');
SetResourceSource(rsJS);
RL:=GetResourceNames;
For S in RL do
begin
Writeln('--- Found resource ',S,' : ');
if not GetResourceInfo(S,aInfo) then
Writeln('No extra information for resource ',S,' available')
else
begin
Writeln('Name: ',aInfo.Name);
Writeln('Format: ',aInfo.Format);
Writeln('encoding: ',aInfo.Encoding);
Writeln('unit: ',aInfo.resourceunit);
Writeln('data length: ',Length(aInfo.data));
end;
end;
if not GetResourceInfo('help',aInfo) then
Writeln('resource help not found !')
else
begin
Writeln('Usage:');
Writeln(TNJSBuffer.from(ainfo.Data,'base64').toString);
end;
end.

BIN
demo/resources/down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

4
demo/resources/help.txt Normal file
View File

@ -0,0 +1,4 @@
This demo is compiler with the help text embedded.
NodeJS applications do not have an associated HTML page so -JRjs is the best
option to use till another mechanism appears.

View File

@ -0,0 +1,26 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Javascript resource demo</title>
<script type="application/javascript" src="htmldemo.js"></script>
</head>
<body>
<h1>Javascript resource demo</h1>
<div id="pasjsconsole"></div>
<script type="application/javascript">
window.onload= rtl.run;
</script>
<button type="button" id="doinsert">Insert HTML from resource</button>
<h1 id="headertext">Press button to insert HTML below from resource data</h1>
<div id="playarea">
</div>
<p>
<div>
Created using &nbsp; <a target="_blank" href="https://wiki.freepascal.org/pas2js">pas2js.</a> &nbsp;&nbsp;Sources: &nbsp;
<a target="new" href="htmldemo.lpr">Program</a>.
</div>
</p>
</body>
</html>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
<Runnable Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="htmldemo"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<CustomData Count="3">
<Item0 Name="MaintainHTML" Value="1"/>
<Item1 Name="PasJSWebBrowserProject" Value="1"/>
<Item2 Name="RunAtReady" Value="1"/>
</CustomData>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
<Modes Count="0"/>
</RunParams>
<Units>
<Unit>
<Filename Value="htmldemo.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="consoledemo"/>
</Unit>
<Unit>
<Filename Value="htmldemo.html"/>
<IsPartOfProject Value="True"/>
<CustomData Count="1">
<Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
</CustomData>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target FileExt=".js">
<Filename Value="htmldemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="js"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
<AllowLabel Value="False"/>
<CPPInline Value="False"/>
<UseAnsiStrings Value="False"/>
</SyntaxOptions>
</Parsing>
<CodeGeneration>
<TargetOS Value="browser"/>
</CodeGeneration>
<Linking>
<Debugging>
<GenerateDebugInfo Value="False"/>
<UseLineInfoUnit Value="False"/>
</Debugging>
</Linking>
<Other>
<CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude -JRjs"/>
<CompilerPath Value="$(pas2js)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,52 @@
program consoledemo;
{$mode objfpc}
{$R testres.html}
uses
browserconsole, JS, Classes, SysUtils, types, p2jsres, unita, unitb, web;
function DoOnClick(aEvent: TJSMouseEvent): boolean;
var
el : TJSHTMLElement;
aInfo : TResourceInfo;
begin
Result:=False;
el:=TJSHTMLElement(document.getelementByid('playarea'));
if not GetResourceInfo('testres',aInfo) then
el.innerhtml:='resource testres not found !'
else
el.innerhtml:=window.atob(ainfo.Data);
el:=TJSHTMLElement(document.getelementByid('headertext'));
el.innertext:='Below HTML was inserted from resource data';
end;
Var
RL : TStringDynArray;
aInfo : TResourceInfo;
el : TJSHTMLElement;
S : String;
begin
Writeln('Javascript embedded resources:');
SetResourceSource(rsJS);
RL:=GetResourceNames;
For S in RL do
begin
Writeln('--- Found resource name: ',S,' : ');
if not GetResourceInfo(S,aInfo) then
Writeln('No extra information for resource ',S,' available !')
else
begin
Writeln('Name: ',aInfo.Name);
Writeln('Format: ',aInfo.Format);
Writeln('encoding: ',aInfo.Encoding);
Writeln('unit: ',aInfo.resourceunit);
Writeln('data length: ',Length(aInfo.data));
end;
end;
el:=TJSHTMLButtonElement(document.getelementByid('doinsert'));
el.onclick:=@DoOnClick;
end.

View File

@ -0,0 +1,42 @@
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--
copied from HTML generated by compiler
-->
<link rel="preload" id="resource-left" data-unit="htmllinkdemo" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAABmJLR0QA/wD/AP+gvaeTAAAFb0lEQVRoge2a328UVRTHv2dmdhVZjNhQtmUbowEh8UFJpfyoSxZfCNpiN1ArFAw8SJGESAz8AUQTH0BN9MFQTTRSwU1NaNpCwxMbKS4oRV9MQFBj3JahDWDolgo7d44PVjFt7+zc+YFo9pP0YXvuPed8987M3nPmAmXKlClT5t6FwnQ+/FwqbuvWszZjqQZaxMBjAFeAEAMAMAoAXSXgJxt8XiOc1oRxovJY1gwrp8AF59N1FYYVbWUbm0F42psX+oYYB63orUOJI19fDTK/wATn16QSmm7tJuAVAA8E5HaMiD4ssrW/pjc3GIRD34K5tjZypWrGDgbeBCYu1eC5CWBfQcx6a0Ff3y0/jnwJHlxbv5BsyhDwpB8/biHgO8tGS+JY/w9efWheJw41JtdpNp29W2IBgIGndA1nhxqeSXv14Unw5cbkFmL+HOFdwk7MIqBzqKF+u5fJyoKHGuvbwPwxAMNLwIDQCfSB+Xxyp+pEpXt4qDG5jpgzAHTVQCEhmGh9dc/JLrcTXAseXrt8vrD1AQAPekotPApMYkl1T+68m8GuLunvm5+IWrb+Be49sQAQI9YOcW1txM1gV4Irfp/9+t18GqtDi83q+19zNbLUgF8bls8zoF8AMNN3XuFSMIr0+JzjJy87DSq5wjr0Pbj3xQJAzIrw7lKDHAXn03UVE3tj3xDQJYRRI4RRA6AvCJ/T0JZP11U4DXAUbNy+byMCKQQoM7dgNCf6svlEXzYvhLHNv89pmakXIxucBjgKZvDL/nOgTLygb6Js1vr7P1E7xDqcNjtZpYJHVierQKj1GXyKWE6lDF3Y7/nz68gSM72iUmaUChZRXgU/1RShc4rY5mb9Skx8wkCTZ79uIhdplcwoFWwzlvqImYmPGhsnr6w5bn7G4Fbvft2G15bJTFLBGmiRt2DylQW4xZNPRZh5ocwmrXgYPF89FGXio1PvWXPc7LhbYifyWCCzOJV4DymFALrmTlpZAJj4/NLEnzL5NamErlvtANYoTJstMzj9LCkV95Ywdk4WGwSJvmze1rU2tVkszd1zi+e/ipPggoojQ7fe51Qq8C7I4AsrazTbblecNiozyBMkXAfjYbcRGGgyY6KDU6mpD62Y8P7QEraHSfSbzCJdYWL6UT0Qt5gx6/A/V5qyWSs+I95KxB3q/rzCF2UW+cYD7KplMg3rJ1b6jujOTjF3NLIVoIxHn0oQ0QWZTb7xIJz2HvLfXWmGnZPZ5IKFcQIA+4grXWkCXHcZPcBkcFZmlAr+85UlnfUZu2WK6GzWsoSh3E9W4Ez8yFfDMqPj7zAxDvqPP43oUOthON4yjoHz6boKvRj9BQH0tAjosoSxk6I2acI+ALWtolvGROT2I07vlEt+02Zj8l1m3hVsXiFBeLuqp9+xkVdya1lkaz+AscCSCo9RXRj7Sw0qKbimNzcIxhvB5BQijL1uzoa4Kh7i5vg7AH/rP6vQOBc3x131yVwJpoGBoq7ZLwK44SutcCjYGm+kgYGim8Guy8PK7twlBrYAEF4zCwFBzK3zuk9Jt5KTUaqHq3v7jzBjh3peocBEtD1+9FS3yiTlBkD10f52EG0FEHh3QwHBxK/Ge05+pDrR845nqDHZRMyfApjl1YdHbhDzZtWV/QtfW7zhhpULBEQGoMV+/ChwTtdES2V37pJXB756WpW9X16MFyJ1BOyCQ1slAG4C2HttxvXlfsQCAR49HFmdrBKGvYeJtiG498ljAA7otrEvqAOnoRwu1YuRDSDaBEadhxgM4AyADqsoDtccz10LMr9Qjw+b6RWVKNIqkLaMwYvAeBTAHNzpeRcAjIDwM4HOg+3TiPAJp3q2TJkyZcr8n/kDIZn7et3yi2cAAAAASUVORK5CYII=" />
<link rel="preload" id="resource-right" data-unit="htmllinkdemo" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAABmJLR0QA/wD/AP+gvaeTAAAFcklEQVRoge2aXWwUVRTH/2dmt6TQitrYWAoxGhDelMiHvrXGhH6EBAOlbLutNLa7LQlqDLwv0cQHiA/4ULqtwcLSsl0TiaRdSJps34BY0UcQ1CgsRQwisNDQnTvHh1LBkjs7H3dIY/b3uOfcc84/Z2bvx1ygSJEiRYosXMjP4IebRl8UOt5mDRsZtIZMvAJCBYCyhy45MG6yhl8IfAGsnQ0YZqYj1Xjdr5qUCx5sH6+Ymcm3grgNwDpXQRjfMeHoomDJ0HtH3rmpsj5lgvtbx5aTiT1M6AJjsaKw9wD0G4Y40JPanFUR0LPgvshkkHJ/7CKmT/HoUVUL4T7A+6dv0WcfpBseeAvlgS/D6dVCmEkCveYljgN+ZJObI8nGn9wG0NwOjIdGt5qCJ5+iWAB4nTSajO9Iv+s2gCvB8Zb0TgIdh1+PsDXlRJyK7xjtdjPYseCBUDpKzIcBBNwkVIRORL3x0NhupwMdvcPx0OhWAiUB6E4T+YQgYFvncMMJuwNsCx4In1ppCvN7Ap5xV5tv5Ezo66PDmy7Ycbb1SI80jZSYQny9AMUCQJkGMdQXmQzacbYl+Hag/OOn/G/slLX6nRsf2nEs+Ej3Np2sDgT0iwCWeC7LX3Kmrr0aTdRNWTkV7HAwoO/FwhcLAGW64D2FnCwFD7aPVzChS11NjyBCGhpWQMMKBmz/y1rB4Ohg+3iFlY+l4Af5mRaFG4H/wIRI17GGq13HGq5emyptAiGpIOySvDETsnKwFExAu4IiChKbqDWy10rDKkQzc5uVXSq4L3yqCsAbXguQwSa+iNVk/l2tqRNN63vbTlfKrFLBuiFq4eOJCAFbqqumh+eLXprPtQKc8BI6kBe1MqNUMGvY6CGpXbZVL5tOPC56e2q7yE4t7vDUacKbMpNcMGiN64ROYDSr7jQRVstsUsHEWOkmmUuUdppNrJLZrLZ4zzpKAh4VhhlVdfYEzHY6VpMJL6uaXkTAFtsDCc/JTFbTkqPNPWnUrVLsHLGJWoM0ON33Smt3fcTzNNGFrmy2sBKccxKIGPH+1rHlHut5glhNJmCQOOhw2F2ZweodvgXgebsZmFEPxpX+0JiTwh5BSGavlYZjE7XG3E+xmkygetl0Auzg/QUAxt8yk3xaIvzsKIk3UvPFjjSN6NVV01+B0ew0GGm4JLPJpyWwrSMTzxCS2anSlvmdvR0sOwag1U1IZlyU2eTvMGtn3SRziNLOzsHgMzKbVHDAMDMA2G3SQjBwQnVn50KLQGBCZpQK7kg1Xgdj0kNiS0jDbskflOvOAgAY53qObrohM1vOw0w46im5TZSJBVBo/W05oQ+2j1fM5Gd+gw9nWkRIMyGiC50MEgcdLR3l3CsJlrxk9U3ZssMPB/YrKOQJmFEPE1cEid8ViQWAQ4U+oBdcWhqGOIDZD9MLnbsBgw8UcioouCe1OcuET9TU5Cv77NwNsbV54LLKzwH84LkkvyCcN8srba23bQmOxtflSde2M3DHW2W+kNM0aonG1+XtONveHnYm6i6DaScA4bYyHxDM1Pp+ol66lJyPo/1w5Hj9NyDa5bwuX2ACd0eO13/rZJDjA4Cuofo4E3UAMAo6+4cgUE/ncOOA04GuTxIGQmNbGDgCoNxtDDcwcAdMbU47O4eno5NDLSdX6awnAaz1Esc2hPOkac2dibrLbkN4OtPqHtp8KTtVuoGJP4LFsYpnCPdBvG9pPveWF7GzoRTRFz5VRabYS0wRqFt73yNQn26Y+1VdOPXlcmnemAmBEWZgg4scDMY5gBMk9OHOVN1fKuvz9fpwb9vpykBe1M5+66E1AL8M4AU8fn0Y+BOgXwG+AMZZI6hnrPazRYoUKVLk/8w/yKIEWACzZN8AAAAASUVORK5CYII=" />
<link rel="preload" id="resource-up" data-unit="htmllinkdemo" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAABmJLR0QA/wD/AP+gvaeTAAAFTklEQVRoge2a208UVxzHv7/ZGUgFxEt6MZY0Nl5IVBaz3Non6FvfaArFijb6UGptqED0HZsmfYC6XGJatUmbSrWUJiX9A4p96iKLFZQEKtWkalrbCMqtgZ2ZXx+gcUM5szNnzqA2+3nc3zm/8/3md3ZmzgVIkyZNmjSPLxRk8p2Xjj+naeYrBJQykK8BLzKwEUD2UpMZAu7ZwA0CRsEcs9joGylp+SMoTcoN5/e/tzEjlFkL5gMgFMnkYKIBje1z81bi/GjpqXsq9SkzXBCrfx66fgzA2wDWKEo7C+azZFDrUGH0joqEvg1H4nVGAllHAHyIh1NVNXNgaplbl/hofFvnvJ9EvgwXDBzdQaR1MxD2k8cDV8iimqHSk7/IJtBkOxYMNL0O0uKraBYACjnE8fBg42uyCaQM7x5sOgjirxHcFHYihxk94XjjYZnOng2HB5reIebPAegyAyoixMAn4XhDvdeOnv7Di9OYuwGEvA4UEBaDq64WtfW67eDa8M7Bxq0aY5CAtXLaAmOGoRVfLfp41E1jV1N650hzhs74VoVZAvXCNPNgmnkEcl0ZB7IJ9vlIvM5w09iVYf3vB00qnsYE9KyfXls9XNZ5e7is8/b2G7eqmNHlNy+APQmsOepSgzPhK42b2cQYgCxfkpi7N8ys23+xotlM/rm8r1mfyL7fBaIaX/mBGQO8fbCo7XenRikrzCaOw6dZAnpWMgsAFyuazR0379QqqHT2AnDMhRYxiwuBjN/g59tYUNnlKKr07IK18ILTgsOxwhmhzFr4MOtU2eUoqnSWoRt7nRo4T2nmA9JDM3evn87dl2y2vK/5Px8ryb/1vNFjbZzJPQTmbtlhiektp7jQcCTesAmEiNSgK1S2+pvq0GTO1BfL207kPLiQbFpBpYt3xY4+KwoKDScY5ZBYTRGod6XKjm3Z/BWDa1foUjWRfb9rpUpLvqcpZITKRUHxlCYqkxgMbCbql5tN+TAiqllu+mJFs8lmwvO3MgCwbQu1Cw0zkC8zWDKenrwrmLY1Q3K9TkLtwhUPAVulxjL0MwWx+jpbM2hSm+oAqNJ1X6KayZypzIJYfb2tGaSF+DTYuwQisXanJd4670MBYLwKXb+lgWW0gsGV0PVKDQypBADYQbvTa+lRLO5VkSMKSG/xPKk4GZ5ZNRXqmRYFHAzzZBBKVgMC7otiDq8l+jUYOcHDhOuimNAwAa62TB5LbB4ThcRTmjkWiJhVgDT6SRQTGrYt/gHSb8JHClsJ+0dRUGj4Wln7XSaKB6MpUPqvlbXfFQUd38Ma2+fU6wkcR82OhuetxHkAs0rlBMvsgrXguHngaHi09NQ9MJ9VqylQPk11gJ7y05IMasWTUeVpy9ZbUzVKaXioMHqHmT9Qo2nppsASuy415anKS8AJN3dDXJ0AZtBcNIGsvQD2+FaWtF7WiM/4zrfIZR2zHW4a/i8O08B20XBxu/DrKhnXy8ORSHRcIxwEYMkqCwALTLVuzQIe18NDkeh3TDjiXVcgMMCHh4tPfu+lk+cNgKuR6BkmOgQg5WlCgFjE9O5wUdtnXjtK3+LZHW+oJNCXcNhOCQIGpojpgNfK/ouva0uFP7+/zbZC3VDx9HbHZYtQMxKJjssm8LWndWVPx/UN07klABrgsK2igDkwnbCeyn3Jj1lA4dXDSLxhk0l0nBl18Ht4/pBZBp+2baNF1YXTQC6XGlrGm0TYD6BEYgwG0M/EXfY8XRh5OTqhUl+g14cLho49Q6ZdsXjWQ/kgbAHwNJKuDwP4C4ybAI+SpsVY1/qGw61/BqkrTZo0adI8rvwDpmICIqoZ+uMAAAAASUVORK5CYII=" />
<link rel="preload" id="resource-down" data-unit="htmllinkdemo" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAABmJLR0QA/wD/AP+gvaeTAAAFhUlEQVRoge2aTWwUZRjH/89Md0tlFUkDWCkkGLYQlS9322K8LGKgYDUY2BRsWerB1pCYGAMnr0YPcJKTIhGXbWtTE5EgSzFKPZWF3YbWS4GNUNJSPkIldtuFtjOPh25BS2d25p2ZpST7u7XP5z/PZub9GCBPnjx58sxeyMnk5VvrX1ChvimBK5lpJYCXCChmwJMpnmLgLoC/iLiXVekcSXT2wqmjN53qyXbBFRtDxYqLaol4NwC/WBa+wKBj8hiaz/8Wvmtnf7YJrtxSWzoBeR8BHwJ4xqa0IwAddsl8sPNkeMCOhJYF+3wNLmnR/b3M+ByZn6oDjIJw4B7P+zIZPfTASiJLgv1VdStYklqJscZKHhNclAg150+FL4smkEQD/Vv3bAdJ8RyKBYC1KiNeURV6TzSBLBJUXrW7HkAYwBzRwhYoZMKOkrLVtwev9MTNBpsW7K8KNYLoW1j4ddiARKDqEu+aocFk93kzgaYE+7fu2Q7gOzxZsQ8hYFOJd1XPYLKn10SMMV7bXLdckqQEgOeEunOOFCtSeeLMUUOiDU3qlWDQTbL0I+wQS/jFJaNUhrIEQNRyPsBDstrs8zW4jDgbEjxnuOhTu57GMisfdZ4MD8SiTf2kyI125ASwjhbc/8SIY9af9OvVocXjCi4BmGu5LQDxaPh/Nf1bQmxHXgApVtWyRHtkUM8p64THFOyHTWIdxkMk7cvmpCu4YmOoOLM2fjogNFZsDBXruegKVlxUC/s2ArlgrlrIO/UcdAVntnhPGRTSs2oK9m2uKwHgs70fp2GUV767a5GWWXvCsrQBDp+IOASp466AllFTsASudKSdHMCg9Vo2TcGZM6inFF6hZdF5aPFyJ1rJEV4tg45get6JTnKEZu96ryWnzqdywbNahlmxr80leoJTOevCfoa1DHqC/xYsFpWhLJnc79Jx8+F0/FG88H75npZBUzABSZFKMpSGWLSpPxZt6vek+4IAWk2Et3rSfcGpeBlKg0gPAK5oGbQnTHxJsNhDOjo6Jjzp63UwJrrVk75e19HRMTH1D1VxC670SLN37YWHKp0TKaWg4FAgECiY+tug6MfEBgKBApbVr0R6IEKnlk1TsOwe+x2AwGkEb0sVLW2ZLnqZJ10LQuTx5qhtuthgMCgPFy05CvA28/XBUsHYH1pGTcGxEy23ADZ90J1hR6poaeS/otva2hTP6PUPpjvOHe17f/pkr6aKmghUK1KYgNhk7zOj+x5m0DGRohlqZpr0dKeZJ4sa4aoM3Z51BctjaAYwIlx8hklrYXWyGUZoXP8BqXvzMHC1O/2id+0CAJrbLQO8Ouaa93JZ6fyfrl27ps7kEAwG5Vtc/D2BdlmoAwIdunAm/LOeT9alpUvmg7A2ZUBn0jZNFgCGQXQwm1PWu6X+y93DJd41CgFvWWzosUnbNVkAYPBn8Wj412x+hl7sPl+DixbejwFYZ7WxyaXjxMeq4qbJ96zQq2d6zi6+Xbg+kfhmPKun0ZSz+TINrPrjpyOGVoaGt4dd7ZGkxKgHoIh25gAKmGqNigVM3g8PJLt7F3vX3gTwjunW7IeZ0JiIhlvMBJn+AuBGsjuxePnqPhBV48kdIChg7E1Ew4fNBgp943Ej2XOxxLvqTwK9DaBQJIcF/gHTzvjpcLNIsKWD9srqeq+iqK2w5eltBOpSVaWmqz0itFcHBCc8xcDli0NlpfOPjLvnDQF4A85NexSEL9KedH3PiR/uWElk21WKb3NdCcm0H0wNsO8+eQSMr0mSDtj1wakjH5eqbuwCUAegQqAGExBj4ohLcbd0th8ZsrM/Ry/LVm/avbBQpg0MWg9WV4JoGYAFeHTmnQJwB8xXQVIvgc89UPhsz5ljt53sK0+ePHnyzFb+BYW/6T+M0TFbAAAAAElFTkSuQmCC" />
<!--
end of copy
-->
<title>HTML link</title>
<script src="htmllinkdemo.js"></script>
</head>
<body>
<h1>HTML Preload link resources</h1>
<p>
This demo demonstrates how to load images from resources. Click the below image to round-robin between the available images.
</p>
<center>
<img id="theimage" src="" alt="The image" width=60 height=60>
</center>
<script>
window.addEventListener("load", rtl.run);
</script>
<div>
Created using &nbsp; <a target="_blank" href="https://wiki.freepascal.org/pas2js">pas2js.</a> &nbsp;&nbsp;Sources: &nbsp;
<a target="new" href="htmllinkdemo.lpr">Program</a>.
</div>
<div>
<a target="_blank" href="https://icons8.com/icons/set/circled-up-2">Scroll Up</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a><br>
<a target="_blank" href="https://icons8.com/icons/set/circled-left">Go Back</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a><br>
<a target="_blank" href="https://icons8.com/icons/set/circled-right">Circled Right</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a><br>
<a target="_blank" href="https://icons8.com/icons/set/circled-down-2">Scroll Down</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a><br>
</div>
</body>
</html>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
<Runnable Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="htmllinkdemo"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<CustomData Count="5">
<Item0 Name="MaintainHTML" Value="1"/>
<Item1 Name="PasJSHTMLFile" Value="project1.html"/>
<Item2 Name="PasJSPort" Value="0"/>
<Item3 Name="PasJSWebBrowserProject" Value="1"/>
<Item4 Name="RunAtReady" Value="1"/>
</CustomData>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
<Modes Count="0"/>
</RunParams>
<Units>
<Unit>
<Filename Value="htmllinkdemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="htmllinkdemo.html"/>
<IsPartOfProject Value="True"/>
<CustomData Count="1">
<Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
</CustomData>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target FileExt=".js">
<Filename Value="htmllinkdemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="js"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
<AllowLabel Value="False"/>
<CPPInline Value="False"/>
<UseAnsiStrings Value="False"/>
</SyntaxOptions>
</Parsing>
<CodeGeneration>
<TargetOS Value="browser"/>
</CodeGeneration>
<Linking>
<Debugging>
<GenerateDebugInfo Value="False"/>
<UseLineInfoUnit Value="False"/>
</Debugging>
</Linking>
<Other>
<CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
<CompilerPath Value="$(pas2js)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,46 @@
program htmllinkdemo;
{$mode objfpc}
uses
JS, Classes, SysUtils, Web, p2jsres;
{$R left.png}
{$R right.png}
{$R up.png}
{$R down.png}
Const
MaxImages = 4;
ImageResources : Array[1..MaxImages] of string = ('up','right','down','left');
Var
Img : TJSHTMLImageElement;
CurrentImage: Integer = 1;
Procedure ShowCurrentImage;
Var
aInfo : TResourceInfo;
begin
if not GetResourceInfo(ImageResources[CurrentImage],aInfo) then
Writeln('No info for image ',ImageResources[CurrentImage])
else
Img.Src:='data:'+aInfo.format+';base64,'+aInfo.Data;
end;
function RotateImage(aEvent: TJSMouseEvent): boolean;
begin
Inc(CurrentImage);
if CurrentImage>MaxImages then
CurrentImage:=1;
ShowCurrentImage;
end;
begin
SetResourceSource(rsHTML);
Img:=TJSHTMLImageElement(Document.GetElementByID('theimage'));
Img.OnClick:=@RotateImage;
ShowCurrentImage;
end.

View File

@ -0,0 +1,32 @@
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Project1</title>
<script src="htmlloadlinkdemo.js"></script>
</head>
<body>
<h1>Dynamically loaded HTML Preload link resources</h1>
<p>
This demo demonstrates how to load resources and then load images from these resources.<br>
Click the below image to round-robin between the available images.
</p>
<center>
<img id="theimage" src="" alt="The image" width=60 height=60>
</center>
<script>
window.addEventListener("load", rtl.run);
</script>
<div>
Created using &nbsp; <a target="_blank" href="https://wiki.freepascal.org/pas2js">pas2js.</a> &nbsp;&nbsp;Sources: &nbsp;
<a target="new" href="htmlloadlinkdemo.lpr">Program</a>.
</div>
<div>
<a target="_blank" href="https://icons8.com/icons/set/circled-up-2">Scroll Up</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a><br>
<a target="_blank" href="https://icons8.com/icons/set/circled-left">Go Back</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a><br>
<a target="_blank" href="https://icons8.com/icons/set/circled-right">Circled Right</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a><br>
<a target="_blank" href="https://icons8.com/icons/set/circled-down-2">Scroll Down</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a><br>
</div>
</body>
</html>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
<Runnable Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="htmlloadlinkdemo"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<CustomData Count="4">
<Item0 Name="MaintainHTML" Value="1"/>
<Item1 Name="PasJSHTMLFile" Value="project1.html"/>
<Item2 Name="PasJSPort" Value="0"/>
<Item3 Name="PasJSWebBrowserProject" Value="1"/>
</CustomData>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
<Modes Count="0"/>
</RunParams>
<Units>
<Unit>
<Filename Value="htmlloadlinkdemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="htmlloadlinkdemo.html"/>
<IsPartOfProject Value="True"/>
<CustomData Count="1">
<Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
</CustomData>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target FileExt=".js">
<Filename Value="htmlloadlinkdemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="js"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
<AllowLabel Value="False"/>
<CPPInline Value="False"/>
<UseAnsiStrings Value="False"/>
</SyntaxOptions>
</Parsing>
<CodeGeneration>
<TargetOS Value="browser"/>
</CodeGeneration>
<Linking>
<Debugging>
<GenerateDebugInfo Value="False"/>
<UseLineInfoUnit Value="False"/>
</Debugging>
</Linking>
<Other>
<CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
<CompilerPath Value="$(pas2js)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,64 @@
program htmlloadlinkdemo;
{$mode objfpc}
uses
Classes, Web, p2jsres;
{$R left.png}
{$R right.png}
{$R up.png}
{$R down.png}
Const
MaxImages = 4;
ImageResources : Array[1..MaxImages] of string = ('up','right','down','left');
Var
Img : TJSHTMLImageElement;
CurrentImage: Integer = 1;
Procedure ShowCurrentImage;
Var
aInfo : TResourceInfo;
begin
if not GetResourceInfo(ImageResources[CurrentImage],aInfo) then
Writeln('No info for image ',ImageResources[CurrentImage])
else
Img.Src:='data:'+aInfo.format+';base64,'+aInfo.Data;
end;
function RotateImage(aEvent: TJSMouseEvent): boolean;
begin
Result:=False;
Inc(CurrentImage);
if CurrentImage>MaxImages then
CurrentImage:=1;
ShowCurrentImage;
end;
procedure OnLoaded(const LoadedResources: array of String);
Var
S : String;
begin
// Some info
for S in LoadedResources do
Writeln('Found resource: ',S);
Img.OnClick:=@RotateImage;
ShowCurrentImage;
end;
procedure OnLoadFailed(const aError: string);
begin
window.alert('Failed to load resources : '+AError)
end;
begin
SetResourceSource(rsHTML);
Img:=TJSHTMLImageElement(Document.GetElementByID('theimage'));
LoadHTMLLinkResources('htmlloadlinkdemo-res.html',@OnLoaded,@OnLoadFailed);
end.

BIN
demo/resources/left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
demo/resources/right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,5 @@
<h3>Hello Resource World Part A</h3>
<p>
This message is saved in a resource file (Part A).
</p>

View File

@ -0,0 +1,5 @@
<h3>Hello Resource World Part B</h3>
<p>
This message is saved in a resource file (Part B).
</p>

View File

@ -0,0 +1,2 @@
<h3>Test resource in HTML</h3>
This is a main program file resource in HTML.

16
demo/resources/unita.pp Normal file
View File

@ -0,0 +1,16 @@
unit unita;
interface
Procedure Testa;
implementation
{$R testa.html}
Procedure Testa;
begin
end;
end.

16
demo/resources/unitb.pp Normal file
View File

@ -0,0 +1,16 @@
unit unitb;
interface
Procedure Testa;
implementation
{$R TestB.html}
Procedure Testa;
begin
end;
end.

BIN
demo/resources/up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

308
packages/rtl/p2jsres.pp Normal file
View File

@ -0,0 +1,308 @@
unit p2jsres;
{$mode objfpc}
{$h+}
{$modeswitch externalclass}
interface
uses types;
Type
TResourceSource = (rsJS,rsHTML);
TResourceInfo = record
name : string;
encoding : string;
resourceunit : string;
format : string;
data : string;
end;
TResourceEnumCallBack = Reference to function(const resName : string) : boolean;
TResourcesLoadedEnumCallBack = Reference to Procedure(const LoadedResources : Array of String);
TResourcesLoadErrorCallBack = Reference to Procedure(const aError : string);
Function SetResourceSource(aSource : TResourceSource) : TResourceSource;
Function GetResourceNames : TStringDynArray;
Function GetResourceNames(aSource : TResourceSource) : TStringDynArray;
Function EnumResources(aCallback : TResourceEnumCallBack) : Integer;
Function EnumResources(aSource : TResourceSource; aCallback : TResourceEnumCallBack) : Integer;
Function GetResourceInfo(Const aName : String; var aInfo : TResourceInfo) : Boolean;
Function GetResourceInfo(aSource : TResourceSource; Const aName : String; var aInfo : TResourceInfo) : Boolean;
Procedure LoadHTMLLinkResources(const aURL : String; OnLoad : TResourcesLoadedEnumCallBack = Nil; OnError : TResourcesLoadErrorCallBack = Nil);
implementation
uses sysutils, js, web;
var
gMode: TResourceSource;
{ ---------------------------------------------------------------------
Global entry points
---------------------------------------------------------------------}
Function SeTResourceSource(aSource : TResourceSource) : TResourceSource;
begin
Result:=gMode;
gMode:=aSource;
end;
Function GetResourceNames : TStringDynArray;
begin
Result:=GetResourceNames(gMode);
end;
Function EnumResources(aCallback : TResourceEnumCallBack) : Integer;
begin
Result:=EnumResources(gMode,aCallback);
end;
Function GetResourceInfo(Const aName : String; var aInfo : TResourceInfo) : Boolean;
begin
Result:=GetResourceInfo(gMode,aName,aInfo);
end;
{ ---------------------------------------------------------------------
JS resources
---------------------------------------------------------------------}
Type
TRTLResourceInfo = class external name 'Object' (TJSObject)
name : string;
encoding : string;
resourceunit : string; external name 'unit';
format : string;
data : string;
end;
function rtlGetResourceList : TStringDynArray; external name 'rtl.getResourceList';
function rtlGetResource(const aName : string) : TRTLResourceInfo; external name 'rtl.getResource';
Function GetRTLResourceInfo(Const aName : String; var aInfo : TResourceInfo) : Boolean;
Var
RTLInfo : TRTLResourceInfo;
begin
RTLInfo:=rtlGetResource(lowercase(aName));
Result:=Assigned(RTLInfo);
if Result then
begin
aInfo.name:=RTLinfo.name;
aInfo.encoding:=RTLinfo.encoding;
aInfo.format:=RTLinfo.format;
aInfo.resourceunit:=RTLinfo.resourceunit;
aInfo.data:=RTLinfo.data;
end;
end;
{ ---------------------------------------------------------------------
HTML resources
---------------------------------------------------------------------}
Const
IDPrefix = 'resource-';
Function IsResourceLink(L : TJSHTMLLinkElement) : Boolean;
begin
Result:=(Copy(L.id,1,Length(IDPrefix))=IDPrefix) and (isDefined(L.Dataset['unit'])) and (Copy(L.href,1,4)='data')
end;
Function GetHTMLResources : TStringDynArray;
Var
LC : TJSHTMLCollection;
L : TJSHTMLLinkElement;
I : Integer;
ID : String;
begin
SetLength(Result,0);
if not isDefined(document) then // If called in Node...
exit;
// No cache, we do this dynamically: it's possible to add link nodes at runtime.
LC:=document.getElementsByTagName('link');
For I:=0 to LC.length-1 do
begin
L:=TJSHTMLLinkElement(LC[i]);
ID:=L.ID;
if IsResourceLink(L) then
begin
Delete(ID,1,Length(IDPrefix));
if (ID<>'') then
TJSArray(Result).Push(ID);
end;
end;
end;
Function GetHTMLResourceInfo(Const aName : String; var aInfo : TResourceInfo) : Boolean;
Var
el : TJSElement;
L : TJSHTMLLinkElement absolute el;
S : String;
I : Integer;
begin
Result:=False;
if not isDefined(document) then // If called in Node...
exit;
El:=document.getElementByID(IDPrefix+lowercase(aName));
Result:=assigned(el) and SameText(el.tagName,'link');
if not Result then
exit;
ainfo.name:=lowercase(aName);
ainfo.Resourceunit:=String(L.Dataset['unit']);
S:=L.href;
S:=Copy(S,6,Length(S)-5); // strip data;
I:=Pos(',',S);
aInfo.data:=Copy(S,I+1,Length(S)-1);
S:=copy(S,1,I-1);
I:=Pos(';',S);
if I=0 then
aInfo.encoding:=''
else
begin
aInfo.encoding:=Copy(S,I+1,Length(S)-1);
S:=Copy(S,1,I-1);
end;
aInfo.Format:=S;
end;
Function HasTemplate : Boolean;
begin
asm
return ('content' in document.createElement('template'))
end;
end;
Procedure LoadHTMLLinkResources(const aURL : String; OnLoad : TResourcesLoadedEnumCallBack = Nil; OnError : TResourcesLoadErrorCallBack = Nil);
function FetchOK(Res : JSValue) : JSValue;
var
Response : TJSResponse absolute res;
begin
Result:=Nil;
if not Response.ok then
begin
if Assigned(OnError) then
Raise TJSError.New('HTTP Error for URL aURL, status = '+IntToStr(Response.status)+' : '+Response.statusText)
end
else
Result:=Response.Text();
end;
function BlobOK(Res : JSValue) : JSValue;
Var
aText : String absolute res;
ID : String;
Tmpl : TJSHTMLTemplateElement;
El : TJSHTMLElement;
L : TJSHTMLLinkElement absolute El;
Arr : TStringDynArray;
aParent : TJSHTMLElement;
begin
Result:=Nil;
aParent:=TJSHTMLElement(document.head);
if aParent=Nil then
aParent:=TJSHTMLElement(document.body);
SetLength(Arr,0);
Tmpl:=TJSHTMLTemplateElement(Document.createElement('template'));
Tmpl.innerhtml:=TJSString(aText).trim;
el:=TJSHTMLElement(Tmpl.Content.firstElementChild);
While El<>Nil do
begin
if SameText(El.tagName,'link') and IsResourceLink(L) then
begin
aParent.Append(TJSHTMLElement(document.importNode(l,true)));
ID:=L.ID;
Delete(ID,1,Length(IDPrefix));
if (ID<>'') then
TJSArray(Arr).Push(ID);
end;
el:=TJSHTMLElement(el.nextElementSibling);
end;
if Assigned(OnLoad) then
OnLoad(Arr);
end;
function DoError (aValue : JSValue) : JSValue;
Var
aErr : TJSError absolute aValue;
begin
Result:=Nil;
if Assigned(OnError) then
if aErr=Nil then
OnError('Error: ' + aErr.message)
end;
begin
if not HasTemplate then
begin
if Assigned(OnError) then
OnError('No template support in this browser')
end
else
window.fetch(aURL)._then(@FetchOK)._then(@BlobOK).catch(@doError);
end;
{ ---------------------------------------------------------------------
Global entries, specifying resource mode
---------------------------------------------------------------------}
Function GetResourceNames(aSource : TResourceSource) : TStringDynArray;
begin
case aSource of
rsJS : Result:=rtlGetResourceList;
rsHTML : Result:=GetHTMLResources;
end;
end;
Function EnumResources(aSource : TResourceSource; aCallback : TResourceEnumCallBack) : Integer;
Var
RL : TStringDynArray;
I : Integer;
ContinueEnum : Boolean;
begin
Result:=0;
RL:=GetResourceNames(aSource);
I:=0;
Result:=Length(RL);
ContinueEnum:=True;
While (I<Result) and ContinueEnum do
begin
ContinueEnum:=aCallBack(RL[i]);
Inc(I);
end;
end;
Function GetResourceInfo(aSource : TResourceSource; Const aName : String; var aInfo : TResourceInfo) : Boolean;
begin
case aSource of
rsJS : Result:=GetRTLResourceInfo(aName,aInfo);
rsHTML : Result:=GetHTMLResourceInfo(aName,aInfo);
end;
end;
end.