From 4c00333115e027c7710795d4d7949849167b9a50 Mon Sep 17 00:00:00 2001 From: Daniele Teti Date: Sun, 18 Aug 2024 11:40:14 +0200 Subject: [PATCH] Improved template engines mechanism --- .../WebSiteControllerU.pas | 2 +- .../CustomTemplateProFiltersU.pas | 8 ---- .../ServerSideViewsTemplatePro.dpr | 6 +-- .../ServerSideViewsTemplatePro.dproj | 40 +++++++++++++++---- .../bin/people.data | 2 +- .../bin/templates/partials/footer.tpro | 3 -- sources/MVCFramework.IntfObjectPool.pas | 1 + .../MVCFramework.View.Renderers.Mustache.pas | 12 ++---- ...VCFramework.View.Renderers.TemplatePro.pas | 7 ++-- sources/MVCFramework.pas | 16 ++++---- 10 files changed, 52 insertions(+), 45 deletions(-) diff --git a/samples/serversideviews_mustache/WebSiteControllerU.pas b/samples/serversideviews_mustache/WebSiteControllerU.pas index c1d63d94..551b2aee 100644 --- a/samples/serversideviews_mustache/WebSiteControllerU.pas +++ b/samples/serversideviews_mustache/WebSiteControllerU.pas @@ -106,7 +106,7 @@ begin begin var lJItm := lJDevices.AddObject; lJItm.S['name'] := lItem; - lJItm.B['selected'] := TArray.BinarySearch(lDevices, lItem, lIdx); + lJItm.B['selected'] := TArray.BinarySearch(lPerson.Devices, lItem, lIdx); end; Result := Page(['editperson'], lJObj); finally diff --git a/samples/serversideviews_templatepro/CustomTemplateProFiltersU.pas b/samples/serversideviews_templatepro/CustomTemplateProFiltersU.pas index 861956b8..c12ae6ee 100644 --- a/samples/serversideviews_templatepro/CustomTemplateProFiltersU.pas +++ b/samples/serversideviews_templatepro/CustomTemplateProFiltersU.pas @@ -29,19 +29,11 @@ interface uses System.Rtti; -//uses -// mormot.core.mustache; - function MyHelper1(const aValue: TValue; const aParameters: TArray): string; function MyHelper2(const aValue: TValue; const aParameters: TArray): string; implementation -uses - MVCFramework.View.Renderers.Mustache, System.SysUtils; - -{ TMyMustacheHelpers } - function MyHelper1(const aValue: TValue; const aParameters: TArray): string; begin Result := aValue.ToString + ' (I''m The MyHelper1)'; diff --git a/samples/serversideviews_templatepro/ServerSideViewsTemplatePro.dpr b/samples/serversideviews_templatepro/ServerSideViewsTemplatePro.dpr index 0468b4e4..2b9a3a4d 100644 --- a/samples/serversideviews_templatepro/ServerSideViewsTemplatePro.dpr +++ b/samples/serversideviews_templatepro/ServerSideViewsTemplatePro.dpr @@ -12,6 +12,7 @@ uses Winapi.Windows, {$ENDIF } IdHTTPWebBrokerBridge, + TemplatePro, MVCFramework.View.Renderers.TemplatePro, Web.WebReq, Web.WebBroker, @@ -19,8 +20,7 @@ uses WebSiteControllerU in 'WebSiteControllerU.pas', DAL in 'DAL.pas', MyDataModuleU in '..\renders\MyDataModuleU.pas' {MyDataModule: TDataModule}, - CustomTemplateProFiltersU in 'CustomTemplateProFiltersU.pas', - TemplatePro in '..\..\..\templatepro\TemplatePro.pas'; + CustomTemplateProFiltersU in 'CustomTemplateProFiltersU.pas'; {$R *.res} @@ -35,7 +35,7 @@ begin LServer.DefaultPort := APort; LServer.Active := True; {$IFDEF MSWINDOWS} - //ShellExecute(0, 'open', PChar('http://localhost:' + inttostr(APort)), nil, nil, SW_SHOW); + ShellExecute(0, 'open', PChar('http://localhost:' + inttostr(APort)), nil, nil, SW_SHOW); {$ENDIF} LogI('Ctrl+C to stop the server'); WaitForTerminationSignal; diff --git a/samples/serversideviews_templatepro/ServerSideViewsTemplatePro.dproj b/samples/serversideviews_templatepro/ServerSideViewsTemplatePro.dproj index dcd587e3..1bd3294f 100644 --- a/samples/serversideviews_templatepro/ServerSideViewsTemplatePro.dproj +++ b/samples/serversideviews_templatepro/ServerSideViewsTemplatePro.dproj @@ -6,8 +6,8 @@ ServerSideViewsTemplatePro.dpr True Debug - Win32 - 1 + Win64 + 3 Console ServerSideViewsTemplatePro @@ -35,6 +35,12 @@ true true + + true + Cfg_1 + true + true + true Base @@ -57,12 +63,20 @@ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 1033 .\bin - CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(ModuleName);FileDescription=$(ModuleName);ProductName=$(ModuleName) + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) None DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;frxe23;vclFireDAC;emsclientfiredac;DataSnapFireDAC;svnui;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;ipstudiowinwordxp;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;DelphiCookbookListViewAppearance;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;bdertl;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;frxTee23;JclDeveloperTools;vclie;CPortLibDXE;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;Jcl;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;ipstudiowinclient;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DTKANPRPackage;DBXSybaseASADriver;CustomIPTransport;vcldsnap;CodeSiteExpressPkg;SampleListViewMultiDetailAppearancePackage;bindcomp;appanalytics;ipstudiowin;DBXInformixDriver;officeXPrt;IndyIPClient;bindcompvcl;frxDB23;vcldbx;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;JclVcl;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;frx23;JclContainers;fmxase;$(DCC_UsePackage) + none DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;ipstudiowinclient;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;ipstudiowin;DBXInformixDriver;officeXPrt;IndyIPClient;bindcompvcl;TeeUI;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + Debug + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + .\bin + (None) + none DEBUG;$(DCC_Define) @@ -80,8 +94,9 @@ false true true - CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) - none + + + 1033 false @@ -104,7 +119,6 @@ TDataModule - Base @@ -140,6 +154,18 @@ true + + + ServerSideViewsTemplatePro.exe + true + + + + + ServerSideViewsTemplatePro.rsm + true + + 1 @@ -1001,7 +1027,7 @@ True - False + True 12 diff --git a/samples/serversideviews_templatepro/bin/people.data b/samples/serversideviews_templatepro/bin/people.data index c57b08c9..67bf8345 100644 --- a/samples/serversideviews_templatepro/bin/people.data +++ b/samples/serversideviews_templatepro/bin/people.data @@ -1 +1 @@ -[{"first_name":"Daniele","last_name":"Teti","age":43,"devices":[],"guid":"49E8419B66C744529D63DB292389D541"},{"first_name":"Peter","last_name":"Parker","age":23,"devices":[],"guid":"C5489969A04D4AE4B00D4FC50C8ADB5C"},{"first_name":"Bruce","last_name":"Banner","age":50,"devices":[],"guid":"B41D180F30584558B4F4A1AAF849FFA3"},{"first_name":"Sue","last_name":"Storm","age":33,"devices":[],"guid":"3F058118B8C6470D9684E127BC30A84A"},{"first_name":"Scott","last_name":"Summer","age":35,"devices":[],"guid":"3518D8C6F60E42D19C5A7250ADEADC33"},{"first_name":"Reed","last_name":"Richards","age":45,"devices":["smartphone","desktop"],"guid":"09C85C9DEB714476AADB9EB0AD689536"},{"first_name":"45","last_name":"45","age":45,"devices":["smartphone","laptop"],"guid":"A53742C5F79E4274ADBD61DE8E579368"}] \ No newline at end of file +[{"first_name":"Daniele","last_name":"Teti","age":43,"devices":[],"guid":"49E8419B66C744529D63DB292389D541"},{"first_name":"Peter","last_name":"Parker","age":23,"devices":[],"guid":"C5489969A04D4AE4B00D4FC50C8ADB5C"},{"first_name":"Bruce","last_name":"Banner","age":50,"devices":[],"guid":"B41D180F30584558B4F4A1AAF849FFA3"},{"first_name":"Sue","last_name":"Storm","age":33,"devices":[],"guid":"3F058118B8C6470D9684E127BC30A84A"},{"first_name":"Scott","last_name":"Summer","age":35,"devices":[],"guid":"3518D8C6F60E42D19C5A7250ADEADC33"},{"first_name":"Reed","last_name":"Richards","age":45,"devices":["smartphone","desktop"],"guid":"09C85C9DEB714476AADB9EB0AD689536"}] \ No newline at end of file diff --git a/samples/serversideviews_templatepro/bin/templates/partials/footer.tpro b/samples/serversideviews_templatepro/bin/templates/partials/footer.tpro index 8ca9880d..dbdc95f5 100644 --- a/samples/serversideviews_templatepro/bin/templates/partials/footer.tpro +++ b/samples/serversideviews_templatepro/bin/templates/partials/footer.tpro @@ -4,9 +4,6 @@
-
- N.B. All these views are UTF-8 encoded with BOM -
Powered by DMVCFramework
diff --git a/sources/MVCFramework.IntfObjectPool.pas b/sources/MVCFramework.IntfObjectPool.pas index d691c1c3..2bc0fe96 100644 --- a/sources/MVCFramework.IntfObjectPool.pas +++ b/sources/MVCFramework.IntfObjectPool.pas @@ -277,3 +277,4 @@ begin end; end. + diff --git a/sources/MVCFramework.View.Renderers.Mustache.pas b/sources/MVCFramework.View.Renderers.Mustache.pas index 517f8255..3d2c21f4 100644 --- a/sources/MVCFramework.View.Renderers.Mustache.pas +++ b/sources/MVCFramework.View.Renderers.Mustache.pas @@ -52,7 +52,7 @@ type function RenderJSON(lViewEngine: TSynMustache; const JSON: UTF8String; Partials: TSynMustachePartials; Helpers: TSynMustacheHelpers; OnTranslate: TOnStringTranslate; EscapeInvert: boolean): UTF8String; virtual; public - procedure Execute(const ViewName: string; const OutputStream: TStream); override; + procedure Execute(const ViewName: string; const Builder: TStringBuilder); override; constructor Create(const AEngine: TMVCEngine; const AWebContext: TWebContext; const AViewModel: TMVCViewDataObject; const AContentType: string); override; @@ -131,12 +131,11 @@ begin Result := lViewEngine.RenderJSON(JSON, Partials, Helpers, OnTranslate, EscapeInvert); end; -procedure TMVCMustacheViewEngine.Execute(const ViewName: string; const OutputStream: TStream); +procedure TMVCMustacheViewEngine.Execute(const ViewName: string; const Builder: TStringBuilder); var lViewFileName: string; lViewTemplate: UTF8String; lViewEngine: TSynMustache; - lSW: TStreamWriter; begin PrepareModels; lViewFileName := GetRealFileName(ViewName); @@ -144,12 +143,7 @@ begin raise EMVCFrameworkViewException.CreateFmt('View [%s] not found', [ViewName]); lViewTemplate := StringToUTF8(TFile.ReadAllText(lViewFileName, TEncoding.UTF8)); lViewEngine := TSynMustache.Parse(lViewTemplate); - lSW := TStreamWriter.Create(OutputStream); - try - lSW.Write(UTF8Tostring(RenderJSON(lViewEngine, FJSONModelAsString, fPartials, fHelpers, nil, false))); - finally - lSW.Free; - end; + Builder.Append(UTF8Tostring(RenderJSON(lViewEngine, FJSONModelAsString, fPartials, fHelpers, nil, false))); end; procedure TMVCMustacheViewEngine.LoadHelpers; diff --git a/sources/MVCFramework.View.Renderers.TemplatePro.pas b/sources/MVCFramework.View.Renderers.TemplatePro.pas index 40c20572..1496b2e5 100644 --- a/sources/MVCFramework.View.Renderers.TemplatePro.pas +++ b/sources/MVCFramework.View.Renderers.TemplatePro.pas @@ -34,7 +34,7 @@ type { This class implements the TemplatePro view engine for server side views } TMVCTemplateProViewEngine = class(TMVCBaseViewEngine) public - procedure Execute(const ViewName: string; const OutputStream: TStream); override; + procedure Execute(const ViewName: string; const Builder: TStringBuilder); override; end; implementation @@ -73,8 +73,7 @@ begin end; end; -procedure TMVCTemplateProViewEngine.Execute(const ViewName: string; - const OutputStream: TStream); +procedure TMVCTemplateProViewEngine.Execute(const ViewName: string; const Builder: TStringBuilder); var lTP: TTProCompiler; lViewFileName: string; @@ -120,7 +119,7 @@ begin end; lCompiledTemplate.AddFilter('json', DumpAsJSONString); //lCompiledTemplate.DumpToFile(TPath.Combine(AppPath, 'TProDump.txt')); - TStringStream(OutputStream).WriteString(lCompiledTemplate.Render); + Builder.Append(lCompiledTemplate.Render); except on E: ETProException do begin diff --git a/sources/MVCFramework.pas b/sources/MVCFramework.pas index c6684526..9f2db2b3 100644 --- a/sources/MVCFramework.pas +++ b/sources/MVCFramework.pas @@ -1286,7 +1286,7 @@ type const AContentType: string); overload; virtual; destructor Destroy; override; - procedure Execute(const ViewName: string; const OutputStream: TStream); virtual; abstract; + procedure Execute(const ViewName: string; const Builder: TStringBuilder); virtual; abstract; property ViewName: string read FViewName; property WebContext: TWebContext read FWebContext; @@ -4149,9 +4149,9 @@ end; function TMVCController.GetRenderedView(const AViewNames: TArray; const JSONModel: TJSONObject): string; var - lView: TMVCBaseViewEngine; lViewName: string; lStrStream: TStringStream; + lView: TMVCBaseViewEngine; lViewName: string; lStrStream: TStringBuilder; begin - lStrStream := TStringStream.Create('', TEncoding.UTF8); + lStrStream := TStringBuilder.Create; try lView := FEngine.ViewEngineClass.Create(Engine, Context, FViewModel, JSONModel, ContentType); try @@ -4162,8 +4162,7 @@ begin finally lView.Free; end; - lStrStream.Position := 0; - Result := lStrStream.DataString; + Result := lStrStream.ToString; finally lStrStream.Free; end; @@ -4792,9 +4791,9 @@ end; function TMVCController.GetRenderedView(const AViewNames: TArray): string; var - lView: TMVCBaseViewEngine; lViewName: string; lStrStream: TStringStream; + lView: TMVCBaseViewEngine; lViewName: string; lStrStream: TStringBuilder; begin - lStrStream := TStringStream.Create('', TEncoding.UTF8); + lStrStream := TStringBuilder.Create; try lView := FEngine.ViewEngineClass.Create( Engine, Context, @@ -4808,8 +4807,7 @@ begin finally lView.Free; end; - lStrStream.Position := 0; - Result := lStrStream.DataString; + Result := lStrStream.ToString; finally lStrStream.Free; end;