From faa11c13b5fd7972998f593454f7d4e4a60725e3 Mon Sep 17 00:00:00 2001 From: Hossain Khan Date: Sat, 18 Jul 2020 11:45:22 -0400 Subject: [PATCH 1/6] [ADDED] Custom view creation guide. --- README.md | 103 +++++++++++++++++- .../yaash/prismjs/PrismJsHtmlTemplate.kt | 2 +- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 866b104..c9518b2 100644 --- a/README.md +++ b/README.md @@ -74,4 +74,105 @@ webView.apply { Here is a screenshot taken from a demo static html page that has syntax highlighting using Prism JS. | ![device-2020-07-18-092715](https://user-images.githubusercontent.com/99822/87853541-fc52d700-c8d8-11ea-9dc6-2d4c624f3b74.png) | ![device-2020-07-18-092727](https://user-images.githubusercontent.com/99822/87853542-fceb6d80-c8d8-11ea-9641-4ecf927b5a01.png) | ![device-2020-07-18-092736](https://user-images.githubusercontent.com/99822/87853543-fe1c9a80-c8d8-11ea-9e11-c9779202368e.png) | -| --- | --- | --- | \ No newline at end of file +| --- | --- | --- | + +## Building your own Fragment or Custom View +Ideally, there should be a modular component or custom-view that you **re-use** syntax highlighting with dynamic content. +For that having a `Fragment` or custom `View` is ideal. + +We can taken the learning from [above](#under-the-hood) to wrap the library in fragment or custom view. Both comes with advantage of it's own. +Regardless if which option is choosen, the underlying code is _almost_ identical. + +### Custom View +The advantage of custom view is that, it can be used in `Fragment` too. Let's take a look how we can templatize the HTML to load source code dynamically. + +In this case, all we need to do is move the [html content defined above] to a `String` variable with options you need. + +#### PrismJS Template +```kotlin +fun prismJsHtmlContent( + formattedSourceCode: String, + language: String, + showLineNumbers: Boolean = true +): String { + return """ + + + + + + + + + + + +
+${formattedSourceCode}
+
+ + +""" +} +``` + +In this example, we have `showLineNumbers` as optional parameter, likewise we could have line highlighting parameter and so on. +PrismJS has [dozens of plugins](https://prismjs.com/download.html) that you can use and expose those options though this function. + +#### Creating custom syntax highlighter WebView +Here you just need to extend the `WebView` and expose a function `bindSyntaxHighlighter()` to send source code and configurations. +```kotlin +class SyntaxHighlighterWebView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : WebView(context, attrs, defStyleAttr) { + companion object { + private const val ANDROID_ASSETS_PATH = "file:///android_asset/" + } + + @SuppressLint("SetJavaScriptEnabled") + fun bindSyntaxHighlighter( + formattedSourceCode: String, + language: String, + showLineNumbers: Boolean = false + ) { + settings.javaScriptEnabled = true + webChromeClient = WebViewChromeClient() + webViewClient = AppWebViewClient() + + loadDataWithBaseURL( + ANDROID_ASSETS_PATH /* baseUrl */, + prismJsHtmlContent(formattedSourceCode, language, showLineNumbers) /* html-data */, + "text/html" /* mimeType */, + "utf-8" /* encoding */, + "" /* failUrl */ + ) + } +} +``` + +#### Use custom view from Fragment or Activity + +Using the newly defined `SyntaxHighlighterWebView` in `Fragment` or `Activity` is business as usual that you are used to. + +In your Layout XML file, add the view with proper layout parameters. + +```xml + +``` + +When `Fragment` or `Activity` is loaded, get reference to `SyntaxHighlighterWebView` and bind it with source code. +```kotlin +val syntaxHighlighter = findViewById(R.id.syntax_highlighter_webview) + +syntaxHighlighter.bindSyntaxHighlighter( + formattedSourceCode = "data class Student(val name: String)", + language = "kotlin" +) +``` + +That's it, you have re-usable custom view that you can use anywhere in the layout. \ No newline at end of file diff --git a/highlighter/src/main/java/dev/hossain/yaash/prismjs/PrismJsHtmlTemplate.kt b/highlighter/src/main/java/dev/hossain/yaash/prismjs/PrismJsHtmlTemplate.kt index cc6cf21..5395dfe 100644 --- a/highlighter/src/main/java/dev/hossain/yaash/prismjs/PrismJsHtmlTemplate.kt +++ b/highlighter/src/main/java/dev/hossain/yaash/prismjs/PrismJsHtmlTemplate.kt @@ -12,7 +12,7 @@ package dev.hossain.yaash.prismjs */ fun prismJsHtmlContent( formattedSourceCode: String, - language: String, + language: String, // Language available via plugin https://prismjs.com/index.html#supported-languages showLineNumbers: Boolean = true ): String { return """ From 0eef9998b5b21fa7a68621c2ec7983f195b33dd7 Mon Sep 17 00:00:00 2001 From: Hossain Khan Date: Sat, 18 Jul 2020 11:45:37 -0400 Subject: [PATCH 2/6] [UPDATE] Version bump for next tagging --- example/build.gradle | 4 ++-- highlighter/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/build.gradle b/example/build.gradle index c0bf8b0..888216b 100644 --- a/example/build.gradle +++ b/example/build.gradle @@ -10,8 +10,8 @@ android { applicationId "dev.hossain.yaash.example" minSdkVersion rootProject.ext.androidMinSdkVersion targetSdkVersion rootProject.ext.androidTargetSdkVersion - versionCode 1 - versionName "1.0" + versionCode 2 + versionName "1.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/highlighter/build.gradle b/highlighter/build.gradle index ab80715..82f131a 100644 --- a/highlighter/build.gradle +++ b/highlighter/build.gradle @@ -9,8 +9,8 @@ android { defaultConfig { minSdkVersion rootProject.ext.androidMinSdkVersion targetSdkVersion rootProject.ext.androidTargetSdkVersion - versionCode 1 - versionName "1.0" + versionCode 2 + versionName "1.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" From 60f0f33a29b98b044a0771c38be0693158ae2164 Mon Sep 17 00:00:00 2001 From: Hossain Khan Date: Sat, 18 Jul 2020 11:49:51 -0400 Subject: [PATCH 3/6] [UPDATE] Added some clarity with intention --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c9518b2..7bbb392 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ yet another android syntax highlighter (YAASH) ### Objective -Explore well established web based syntax highlighter like [PrismJS](https://prismjs.com/) and [highlight.js](https://highlightjs.org/), and showcase how anybody can quickly incorporate these into their project by following some examples provided here. +Explore well established web based syntax highlighter like [PrismJS](https://prismjs.com/) and [highlight.js](https://highlightjs.org/), +and showcase how anybody can quickly incorporate these into their project by following some examples provided here. -The objective is not exactly to provide a _library_ that you can use with Gradle. +> The intention is **NOT** to create another library project that gets abandoned over time. +Feel free to copy parts of code that is necessary for you to add syntax highlighting support to you app. ## Existing Syntax Highlighting Libraries @@ -86,7 +88,7 @@ Regardless if which option is choosen, the underlying code is _almost_ identical ### Custom View The advantage of custom view is that, it can be used in `Fragment` too. Let's take a look how we can templatize the HTML to load source code dynamically. -In this case, all we need to do is move the [html content defined above] to a `String` variable with options you need. +In this case, all we need to do is move the [html content defined above](#2-use-htmlcssjs-asset) to a `String` variable with options you need. #### PrismJS Template ```kotlin From 7f1878ba6eb9b8bed98139415b37f84d8a6047a0 Mon Sep 17 00:00:00 2001 From: Hossain Khan Date: Sat, 18 Jul 2020 12:10:15 -0400 Subject: [PATCH 4/6] [ADDED] Docs for custom highlighter fragment. --- README.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7bbb392..293ccf6 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ yet another android syntax highlighter (YAASH) Explore well established web based syntax highlighter like [PrismJS](https://prismjs.com/) and [highlight.js](https://highlightjs.org/), and showcase how anybody can quickly incorporate these into their project by following some examples provided here. + > The intention is **NOT** to create another library project that gets abandoned over time. Feel free to copy parts of code that is necessary for you to add syntax highlighting support to you app. @@ -82,15 +83,16 @@ Here is a screenshot taken from a demo static html page that has syntax highligh Ideally, there should be a modular component or custom-view that you **re-use** syntax highlighting with dynamic content. For that having a `Fragment` or custom `View` is ideal. -We can taken the learning from [above](#under-the-hood) to wrap the library in fragment or custom view. Both comes with advantage of it's own. -Regardless if which option is choosen, the underlying code is _almost_ identical. +We can taken the learning from [above](#under-the-hood) to wrap the library in fragment or custom view. +Both comes with advantage of it's own. +Regardless if which option is chosen, the underlying code is _almost_ identical. ### Custom View The advantage of custom view is that, it can be used in `Fragment` too. Let's take a look how we can templatize the HTML to load source code dynamically. In this case, all we need to do is move the [html content defined above](#2-use-htmlcssjs-asset) to a `String` variable with options you need. -#### PrismJS Template +#### PrismJS Template Function ```kotlin fun prismJsHtmlContent( formattedSourceCode: String, @@ -177,4 +179,74 @@ syntaxHighlighter.bindSyntaxHighlighter( ) ``` -That's it, you have re-usable custom view that you can use anywhere in the layout. \ No newline at end of file +That's it, you have re-usable custom view that you can use anywhere in the layout. + +## Fragment +`Fragment` is a modular UI component that can be use in a `Activity`. It comes with it's own flexibility like: +* Being able to replace whole screen content +* Replace only part of the content +* Use with navigation library as destination +* and so on + +In this case `Fragment` is just a shell that loads `WebView` and configures it such that it +can show syntax highlighted source code. + +### Create custom Syntax Highlighter Fragment + +Based on Android [official guide](https://developer.android.com/guide/components/fragments#Example) +we need to pass all the required data needed for `prismJsHtmlContent` function [defined above](#prismjs-template-function) +```kotlin +fun newInstance( + formattedSourceCode: String, + language: String, + showLineNumbers: Boolean = false +) = SyntaxHighlighterFragment().apply { + arguments = Bundle().apply { + putString(ARG_KEY_SOURCE_CODE_CONTENT, formattedSourceCode) + putString(ARG_KEY_CODE_LANGUAGE, language) + putBoolean(ARG_KEY_SHOW_LINE_NUMBERS, showLineNumbers) + } +} +``` + +> See [SyntaxHighlighterFragment.kt](https://github.com/amardeshbd/android-syntax-highlighter/blob/develop/highlighter/src/main/java/dev/hossain/yaash/prismjs/SyntaxHighlighterFragment.kt) +> source code for full example. + +And finally when `Fragment#onViewCreated()` is called, we use the extracted the bundle parameters +to initialize and load the syntax highlighting. + +```kotlin +@SuppressLint("SetJavaScriptEnabled") +override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val webView: WebView = view.findViewById(R.id.web_view) + + webView.apply { + settings.javaScriptEnabled = true + webChromeClient = WebViewChromeClient() + webViewClient = AppWebViewClient() + + loadDataWithBaseURL( + ANDROID_ASSETS_PATH /* baseUrl */, + prismJsHtmlContent(sourceCode, language, showLineNumbers) /* html-data */, + "text/html" /* mimeType */, + "utf-8" /* encoding */, + "" /* failUrl */ + ) + } +} +``` + +### Using the Syntax Highlighter Fragment +From your `Activity` or `Fragment`, create an instance of `SyntaxHighlighterFragment` and add that +to fragment container on the screen. +```kotlin +val fragment = SyntaxHighlighterFragment.newInstance( + formattedSourceCode = "data class Student(val name: String)", + language = "kotlin", + showLineNumbers = true +) +``` + +> See [PrismJsDemoActivity.kt](https://github.com/amardeshbd/android-syntax-highlighter/blob/develop/example/src/main/java/dev/hossain/yaash/example/ui/demoprismjs/PrismJsDemoActivity.kt) +> source code for full example. From 6660f92b7886aee93e787b362a7f1997d485f2c8 Mon Sep 17 00:00:00 2001 From: Hossain Khan Date: Sat, 18 Jul 2020 12:13:25 -0400 Subject: [PATCH 5/6] [ADDED] Note about the `web_view` --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 293ccf6..a833999 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,7 @@ to initialize and load the syntax highlighting. @SuppressLint("SetJavaScriptEnabled") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + // Loads the plain `WebView` defined in `fragment_highlighter.xml` val webView: WebView = view.findViewById(R.id.web_view) webView.apply { From 8a58b9f5cfe5353942393c74dc72e047efdfd935 Mon Sep 17 00:00:00 2001 From: Hossain Khan Date: Sat, 18 Jul 2020 12:22:51 -0400 Subject: [PATCH 6/6] [FIXED] Some PR review comments https://github.com/amardeshbd/android-syntax-highlighter/pull/17#pullrequestreview-451066869 --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a833999..fa6539f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ and showcase how anybody can quickly incorporate these into their project by fol > The intention is **NOT** to create another library project that gets abandoned over time. -Feel free to copy parts of code that is necessary for you to add syntax highlighting support to you app. +Feel free to copy parts of code that is necessary for you to add syntax highlighting support to your app. ## Existing Syntax Highlighting Libraries @@ -59,7 +59,8 @@ For example: ``` > NOTE: For most cases, hard coding sample code for each sample-code is not ideal. -> Soon, we will explore how to make the HTML file as template and inject source code from Activity or Fragment. +> Soon, we will explore how to make the HTML file as template and inject source code from Activity or Fragment. +> See [Custom View](#building-your-own-fragment-or-custom-view) section below for detailed instructions. ### 3. Load the static HTML on `WebView` Finally on your Activity or Fragment, once view is loaded initialize `WebView` with local html file from `assets`. @@ -83,12 +84,13 @@ Here is a screenshot taken from a demo static html page that has syntax highligh Ideally, there should be a modular component or custom-view that you **re-use** syntax highlighting with dynamic content. For that having a `Fragment` or custom `View` is ideal. -We can taken the learning from [above](#under-the-hood) to wrap the library in fragment or custom view. -Both comes with advantage of it's own. +We can taken the learning from [above](#under-the-hood) to wrap the JavaScript based syntax highlighting library +in fragment or custom view using `WebView`. Both comes with advantage of it's own. Regardless if which option is chosen, the underlying code is _almost_ identical. ### Custom View -The advantage of custom view is that, it can be used in `Fragment` too. Let's take a look how we can templatize the HTML to load source code dynamically. +The advantage of custom view is that, it can be used anywhere, `Activity` or `Fragment`. +Let's take a look how we can templatize the HTML to load source code dynamically. In this case, all we need to do is move the [html content defined above](#2-use-htmlcssjs-asset) to a `String` variable with options you need. @@ -120,7 +122,7 @@ fun prismJsHtmlContent( } ``` -In this example, we have `showLineNumbers` as optional parameter, likewise we could have line highlighting parameter and so on. +In this example, we have `showLineNumbers` as optional parameter, likewise we could have line number parameter to highlight a line or section. PrismJS has [dozens of plugins](https://prismjs.com/download.html) that you can use and expose those options though this function. #### Creating custom syntax highlighter WebView