আপনি ন্যূনতম প্রচেষ্টায় গতিশীল পৃষ্ঠা তৈরি করতে Google Apps স্ক্রিপ্ট কোড এবং HTML মিশ্রিত করার জন্য টেমপ্লেট ব্যবহার করতে পারেন। যদি আপনি PHP, ASP, অথবা JSP এর মতো কোড এবং HTML মিশ্রিত টেমপ্লেটিং ভাষা ব্যবহার করে থাকেন, তাহলে বাক্য গঠনটি পরিচিত মনে হওয়া উচিত।
স্ক্রিপ্টলেট
অ্যাপস স্ক্রিপ্ট টেমপ্লেটগুলিতে স্ক্রিপ্টলেট নামে তিনটি বিশেষ ট্যাগ থাকতে পারে। একটি স্ক্রিপ্টলেটের ভিতরে, আপনি একটি সাধারণ অ্যাপস স্ক্রিপ্ট ফাইলে কাজ করে এমন যেকোনো কোড লিখতে পারেন: স্ক্রিপ্টলেটগুলি অন্যান্য কোড ফাইলে সংজ্ঞায়িত ফাংশনগুলিকে কল করতে পারে, গ্লোবাল ভেরিয়েবলগুলি উল্লেখ করতে পারে, অথবা যেকোনো অ্যাপস স্ক্রিপ্ট API ব্যবহার করতে পারে। আপনি এমনকি স্ক্রিপ্টলেটের মধ্যে ফাংশন এবং ভেরিয়েবলগুলিকে সংজ্ঞায়িত করতে পারেন, এই সতর্কতা সহ যে কোড ফাইল বা অন্যান্য টেমপ্লেটগুলিতে সংজ্ঞায়িত ফাংশন দ্বারা সেগুলিকে কল করা যাবে না।
যদি আপনি নিম্নলিখিত উদাহরণটি স্ক্রিপ্ট এডিটরে পেস্ট করেন, <?= ... ?> ট্যাগের (একটি প্রিন্ট স্ক্রিপ্টলেট ) বিষয়বস্তু ইটালিক আকারে প্রদর্শিত হবে। ব্যবহারকারীকে পৃষ্ঠাটি পরিবেশন করার আগে এই কোডটি সার্ভারে চলে। যেহেতু পৃষ্ঠাটি পরিবেশন করার আগে স্ক্রিপ্টলেট কোড কার্যকর হয়, তাই এটি প্রতি পৃষ্ঠায় কেবল একবার চালানো যেতে পারে। ক্লায়েন্ট-সাইড জাভাস্ক্রিপ্ট বা অ্যাপস স্ক্রিপ্ট ফাংশনগুলির বিপরীতে যা আপনি google.script.run এর মাধ্যমে কল করেন, পৃষ্ঠা লোড হওয়ার পরে স্ক্রিপ্টলেটগুলি আবার কার্যকর করতে পারে না।
কোড.জিএস
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
ইনডেক্স.এইচটিএমএল
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Hello, World! The time is <?= new Date() ?>.
</body>
</html>
মনে রাখবেন যে টেমপ্লেট করা HTML এর জন্য doGet ফাংশনটি মৌলিক HTML তৈরি এবং পরিবেশনের উদাহরণ থেকে আলাদা। এখানে দেখানো ফাংশনটি HTML ফাইল থেকে একটি HtmlTemplate অবজেক্ট তৈরি করে, তারপর স্ক্রিপ্টলেটগুলি কার্যকর করার জন্য তার evaluate পদ্ধতিটি কল করে এবং টেমপ্লেটটিকে একটি HtmlOutput অবজেক্টে রূপান্তর করে যা স্ক্রিপ্টটি ব্যবহারকারীকে পরিবেশন করতে পারে।
স্ট্যান্ডার্ড স্ক্রিপ্টলেট
স্ট্যান্ডার্ড স্ক্রিপ্টলেট, যা <? ... ?> সিনট্যাক্স ব্যবহার করে, পৃষ্ঠায় স্পষ্টভাবে কন্টেন্ট আউটপুট না করেই কোড এক্সিকিউট করে। যাইহোক, এই উদাহরণে দেখা যাচ্ছে যে, স্ক্রিপ্টলেটের ভিতরে থাকা কোডের ফলাফল স্ক্রিপ্টলেটের বাইরের HTML কন্টেন্টকে প্রভাবিত করতে পারে:
কোড.জিএস
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
ইনডেক্স.এইচটিএমএল
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? if (true) { ?>
<p>This is always served!</p>
<? } else { ?>
<p>This is never served.</p>
<? } ?>
</body>
</html>
স্ক্রিপ্টলেট প্রিন্ট করুন
<?= ... ?> সিনট্যাক্স ব্যবহার করে এমন স্ক্রিপ্টলেট প্রিন্ট করার সময়, তাদের কোডের ফলাফল কনটেক্সচুয়াল এস্কেপিং ব্যবহার করে পৃষ্ঠায় আউটপুট করা হয়।
কনটেক্সচুয়াল এস্কেপিং এর অর্থ হল অ্যাপস স্ক্রিপ্ট পৃষ্ঠায় আউটপুটের প্রেক্ষাপট ট্র্যাক করে — একটি HTML অ্যাট্রিবিউটের ভিতরে, একটি ক্লায়েন্ট-সাইড script ট্যাগের ভিতরে, অথবা অন্য কোথাও — এবং ক্রস-সাইট স্ক্রিপ্টিং (XSS) আক্রমণ থেকে রক্ষা করার জন্য স্বয়ংক্রিয়ভাবে এস্কেপ অক্ষর যোগ করে।
এই উদাহরণে, প্রথম প্রিন্টিং স্ক্রিপ্টলেটটি সরাসরি একটি স্ট্রিং আউটপুট করে; এর পরে একটি স্ট্যান্ডার্ড স্ক্রিপ্টলেট আসে যা একটি অ্যারে এবং একটি লুপ সেট আপ করে, তারপরে আরেকটি প্রিন্টিং স্ক্রিপ্টলেট অ্যারের বিষয়বস্তু আউটপুট করে।
কোড.জিএস
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
ইনডেক্স.এইচটিএমএল
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<?= 'My favorite Google products:' ?>
<? var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ?>
<b><?= data[i] ?></b>
<? } ?>
</body>
</html>
মনে রাখবেন যে একটি প্রিন্টিং স্ক্রিপ্টলেট শুধুমাত্র তার প্রথম স্টেটমেন্টের মান আউটপুট করে; বাকি যেকোনো স্টেটমেন্ট এমনভাবে আচরণ করে যেন সেগুলি একটি স্ট্যান্ডার্ড স্ক্রিপ্টলেটে রয়েছে। সুতরাং, উদাহরণস্বরূপ, স্ক্রিপ্টলেট <?= 'Hello, world!'; 'abc' ?> শুধুমাত্র "Hello, world!" প্রিন্ট করে।
জোর করে স্ক্রিপ্টলেট মুদ্রণ করা
ফোর্স-প্রিন্টিং স্ক্রিপ্টলেট, যা <?!= ... ?> সিনট্যাক্স ব্যবহার করে, স্ক্রিপ্টলেট প্রিন্ট করার মতো, তবে তারা প্রাসঙ্গিক এস্কেপিং এড়ায়।
যদি আপনার স্ক্রিপ্ট অবিশ্বস্ত ব্যবহারকারীর ইনপুট অনুমোদন করে তবে কনটেক্সচুয়াল এস্কেপিং গুরুত্বপূর্ণ। বিপরীতে, যদি আপনার স্ক্রিপ্টলেটের আউটপুটে ইচ্ছাকৃতভাবে HTML বা স্ক্রিপ্ট থাকে যা আপনি ঠিক যেমনটি নির্দিষ্টভাবে সন্নিবেশ করতে চান তবে আপনাকে জোর করে প্রিন্ট করতে হবে।
সাধারণ নিয়ম হিসেবে, জোর করে স্ক্রিপ্টলেট প্রিন্ট করার পরিবর্তে প্রিন্টিং স্ক্রিপ্টলেট ব্যবহার করুন, যদি না আপনি জানেন যে আপনাকে HTML বা জাভাস্ক্রিপ্ট অপরিবর্তিত রেখে প্রিন্ট করতে হবে।
স্ক্রিপ্টলেটে অ্যাপস স্ক্রিপ্ট কোড
স্ক্রিপ্টলেটগুলি কেবল সাধারণ জাভাস্ক্রিপ্ট চালানোর মধ্যেই সীমাবদ্ধ নয়; আপনি আপনার টেমপ্লেটগুলিকে অ্যাপস স্ক্রিপ্ট ডেটাতে অ্যাক্সেস দেওয়ার জন্য নিম্নলিখিত তিনটি কৌশল ব্যবহার করতে পারেন।
তবে মনে রাখবেন, যেহেতু টেমপ্লেট কোডটি ব্যবহারকারীকে পৃষ্ঠাটি পরিবেশন করার আগে কার্যকর হয়, তাই এই কৌশলগুলি কেবল একটি পৃষ্ঠায় প্রাথমিক সামগ্রী ফিড করতে পারে। ইন্টারেক্টিভভাবে একটি পৃষ্ঠা থেকে অ্যাপস স্ক্রিপ্ট ডেটা অ্যাক্সেস করতে, পরিবর্তে google.script.run API ব্যবহার করুন।
একটি টেমপ্লেট থেকে অ্যাপস স্ক্রিপ্ট ফাংশন কল করুন
স্ক্রিপ্টলেটগুলি অ্যাপস স্ক্রিপ্ট কোড ফাইল বা লাইব্রেরিতে সংজ্ঞায়িত যেকোনো ফাংশনকে কল করতে পারে। এই উদাহরণে স্প্রেডশিট থেকে ডেটা টেমপ্লেটে টেনে আনার এবং তারপর ডেটা থেকে একটি HTML টেবিল তৈরি করার একটি উপায় দেখানো হয়েছে।
কোড.জিএস
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
function getData() {
return SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues();
}
ইনডেক্স.এইচটিএমএল
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? var data = getData(); ?>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
সরাসরি অ্যাপস স্ক্রিপ্ট এপিআই-তে কল করুন
আপনি স্ক্রিপ্টলেটে সরাসরি অ্যাপস স্ক্রিপ্ট কোড ব্যবহার করতে পারেন। এই উদাহরণটি একটি পৃথক ফাংশনের পরিবর্তে টেমপ্লেটেই ডেটা লোড করে পূর্ববর্তী উদাহরণের মতো একই ফলাফল অর্জন করে।
কোড.জিএস
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
ইনডেক্স.এইচটিএমএল
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? var data = SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues(); ?>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
টেমপ্লেটগুলিতে ভেরিয়েবল পুশ করুন
পরিশেষে, আপনি HtmlTemplate অবজেক্টের বৈশিষ্ট্য হিসেবে ভেরিয়েবলগুলিকে একটি টেমপ্লেটে পুশ করতে পারেন। আবারও, এই উদাহরণটি পূর্ববর্তী উদাহরণগুলির মতো একই ফলাফল অর্জন করে।
কোড.জিএস
function doGet() {
var t = HtmlService.createTemplateFromFile('Index');
t.data = SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues();
return t.evaluate();
}
ইনডেক্স.এইচটিএমএল
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
ডিবাগ টেমপ্লেট
টেমপ্লেট ডিবাগ করা কঠিন হতে পারে কারণ আপনার লেখা কোডটি সরাসরি কার্যকর করা হয় না। পরিবর্তে, সার্ভার আপনার টেমপ্লেটটিকে কোডে রূপান্তরিত করে, তারপর সেই ফলাফলযুক্ত কোডটি কার্যকর করে।
যদি টেমপ্লেটটি আপনার স্ক্রিপ্টলেটগুলিকে কীভাবে ব্যাখ্যা করছে তা স্পষ্ট না হয়, তাহলে HtmlTemplate ক্লাসের দুটি ডিবাগিং পদ্ধতি আপনাকে কী ঘটছে তা আরও ভালভাবে বুঝতে সাহায্য করতে পারে।
getCode ফাংশন
getCode ফাংশনটি একটি স্ট্রিং প্রদান করে যার মধ্যে সার্ভার টেমপ্লেট থেকে তৈরি কোড থাকে। যদি আপনি কোডটি লগ করেন , তারপর স্ক্রিপ্ট এডিটরে পেস্ট করেন, তাহলে আপনি এটি চালাতে এবং সাধারণ অ্যাপস স্ক্রিপ্ট কোডের মতো ডিবাগ করতে পারবেন।
এখানে সেই টেমপ্লেটটি রয়েছে যা আবার Google পণ্যের একটি তালিকা প্রদর্শন করে, তারপরে getCode এর ফলাফল দেখায়:
কোড.জিএস
function myFunction() {
Logger.log(HtmlService
.createTemplateFromFile('Index')
.getCode());
}
ইনডেক্স.এইচটিএমএল
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<?= 'My favorite Google products:' ?>
<? var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ?>
<b><?= data[i] ?></b>
<? } ?>
</body>
</html>
লগ (মূল্যায়ন করা হয়েছে)
(function() { var output = HtmlService.initTemplate(); output._ = '<!DOCTYPE html>\n';
output._ = '<html>\n' +
' <head>\n' +
' <base target=\"_top\">\n' +
' </head>\n' +
' <body>\n' +
' '; output._$ = 'My favorite Google products:' ;
output._ = ' '; var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ;
output._ = ' <b>'; output._$ = data[i] ; output._ = '</b>\n';
output._ = ' '; } ;
output._ = ' </body>\n';
output._ = '</html>';
/* End of user code */
return output.$out.append('');
})();
getCodeWithComments ফাংশন
getCodeWithComments ফাংশনটি getCode() এর অনুরূপ, কিন্তু মূল্যায়ন করা কোডটিকে মন্তব্য হিসেবে ফেরত দেয় যা মূল টেমপ্লেটের পাশাপাশি প্রদর্শিত হয়।
মূল্যায়ন করা কোডটি দেখুন
মূল্যায়ন করা কোডের যেকোনো নমুনায় আপনি প্রথমেই যে জিনিসটি লক্ষ্য করবেন তা হল HtmlService.initTemplate পদ্ধতি দ্বারা তৈরি অন্তর্নিহিত output অবজেক্ট। এই পদ্ধতিটি নথিভুক্ত নয় কারণ শুধুমাত্র টেমপ্লেটগুলিকেই এটি ব্যবহার করতে হয়। output হল একটি বিশেষ HtmlOutput অবজেক্ট যার দুটি অস্বাভাবিক নামযুক্ত বৈশিষ্ট্য রয়েছে, _ এবং _$ , যা append এবং appendUntrusted কল করার জন্য সংক্ষিপ্ত।
output আরও একটি বিশেষ বৈশিষ্ট্য আছে, $out , যা একটি নিয়মিত HtmlOutput অবজেক্টকে বোঝায় যার এই বিশেষ বৈশিষ্ট্যগুলি নেই। টেমপ্লেটটি কোডের শেষে সেই স্বাভাবিক অবজেক্টটি ফেরত দেয়।
এখন যেহেতু আপনি এই সিনট্যাক্সটি বুঝতে পেরেছেন, আপনি বাকি কোডটি অনুসরণ করতে পারেন। স্ক্রিপ্টলেটের বাইরের HTML কন্টেন্ট (যেমন b ট্যাগ) output._ = ( contextual escaping ছাড়া) ব্যবহার করে যুক্ত করা হয়, এবং স্ক্রিপ্টলেটগুলি জাভাস্ক্রিপ্ট হিসাবে যুক্ত করা হয় (স্ক্রিপ্টলেটের ধরণের উপর নির্ভর করে কনটেক্সচুয়াল escaping সহ বা ছাড়াই)।
মূল্যায়ন করা কোডটি টেমপ্লেট থেকে লাইন নম্বরগুলি সংরক্ষণ করে। মূল্যায়ন করা কোডটি চালানোর সময় যদি আপনি কোনও ত্রুটি পান, তাহলে লাইনটি টেমপ্লেটের সমতুল্য বিষয়বস্তুর সাথে সঙ্গতিপূর্ণ হবে।
মন্তব্যের শ্রেণিবিন্যাস
যেহেতু মূল্যায়ন করা কোড লাইন নম্বর সংরক্ষণ করে, তাই স্ক্রিপ্টলেটের ভিতরের মন্তব্যগুলি অন্যান্য স্ক্রিপ্টলেট এবং এমনকি HTML কোডকেও মন্তব্য করতে পারে। এই উদাহরণগুলি মন্তব্যের কিছু আশ্চর্যজনক প্রভাব দেখায়:
<? var x; // a comment ?> This sentence won't print because a comment begins
inside a scriptlet on the same line.
<? var y; // ?> <?= "This sentence won't print because a comment begins inside
a scriptlet on the same line.";
output.append("This sentence prints because it's on the next line, even though
it's in the same scriptlet.") ?>
<? doSomething(); /* ?>
This entire block is commented out,
even if you add a */ in the HTML
or in a <script> */ </script> tag,
<? until you end the comment inside a scriptlet. */ ?>