From f2feb6fa6e9695969480dbd164e4423ab539fc71 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Fri, 16 Dec 2022 09:19:01 +0800 Subject: [PATCH 1/2] Handle pulling locale from open graph metadata This also fixes parsing language codes which are split by an underscore. --- packages/readabilityjs/Readability.js | 10 +- .../blog.jetbrains.com/expected-metadata.json | 12 + .../blog.jetbrains.com/expected.html | 182 +++ .../test-pages/blog.jetbrains.com/source.html | 1391 +++++++++++++++++ .../test-pages/blog.jetbrains.com/url.txt | 1 + 5 files changed, 1593 insertions(+), 3 deletions(-) create mode 100644 packages/readabilityjs/test/test-pages/blog.jetbrains.com/expected-metadata.json create mode 100644 packages/readabilityjs/test/test-pages/blog.jetbrains.com/expected.html create mode 100644 packages/readabilityjs/test/test-pages/blog.jetbrains.com/source.html create mode 100644 packages/readabilityjs/test/test-pages/blog.jetbrains.com/url.txt diff --git a/packages/readabilityjs/Readability.js b/packages/readabilityjs/Readability.js index 27a159863..437e878f5 100644 --- a/packages/readabilityjs/Readability.js +++ b/packages/readabilityjs/Readability.js @@ -1827,7 +1827,7 @@ Readability.prototype = { var metaElements = this._doc.getElementsByTagName("meta"); // property is a space-separated list of values - var propertyPattern = /\s*(dc|dcterm|og|twitter|article)\s*:\s*(author|creator|description|title|site_name|published_time|published|date|image)\s*/gi; + var propertyPattern = /\s*(dc|dcterm|og|twitter|article)\s*:\s*(locale|author|creator|description|title|site_name|published_time|published|date|image)\s*/gi; // name is a single value var namePattern = /^\s*(?:(dc|dcterm|og|twitter|weibo:(article|webpage))\s*[\.:]\s*)?(author|creator|description|title|site_name|date|image)\s*$/i; @@ -2920,8 +2920,12 @@ Readability.prototype = { return 'English'; } - let lang = new Intl.DisplayNames(['en'], {type: 'language'}); - return lang.of(code.split('-')[0]); + try { + let lang = new Intl.DisplayNames(['en'], {type: 'language'}); + return lang.of(code.split('_')[0]); + } catch { + return 'English' + } }, /** diff --git a/packages/readabilityjs/test/test-pages/blog.jetbrains.com/expected-metadata.json b/packages/readabilityjs/test/test-pages/blog.jetbrains.com/expected-metadata.json new file mode 100644 index 000000000..1bcb6b0dc --- /dev/null +++ b/packages/readabilityjs/test/test-pages/blog.jetbrains.com/expected-metadata.json @@ -0,0 +1,12 @@ +{ + "title": "The .NET Tools Blog", + "byline": null, + "dir": null, + "excerpt": "You’ve likely heard about Blazor, .NET’s frontend framework for writing web applications. Blazor lets you use your existing C# skills to build full-stack applications, from client to server. One way t", + "siteName": "The JetBrains Blog", + "siteIcon": "https://blog.jetbrains.com/wp-content/themes/jetbrains/assets/img/favicons/favicon.ico", + "previewImage": "https://blog.jetbrains.com/wp-content/uploads/2022/10/rd-how-tos-blog-social-share-image-1280x720-1.png", + "publishedDate": "2022-12-14T16:00:00.000Z", + "language": "English", + "readerable": true +} diff --git a/packages/readabilityjs/test/test-pages/blog.jetbrains.com/expected.html b/packages/readabilityjs/test/test-pages/blog.jetbrains.com/expected.html new file mode 100644 index 000000000..3ceeddf44 --- /dev/null +++ b/packages/readabilityjs/test/test-pages/blog.jetbrains.com/expected.html @@ -0,0 +1,182 @@ +
+
+
+
+

Dotnet logo

+
+
+

The Future of .NET with WASM

+
+

Khalid Abuhakmeh

+
+ +

You’ve likely heard about Blazor, .NET’s frontend framework for writing web applications. Blazor lets you use your existing C# skills to build full-stack applications, from client to server. One way to construct Blazor applications is to compile your frontend into a WebAssembly (WASM) file and deploy and run your app in a web browser. The Blazor WASM approach can help you build client experiences similar to native desktop applications with a native performance profile.

+

But what about WebAssembly on the server? In this post, we’ll see the benefits of using WASM outside the browser and its potential as a transformative technology on the server. 

+

+ What is WebAssembly? +

+

WebAssembly is a low-level assembly-like language with a binary format that runs in modern web browsers. As a result, WebAssembly programs can perform at near-native speeds allowing for new and exciting applications for web clients from desktop-like apps, emulators, high-performance video games, photo editors, and more. The additional benefit of WebAssembly is it can be run either as an extra add-on via service workers, enhancing or replacing the existing JavaScript experience on the client.

+

The designers of WebAssembly always meant it to run alongside the current web model. Developers unfamiliar with JavaScript can choose from a wide range of languages to write WebAssembly, including C, C++, C#, Go, Python and Rust, with many more languages looking at targeting WASM as an artifact of compilation. For .NET developers, you can think of the .wasm file extension as a .dll or .exe format. The file format is a standard, and WebAssembly System Interface (WASI) compliant runtime will be able to consume them.

+

One such runtime we’ll be exploring in this post is Wasmtime.

+

+ What is Wasmtime? +

+

Developed by the Bytecode Alliance, Wasmtime is a runtime for WebAssembly, allowing you to consume .wasm files and run them on Windows, macOS, or Linux systems outside a web client. Wasmtime is a fast, secure, and standards-compliant runtime for WebAssembly, and supports the WebAssembly System Interface (WASI).

+

The most crucial feature of Wasmtime is its ability to interact with the native operating system, allowing for configurable access to system resources. Resources include disk access, TCP listeners, hardware input interfaces, and more.

+

In addition to running standalone .wasm files, you can use Wasmtime inside your applications to consume third-party dependencies. The portability of the WASM format opens up a world where you can have native interop with a standard format across all languages.

+

Wasmtime also supports debugging using popular native debugging tools like GDB or LLDB, which many of the IntelliJ-family products already support. The debugging experience depends on your technology stack’s build tools.

+

Speaking of build tools, let’s build our first WASM server application, but first, let’s install Wasmtime.

+

+ Installing Wasmtime +

+

Wasmtime is a CLI executable, so it’s straightforward to install on any environment. The first step is to visit the official Bytecode Alliance website. You can also just run the following command.

+
curl https://wasmtime.dev/install.sh -sSf | bash
+

Windows users can do the same using the Windows Subsystem for Linux (WSL), or grab the installer from the Wasmtime releases page.

+

You can check you’ve successfully installed Wasmtime by running the command wasmtime –version from the command line.

+
> wasmtime --version
+wasmtime-cli 1.0.1
+

+ Compiling a WASM .NET application +

+

+ Note: You’ll need the latest version of .NET 7 SDK installed +

+

Our goal in this section is to take a C# Console application and compile it to a .wasm file. The solution will be a self-contained application that won’t need unique WASI resources like TCP listeners, file access, or environment variables. 

+

First, let’s start with a brand new Console Application project. From JetBrains Rider’s new solution window, select the “Console Application” template and call it “HelloWasm” or whatever you’d like. 

+
+ +
+

Once the solution is ready, you’ll need to add the “Wasi.Sdk” NuGet package to your console project. If you don’t see the package, be sure that you have the Prerelease checkbox checked.

+
+ +
Wasi.Sdk Nuget package in JetBrains Rider’s NuGet tool window
+
+

You’re ready to compile the console application into a .wasm artifact. Before doing so, change the line in Program.cs to the following:

+
Console.WriteLine("Hello, Wasmtime!");
+

Building your project, you will see references to bundling System libraries commonly used in .NET applications. Remember that WASM is native byte code. The .NET runtime must be packaged and shipped as part of your artifact. This is not any different than Blazor WASM deployments for a web client.

+
+ +
Building a Wasi.Sdk-powered .NET project inside of JetBrains Rider
+
+

Now, let’s run our WASM file using Wasmtime. In Rider, you’ll use the Run Anything dialog (Ctrl+Ctrl) to run the following command:

+
wasmtime ./HelloWasm/bin/Debug/net7.0/HelloWasm.wasm
+

When successful, you should see your Console application’s output.

+
+ +
Successful output in JetBrains Rider’s “Run Anything” tool window
+
+

Awesome! You just wrote your first WASM-targeted .NET application. Now you could deploy the .wasm file to any host that supports WebAssmebly.

+

+ Consuming WASM and WAT modules from .NET +

+

While it’s certainly possible to consume a .wasm file in .NET, it is a bit more tedious than the plug-and-play experience of a NuGet package. Currently, there is a Wasmruntime NuGet package that contains low-level APIs for dealing with the elements of a host. These elements include an Engine, Module, Linker, Store, and more. They allow you to define your custom host, including low-level system calls and what calling them may do on a WASI-compliant system. For more information, I recommend reading excellent Mozilla documentation to understand how WASM interfaces with a host.

+

I would not recommend most developers attempt to write their host; instead, the community should wait for the Byte Code Alliance to create a safe-by-default host.

+

Let’s look at an example where we use the WebAssembly Text (WAT) format to link a C# function to WebAssembly. WAT is a human-readable and editable format representing the WASM binary format.

+
using Wasmtime;
+
+using var engine = new Engine();
+
+using var module = Module.FromText(
+    engine,
+    "hello",
+    "(module (func $hello (import \"\" \"hello\")) (func (export \"run\") (call $hello)))"
+);
+
+using var linker = new Linker(engine);
+using var store = new Store(engine);
+
+linker.Define(
+    "",
+    "hello",
+    Function.FromCallback(store, () => Console.WriteLine("Hello from C#!"))
+);
+
+var instance = linker.Instantiate(store, module);
+var run = instance.GetAction("run")!;
+run();
+
+

The critical thing to note in this example is that our WebAssembly module uses a reference to $hello. Since our C# application manages our WebAssembly context, we can create a definition for $hello using the method Function.FromCallback. In C#, we ask the linker, which now contains both our .wat definition and our new implementation of $hello for the run method. All that’s left is to invoke our Action and see the results.

+
Hello from C#!
+

While it may seem trivial, we’ll be able to run and consume WASM in our .NET applications. That opens up possibilities for solving problems using solutions from other ecosystems.

+

+ The current reality of WASM on the server +

+

While this post has been relatively optimistic about the prospect of WASM, there are limitations to the technology that folks should be aware of, and they will vary based on the WASM host.

+

The first significant limitation is threading. So far, with my testing, Wasmtime only has access to a single thread for execution. Thread limits are not entirely a deal-breaker, but you’ll need to rewrite some of your solutions to reduce the need for threading. This limitation becomes apparent when using an API that involves Thread or Task.Delay, which will halt your running process or terminate it catastrophically. However, threading may not be an issue in the near future as .NET adds multi-threaded support to WASM. Wasmtime also enables multiple threads with an experimental flag, but your technology stack will need to take advantage of that feature.

+

The .NET runtime targeting WASM is the same as Blazor WASM, which is to say it has limits. APIs will not work based on a lack of support from the current WASM host. Missing APIs could limit your ability to solve specific problems. The APIs are still in active development and could change based on features added to Wasmtime and other WASI runtimes.

+

Another issue I’ve found is there is currently no outward socket support. Lack of socket support limits a WASM application’s ability to communicate with dependencies like a database or web service. Discussions of a Socket specification will resolve this issue, allowing for more robust WASM apps. In addition, this should enable .NET developers to use data access tools like Entity Framework Core or Dapper with few issues.

+

Tooling is another concern; vendors must catch up to the experiences .NET developers have gotten used to developing .NET applications. Luckily for developers, Wasmruntime uses standard debugging tools like LLDB and GDB, making integrating them into existing tools much more manageable.

+

Infrastructure will play an essential role in how you build your WASM solutions. The strength of WASM comes from the ability to start and dispose of executing modules quickly in the vein of “microservices” or “functions”. However, a different architectural approach will require you to rethink your existing applications’ orchestration and units of work. In addition, you and your team may not have the bandwidth to deal with the technical and conceptual challenges simultaneously. 

+

How does a modern WASM-powered application look when deployed? Some folks think it looks like functions as a service (FaaS), while others see it as a replacement for containers in a Kubernetes cluster, and both are perfectly valid. Luckily, many new WASM hosts are springing up along with reliable cloud providers AWS, Microsoft Azure, and Cloudflare, adding options to their ever-expanding list of services.

+

+ Imagining the future of WASM on the server  +

+

We’ve reached the speculative part of the post, where we get to imagine the future of WASM and how it may transform your development experience, from writing code to deploying a solution. So let’s start with the process of development.

+

If you’ve developed any Blazor WASM application, you’ll likely realize that little feels different while writing code. After all, it’s C#! The debugging experience may be slightly different, as you now deal with a completely different host and runtime, specifically the web browser. However, writing solutions to target WASM will feel very similar to Blazor WASM, and I expect the experience to improve as tooling catches up. Switching to WASM apps will be easier for most developers than switching to a new programming paradigm.

+

The frameworks targeting WASM will likely change, as you will want to reconsider how and when functions are executing. For example, Fermyon released a .NET Spin SDK specifically for their hosting platform that targets WASM. Let’s look at how you might write a function given their SDK.

+
using System.Net;
+using Fermyon.Spin.Sdk;
+
+namespace Microservice;
+
+public static class Handler
+{
+    [HttpHandler]
+    public static HttpResponse HandleHttpRequest(HttpRequest request)
+    {
+        return new HttpResponse
+        {
+            StatusCode = HttpStatusCode.OK,
+            BodyAsString = "Hello from .NET",
+        };
+    }
+}
+
+

This example begs questions. For example, how do you transition from ASP.NET Core Minimal Endpoints or ASP.NET Core MVC to this new approach? Does ASP.NET Core need to rethink how to compile existing applications into deployable units? I expect a lot of conversations and strategies to emerge as developers adopt WASM.

+

We could see WASM replace most instances of containerization, especially when WASM can package both runtimes and the applications that depend on them in one portable package. Advantages you could hope to see: Reduced CPU and memory usage, decreased cold-boot times, reduced hosting bills, and more significant economies of scale.

+

These .wasm files can also be considerably smaller as they don’t have the same need for layers found in images built on entire operating systems. The portability and efficiency of WASM hosts will lead to more hosting options from vendors, new and old.

+

Finally, the most exciting prospect of WASM on the server is the fulfillment of an agnostic cloud environment, where you, as the developer, no longer have to worry about regions. WASM can be deployed simultaneously to many global regions beyond cloud vendors’ limited and congested regions. WASM can start closest to your users and provide them with the fastest experience possible regardless of their country of origin. This democratization of user experience is most exciting for folks delivering global-scale applications.

+

+ Conclusion +

+

In this post, we delved into WebAssembly and the efforts to run it on the server using Wasmtime. While it’s still relatively new, the promise of WASM on the server is exciting, and .NET is at the forefront of giving developers more hosting options. As tooling and development experience improves, so will the solutions developers deliver to customers. As you’ve seen, the experience even now is good.

+

There are limitations with WASM, but like all technologies, the community will push solutions forward, and progress will occur. It’s still important to be careful when choosing cutting-edge technologies as solutions, as you’ll likely be some of the first and only folks experiencing those issues. 

+

That said, I’m cautiously optimistic about the future of WASM, and I hope you found something in this article that has sparked your curiosity to explore the topic further.

+
+
+

+

Discover more

+

+
+
+
+
\ No newline at end of file diff --git a/packages/readabilityjs/test/test-pages/blog.jetbrains.com/source.html b/packages/readabilityjs/test/test-pages/blog.jetbrains.com/source.html new file mode 100644 index 000000000..d3cfd85dc --- /dev/null +++ b/packages/readabilityjs/test/test-pages/blog.jetbrains.com/source.html @@ -0,0 +1,1391 @@ + + + + + The Future of .NET with WASM | The .NET Tools Blog + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + +
+
+ .NET Tools How-To's +

+ The Future of .NET with WASM +

+ + +

+ You’ve likely heard about Blazor, .NET’s frontend framework for writing web applications. Blazor lets you use your existing C# skills to build full-stack applications, from client to server. One way to construct Blazor applications is to compile your frontend into a WebAssembly (WASM) file and deploy and run your app in a web browser. The Blazor WASM approach can help you build client experiences similar to native desktop applications with a native performance profile. +

+

+ But what about WebAssembly on the server? In this post, we’ll see the benefits of using WASM outside the browser and its potential as a transformative technology on the server.  +

+

+ What is WebAssembly? +

+

+ WebAssembly is a low-level assembly-like language with a binary format that runs in modern web browsers. As a result, WebAssembly programs can perform at near-native speeds allowing for new and exciting applications for web clients from desktop-like apps, emulators, high-performance video games, photo editors, and more. The additional benefit of WebAssembly is it can be run either as an extra add-on via service workers, enhancing or replacing the existing JavaScript experience on the client. +

+

+ The designers of WebAssembly always meant it to run alongside the current web model. Developers unfamiliar with JavaScript can choose from a wide range of languages to write WebAssembly, including C, C++, C#, Go, Python and Rust, with many more languages looking at targeting WASM as an artifact of compilation. For .NET developers, you can think of the .wasm file extension as a .dll or .exe format. The file format is a standard, and WebAssembly System Interface (WASI) compliant runtime will be able to consume them. +

+

+ One such runtime we’ll be exploring in this post is Wasmtime. +

+

+ What is Wasmtime? +

+

+ Developed by the Bytecode Alliance, Wasmtime is a runtime for WebAssembly, allowing you to consume .wasm files and run them on Windows, macOS, or Linux systems outside a web client. Wasmtime is a fast, secure, and standards-compliant runtime for WebAssembly, and supports the WebAssembly System Interface (WASI). +

+

+ The most crucial feature of Wasmtime is its ability to interact with the native operating system, allowing for configurable access to system resources. Resources include disk access, TCP listeners, hardware input interfaces, and more. +

+

+ In addition to running standalone .wasm files, you can use Wasmtime inside your applications to consume third-party dependencies. The portability of the WASM format opens up a world where you can have native interop with a standard format across all languages. +

+

+ Wasmtime also supports debugging using popular native debugging tools like GDB or LLDB, which many of the IntelliJ-family products already support. The debugging experience depends on your technology stack’s build tools. +

+

+ Speaking of build tools, let’s build our first WASM server application, but first, let’s install Wasmtime. +

+

+ Installing Wasmtime +

+

+ Wasmtime is a CLI executable, so it’s straightforward to install on any environment. The first step is to visit the official Bytecode Alliance website. You can also just run the following command. +

+
+
+ +
+
+
+
+ curl https://wasmtime.dev/install.sh -sSf | bash +
+
+
+
+ curl https://wasmtime.dev/install.sh -sSf | bash +
+
+
+
curl https://wasmtime.dev/install.sh -sSf | bash
+

+ Windows users can do the same using the Windows Subsystem for Linux (WSL), or grab the installer from the Wasmtime releases page. +

+

+ You can check you’ve successfully installed Wasmtime by running the command wasmtime –version from the command line. +

+
+
+ +
+
+
+
+ > wasmtime --version +
+
+
+
+ wasmtime-cli 1.0.1 +
+
+
+
+ > wasmtime --version wasmtime-cli 1.0.1 +
+
+
+
> wasmtime --version
+wasmtime-cli 1.0.1
+

+ Compiling a WASM .NET application +

+

+ Note: You’ll need the latest version of .NET 7 SDK installed +

+

+ Our goal in this section is to take a C# Console application and compile it to a .wasm file. The solution will be a self-contained application that won’t need unique WASI resources like TCP listeners, file access, or environment variables.  +

+

+ First, let’s start with a brand new Console Application project. From JetBrains Rider’s new solution window, select the “Console Application” template and call it “HelloWasm” or whatever you’d like.  +

+
+ +
+

+ Once the solution is ready, you’ll need to add the “Wasi.Sdk” NuGet package to your console project. If you don’t see the package, be sure that you have the Prerelease checkbox checked. +

+
+ +
+ Wasi.Sdk Nuget package in JetBrains Rider’s NuGet tool window +
+
+

+ You’re ready to compile the console application into a .wasm artifact. Before doing so, change the line in Program.cs to the following: +

+
+
+ +
+
+
+
+ Console.WriteLine("Hello, Wasmtime!"); +
+
+
+
+ Console.WriteLine("Hello, Wasmtime!"); +
+
+
+
Console.WriteLine("Hello, Wasmtime!");
+

+ Building your project, you will see references to bundling System libraries commonly used in .NET applications. Remember that WASM is native byte code. The .NET runtime must be packaged and shipped as part of your artifact. This is not any different than Blazor WASM deployments for a web client. +

+
+ +
+ Building a Wasi.Sdk-powered .NET project inside of JetBrains Rider +
+
+

+ Now, let’s run our WASM file using Wasmtime. In Rider, you’ll use the Run Anything dialog (Ctrl+Ctrl) to run the following command: +

+
+
+ +
+
+
+
+ wasmtime ./HelloWasm/bin/Debug/net7.0/HelloWasm.wasm +
+
+
+
+ wasmtime ./HelloWasm/bin/Debug/net7.0/HelloWasm.wasm +
+
+
+
wasmtime ./HelloWasm/bin/Debug/net7.0/HelloWasm.wasm
+

+ When successful, you should see your Console application’s output. +

+
+ +
+ Successful output in JetBrains Rider’s “Run Anything” tool window +
+
+

+ Awesome! You just wrote your first WASM-targeted .NET application. Now you could deploy the .wasm file to any host that supports WebAssmebly. +

+

+ Consuming WASM and WAT modules from .NET +

+

+ While it’s certainly possible to consume a .wasm file in .NET, it is a bit more tedious than the plug-and-play experience of a NuGet package. Currently, there is a Wasmruntime NuGet package that contains low-level APIs for dealing with the elements of a host. These elements include an Engine, Module, Linker, Store, and more. They allow you to define your custom host, including low-level system calls and what calling them may do on a WASI-compliant system. For more information, I recommend reading excellent Mozilla documentation to understand how WASM interfaces with a host. +

+

+ I would not recommend most developers attempt to write their host; instead, the community should wait for the Byte Code Alliance to create a safe-by-default host. +

+

+ Let’s look at an example where we use the WebAssembly Text (WAT) format to link a C# function to WebAssembly. WAT is a human-readable and editable format representing the WASM binary format. +

+
+
+ +
+
+
+
+ using Wasmtime; +
+
+
+
+
+ using var engine = new Engine(); +
+
+
+
+
+ using var module = Module.FromText( +
+
+
+
+ engine, +
+
+
+
+ "hello", +
+
+
+
+ "(module (func $hello (import \"\" \"hello\")) (func (export \"run\") (call $hello)))" +
+
+
+
+ ); +
+
+
+
+
+ using var linker = new Linker(engine); +
+
+
+
+ using var store = new Store(engine); +
+
+
+
+
+ linker.Define( +
+
+
+
+ "", +
+
+
+
+ "hello", +
+
+
+
+ Function.FromCallback(store, () => Console.WriteLine("Hello from C#!")) +
+
+
+
+ ); +
+
+
+
+
+ var instance = linker.Instantiate(store, module); +
+
+
+
+ var run = instance.GetAction("run")!; +
+
+
+
+ run(); +
+
+
+
+ using Wasmtime; using var engine = new Engine(); using var module = Module.FromText( engine, "hello", "(module (func $hello (import \"\" \"hello\")) (func (export \"run\") (call $hello)))" ); using var linker = new Linker(engine); using var store = new Store(engine); linker.Define( "", "hello", Function.FromCallback(store, () => Console.WriteLine("Hello from C#!")) ); var instance = linker.Instantiate(store, module); var run = instance.GetAction("run")!; run(); +
+
+
+
using Wasmtime;
+
+using var engine = new Engine();
+
+using var module = Module.FromText(
+    engine,
+    "hello",
+    "(module (func $hello (import \"\" \"hello\")) (func (export \"run\") (call $hello)))"
+);
+
+using var linker = new Linker(engine);
+using var store = new Store(engine);
+
+linker.Define(
+    "",
+    "hello",
+    Function.FromCallback(store, () => Console.WriteLine("Hello from C#!"))
+);
+
+var instance = linker.Instantiate(store, module);
+var run = instance.GetAction("run")!;
+run();
+
+

+ The critical thing to note in this example is that our WebAssembly module uses a reference to $hello. Since our C# application manages our WebAssembly context, we can create a definition for $hello using the method Function.FromCallback. In C#, we ask the linker, which now contains both our .wat definition and our new implementation of $hello for the run method. All that’s left is to invoke our Action and see the results. +

+
+
+ +
+
+
+
+ Hello from C#! +
+
+
+
+ Hello from C#! +
+
+
+
Hello from C#!
+

+ While it may seem trivial, we’ll be able to run and consume WASM in our .NET applications. That opens up possibilities for solving problems using solutions from other ecosystems. +

+

+ The current reality of WASM on the server +

+

+ While this post has been relatively optimistic about the prospect of WASM, there are limitations to the technology that folks should be aware of, and they will vary based on the WASM host. +

+

+ The first significant limitation is threading. So far, with my testing, Wasmtime only has access to a single thread for execution. Thread limits are not entirely a deal-breaker, but you’ll need to rewrite some of your solutions to reduce the need for threading. This limitation becomes apparent when using an API that involves Thread or Task.Delay, which will halt your running process or terminate it catastrophically. However, threading may not be an issue in the near future as .NET adds multi-threaded support to WASM. Wasmtime also enables multiple threads with an experimental flag, but your technology stack will need to take advantage of that feature. +

+

+ The .NET runtime targeting WASM is the same as Blazor WASM, which is to say it has limits. APIs will not work based on a lack of support from the current WASM host. Missing APIs could limit your ability to solve specific problems. The APIs are still in active development and could change based on features added to Wasmtime and other WASI runtimes. +

+

+ Another issue I’ve found is there is currently no outward socket support. Lack of socket support limits a WASM application’s ability to communicate with dependencies like a database or web service. Discussions of a Socket specification will resolve this issue, allowing for more robust WASM apps. In addition, this should enable .NET developers to use data access tools like Entity Framework Core or Dapper with few issues. +

+

+ Tooling is another concern; vendors must catch up to the experiences .NET developers have gotten used to developing .NET applications. Luckily for developers, Wasmruntime uses standard debugging tools like LLDB and GDB, making integrating them into existing tools much more manageable. +

+

+ Infrastructure will play an essential role in how you build your WASM solutions. The strength of WASM comes from the ability to start and dispose of executing modules quickly in the vein of “microservices” or “functions”. However, a different architectural approach will require you to rethink your existing applications’ orchestration and units of work. In addition, you and your team may not have the bandwidth to deal with the technical and conceptual challenges simultaneously.  +

+

+ How does a modern WASM-powered application look when deployed? Some folks think it looks like functions as a service (FaaS), while others see it as a replacement for containers in a Kubernetes cluster, and both are perfectly valid. Luckily, many new WASM hosts are springing up along with reliable cloud providers AWS, Microsoft Azure, and Cloudflare, adding options to their ever-expanding list of services. +

+

+ Imagining the future of WASM on the server  +

+

+ We’ve reached the speculative part of the post, where we get to imagine the future of WASM and how it may transform your development experience, from writing code to deploying a solution. So let’s start with the process of development. +

+

+ If you’ve developed any Blazor WASM application, you’ll likely realize that little feels different while writing code. After all, it’s C#! The debugging experience may be slightly different, as you now deal with a completely different host and runtime, specifically the web browser. However, writing solutions to target WASM will feel very similar to Blazor WASM, and I expect the experience to improve as tooling catches up. Switching to WASM apps will be easier for most developers than switching to a new programming paradigm. +

+

+ The frameworks targeting WASM will likely change, as you will want to reconsider how and when functions are executing. For example, Fermyon released a .NET Spin SDK specifically for their hosting platform that targets WASM. Let’s look at how you might write a function given their SDK. +

+
+
+ +
+
+
+
+ using System.Net; +
+
+
+
+ using Fermyon.Spin.Sdk; +
+
+
+
+
+ namespace Microservice; +
+
+
+
+
+ public static class Handler +
+
+
+
+ { +
+
+
+
+ [HttpHandler] +
+
+
+
+ public static HttpResponse HandleHttpRequest(HttpRequest request) +
+
+
+
+ { +
+
+
+
+ return new HttpResponse +
+
+
+
+ { +
+
+
+
+ StatusCode = HttpStatusCode.OK, +
+
+
+
+ BodyAsString = "Hello from .NET", +
+
+
+
+ }; +
+
+
+
+ } +
+
+
+
+ } +
+
+
+
+ using System.Net; using Fermyon.Spin.Sdk; namespace Microservice; public static class Handler { [HttpHandler] public static HttpResponse HandleHttpRequest(HttpRequest request) { return new HttpResponse { StatusCode = HttpStatusCode.OK, BodyAsString = "Hello from .NET", }; } } +
+
+
+
using System.Net;
+using Fermyon.Spin.Sdk;
+
+namespace Microservice;
+
+public static class Handler
+{
+    [HttpHandler]
+    public static HttpResponse HandleHttpRequest(HttpRequest request)
+    {
+        return new HttpResponse
+        {
+            StatusCode = HttpStatusCode.OK,
+            BodyAsString = "Hello from .NET",
+        };
+    }
+}
+
+

+ This example begs questions. For example, how do you transition from ASP.NET Core Minimal Endpoints or ASP.NET Core MVC to this new approach? Does ASP.NET Core need to rethink how to compile existing applications into deployable units? I expect a lot of conversations and strategies to emerge as developers adopt WASM. +

+

+ We could see WASM replace most instances of containerization, especially when WASM can package both runtimes and the applications that depend on them in one portable package. Advantages you could hope to see: Reduced CPU and memory usage, decreased cold-boot times, reduced hosting bills, and more significant economies of scale. +

+

+ These .wasm files can also be considerably smaller as they don’t have the same need for layers found in images built on entire operating systems. The portability and efficiency of WASM hosts will lead to more hosting options from vendors, new and old. +

+

+ Finally, the most exciting prospect of WASM on the server is the fulfillment of an agnostic cloud environment, where you, as the developer, no longer have to worry about regions. WASM can be deployed simultaneously to many global regions beyond cloud vendors’ limited and congested regions. WASM can start closest to your users and provide them with the fastest experience possible regardless of their country of origin. This democratization of user experience is most exciting for folks delivering global-scale applications. +

+

+ Conclusion +

+

+ In this post, we delved into WebAssembly and the efforts to run it on the server using Wasmtime. While it’s still relatively new, the promise of WASM on the server is exciting, and .NET is at the forefront of giving developers more hosting options. As tooling and development experience improves, so will the solutions developers deliver to customers. As you’ve seen, the experience even now is good. +

+

+ There are limitations with WASM, but like all technologies, the community will push solutions forward, and progress will occur. It’s still important to be careful when choosing cutting-edge technologies as solutions, as you’ll likely be some of the first and only folks experiencing those issues.  +

+

+ That said, I’m cautiously optimistic about the future of WASM, and I hope you found something in this article that has sparked your curiosity to explore the topic further. +

+
+ + +
+ +
+
+
+
+ +
+
+
+
+
+
+
+

+ Discover more +

+
+
+ + + + +
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/readabilityjs/test/test-pages/blog.jetbrains.com/url.txt b/packages/readabilityjs/test/test-pages/blog.jetbrains.com/url.txt new file mode 100644 index 000000000..dc0f2fbe5 --- /dev/null +++ b/packages/readabilityjs/test/test-pages/blog.jetbrains.com/url.txt @@ -0,0 +1 @@ +https://blog.jetbrains.com/dotnet/2022/12/15/the-future-of-net-with-wasm/?utm_campaign=rider&utm_content=blazor-wasm-future&utm_medium=referral&utm_source=twitter \ No newline at end of file From 3277b1d2290627d51a565b42dfe8671d2c803238 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Fri, 16 Dec 2022 09:24:36 +0800 Subject: [PATCH 2/2] Add another testcase for locale parsing --- .../expected-metadata.json | 12 + .../community.musictribe.com/expected.html | 35 + .../community.musictribe.com/source.html | 4972 +++++++++++++++++ .../community.musictribe.com/url.txt | 1 + 4 files changed, 5020 insertions(+) create mode 100644 packages/readabilityjs/test/test-pages/community.musictribe.com/expected-metadata.json create mode 100644 packages/readabilityjs/test/test-pages/community.musictribe.com/expected.html create mode 100644 packages/readabilityjs/test/test-pages/community.musictribe.com/source.html create mode 100644 packages/readabilityjs/test/test-pages/community.musictribe.com/url.txt diff --git a/packages/readabilityjs/test/test-pages/community.musictribe.com/expected-metadata.json b/packages/readabilityjs/test/test-pages/community.musictribe.com/expected-metadata.json new file mode 100644 index 000000000..f673d577b --- /dev/null +++ b/packages/readabilityjs/test/test-pages/community.musictribe.com/expected-metadata.json @@ -0,0 +1,12 @@ +{ + "title": "Controlling an XR12 via MIDI using an XTouch Mini", + "byline": null, + "dir": null, + "excerpt": "This page displays a discussion entry.", + "siteName": null, + "siteIcon": "http://fakehost/test/public/core_file/ec/5d/02/f6baf292a4e76c51e82e87d5cb98ad61.ico?c=5097", + "previewImage": "https://community.musictribe.com/", + "publishedDate": null, + "language": "English", + "readerable": true +} diff --git a/packages/readabilityjs/test/test-pages/community.musictribe.com/expected.html b/packages/readabilityjs/test/test-pages/community.musictribe.com/expected.html new file mode 100644 index 000000000..8d0a9b7b8 --- /dev/null +++ b/packages/readabilityjs/test/test-pages/community.musictribe.com/expected.html @@ -0,0 +1,35 @@ +
+
+
+
+
+

I have a regular small sound job that I handle with an XR12 controlled from a 10" Android tablet running Mixing Station X Air Pro. The only challenge with this job is that I get very little time for get-in and get-out so any problems in setting up could be disastrous. I carry a spare 7" tablet, backup access point and an OTG adaptor for wired Ethernet but I don't have much time for trouble-shooting.

+

I have long thought it would be good to have basic control via MIDI in case I lost my normal user interface but I did not want a large and/or expensive controller. I did want the controller to have feedback for mute states and fader levels. I have achieved this using the XTouch Mini.

+

The XTouch Mini, in common with most small and reasonably priced controllers, is a USB MIDI device and the XR12 requires DIN MIDI. This can be resolved, though, with a USB/DIN MIDI converter. The Kenton MIDI USB Host would work but is rather expensive. The HobbyTronics MIDI USB-DIN Converter is much lower cost but looks a little fragile (*) so would need to be repackaged for life on the road. I took the low-cost route by using HobbyTronics USB Host Mini (preloaded with MIDI firmware) plus a HobbyTronics MIDI Breakout. These two boards are mounted in a small box along with a connector for 5Vdc power. The converter and controller only draw about 100mA so I can run it for over twelve hours from a 2000mAh phone powerbank if there is no convenient power outlet or spare USB-A port.

+

Using the XTouch Editor, I have programmed eight encoders and eight buttons to control the faders and mutes for the critical channels and buses using the published MIDI messages. The encoder LED rings and mute LEDs follow the XR state when controlled by both the MIDI board and the normal network UI. When first turned on, though, the XTouch does not reflect the state of the XR. The quick solution to this is to load an XR snapshot which gives instant synchronization so I programmed one of the spare XTouch buttons to load my default snapshot. As another handy shortcut, I use the encoder press functions to set default fader levels for their respective channels/buses. This is another way to get the faders synchronized without loading a snapshot.

+

So I have achieved what I set out to do: I can take control of the basic mute and fader functions of the XR if my tablet and/or network fail. I hope that I don't need this capability but it's in the mixer's gig-bag just in case.

+

(*) HobbyTronics have improved this product. It should not now need repackaging. See HobbyTronics USB/Midi Converter.XTouch Mini.jpgInside.jpgConverter.jpg

+
+
+
+

+

+
+
+

+

+
+
+

+

Original text

+

+
+

Contribute a better translation +

+
+
+
+

We use cookies on this site to enhance your user experience.
By clicking any link on this page you are giving your consent for us to set cookies. Learn more
+

+
+
\ No newline at end of file diff --git a/packages/readabilityjs/test/test-pages/community.musictribe.com/source.html b/packages/readabilityjs/test/test-pages/community.musictribe.com/source.html new file mode 100644 index 000000000..8f232cd3e --- /dev/null +++ b/packages/readabilityjs/test/test-pages/community.musictribe.com/source.html @@ -0,0 +1,4972 @@ + + + + + + Discussion View - Music Tribe Community + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+ +
+
+
+

+ Discover +

+ +
+
+
+
+
+
+

+ Controlling an XR12 via MIDI using an XTouch Mini +

+
+
+

+ by RexBeckett +

+
+
+ 2017-02-25 +
+ +
+
+
+ I have a regular small sound job that I handle with an XR12 controlled from a 10" Android tablet running Mixing Station X Air Pro. The only challenge with this job is that I get very little time for get-in and get-out so any problems in setting up could be disastrous. I carry a spare 7" tablet, backup access point and an OTG adaptor for wired Ethernet but I don't have much time for trouble-shooting.
+
+
+
+ I have long thought it would be good to have basic control via MIDI in case I lost my normal user interface but I did not want a large and/or expensive controller. I did want the controller to have feedback for mute states and fader levels. I have achieved this using the XTouch Mini.
+
+
+
+ The XTouch Mini, in common with most small and reasonably priced controllers, is a USB MIDI device and the XR12 requires DIN MIDI. This can be resolved, though, with a USB/DIN MIDI converter. The Kenton MIDI USB Host would work but is rather expensive. The HobbyTronics MIDI USB-DIN Converter is much lower cost but looks a little fragile (*) so would need to be repackaged for life on the road. I took the low-cost route by using HobbyTronics USB Host Mini (preloaded with MIDI firmware) plus a HobbyTronics MIDI Breakout. These two boards are mounted in a small box along with a connector for 5Vdc power. The converter and controller only draw about 100mA so I can run it for over twelve hours from a 2000mAh phone powerbank if there is no convenient power outlet or spare USB-A port.
+
+
+
+ Using the XTouch Editor, I have programmed eight encoders and eight buttons to control the faders and mutes for the critical channels and buses using the published MIDI messages. The encoder LED rings and mute LEDs follow the XR state when controlled by both the MIDI board and the normal network UI. When first turned on, though, the XTouch does not reflect the state of the XR. The quick solution to this is to load an XR snapshot which gives instant synchronization so I programmed one of the spare XTouch buttons to load my default snapshot. As another handy shortcut, I use the encoder press functions to set default fader levels for their respective channels/buses. This is another way to get the faders synchronized without loading a snapshot.
+
+
+
+ So I have achieved what I set out to do: I can take control of the basic mute and fader functions of the XR if my tablet and/or network fail. I hope that I don't need this capability but it's in the mixer's gig-bag just in case.
+
+
+
+ (*) HobbyTronics have improved this product. It should not now need repackaging. See HobbyTronics USB/Midi Converter.XTouch Mini.jpgInside.jpgConverter.jpg +
+
+
+
+ +
+ + +
+
+ + + + +
+
+ +
    + +

    + 38 Replies +

    +
  • + +
    + TsolisKostantin +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    TsolisKostantin +

    + Sorry for the double post, for some reason though I ctrl-F5 the page got stuck to my original post! +

    +
      +
    • · +
    • +
    • + November 18 2019 +
    • +
    +
    +
    +
      +
      + +
      +
    • +
    • + +
      + RexBeckett +
      +
      +
      +
      + +
      +
      +
      + +
      +
      +
      +
      RexBeckett +

      + @TsolisKostantin  +

      +

      + I did reply to you post. A simple USB/Midi cable will not do what you want. Do you need some additional information? +

      +
        +
      • · +
      • +
      • + November 18 2019 +
      • +
      +
      +
      +
        +
        + +
        +
      • +
      • + +
        + TsolisKostantin +
        +
        +
        +
        + +
        +
        +
        + +
        +
        +
        +
        TsolisKostantin +

        + For some reason my page was "stuck" to my original post!  +

        +

        + Will these host do the job for sure? +

        +

        + Yours, +

        +
          +
        • · +
        • +
        • + November 18 2019 +
        • +
        +
        +
        +
          +
          + +
          +
        • +
        • + +
          + Jille +
          +
          +
          +
          + +
          +
          +
          + +
          +
          +
          +
          Jille +

          + I have programmed an x-touch mini to control an XR18. Everything works well, but I cannot programm the 'snapshot' function you mentioned in your article. I triewd several possible solutions, but none of them works. Can you send me a screenshot of the x-touch editor within the right solution to programm getting the snapshot at first startup of the x-touch mini. +

          +

          + It would help me a lot. It's just the last piece of the puzzle. +

          +
            +
          • · +
          • +
          • + February 15 2020 +
          • +
          +
          +
          +
            +
            + +
            +
          • +
          • + +
            + RexBeckett +
            +
            +
            +
            + +
            +
            +
            + +
            +
            +
            +
            RexBeckett +
            + +
            + @Jille wrote:
            +

            + I have programmed an x-touch mini to control an XR18. Everything works well, but I cannot programm the 'snapshot' function you mentioned in your article. I triewd several possible solutions, but none of them works. Can you send me a screenshot of the x-touch editor within the right solution to programm getting the snapshot at first startup of the x-touch mini. +

            +

            + It would help me a lot. It's just the last piece of the puzzle. +

            +
            +
            +

            + @Jille  +

            +

            + In the screenshot, button 9 is set to load snapshot 1 which will also synchronize the X-Touch Mini. In current Air firmware you can also synchronize the X-Touch Mini by requesting a Midi Dump. This is done by sending value 127 to controller 127 on Midi channel 1. Button 10 in the screenshot is set to do this. The advantage is that it doesn't change any mixer settings. +

            +

            + X-Touch EditorX-Touch Editor +

            +
              +
            • · +
            • +
            • + February 15 2020 +
            • +
            +
            +
            +
              +
              + +
              +
            • +
            • + +
              + Jille +
              +
              +
              +
              + +
              +
              +
              + +
              +
              +
              +
              Jille +

              + Okay, still not working just like I want. +

              +

              + First... for snapshot 1 the min value should be 0. But that's not my problem. +

              +

              + With this programming I really can load a snapshot. That's working well. +

              +

              + But my x-touch mini stil does not synchronise. So when I turn a button, the fader will always fall back to 0. +

              +

              + I updated already the firmware of the XR18, but no result. +

              +

              + And also the midi-dump does not work. +

              +

              + I don't know anymore, but struggeling on. +

              +
                +
              • · +
              • +
              • + February 16 2020 +
              • +
              +
              +
              +
                +
                + +
                +
              • +
              • + +
                + RexBeckett +
                +
                +
                +
                + +
                +
                +
                + +
                +
                +
                +
                RexBeckett +
                + +
                + @Jille wrote:
                +

                + Okay, still not working just like I want. +

                +

                + First... for snapshot 1 the min value should be 0. But that's not my problem. +

                +

                + With this programming I really can load a snapshot. That's working well. +

                +

                + But my x-touch mini stil does not synchronise. So when I turn a button, the fader will always fall back to 0. +

                +

                + I updated already the firmware of the XR18, but no result. +

                +

                + And also the midi-dump does not work. +

                +

                + I don't know anymore, but struggeling on. +

                +
                +
                +

                + @Jille  +

                +

                + Make sure that you have changed the GLOBAL CH to Off or > 3. Otherwise the control modes can be scrambled by Midi messages from the XR18. +

                +

                +   +

                +

                + What are you using to convert between the X-Touch USB and the XR18 DIN Midi?  +

                +

                + Have you enabled Midi transmission on the XR18? +

                +

                + Setup, Audio/MidiSetup, Audio/Midi +

                +
                  +
                • · +
                • +
                • + February 16 2020 +
                • +
                +
                +
                +
                  +
                  + +
                  +
                • +
                • + +
                  + Jille +
                  +
                  +
                  +
                  + +
                  +
                  +
                  + +
                  +
                  +
                  +
                  Jille +

                  + I switched the DIN X-OSC off, but no change. +

                  +

                  + I programmed also snapshot 2 under a free button.  +

                  +

                  + Now I can switch between 2 snapshots, but still no synchronising for the X-touch mini. +

                  +

                  + So after activating a snapshot and then use an encoder for changing the fader the fader jumps to the bottom. +

                  +

                  + But that's also the problem when I use the fader on my laptop. The button will not synchronise. So after changing a volume on the laptop and the changing the volume with the encoder on the mini the volume will jump to an earlyer use volume of the mini. The mini is not synchronising. +

                  +
                    +
                  • · +
                  • +
                  • + February 16 2020 +
                  • +
                  +
                  +
                  +
                    +
                    + +
                    +
                  • +
                  • + +
                    + RexBeckett +
                    +
                    +
                    +
                    + +
                    +
                    +
                    + +
                    +
                    +
                    +
                    RexBeckett +
                    + +
                    + @Jille wrote:
                    +

                    + I switched the DIN X-OSC off, but no change. +

                    +

                    + I programmed also snapshot 2 under a free button.  +

                    +

                    + Now I can switch between 2 snapshots, but still no synchronising for the X-touch mini. +

                    +

                    + So after activating a snapshot and then use an encoder for changing the fader the fader jumps to the bottom. +

                    +

                    + But that's also the problem when I use the fader on my laptop. The button will not synchronise. So after changing a volume on the laptop and the changing the volume with the encoder on the mini the volume will jump to an earlyer use volume of the mini. The mini is not synchronising. +

                    +
                    +
                    +

                    + @Jille  +

                    +

                    + You do have both Midi In and Out connections (two cables) from the XR18 to the Kenton converter do you? If so it seems that there must be a problem with the X-Touch Mini, the Kenton converter, the Midi cable or the XR18 Midi output. I usually debug Midi problems using a USB Midi adapter like this and MIDI-OX to check the each part of the system can transmit and receive. +

                    +
                      +
                    • · +
                    • +
                    • + February 16 2020 +
                    • +
                    +
                    +
                    +
                      +
                      + +
                      +
                    • +
                    • + +
                      + Jille +
                      +
                      +
                      +
                      + +
                      +
                      +
                      + +
                      +
                      +
                      +
                      Jille +

                      + @RexBeckett  +

                      +

                      + Okay, found the problem. I used brand new midi-cables which I ordered with the mini. but one of them is not okay. +

                      +

                      + I also wanted to test with the X-touch compact, so I ordered that one. And this compact shows midi-signals on the front.  +

                      +

                      + Still no midi-in signal. In a clear moment I switched the midi-cables and then no midi-out signal anymore. +

                      +

                      + Took another midi-cable and everthing seems to work now. Even the mini takes the right positions directly after connecting, so also without downloading settings.  +

                      +

                      + Thanks again. For sofar I'm happy. +

                      +
                        +
                      • · +
                      • +
                      • + February 19 2020 +
                      • +
                      +
                      +
                      +
                        +
                        + +
                        +
                      • +
                      +
                      +
                      + +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      + + +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      +
                      + prev +
                      +
                      + next +
                      +
                      +
                      +
                      +
                      +
                      +
                      + +
                      +
                      +
                      + +
                      +
                      +
                      +
                      + +
                      +
                      +
                      +
                      +
                      +
                      + +
                      +
                      +
                      +

                      + Original text +

                      +
                      +
                      +
                      +
                      +
                      + +
                      +
                      +
                      +
                      +
                      + +
                      +
                      +
                      + + +
                      +
                      +
                      +
                      +
                      +
                      + We use cookies on this site to enhance your user experience.
                      + By clicking any link on this page you are giving your consent for us to set cookies. Learn more
                      +
                      + +
                      +
                      +
                      + + diff --git a/packages/readabilityjs/test/test-pages/community.musictribe.com/url.txt b/packages/readabilityjs/test/test-pages/community.musictribe.com/url.txt new file mode 100644 index 000000000..4598f262b --- /dev/null +++ b/packages/readabilityjs/test/test-pages/community.musictribe.com/url.txt @@ -0,0 +1 @@ +https://community.musictribe.com/discussions/77059/213157/controlling-an-xr12-via-midi-using-an-xtouch-mini \ No newline at end of file