LIVE CODING - WordPress Migration to Blazor - PART 3
November 6, 2024
• 316 views
career advicesoftware engineeringsoftware engineermicrosoftmsftAMAask me anythinglive streamlivestreamsoftware engineering managerengineering managerengineering manager day in the lifeprincipal engineerprincipal software engineerengineering managementengineering management careerbig techbig tech amadevin aicognition labsdevin cognitionaicognition aidevin software engineerai software engineerartificial intelligence
It's time! WordPress on AWS LightSail has been non-stop problems for nearly 2 years now.
Time for a change.
I'll be looking into using LinkDotNet.Blog by Steven Giesel as my blog engine of choice. But migrations are never easy, so this will be the first of many sessions trying to figure out how I can get my blog setup before going live.
Remember -- I need to keep as many links active as possible so I don't ruin my SEO!
View Transcript
start on Tik Tok so I just need one moment should only take a second let's go ahead and get that done awesome I think that's it um I got to mute my computer cool okay well for fortunately I am joined by both the cats once again so we have veto and Vinnie behind me um my wife is gone but if and she's not coming back until the evening so they're not going to attack the door again because once she comes home they both they both really want to get her attention so I'm safe for now um kind of because they like to explore so um we'll see veto right now is still on the couch he's usually the uh the Explorer Vinnie is the fatter one and he's usually very much just wants to sleep and eat so he's he's currently causing a little bit
of Havoc back there but we should be okay um this stream compared to the one I do at night is more about actually trying to write some code and I'm continuing on the series where I am talking about migrating my blog from or press over to Blazer so for folks that are kind of new to what I've been doing here because it's been a little bit I had a vacation um so I didn't stream for two weeks on this but this is the Blazer blog engine that I'll be using I'm putting it in the chat so you can check that out this is I can't say his name properly and I I apologize um Steven uh Gil I he said I think I got like a six or seven out of 10 on his name so I apologize I can't do it right um but
this is what I'm going to be using personally um for a little bit of context uh when I started Dev leader it was this blog uh sorry I didn't put the link to my blog uh it was this blog that I've been working on um so I'll put the link to that so this is my blog um and that was in 2013 and I'm rubbing my eyes cuz I just woke up but in 2013 I started my blog so that's been kind of the foundation of like uh when I create content it usually starts off as a blog post and even when uh so I haven't been blogging for most of this year because I've been building brand ghost I just haven't had time but the way that content creation works for me is generally from a blog post or a video idea but then
I would create the blog post if there's a good Associated video I want to make with it I would make that and and then from there I can come up with posts and stuff for other platforms so the blog is one of the core parts of like how I like to put information out on the internet so my blog is for the last yeah six months or so maybe a little longer now it's only been used for hosting my newsletter articles because that's the one piece of like blog content that I'm being consistent with the rest um the rest I just don't have time for uh until I'm further along in brand ghost and then I can go back to to creating blog articles so um I used WordPress back in 2013 um I remember it was a bit of a pain in the butt
sometimes but when I started creating content again in 2023 I said hey I'm G to go back to WordPress but I'm going to do it right I'm gonna do it right it felt it felt like a a rewrite hey like hey like you know this time we're going to address all the the tech that it'll be perfect uh no uh definitely not so uh it it reached a point not long in where uh you know when you're try if you haven't done this kind of thing before if you have a Blog website or so if you haven't done it and you want to have a Blog website there's a lot of things that go into trying to make sure that it's optimized whether that's performance or your the keyword usage things like that uh even like the layout can affect your ranking based on how
Bots are crawling your pages so um especially the performance of the site is a huge factor and so when you're using Wordpress and plugins and stuff like that like for I was running ads at one point and uh then the problem is like okay now the I got these plugins turned on now their performance is taking a hit so then you layer on more settings for your optimizations and now there's more complexity like once caching is turned on like good luck um anyway like the whole point is that I wanted to do it right with WordPress and uh I've been spending like well over a year now uh basically constantly fighting WordPress uh I run my WordPress instance on light sale uh which is an Amazon service it's actually it's kind of nice it's like a very it feels like a I like a no-brain
kind of way to just have a container uh running in a in a in the cloud uh except except my WordPress instance is nonstop crashing so uh and I have no idea why uh so basically like every two days or something I I'll get an alert that comes to me and it's like CPU usage is like way too high and I'm like that's super weird and then the alert changes shortly after like CPU usage is way below normal and then I look and it basically spiked up and plummeted and it's you know all the services are off and it's got to be a plugin uh that's causing my WordPress to crash and I'm just at the point now where I'm like Hey Stephen who is in the chat on YouTube hey Steve uh he's come up with a Blazer blog engine he writes a lot
of awesome content uh Stephen uh where is your website I want to put it in the chat so people can can see it so Stephen's website is right here so uh I'm like hey if I'm if I'm G to have to accept that I'm going to be spending time touching the the blog engine right that because I'm already doing this with WordPress I'm like I might as well pick something that I can put my hands into and feel like I have full control like kind of going the exact opposite direction it's like I'm already seeing that I'm touching it all the time I might as well pick something that's not WordPress cuz working in WordPress and the plugin system they have and stuff like the the ecosystems cool because there's so many people that can create things but I don't want to be one of
the people tweaking and modifying stuff in that ecosystem uh so it's it's just proving that it's not a good fit for me um over the past few streams that I've done uh like Stephen has jumped into the chat like he is right now uh and you know we didn't coordinate this or anything um it's like oh gel did I do it Stephen did I do it right gel I think the diesel example is very [Laughter] good I wanted to make I wanted to say Gil right but gel hopefully I've gotten it finally and then I can do his name Justice that would be awesome um yeah like he's been able to jump into the chat um 10 out of 10 finally I've done it um uh jump into the chat and and kind of walk me through different things uh when I was streaming about
this before I was calling out like I want to be fully transparent right like uh I don't expect that uh Steven's blog engine will do everything that I had on WordPress out of the box and that's because it's his blog engine like he's building something that is obviously got to be something he wants to use um and oh no the cats are already starting no buddy you got to come here thank you um and I'm I'm just a potential user that has some feature requests but um what's been really cool is there's been a couple things that I've called out and like he's extremely active on it so one of the last things this is like again totally unexpected I I had in between the last stream and now I I said to Stephen like hey I remembered something that I never came up on
the streams and it has to do with my newsletter so for context and I promise I'm going to try to get into some actual code today but I just want to give you some framing uh for context I have my newsletter on substack it gets paywalled when it's archived so after a month uh the newsletter articles get archived and that's you know you have that month to go view them that's where if you want to check them out for free that's the spot but on my blog I have like sort of the original Master Copy of them and they're pay walled there um so I realized oh crap like I don't think there's a way with Steven's blog engine to be able to do the pay Walling so I can't have like a like a members only kind of thing so what's really awesome is
that and I got to move something one sec it's in the way um what's really awesome if I share my screen here so I was talking with step about this and I said hey I don't know if you plan on building this but like if not I will probably at least on a fork or something have to try and build my own for uh members and authentication but he went ahead and in in like a day had like a prototype and something whipped up and I think there's been a couple more commits I haven't I've been uh super busy over the past few days I have not yet got to go see it but um I don't know if we'll get time today to go do this perhaps not because I want to try converting some posts but um this will be something that I
actively use right so he went ahead and built the feature um to essentially allow uh me to have users on my blog that can be uh that I can try to uh get coordinated with uh substack memberships and stuff like that which is awesome uh so I think at this point in terms of features that like are I'm going to use like the word missing that's not you know again not I'm not blaming stepen for this trying to I'm trying to in my head figure out feature parody so that I have a migration path because migrating a Blog where like all of your stuff has just lived is like it's kind of a scary process the only thing that I think is sort of missing and it's not it's not even a feature that has to get built is like I have to figure out
and understand how I migrate certain pages and the one example I had um if I go back to sharing my screen here so on my blog um like and you can see like this you see how this stupid purple at the top that's not supposed to be like that like that that's actually a bug because there's some caching involved in The Styling um and like how ridiculous that looks where it's a purple highlight and black background on courses and stuff like that's not not supposed to look like that but these Links at the top that I have um they don't necessarily have to exist like this in the future but um I have these like these Pages where uh for example maybe this one that's like a bunch of YouTube links um this one doesn't necessarily have to exist that's fine but something like my
chuses landing page this is where uh you see that the spinner and everything it's just this is a terrible experience but um this is like a landing page that I have links to a bunch of places on the internet already so I would love to still have like a you know an ability to make sure I can have landing pages and stuff which should be like I said so I don't even think that's a feature that needs to be asked for this is just the ability for me to go make some pages uh so that should be totally fine um so and I'm just reading Steven's comments in the chat so this is uh perfect as this still somewhat draft State awesome this is for the member stuff but at the very very least it might be a jumping off point for a fork that
supports us out of the yeah great and always keep up the features I really like that whether or not I will use that is not so important in the first place and that's been like that's been a cool thing like from again I'm not like I hope Steven doesn't feel like this like I don't feel like I'm hounding him just kind of talking about the migration path I have and I have felt very supported and that every single time I talk about something he has been like okay noted and like fully up to him if he wants to go pursue it or not but but um we I think there's a mutual understanding that like there's going to be stuff that just literally doesn't make sense for him to put into the blog engine and that's totally fine like I will have to Fork it
and build some pieces myself that's cool but that's the whole point of being able to have this because I don't want to go do this in WordPress because it's going to be a nightmare um so with that said um I think what I'm going to have to do cuz I we had a bit of a a brand ghost uh scare when I was in Hawaii because the Azure the Azure billing turned off cuz my credit card expired it was the worst timing in my entire life and so I I nuked the I all I put the database that had my my blog post that I cloned from WordPress I put that into the Azure subscription and I was like I'm going to get rid of that because it had a monthly cost but I'm going to take the now we Pro last time we can
take the HTML from my post and they're almost perfect which is so cool because I thought that I was going to have to do HTML to markdown conversion on everything um I forgot stepen put the short code support in that was one big thing that was missing uh I say missing sorry missing from feature parody that I wanted um so I think like I think I want to try converting a post and there's a couple of things that are interesting like some of the YouTube embeds don't work unless we change them to be a certain format um what I'm not going to do on stream is actually do the uh because I'm going to be bulk converting post that was the framing here um some of the the the picture hosting right I need to make sure that I put that up into Azure blob
storage so we can write something but I'm not going to actually do the upload to Azure CU I don't want to configure that and stuff on stream I'm a little bit nervous to have like some of the cloud stuff I'll do this at some point in the future but it makes me a little bit nervous to be doing that stuff live because if I have something visible at the wrong time I don't want to have to be paranoid about someone watching a video later and being like Oh like Nick left this open like I just don't want to worry about it for now so we can go through at least some pseudo code and uh the part where it's actually going to have to do the upload to Azure if you haven't worked with the Azure blob storage n get package it is so uh
so simple and straightforward the first time I had to go use it I was like there's no way it works like this and sure enough it's one of those things like it's pretty rare I find like you code it for the first time and it works and you're like how like how did that run the first time it's supposed to be broken isn't it but uh no it uh it works really well so I'm not nervous about that personally but I want it to be transparent that like that part's going to be pseudo code so what I'm going to do is on a different screen so it's not in your face uh I will try to pull the um the HTML for a blog post uh I am going to go open up visual studio here and try to get the blog open and I
remembered I need to use Visual Studio preview you so let me do that because that has net9 loaded that's going oh you know what I might have uh I actually might have some of the blog posts in the sqlite database so we'll go ahead and run this I'm just reading Steven's last message so he was saying no does enjoy that for the the feature discussion the idea is to open that to a wide variety of people the most the most stuff should be configurable in some way or another and I'm 100% on board that's cool that's like that's that's how it's felt so I feel like Stephen's not just doing that lip service and saying like you know here's whatever how I feel and it's not real like that's honestly what it's felt like the entire time um and if I go refresh my browser
over here I just wanted to show you the blog is running uh I am not authorized so um yeah this is actually I don't have to Port anything probably uh I do have uh this is some of the HTML that's directly from my blog so one sec let me get this a little bit better who I zoomed the wrong way um so if I'm just doing a little bit of recap here cuz if folks haven't watched the previous live streams and even for me it's been a couple weeks but um just to recall that the idea this zooms oh I'm zooming in different spots here one sec okay so the idea is that this is supposed to be markdown and what I didn't realize until I guess the last stream was that markdown will support HTML I I literally did not know this so my
assumption was that all of this HTML that you see here uh I thought that I was going to have to Port all of this like with um what is I think it's called Mark dig uh or I like a combination of HTML agility pack and Mark dig I thought I was going to have to convert every blog article from HTML over to markdown but it just like like an over 90% success in my opinion just works out of the box like this going forward forward I will write my blog post in markdown just so that it doesn't feel like like this stuff's pretty gross if we're looking through it and you can see that like there's these extra comments and stuff that get added in and that's from WordPress itself I think for for how some of the the plugins and the tools work so
that will go away um one of okay and then I would I my list is somewhere it was a short list but I had a list of things that were like keep these in mind when we're converting blog posts one of them is that the table of contents which I think I've already pulled out of this one the table of contents needs to be stripped out of my blog post because we get it for free now which is super cool um I need to see if there is a short code on this one how do we do short codes um because Steph did add the support for short codes which is again that was a a feature that I was looking for because for context I have some spots on my articles where I want to embed like a chorus advertisement or I want to
uh embed like for some design patterns I have a free ebook that's uh sorry it's not it's a paid for ebook but it has the uh like I can't remember how many design patterns like across the Spectrum and when I write design pattern articles I like being able to mention that I have this ebook but it's basically I use a short code to ins insert like some common uh advertisement or text or something like that um Stephen said one thing that's currently open the automatic table of content generation oh from HTML that's right so that was one thing we noticed is that uh making the table of contents works very well out of the box for markdown but because I was dropping in these uh HTML Bas post it wasn't picking up the headings uh so he's saying it's a bit tricky it's not working
currently uh and is's going to have to write a parser um but yeah and like so this is and he said like there's a workaround and it's technically just converting the the the headings to to being an actual markdown which uh like I could do that right like I could go write a converter that does that so and it sounds like I'm assuming he plans he said like would need a par to be written so that might be something that sits on his backlog for a while maybe he wants to address it at some point and great um my cat's trying to eat my microphone stand now Vinnie come on man it's the fat one so he's literally probably trying to eat it because he's he's fat buddy stop that okay so what I want to do is I want to actually go through uh
let's go back to the homepage um and if I click this one so recall if I look at this URL for this one this is still going you can see like the wp content uploads um watch out buddy so I'm GNA have to figure that out uh in terms of like as much as possible for the stuff that exists I want to maintain um what this looks like so I might have to figure out how to get my Azure blob storage like basically when someone's hitting a URL that starts with WP content uh I might have to change the Blazer part to be able to handle that and say like Hey look it's trying to go to blob storage um and then I could have in Blob storage like an uploads folder I don't know I'm going to have to figure that out um but
that's the part that what we're going to do in the example today is we're going to walk through the code uh we we'll do a naive parser it's certainly not going to be optimal but the reason that I don't actually care is because the goal is to not run this regularly I just need to Port my content over and if it's slow if it's not optimal I don't care like it's not it's not going to matter um the one thing we had some trouble with so these are more pictures that have to handle but the code embed worked perfectly it was video embeds so this is where we were playing around with it um these sections that you see here with the headers these sections have these videos here and I like in my own blog I did not uh put the videos like this
they're actually in beds uh Saul yes this is open give me one second um cuz I don't think the links through nicely on LinkedIn so uh I just want to put the link to Steven's uh repository here so let me copy this back over and I will put it on LinkedIn so that should have gone through failed to post the comment yeah thank you LinkedIn okay um give me one moment so sorry I'll try again um I think it was trying to make the preview card or something and then it failed I'll try it one more time seems like it went there we go I can see it in the the share chat I just realized too the share chat's not visible on this view there you go folks sorry you can tell I'm not a pro streamer someday Maybe maybe um cool okay so
jumping back one thing that we're going to have to do is figured this part out and I think we have an example in this post where we did it a little bit because this is actually an embed now so let's go ahead and I'm going to duplicate this tab we're going to go edit this one so admin how do we go edit these edit there's an edit button right there I'm just blind okay so if we go to the end of this uh we go to the end do we have embed yeah so I think I put in both of these and I think that this is the one that doesn't work I I'd have to go back and watch my last live stream it's been two weeks now this is the one that doesn't work but this one does let's just quickly find out
so um if I take this out oh one sec okay I remember we had to actually go get the embed link so let me take this one out and save it make it visible immediately it's cached right so we want to bust the cash um if I refresh this one does the video go away no so that's good I got the right one the the one we need to use so if you weren't on the the last live stream where I was going through this we were trying to talk about which uh which style we needed to use so it's on my clipboard this one the video tag does not work does not work but if we do the embed it seems to work so let me go ahead and put this on can I make this actually take the right size uh my blog
post like all the videos are generally like a standard embed size um so like I think it's 600 by 400 I don't know anymore because in WordPress it's configured in one spot and then I don't think about it but let me go um again bust the cache on that update it and hopefully this becomes bigger ah yes okay perfect so the only thing that's missing on this is just to center it um but that means that when we go write a parser uh I'm probably going to be using a lot of regular Expressions which is super gross but probably going to do that and we'll be able to look for the uh YouTube URLs my God cat stop eating all the cables Vinnie Vinnie come on buddy I like having the cats in here when I'm streaming cuz it's kind of funny when they're running
around in the back but like this guy is literally pulling cables out one sec there he is yeah you can't eat my cables buddy okay maybe I can just hold them on my lap uh at least for a little bit so the video stuff we can be able to parse that'll be good um we can try doing header replacement just to get the um for now at least the markdown headers so we can do uh probably again I'm I'm probably using Rex for a lot of this stuff it's going to be terribly slow and inefficient but I don't care because like I said it's just to convert it once so we can try doing that um and then I want to write um a parser that's going to look for uh image links right so the the images let's see if we can go back
to here um if I take this text and we go back into here if I look for that ah it doesn't show up okay how do we oh it does sorry it's the searching is weird on on the browser because it was trying to search the page but not like the text box but if I scroll down a little bit um basically if I look for images that have this as a prefix or even maybe the whole part that's going to be a trigger for me when I'm doing migration that I will need to basically download the picture re-upload it to Azure blob storage and ideally I can keep the same URL so we'll write a little thing that it's it's going to be a little bit stubbed out but we can put something there so if that sounds cool maybe we'll try that out
so so I'm going to get another instance of Visual Studio open up this will be the start of the conversion tool that'll get built uh no this probably doesn't make sense for literally anyone else to use so making it available is kind it's kind of silly unless you just want to play with the code but unless you have the same plugins and stuff as me in WordPress and same configuration it might seem kind of useless but I don't know if uh Vinnie is still eating cables come on buddy um if you're watching this and you're like hey like that's something I would want then maybe I can just open it up but I'm making a project right now just give me a sec just a console app nothing fancy it will be WordPress to Blazer migrator not the best at naming things but hey that'll
do console app and uh maybe something we can try doing this will be kind of interesting maybe is I wonder if there's a way to write so I've talked about this before when I write code that's like using parsers and stuff like that um I like I actually like do not it's not quite tdd cuz I would never call myself someone who practices tdd because I think tdd people would be upset with me but uh when I write parsers I really like making sure that I have tests in place because when I'm writing parsers are going to be super messy and I just want to make sure I'm not breaking things so I might actually do that um so one sec let me make another project in here it will just be the class library for the test and what I'm thinking of doing this
is not generally how I would recommend uh people go write their functional tests or anything like that but I'm literally going to have an example input and what I hope the output can look like and this is again just so I can write a huge functional test that will exercise all of my parsers and we can put the output code into uh into Ste uh Steven's blog engine as long as it's looking right then I can use that as the expected output then we have something to try and match on there might be some weird stuff with white space and things like that because it's a lot of text but I think that's how we'll start looking at it so I'm just going to add a dependency to the other project so we have a reference to it um I will need something like um
xunit we'll get that installed sorry I know this is the boring stuff um and I spent most of the stream time um catching people up but I think we're we're getting there because once I have this in place uh you don't need to watch me run the the migration so that's why I'm saying it doesn't matter how slow it is like it just got to work light mode to dark mode change your theme now where where is it light mode where do you where do you see and your name's not coming through in the chat so um where do you see light mode I don't use light mode on anything um and then I need the test SDK man Vinnie is now eating envelopes I don't I didn't even know I had an envelope in here any is eating it he will find anything that
can be uh almost eaten so um oh you're you're saying I'm you drew your arrow oh light I thought you drew an arrow but it's a greater than light mode is greater than dark mode man I don't even know I don't even know who you are cu cu the name's not coming through but I won't tolerate that Let me refresh it I'm looking on LinkedIn I'm going to I'm going to ban you from the chat oh it's Ryan even better should have banned you from the start Ryan is uh the EM that I'm making courses with uh so we're going to wrap up our our second course I'm not telling you what the topic is yet but it is career Focus so that's really cool um that's why Ryan's sassing me but maybe today I'll give him a pass and no ban from the chat
that's okay so I think it's because I'm using C and he doesn't like C but that's okay um now that we have a test class basically we would need I don't have I don't have co-pilot on here I'm not going to be able to code anything now um asynchronous probably so we'll have to have a test method and this one's going like I said this one's going to be super dumb um he's lying no idea he is yeah okay okay uh it's funny because it works perfectly because his name is coming through his LinkedIn user but I have the proof and this is going to be Inception look there he is there's the traitor get him Ryan Murphy right there he can't hide cool okay so what we're going like I said what we're going to do is take a snapshot of the input and
we're going to massage it to get the output we want um I don't have a great way to do this I feel like it's going to be terrible no matter what so if I take a that's not the window I want where's the window that has the text so if I take this um I might even just load it from a file because it's pretty nasty uh so let's go add vog let's say like blog one input oh yeah that's funny I was like why is there code here but that's because I picked that template I just gave it a different name so we'll do that um and then we can load that in and then we'll have an output so I'm just going to copy and paste it so I'm just going to explain how I would want to go about making uh like
iteratively making a parer to go handle this stuff so right now the input and the output are the exact same which is obviously not right so we can uh we can actually start breaking it so when I get the output when we start doing some my voice is going when we start doing some parsing I can drop it into the blog engine we can check it out and say cool that's what we want then we'll go literally paste it into here we'll update this right and then then we go do another iteration so I'm going to keep evolving what the output is as we're making enhancements into the uh into how the parser is working so that will mean that in order for this to work I need to get a file loaded so um and we'll call it just like uh blog so input
HTML and we'll have to do like a file read uh oh I do have what I haven't seen the async versions of these it's been a long time since I've had to do a lot of like file IO stuff so um cool now I don't know where this is anchored to so give me one sec path is a bad name I'll rename it in just a second but I think if I do log one input. TX T if I can type without do I have co-pilot am I losing my mind here I do have co-pilot there it is it's going to say like without co-pilot I don't know how to I don't know how to write code anymore um I want I deleted too much here we go um I just want to double check this and run it because I can't recall if I
need to go up a directory or not or if I have to C I might have to copy these into the bin directory which is fine so this probably doesn't work oh man it's it's as I even said I don't use the async methods right but let me go ahead and I'm just going to make these as a copy to Output directory copy if newer okay sorry for jumping around I just want to get this kind of started because once it's in place it'll be uh I don't want to say easy to it'll be easy to iterate but there still might be some complexity so there we go loaded in the HTML it's going to look terrible blah blah blah I wish you could see my screen right now because you're seeing one quarter of my screen and as you might imagine this entire thing
is taking up uh a 4K resolution and it looks ridiculous um but we have some input we can do the same for the um the output so this will be not that there we go will co-pilot know it does know look I don't have to code anymore excellent okay so now we have these two things we can actually we don't have a parser created um it's funny I actually don't even need the first project well I I guess I will um this is just the test part so um let's go and make uh we'll call it the migrator the migrator that sounds cool and public async task migrate I have no idea um like I'm going to put a cancellation token on here we probably don't even need to worry about that yes if you're writing code that you care about you do want a
cancellation token I don't care about this code I just want to get my blog migrated but if we jump back over to here we should be able to now go make a new migrator right so we have access to that um the migrator is going to need um a input no it doesn't so that's the thing that's going to be a little bit confusing here um I when I go to run and sorry for jumping around here I haven't actually thought all this three yet the migrator itself is going to have to connect to a uh I don't want to I don't want to query WordPress direct uh directly I'm going to dump my WordPress blog articles to my SQL so I'll do that then I can just query a database directly so this will actually want to know where to connect to and then
uh I it needs to know where to write to so I need like a source database and a destination database but one of the things that we can also build is like just migrating uh a particular uh article itself so we can do the conversion so maybe we have a migrator and a converter so migrator just I'm just going to write it here so a WordPress site to a Blazer site nice thanks um not not to Wordpress to for the input and output so we're not writing that yet but we need to write the page converter so we'll call it uh the article article converter and the article converter itself is going to take in the uh input HTML and it's not going to take in the output HTML because that would be silly but it can return it so that's going to be what
this does and right now um sorry I have a microphone in my face and I off even to this day I still glance down at the keyboard when I need to re-anchor my hands and that's why I end up missing a lot of the time so um I don't want a migrator I want a what did I even call it article converter nice I told you I'm not good with names so we will have an article converter and that is going to be I'm going to zoom out a little bit I just realized it's real zoomed in but that's going to be what we're dealing with and then I will put an assertion at the end that we have this right so obviously if I go run this now it's going to be broken but that's the point it doesn't work cuz it's going to
say it's empty because that's what I returned cool now we can start iterating on things so inside of here the things that I wanted to do are uh we need to replace HTML headings with markdown okay so we're going to I'm going to plan on using regular expressions for almost all this stuff just because I think it's going to be super inefficient I keep saying this but I think it's going to work so then we need to um handle images that are on WordPress and find how to upload to blob storage so we're not going to do the actual uploading I just want to make sure that I have a hook for this so that when we go run this I can I can just make sure that it's tracking them so that will be good and then when it's finalized I will actually remove
the stub for uploading to Azure blob storage and uh and put the actual code in there like I said earlier in the Stream that's actually those apis are super easy to work with uh we also need to uh update video tag or embeds to use the proper HTML tags I think that's it um I don't have it well one sec uh use short code support so this one is probably not I'm just doing a time check too I don't actually don't have much longer on this stream but probably do another 20 minutes um so let's try to at least get I want to get this part done and we can probably do the video part done and what's this one's probably easier so let's see let's go back over to here we have um so have a heading H2 how many headings do we have
in this one so have heading we have H3 there's no H4 there's no H1 so we have H2 and H3 now do all of them have cuz what I I explained this a little bit earlier but what I want to be doing is um using a regular expression to do the replacement so now I'm using patterns right like so I'm trying to look at this H3 and saying are all the h3s like the same type of thing so for example has H3 I don't care about any of this stuff right doesn't matter but here so is it going to be safe for me to say write a regular expression that just ignores everything else or do I need are there examples where I actually need any of this stuff um this is going to be interesting so that might be a good one to to
play around with so this is I'm just showing you how I think through this stuff right so give me one sec uh I want to take a copy of that so I'm just going to organize my thoughts here so here's an example of one this one's extra fancy because because of that right I want to make sure that gets handled properly once we convert it uh let's go look for more h3s this is a really simple one so I'll have some examples of that um welcome back Stephen um [Music] H2 interest okay so like here's an example I'm I'm glad I found this one um I don't need strong so I need to be like I want to use this as an example so that when I go to put this to markdown it doesn't just have random like strong tags around it so we'll
move away from that uh so that's a good example to have in here right so yeah Stephen so I was just writing out um you you were G so the goal is that I'm just going to do like uh it's going to be super crude but when I write parsers or converters anything like that where I have to do a lot of I'm going to use regular Expressions a lot just cuz it's going to be the thing that works for me um this is going to be there's going to be some weird complication like I already found a couple of weird HTML headers and I just want to make sure that I have something that I can iterate on and if I can just compare the input to a desired output then I can uh not lose my sanity so this one in particular sorry
it's hidden behind my face this one in particular is going to be super weird so I'm going to need to make sure that the regular expression handles that um what else do we got in here this is a simple H2 so what's awesome um maybe we can use I was going to say like we could uh I found chat GPT for me has been helpful for writing SQL queries because I know how to write SQL but it's really good if I just explain like I have these table schemas write me something that does this it's complicated it's great uh for the most part and then regular Expressions it does really well too um but I don't know if co-pilot can do that um so could I literally ask it Rex um I don't think this is going to be quite what I want but I
just for fun just for fun let's let's go run this I have I full disclosure I haven't even read what it's put in front of me like I wasn't thinking that I would want to match on that but I guess that is common in all of them yeah uh Buran you're right yeah co-pilot requires the comments and I have the comments Above So it seems like it did something uh I don't need the ID but it's just pulling it out because it sees that it's it's common um the level oh the level it's not doing properly but that's actually solvable right because um in markdown one is one pound an H1 and then like this is an H2 because if that's the case we could literally do um new string is it like this and then the count not length level clearly not oh it's
not an integer one sec I'm not even going to try parsing that we'll just do that thanks Stephen yeah it's funny like for things like markdown and things like that I should know it off the top of my head but if I'm not looking at it then I don't trust my brain so uh but yeah this might be something that just works which would blow me away so let's um let's do that um I don't want to call it input HTML the whole way through so this is again you're going to see me writing code in here that like I'm not actually proud of but it's going to work so our output HTML equals the input HTML the reason I'm doing this I'm going to not use HTM uh input HTML at any other point in here um so I want to when I go
to debug this I want to make sure that I can just look at the HTML at the same time so you might see me using uh probably not on this stream because we're running out of time but I'll be using like watches where I can go to different offsets and stuff and I want to be able to compare I want to have the sort of untouched input uh accessible so then I'm going to return the output HTML um it's not going to the test isn't going to pass that's not the point right now I'm going to run this we're going to look at the output but not not in here because unless you have robot eyes it's probably not going to be super helpful um but I can already see like there is a triple here that doesn't look right at all so maybe we
need to pause on this for just a moment I was getting maybe a little too excited it's not text that we want or is it sorry this is uh when it's debugging I realize it's a lot smaller um it wasn't grabbing exactly what we needed so let's go run this again interesting so the text that it's grabbing is the right part in here on this one at least so it's going to be really hard to see I apologize it missed these H2S already it got the this one here so this H2 is correct so I should also put this down in my list I'll put it with the other H2S and we know or at least I saw that one of the h3s was absolutely not right so this one is still a two that text looks right this one is a three what is
the text okay that one looks right I'm just going to have a quick peek at this one so there's two this H3 looks right so I'm pretty sure early on I saw one that was absolutely mangled though another level H3 this also looks right maybe I'm just making stuff up in my head but I'm pretty sure I saw something get kind of crazy also looks right okay let's pull this back up looks good sorry these are going off the screen I realize um again what you're seeing as one quarter of my monitor so so far these are looking okay maybe I'm just being silly um the other thing that maybe happened is that this uh this replacement here I doubt this is the case but this replacement is looking across the entire string and if there was a duplicate it would be replacing it in
spots that we weren't expecting so let me go ahead and run this to the end I could have swore that I saw one that wasn't a good fit though maybe not I might be making it up anyway what we do know is that the H2S at the top are not correct that's okay so we can see if co-pilot will regenerate the uh the Rex for us but I'm going to go back to here I'm going to paste this in so it's the same HTML except we've replaced most of the H2S and h3s uh we will go make it visible now and submit yeah so there's still an H2 at the beginning that's because I missed that one in the sample uh that I fed to co-pilot so we will check it out but so aside from those like we still these are all looking good
right and so this isn't going to be perfect because it's missing the beginning but Steven's right this is working better now and that's because I was able to convert uh some of those HTML tags over to the right thing so oh nice so in the blog there's an i button which gives you a preview also works nicely with short coats perfect thank you one sec I minimized the window and now I can't find anything there we go so over here nice Zoom back out a little bit very cool yeah so if we just wanted to check to make sure these were getting uh picked up that's good but we have one more uh H2 that's not working that I saw at least uh what we could also do is in our test again this isn't I'm not suggesting writing test this way that you would
put into a test Suite this is just me like uh this is me having something programmatic to help verify that I'm not doing stuff that's like totally being missed um we could write something that goes through the text after and just looks for HTML H2S and h3s like just looks for this text and if it finds any of them it's like you're missing it right so have have a bit of a safety net um but okay so this this Rex was wrong because it missed this here and that's because it's looking for the ID which we simply don't need um so let's see if I delete this is it like an optional ID now I don't even think that's I still don't think that works this is the just for like if you're seeing this in front of your eyes right like uh when you
start relying on llms to do stuff a little bit too much like yeah this didn't fix it so if you're like hey I don't I don't know how redx works but like co-pilot or chat GPT is putting this in front of me so like it must work um like it made a different one this time uh this here yeah so Steph's saying that like uh is that I don't know if that's quite right like I need to get this factored into right Stephen the ID equals because this last one doesn't even have ID equals this plus sign is affecting just this I think so if you're if you're constantly just looking at like it's giving you stuff as the output and you're like oh like I'm just going to go use it and then it doesn't work if you don't understand what like how the
regular Expressions actually work or the other example I was talking about with my SQL if you're like I don't I don't actually know SQL but like the the llm is giving this to me and you're like hey it's not working it's it can become really difficult to to try and talk to chat GPT or whatever you're using to say like hey like this is wrong and like here's my observation about it right um better listen to J jpd rather than my gibberish um but this is like like something I would generally put into chat GPT and just say make a Rex that can parse this stuff out um so what I can do and I'm not going to put my chat GPT up on the screen is I'm going to just explain what I'm doing but I'm literally going to take this code and I'm
going to say to chat I'm just I'm typing this in a different window can I hide all my other stuff sure that seems like it's doing what I want at least fix this C code to handle uh and then I'm just going to copy and paste um oh man this chat window is such a pain in the butt it was jumping around so d to handle this HTML uh tag properly the rest of the HTML examples in the comments work here is the code so you'll notice uh oh I can see what it did already and it's basically very very close to what step was saying uh but the comment I made to Stephen was that there's based on the whatever this is hard to explain I'm going to zoom in a little more based on the shape of what we're trying to do like
the ID part is the optional part but can I even see it I think that's the whole thing man regular Expressions suck um but the question mark so there used to be a plus sign plus sign if you're not familiar with Rex is is going to say that we need one or more but we don't need one or more of the ID it's totally optional we're not even using it so the question mark says like could be there or not um and we need that around the entire thing that defines an ID so I bet you if we just take this now um that will probably just work and if it doesn't we tell chat GPT hey you're still wrong you're not Tak taking our jobs that's what we tell it um but as you can see like regular expressions are totally disgusting right and
this one is probably more complicated than it needs to be to be honest and that's another thing that I would say if you're using llms especially for for regular Expressions I've seen them write some some uh rexes that are pretty crazy and I'm like I know I could write one that would work and it wouldn't look this complicated but theirs might be more performant I don't know uh let's go ahead and rerun this test and the check that we want to do is raate at the top boom it did go ahead and get it it's picking up this one here as well there's an H3 so it looked like it did the right thing right there's another H2 right above it so that's pretty cool um thank you Chad GPT Our Savior uh full circle let chat jpt explain the Rex yeah so let me
pull this back up because I didn't actually scroll through it all but look explanation of changes the regular expression now makes the ID attribute optional and then uh it's funny I zoomed in to go do it manually but it literally tells you like this is the part so I wasn't making stuff up this part matches the ID attribute only if it's present uh allowing for headings without that uh and then it says we so they actually changed um the code within uh to not access like this doesn't throw an exception but like we don't use this at all so just get rid of it so interesting right like uh we used co-pilot to go generate some code um and it did a pretty good job and it probably maybe in the very beginning if I would have had this as an example it would have
done a redx like this but I found it after right so my fault I'm the human I messed up gave it another examp example it didn't regenerate it exactly as we wanted which sucks um so then we just use a different llm and instead of saying hey go make this from uh from scratch and like repeating it um I don't personally I don't like using co-pilot in Visual Studio to ask it questions but to write code like with the comments and stuff I love doing but if I I feel like chat GPT I like talking to it to go fix code or generate code and stuff so that's why it was a good fit for me to go take this and explain like hey here's a scenario U that's missing from this logic help me make it work uh and then Stephen saying so uh
and then close the H2 on line three so check also the following you can start an H2 on line one have the header on line two and close on H if you have this it might be a more convoluted Rex oh interesting so I shouldn't um and the only reason I shouldn't is because it's all programmatically generated so that shouldn't have happened but that's a that's a good point right so um let me just take this from the chat and put it into here um oh my goodness oh I'm running so I'm losing all this screen real estate um and he's he corrected his typo so close the H2 online three okay so I I shouldn't have this in my code uh but this would be a perfect Edge case to consider because there's nothing that says that uh these tags have to be across
one line um cool okay so that actually worked now what I would do uh is let me go back to run this so this is like one feature out of this list in my migration that I need so I would take this copy the whole thing and now I'm going to go to blog one output and I just pasted over top of it oh I just saw an H3 I missed one no oh no this one has a link in it oh okay well now we repeat the process right so just to show you my logic is if I go run this now it should pass great but we need to go update this so this is a perfect example let's um pull up chat GPT again and we can say uh it also so thanks that worked perfectly we also need to handle h3s
that or sorry not just h3s headings so that one's disgusting and I will say note that it has uh a hyperlink but we just need the text a heading did I break it okay there we go um okay and now it's explaining right so the updated pattern makes the a tag optional it captures only the in text whether or not hyperlink is present okay let's see um the way that it phrased that I don't think we had an a tag in there before I don't think so it's it's saying it's it made it seem to me like oh now it's just optional but like it it wasn't even there before uh like that's not the change it's the fact that you even added it so what I could do is go back into uh here sorry all this stuff is named very terribly in terms
of the file names and stuff but this regular expression is getting just disgusting but it's okay so if I go run this now it shouldn't work and it fails and you can see this is why I like having like again I I'm not trying to say this is tdd but it's the closest thing I do to tddd you can see that now it's failing because it's saying hey look we we were expecting and there's still this uh this HTML H3 and now it's actually the right thing so the only challenge with this is that I need more text to kind of prove it so um just to give you an example though um if we can we do this one manually this is the output so three and then I need that oh interesting I wonder which one it was going to pick it shouldn't
it shouldn't even look inside of the uh the SL a uh the a tag so anyway let's go run this there might still be another one and that's okay but if we look it shouldn't be complaining about commands and events now if it's going to complain it should complain about something else and it is now it's complaining about safe deployment right so uh if I were to go look for uh that is probably a little bit lower H3 right so if I go change this one manually oh no I already missed it it's not this one it's up here so let's do two do it the same time though one sec okay because this is going to be the next one I just totally scroll past the other H3 though I still can't see it come on eyes turn on there we go um so
writing stuff like this is pretty tedious but um once I have this like I'm if it goes to one more that's beyond these two that I just changed i' I have enough confidence that it's doing what I want so schedule jobs is the next one right so at this point if I see an H3 and it's schedule jobs right um I'm confident now so what I would just do is say great I'm going to trust whatever the output is so let me debug it take the HTML I forgot I still had a breakpoint there and I'm just going to drop it in the output here and it's not going to pass this time cuz it didn't load the right time but if I run it this should now match and great now we have one of the features of this list done at least to
my liking so this was one of the features I talked about I am going to have to drop I apologize but um the next stream because I'm only I'm only working on this during these streaming hours uh because I have other stuff going on this is like a forcing function for me but now we have one of these done which is great we can do the exact same type of logic for this video one so this should be way easier um and then even this is going to be very similar because we're looking for a Rex for images it's just that what we want to do with that is going to look different and maybe if I car since I'll carve out more time for this one um I will call the I'll I'll write the code that will do the uploading to Azure blob
storage but I'm not going to configure it um just in case like my keys and stuff show up but we'll write the code so it's there uh and then we can see how it works but I think that's it um I hope that was at least kind of helpful to see how I approach this kind of thing um the major takeaway that I I wanted to show you was that style of like this is a pretty complicated block of text it's a lot of HTML um Regular expressions are disgusting I mean if I quickly flip back you can see like look at this redx this is gross um I've seen significantly worse uh but they're gross to work with um like man what like what is even going on here it's um it's a nightmare but you can use uh I have found that llms
are extremely good at writing regular Expressions now someone who is a redx pro might say like I disagree they're not performant or something or I can do them Faster by hand that's great great for you I'm not saying I'm not saying humans can't be better all that I'm saying is like I don't want to have to write these I just want them to work and it's actually much faster for me to tell an llm here's the scenarios I need handled go do it and then if I miss a scenario like we saw go update it and then you saw me miss another one and I could have it updated very easily and it just works so um having the test in place this way if I would have asked Chad GPT to update the regular expression and it caused a regression on the first part
we would see that the other headings weren't matching so when we go to repeat this with the video stuff and we go to repeat it with the uh the images that are embedded we'll see the same type of thing if I miss scenarios and I say hey chachy BT like you got to go fix this one up if it causes a regression we should be able to see our test fail at a different spot um and that way we can always go back and forth but I think that's it folks so thank you uh I should be able to resume this you know next week I don't have any there's no more vacations and stuff coming up no more Hawaii for me uh not until next year but yeah uh thanks again Stephen for joining um super thankful that you know you're able to jump
into these and for all the help with the feature ask and stuff so um yeah I'm Hing this helps get some more eyes on on the blog engine and I'm super excited to get over to using this I just had a couple of like WordPress plugins renew when I got the bill and I'm like why am I why am I doing this like get me over to Blazer now um so yeah I'm very motivated to to get migrated over so um yeah we'll get we'll get there soon so thanks folks I appreciate you joining and I'll see you next time take care
Frequently Asked Questions
What is the main focus of this live coding session?
In this session, I'm focusing on migrating my blog from WordPress to Blazor. I'm working on writing code to facilitate this migration and sharing my experiences and challenges along the way.
Why did you decide to move from WordPress to Blazor?
I decided to move from WordPress to Blazor because I've been constantly battling performance issues with my WordPress instance. I wanted a platform where I could have more control and not deal with the complexities of WordPress plugins and caching.
How do you plan to handle the migration of existing blog content?
These FAQs were generated by AI from the video transcript.I plan to handle the migration by writing a parser that will convert my existing HTML blog posts into a format compatible with Blazor. This will involve using regular expressions to replace HTML tags with markdown and uploading images to Azure Blob Storage.
