Skip to content
New issue

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

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

Already on GitHub? Sign in 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