Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

initial adaptor and example with the Sempare Template Engine. #711

Merged
merged 12 commits into from
Jan 3, 2024
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,4 @@ samples/WineCellarSample/winecellarclient_mobile/Android/Debug/WineCellarMobileC
samples/apachemodule/Apache24/logs/httpd.pid
samples/session_file_based/Win32/DEBUG/sessions/
unittests/general/UnitTestReports/
lib/sempare-delphi-template-engine
138 changes: 138 additions & 0 deletions contrib/MVCFramework.View.Renderers.Sempare.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// ***************************************************************************
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2023 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
//
// ***************************************************************************
//
// Sempare Template Engine
//
// Copyright (c) 2019-2023 Conrad Vermeulen and Sempare Limited
//
// https://github.com/sempare/sempare-delphi-template-engine
//
// NOTE: The Sempare Template Engine is available under GPL or commercial license.
//
// Free as in speech, NOT Free as in beer.
//
// ***************************************************************************
//
// This adaptor is licensed under the Apache License.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ***************************************************************************

unit MVCFramework.View.Renderers.Sempare;

interface

uses
MVCFramework,
MVCFramework.Commons,
MVCFramework.Logger,
System.Classes,
Sempare.Template;

type
Template = Sempare.Template.Template;
TTemplateValue = Sempare.Template.TTemplateValue;

TMVCSempareTemplateEngine = class(TMVCBaseViewEngine)
public
class constructor Create;
public
procedure Execute(const ViewName: string; const OutputStream: TStream); override;
end;

implementation

uses
System.SysUtils,
System.TypInfo,
Data.DB,
Sempare.Template.TemplateRegistry,
Sempare.Template.AST,
Sempare.Template.Common,
Sempare.Template.ResourceStrings,
Sempare.Template.Rtti;

class constructor TMVCSempareTemplateEngine.Create;
begin
// The default Start and End token is <% and %> respectively.
// Changing to {{ }} as it is what people may be used to when working with Mustache in the DelphiMVCFramework.
with Template.Resolver.Context do
begin
StartToken := '{{';
EndToken := '}}';
UseHtmlVariableEncoder;
Encoding := TEncoding.UTF8;
end;
end;

procedure TMVCSempareTemplateEngine.Execute(const ViewName: string; const OutputStream: TStream);
begin
try
// the template engine will resolve the view. Using self, the template engine can dereference the ViewEngine properties.
Template.Resolve(ViewName, self, OutputStream);
except
on e: Exception do
begin
Log.Error('[%s] %s', [e.Classname, e.Message], LOGGERPRO_TAG);
raise e;
end;
end;
end;

function DerefBaseViewEngine(const APosition: IPosition; const AObj: TTemplateValue; const ADeref: TTemplateValue; const ARaiseIfMissing: boolean; const AContext: ITemplateContext; out AFound: boolean): TTemplateValue;
var
LViewEngine: TMVCBaseViewEngine;
LKey: string;
LDataSet: TDataSet;
begin
LViewEngine := AObj.AsType<TMVCBaseViewEngine>;
LKey := AsString(ADeref, AContext);
// check if the key exists in the ViewModel
if assigned(LViewEngine.ViewModel) then
begin
AFound := LViewEngine.ViewModel.TryGetValue(LKey, result);
if AFound then
exit;
end;
// check if we have a dataset
if assigned(LViewEngine.ViewDataSets) then
begin
AFound := LViewEngine.ViewDataSets.TryGetValue(LKey, LDataSet);
if AFound then
exit(LDataSet);
end;
// we don't know anything about the key, so behave accordingly
if ARaiseIfMissing then
RaiseError(APosition, SCannotDereferenceValueOnObject, [LKey, SDictionary]);
exit('');
end;

function MatchBaseViewEngine(const ATypeInfo: PTypeInfo; const AClass: TClass): boolean;
begin
exit(AClass = TMVCSempareTemplateEngine);
end;

initialization

RegisterDeref(MatchBaseViewEngine, DerefBaseViewEngine);

end.
12 changes: 12 additions & 0 deletions contrib/get-sempare-template-engine.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@echo off
echo This relies on the git command line to clone the Sempare Template Engine into this directory
echo .
echo This will checkout the Sempare Template engine into ..\lib\sempare-delphi-template-engine
echo .
pause
cd ..\lib
git clone https://github.com/sempare/sempare-delphi-template-engine.git

pause


20 changes: 9 additions & 11 deletions samples/serversideviews_mustache/ServerSideViewsMustache.dpr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ program ServerSideViewsMustache;

{$APPTYPE CONSOLE}


uses
System.SysUtils,
MVCFramework,
MVCFramework.Signal,
{$IFDEF MSWINDOWS}
{$IFDEF MSWINDOWS}
Winapi.ShellAPI,
Winapi.Windows,
{$ENDIF }
{$ENDIF }
IdHTTPWebBrokerBridge,
MVCFramework.View.Renderers.Mustache,
Web.WebReq,
Expand All @@ -25,7 +24,6 @@ uses

{$R *.res}


procedure RunServer(APort: Integer);
var
LServer: TIdHTTPWebBrokerBridge;
Expand All @@ -36,9 +34,9 @@ begin
try
LServer.DefaultPort := APort;
LServer.Active := True;
{$IFDEF MSWINDOWS}
ShellExecute(0, 'open', 'http://localhost:8080', nil, nil, SW_SHOW);
{$ENDIF}
{$IFDEF MSWINDOWS}
ShellExecute(0, 'open', PChar('http://localhost:' + inttostr(APort)), nil, nil, SW_SHOW);
{$ENDIF}
Write('Ctrl+C to stop the server');
WaitForTerminationSignal;
EnterInShutdownState;
Expand All @@ -56,10 +54,10 @@ begin

// these helpers will be available to the mustache views as if they were the standard ones
TMVCMustacheHelpers.OnLoadCustomHelpers := procedure(var MustacheHelpers: TSynMustacheHelpers)
begin
TSynMustache.HelperAdd(MustacheHelpers, 'MyHelper1', TMyMustacheHelpers.MyHelper1);
TSynMustache.HelperAdd(MustacheHelpers, 'MyHelper2', TMyMustacheHelpers.MyHelper2);
end;
begin
TSynMustache.HelperAdd(MustacheHelpers, 'MyHelper1', TMyMustacheHelpers.MyHelper1);
TSynMustache.HelperAdd(MustacheHelpers, 'MyHelper2', TMyMustacheHelpers.MyHelper2);
end;

RunServer(8080);
except
Expand Down
71 changes: 71 additions & 0 deletions samples/serversideviews_sempare/CustomSempareHelpersU.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// ***************************************************************************
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2023 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
//
// ***************************************************************************
//
// Sempare Template Engine
//
// Copyright (c) 2019-2023 Conrad Vermeulen and Sempare Limited
//
// https://github.com/sempare/sempare-delphi-template-engine
//
// NOTE: The Sempare Template Engine is available under GPL or commercial license.
//
// Free as in speech, NOT Free as in beer.
//
// ***************************************************************************
//
// This adaptor is licensed under the Apache License.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ***************************************************************************

unit CustomSempareHelpersU;

interface

// For more information on custom functions in the Sempare Template Engine,
// see https://github.com/sempare/sempare-delphi-template-engine/blob/main/docs/custom-functions.md

type
TMySempareHelpers = class sealed
public
class function MyHelper1(const Value: string): string; static;
class function MyHelper2(const Value: string): string; static;
end;

implementation

uses
System.SysUtils;

{ TMySempareHelpers }

class function TMySempareHelpers.MyHelper1(const Value: string): string;
begin
Result := Value + ' (I''m The MyHelper1)';
end;

class function TMySempareHelpers.MyHelper2(const Value: string): string;
begin
Result := Value + ' (I''m The MyHelper2)';
end;

end.
Loading