Filter out unnecessary attributes while utilizing an anonymous type in ClearScript

In my development project, I am creating a .NET wrapper for the popular java-script library called Linkify.js, utilizing Microsoft's ClearScript.

The challenge I am facing involves implementing the attributes property within the options object parameter for the linkifyHtml function.

This parameter in the java-script code should look like this:

attributes: {
  title: "External Link",
  etc: "etc..."
}

To tackle this issue, I came up with the idea of defining a Attributes property that returns an anonymous type:

Public Class LinkifyFormatOptions 

    Public Property Attributes As Func(Of LinkifyLinkType, String, Object) =
        Function(linkType As LinkifyLinkType, href As String) As Object
            Select Case linkType
                Case LinkifyLinkType.Url
                    Return New With {.test_attribute = "This is a test attribute"}
                Case Else
                    Return Nothing
            End Select
        End Function
        
End Class

... which is then used to build the options object like this:

Friend Function GetLinkifyOptions() As Object
    Dim options As New With {
        .attributes = Function(href As String, linkType As String) As Object
                          Select Case linkType
                              Case "url"
                                  Return Me.Attributes(LinkifyLinkType.Url, href)
                              Case "email"
                                  Return Me.Attributes(LinkifyLinkType.Email, href)
                              Case "hashtag"
                                  Return Me.Attributes(LinkifyLinkType.Hashtag, href)
                              Case "mention"
                                  Return Me.Attributes(LinkifyLinkType.Mention, href)
                              Case "ticket"
                                  Return Me.Attributes(LinkifyLinkType.Ticket, href)
                              Case Else
                                  Return Nothing
                          End Select
                      End Function,
    .className = etc...,
    .formatHref = etc...,
    .etc = etc...
    }
End Function

... and eventually utilized in calling the java-script's linkifyHtml function:

Imports Microsoft.ClearScript
Imports Microsoft.ClearScript.V8

Public Shared Function Linkify(str As String,
                               [interface] As LinkifyInterface,
                               Optional plugins As LinkifyPlugins = LinkifyPlugins.None,
                               Optional formatOptions As LinkifyFormatOptions = Nothing) As String

    ' Validations and other operations...

    Using engine As New V8ScriptEngine("linkify_engine", V8ScriptEngineFlags.DisableGlobalMembers)
    
        Dim options As Object = formatOptions.GetLinkifyOptions()
        ' loading linkify.js scripts and more...
        
        Dim linkifyFunction As ScriptObject = DirectCast(engine.Evaluate("linkifyHtml"), ScriptObject)
        Return CStr(linkifyFunction.Invoke(asConstructor:=False, str, options))
    
    End Using
    
End Function

The glitch arises from the fact that the ClearScript engine exposes unwanted members of the Object type, such as "ToString", "GetHashCode", etc.

After invoking the java-script's linkifyHtml function, the output shows unnecessary details like so:

<p>Domain: <a href="http://example.domain.com" $test_attribute="This is a test attribute" ToString="[object Object]" Equals="[object Object]" GetHashCode="[object Object]" GetType="[object Object]" Finalize="[object Object]" MemberwiseClone="[object Object]" test_attribute="This is a test attribute" toJSON="function toJSON() { [native code] }">example.domain.com</a></p>

Although I managed to solve some issues by setting the V8ScriptEngine.SuppressInstanceMethodEnumeration Property like this:

Using engine As New V8ScriptEngine("linkify_engine", V8ScriptEngineFlags.DisableGlobalMembers)
    engine.SuppressInstanceMethodEnumeration = True
    ' and more...
End Using

There are still remnants like the reflected toJSON function persisting in the output, and I'm unsure how to eliminate them:

<p>Domain: <a href="http://example.domain.com" $test_attribute="This is a test attribute" test_attribute="This is a test attribute" toJSON="function toJSON() { [native code] }">example.domain.com</a></p>

I aim for the desired output to be clean, devoid of the reflected toJSON member and any symbol-prefixed members like $test_attribute:

<p>Domain: <a href="http://example.domain.com" test_attribute="This is a test attribute">example.domain.com</a></p>

If possible, I'd appreciate guidance on how to hide the unwanted members and ensure a seamless operation using qualified types or specific attributes within the Microsoft.ClearScript namespace.

I experimented with custom type definitions to override typical members and applied various attributes without success in masking the toJSON function. Any insights on resolving this hurdle would be greatly appreciated.

Answer №1

After reviewing your issue, I was able to replicate it using the following simplified code:

Dim attributes = New With {.test_attribute = "This is a test attribute"}
Dim options = New With {.attributes = attributes}
Console.WriteLine(engine.Script.linkifyHtml("example.domain.com", options))

Observations: The $test_attribute property appears to be part of an anonymous type, which ClearScript correctly exposes. However, it seems that the presence of toJSON as an enumerable property may be a bug in ClearScript.

Recommendation: Instead of using an anonymous type, consider utilizing a script object. Below is a function that can help create and populate a script object:

Private Function CreateObject(engine As V8ScriptEngine, ParamArray props() As (name As String, value As Object))
    Dim result = engine.Evaluate("({})")
    For Each prop In props
        result(prop.name) = prop.value
    Next
    CreateObject = result
End Function

You can employ this function to achieve the desired functionality:

Dim attributes = CreateObject(engine, ("test_attribute", "This is a test attribute"))
Dim options = CreateObject(engine, ("attributes", attributes))
Console.WriteLine(engine.Script.linkifyHtml("example.domain.com", options))

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Randomly generated numerical value in input field

How can I generate a 15-digit number using JS code and then reduce it to just 5 or 6 digits in a text box? <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script type="text/javascript ...

What is the proper way to update data in reactjs?

I previously had code that successfully updated interval data in the browser and locale without any issues. class Main extends Component { constructor(props) { super(props); this.state = {data: []} } componentWillMount() { fetch('fi ...

The height of a DIV element can vary based on

Looking at this div structure: DIV3 has a fixed height. The nested DIV5 will be receiving content from Ajax, causing its height to change. Additionally, there are some DHTML elements inside it that also affect the height. DIV5 has a fixed min-height set. ...

Having trouble accessing HikVision Web SDK functions in Angular 17

First and foremost, this concerns the HikVision cameras specifically. Because the SDK is compiled to plain JavaScript (with jQuery included), I had to import the JS files in angular.json and use declare in the component TS file (in this instance, camera.c ...

"Troubleshooting problem with fetching JSON data for Highcharts

As a relative newcomer to web development, my usual focus is on server-side work. Currently, I'm diving into a fun little electronic project where a Netduino server handles JSON requests within my LAN. The JSON response format from the Netduino looks ...

There was an error with the response code of 500 on the development server for react-native

An issue has been encountered on the node.js window: error: bundling failed: Error: Unable to resolve module react-native-gesture-handler from node_modules\@react-navigation\native\src\Scrollables.js: react-native-gesture-handler could ...

Building a custom HTML and JavaScript player to showcase multiple videos on a webpage

UPDATE: The solution has been discovered, shared, and marked as the top answer below. In the process of creating my portfolio website using HTML, CSS, and JS, I encountered a challenge regarding the addition of multiple videos on various pages. While fol ...

What is the method to individually determine "true" or "false" using .map() in coding

I am faced with an array of data that needs to be manipulated individually, but it should still function as a cohesive unit. Can you assist me in achieving this? function OrganizeFollow() { const [followStatus, setFollowStatus] = useState([]); co ...

Tips for sending data scraped from a website using Express

I have created a web crawler using Axios and am attempting to upload a file through Express. I currently have 10 different crawlers running with corresponding HTML form methods in Express. However, when I click the button, it downloads a blank file first ...

Why does my POST request result in [object Object] being returned?

I am just starting to learn AngularJS and I am unsure if my POST request is functioning correctly. After making the request, I am receiving an [object Object] response. What does this error indicate? Could it be related to an issue with the form? //Acti ...

"Having trouble implementing sorting functionality on a click event in a React application with Material-UI table

Default behavior displays data in ascending order. Clicking on the table header should toggle between descending and ascending orders. Load Data in ascending order -> On click, change to descending order -> Again on click, change to ascending -> ...

Execute a simulated click function in JavaScript without causing the viewport to move

I have successfully implemented a sticky add to cart feature on my Shopify store. However, there seems to be an issue where clicking on the variations in the sticky area also triggers the same variations on the product page, making it difficult for users t ...

I'm looking for the location of Angular Materials' CSS directives. Where can I find them?

Currently, I am using components from https://material.angularjs.org/latest/ for a searcher project. One specific component I am working with is the md-datepicker, and I would like to implement some custom styles on it such as changing the background colo ...

Guide on integrating AJAX and coding in WordPress using PHP

I created a search box in PHP and it is functioning correctly. However, when I try to integrate it into WordPress, it does not work as expected. It seems like the AJAX functionality is not working properly within WordPress. I would like to add this search ...

Passing data as a parameter to a page in React using history push

My Ionic React application includes functionality where the history.replace method is used to redirect users from the settings page to the login screen upon clicking a logout button. I am looking for a way to include a loggedOut flag in the redirection pro ...

Is there an issue connecting .NET to MySQL using ODBC 5.3?

I am encountering an issue with my ASP.NET webform .NET 4.5 website that utilizes MySQL ODBC to communicate with the MySQL Database. Everything works fine with the 32-bit driver version 5.1.13, but when I upgrade to version 5.3.4, I receive the following e ...

Although responseText functions properly, responseXML remains constantly null

I've searched through all available answers here and still can't find a solution. I'm confident that I haven't overlooked anything obvious. My issue involves loading map markers based on latitude and longitude coordinates. The problem ...

Is it possible to apply a class without using ng-class?

Seeking a more efficient way to apply conditional classes to multiple elements on a validation form page, I am exploring options to assign one of five potential classes to each form input. While the traditional method involves manually specifying the class ...

The Gulp task abruptly terminates before the Stream has a chance to trigger the "end" event

const gulpJasmine = require('gulp-jasmine'); const gulpDebug = require('gulp-debug'); function runTest(platform, testType) { const timer = startTimer(); console.log('started!'); return gulp.src('./src/**/_test/**/ ...

When implementing helmetJS into my project, I noticed that Font Awesome was displaying white squares

Initially, I created an application that utilized this code in the HTML and incorporated classes with Font Awesome icons, which functioned effectively. <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css&q ...